forked from Yara724/api
Added registrar mirrored
This commit is contained in:
@@ -6,6 +6,7 @@ import { StringValue } from "ms";
|
||||
import { AuthGuard, RolesGuard } from "./guards";
|
||||
import { AuthController } from "./auth.controller";
|
||||
import { AuthService } from "./auth.service";
|
||||
import { HashService } from "./providers";
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@@ -25,6 +26,7 @@ import { AuthService } from "./auth.service";
|
||||
{ provide: APP_GUARD, useClass: AuthGuard },
|
||||
{ provide: APP_GUARD, useClass: RolesGuard },
|
||||
AuthService,
|
||||
HashService,
|
||||
],
|
||||
})
|
||||
export class AuthModule {}
|
||||
|
||||
8
src/common/auth/constants/hash.constants.ts
Normal file
8
src/common/auth/constants/hash.constants.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { ScryptOptions } from "node:crypto";
|
||||
|
||||
export const KEY_LENGTH = 64;
|
||||
export const SCRYPT_PARAMS: ScryptOptions = {
|
||||
N: 19456, // CPU/memory cost
|
||||
r: 8, // block size
|
||||
p: 1, // parallelization
|
||||
};
|
||||
68
src/common/auth/providers/hash.provider.ts
Normal file
68
src/common/auth/providers/hash.provider.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import {
|
||||
BinaryLike,
|
||||
randomBytes,
|
||||
scrypt,
|
||||
ScryptOptions,
|
||||
timingSafeEqual,
|
||||
} from "node:crypto";
|
||||
import { promisify } from "node:util";
|
||||
import { Injectable } from "@nestjs/common";
|
||||
import { ConfigService } from "@nestjs/config";
|
||||
import { KEY_LENGTH, SCRYPT_PARAMS } from "../constants/hash.constants";
|
||||
|
||||
const scryptAsync = promisify<
|
||||
BinaryLike,
|
||||
BinaryLike,
|
||||
number,
|
||||
ScryptOptions,
|
||||
Buffer
|
||||
>(scrypt);
|
||||
|
||||
@Injectable()
|
||||
export class HashService {
|
||||
private readonly pepper: string;
|
||||
|
||||
constructor(private readonly configService: ConfigService) {
|
||||
this.pepper = this.configService.get<string>("HASH_PEPPER");
|
||||
}
|
||||
|
||||
private applyPepper(input: string): string {
|
||||
return this.pepper ? `${input}${this.pepper}` : input;
|
||||
}
|
||||
|
||||
private generateSalt(bytes: number = 16): string {
|
||||
return randomBytes(bytes).toString("hex");
|
||||
}
|
||||
|
||||
private async scrypt(password: string): Promise<[string, string]> {
|
||||
const salt = this.generateSalt();
|
||||
const pepperedInput = this.applyPepper(password);
|
||||
const hashedPassword = await scryptAsync(
|
||||
pepperedInput,
|
||||
salt,
|
||||
KEY_LENGTH,
|
||||
SCRYPT_PARAMS,
|
||||
);
|
||||
|
||||
return [salt, hashedPassword.toString("hex")];
|
||||
}
|
||||
|
||||
private async verifyScrypt(
|
||||
password: string,
|
||||
salt: string,
|
||||
hashedPassword: string,
|
||||
): Promise<boolean> {
|
||||
const pepperedInput = this.applyPepper(password);
|
||||
const derived = await scryptAsync(
|
||||
pepperedInput,
|
||||
salt,
|
||||
KEY_LENGTH,
|
||||
SCRYPT_PARAMS,
|
||||
);
|
||||
const storedBuffer = Buffer.from(hashedPassword, "hex");
|
||||
|
||||
if (derived.length !== storedBuffer.length) return false;
|
||||
|
||||
return timingSafeEqual(derived, storedBuffer);
|
||||
}
|
||||
}
|
||||
1
src/common/auth/providers/index.ts
Normal file
1
src/common/auth/providers/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { HashService } from "./hash.provider";
|
||||
@@ -1,7 +1,6 @@
|
||||
export interface JwtPayload {
|
||||
sub: string;
|
||||
role: string;
|
||||
clientId?: string;
|
||||
iat?: number;
|
||||
exp?: number;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user