@nest-boot/hash 7.0.2 → 7.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/hash.module.d.ts +6 -2
- package/dist/hash.module.js +39 -3
- package/dist/hash.module.js.map +1 -1
- package/dist/hash.module.spec.d.ts +1 -0
- package/dist/hash.module.spec.js +76 -0
- package/dist/hash.module.spec.js.map +1 -0
- package/dist/hash.service.d.ts +84 -14
- package/dist/hash.service.js +111 -39
- package/dist/hash.service.js.map +1 -1
- package/dist/hash.service.spec.js +170 -31
- package/dist/hash.service.spec.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/utils/estimate-entropy.d.ts +8 -0
- package/dist/utils/estimate-entropy.js +17 -0
- package/dist/utils/estimate-entropy.js.map +1 -0
- package/dist/utils/estimate-entropy.spec.d.ts +1 -0
- package/dist/utils/estimate-entropy.spec.js +17 -0
- package/dist/utils/estimate-entropy.spec.js.map +1 -0
- package/package.json +7 -3
package/dist/hash.module.d.ts
CHANGED
|
@@ -10,13 +10,17 @@ import { ASYNC_OPTIONS_TYPE, ConfigurableModuleClass, OPTIONS_TYPE } from "./has
|
|
|
10
10
|
* @Module({
|
|
11
11
|
* imports: [
|
|
12
12
|
* HashModule.register({
|
|
13
|
-
* secret:
|
|
14
|
-
* isGlobal: true,
|
|
13
|
+
* secret: process.env.HASH_SECRET
|
|
15
14
|
* }),
|
|
16
15
|
* ],
|
|
17
16
|
* })
|
|
18
17
|
* export class AppModule {}
|
|
19
18
|
* ```
|
|
19
|
+
*
|
|
20
|
+
* Generate a secure secret:
|
|
21
|
+
* ```bash
|
|
22
|
+
* node -e "console.log(require('crypto').randomBytes(32).toString('base64url'))"
|
|
23
|
+
* ```
|
|
20
24
|
*/
|
|
21
25
|
export declare class HashModule extends ConfigurableModuleClass {
|
|
22
26
|
/**
|
package/dist/hash.module.js
CHANGED
|
@@ -10,6 +10,7 @@ exports.HashModule = void 0;
|
|
|
10
10
|
const common_1 = require("@nestjs/common");
|
|
11
11
|
const hash_module_definition_1 = require("./hash.module-definition");
|
|
12
12
|
const hash_service_1 = require("./hash.service");
|
|
13
|
+
const estimate_entropy_1 = require("./utils/estimate-entropy");
|
|
13
14
|
/**
|
|
14
15
|
* Module that provides password hashing services using Argon2.
|
|
15
16
|
*
|
|
@@ -20,13 +21,17 @@ const hash_service_1 = require("./hash.service");
|
|
|
20
21
|
* @Module({
|
|
21
22
|
* imports: [
|
|
22
23
|
* HashModule.register({
|
|
23
|
-
* secret:
|
|
24
|
-
* isGlobal: true,
|
|
24
|
+
* secret: process.env.HASH_SECRET
|
|
25
25
|
* }),
|
|
26
26
|
* ],
|
|
27
27
|
* })
|
|
28
28
|
* export class AppModule {}
|
|
29
29
|
* ```
|
|
30
|
+
*
|
|
31
|
+
* Generate a secure secret:
|
|
32
|
+
* ```bash
|
|
33
|
+
* node -e "console.log(require('crypto').randomBytes(32).toString('base64url'))"
|
|
34
|
+
* ```
|
|
30
35
|
*/
|
|
31
36
|
let HashModule = class HashModule extends hash_module_definition_1.ConfigurableModuleClass {
|
|
32
37
|
/**
|
|
@@ -49,6 +54,37 @@ let HashModule = class HashModule extends hash_module_definition_1.ConfigurableM
|
|
|
49
54
|
exports.HashModule = HashModule;
|
|
50
55
|
exports.HashModule = HashModule = __decorate([
|
|
51
56
|
(0, common_1.Global)(),
|
|
52
|
-
(0, common_1.Module)({
|
|
57
|
+
(0, common_1.Module)({
|
|
58
|
+
providers: [
|
|
59
|
+
{
|
|
60
|
+
provide: hash_service_1.HashService,
|
|
61
|
+
inject: [{ token: hash_module_definition_1.MODULE_OPTIONS_TOKEN, optional: true }],
|
|
62
|
+
useFactory: (options) => {
|
|
63
|
+
const secret = options.secret ?? process.env.HASH_SECRET ?? process.env.APP_SECRET;
|
|
64
|
+
if (!secret) {
|
|
65
|
+
throw new Error("Hash secret is required.\n" +
|
|
66
|
+
"Set HASH_SECRET or APP_SECRET environment variable, or pass a secret option.\n" +
|
|
67
|
+
"Generate a secure secret with:\n" +
|
|
68
|
+
" node -e \"console.log(require('crypto').randomBytes(32).toString('base64url'))\"");
|
|
69
|
+
}
|
|
70
|
+
if (secret.length < 32) {
|
|
71
|
+
throw new Error("Hash secret must be at least 32 characters long.\n" +
|
|
72
|
+
"Set HASH_SECRET or APP_SECRET environment variable, or pass a secret option.\n" +
|
|
73
|
+
"Generate a secure secret with:\n" +
|
|
74
|
+
" node -e \"console.log(require('crypto').randomBytes(32).toString('base64url'))\"");
|
|
75
|
+
}
|
|
76
|
+
if ((0, estimate_entropy_1.estimateEntropy)(secret) < 120) {
|
|
77
|
+
throw new Error("Hash secret appears low-entropy.\n" +
|
|
78
|
+
"Use a randomly generated secret for production.\n" +
|
|
79
|
+
"Generate a secure secret with:\n" +
|
|
80
|
+
" node -e \"console.log(require('crypto').randomBytes(32).toString('base64url'))\"");
|
|
81
|
+
}
|
|
82
|
+
hash_service_1.HashService.init(secret);
|
|
83
|
+
return hash_service_1.HashService.instance;
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
],
|
|
87
|
+
exports: [hash_service_1.HashService],
|
|
88
|
+
})
|
|
53
89
|
], HashModule);
|
|
54
90
|
//# sourceMappingURL=hash.module.js.map
|
package/dist/hash.module.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hash.module.js","sourceRoot":"","sources":["../src/hash.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAoE;AAEpE,
|
|
1
|
+
{"version":3,"file":"hash.module.js","sourceRoot":"","sources":["../src/hash.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAoE;AAEpE,qEAKkC;AAClC,iDAA6C;AAE7C,+DAA2D;AAE3D;;;;;;;;;;;;;;;;;;;;;GAqBG;AA8CI,IAAM,UAAU,GAAhB,MAAM,UAAW,SAAQ,gDAAuB;IACrD;;;;OAIG;IACH,MAAM,CAAU,QAAQ,CAAC,OAA4B;QACnD,OAAO,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACjC,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAU,aAAa,CAC3B,OAAkC;QAElC,OAAO,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC;CACF,CAAA;AApBY,gCAAU;qBAAV,UAAU;IA7CtB,IAAA,eAAM,GAAE;IACR,IAAA,eAAM,EAAC;QACN,SAAS,EAAE;YACT;gBACE,OAAO,EAAE,0BAAW;gBACpB,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,6CAAoB,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;gBACzD,UAAU,EAAE,CAAC,OAA0B,EAAE,EAAE;oBACzC,MAAM,MAAM,GACV,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC;oBAEtE,IAAI,CAAC,MAAM,EAAE,CAAC;wBACZ,MAAM,IAAI,KAAK,CACb,4BAA4B;4BAC1B,gFAAgF;4BAChF,kCAAkC;4BAClC,oFAAoF,CACvF,CAAC;oBACJ,CAAC;oBAED,IAAI,MAAM,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;wBACvB,MAAM,IAAI,KAAK,CACb,oDAAoD;4BAClD,gFAAgF;4BAChF,kCAAkC;4BAClC,oFAAoF,CACvF,CAAC;oBACJ,CAAC;oBAED,IAAI,IAAA,kCAAe,EAAC,MAAM,CAAC,GAAG,GAAG,EAAE,CAAC;wBAClC,MAAM,IAAI,KAAK,CACb,oCAAoC;4BAClC,mDAAmD;4BACnD,kCAAkC;4BAClC,oFAAoF,CACvF,CAAC;oBACJ,CAAC;oBAED,0BAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;oBAEzB,OAAO,0BAAW,CAAC,QAAQ,CAAC;gBAC9B,CAAC;aACF;SACF;QACD,OAAO,EAAE,CAAC,0BAAW,CAAC;KACvB,CAAC;GACW,UAAU,CAoBtB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const testing_1 = require("@nestjs/testing");
|
|
4
|
+
const _1 = require(".");
|
|
5
|
+
const TEST_SECRET = "myTestSecretThatIsAtLeast32Chars!";
|
|
6
|
+
describe("HashModule", () => {
|
|
7
|
+
const originalEnv = process.env;
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
// Reset static instance before each test
|
|
10
|
+
_1.HashService._instance = undefined;
|
|
11
|
+
// Reset environment variables
|
|
12
|
+
process.env = { ...originalEnv };
|
|
13
|
+
delete process.env.HASH_SECRET;
|
|
14
|
+
delete process.env.APP_SECRET;
|
|
15
|
+
});
|
|
16
|
+
afterAll(() => {
|
|
17
|
+
process.env = originalEnv;
|
|
18
|
+
});
|
|
19
|
+
describe("register", () => {
|
|
20
|
+
it("should throw error when secret is missing", async () => {
|
|
21
|
+
await expect(testing_1.Test.createTestingModule({
|
|
22
|
+
imports: [_1.HashModule.register({})],
|
|
23
|
+
}).compile()).rejects.toThrow("Hash secret is required.");
|
|
24
|
+
});
|
|
25
|
+
it("should use HASH_SECRET env when no secret provided", async () => {
|
|
26
|
+
process.env.HASH_SECRET = TEST_SECRET;
|
|
27
|
+
const moduleRef = await testing_1.Test.createTestingModule({
|
|
28
|
+
imports: [_1.HashModule.register({})],
|
|
29
|
+
}).compile();
|
|
30
|
+
const hashService = moduleRef.get(_1.HashService);
|
|
31
|
+
expect(hashService).toBeDefined();
|
|
32
|
+
const hashed = await hashService.hash("password");
|
|
33
|
+
expect(hashed).toContain("$argon2");
|
|
34
|
+
});
|
|
35
|
+
it("should use APP_SECRET env when no secret or HASH_SECRET provided", async () => {
|
|
36
|
+
process.env.APP_SECRET = TEST_SECRET;
|
|
37
|
+
const moduleRef = await testing_1.Test.createTestingModule({
|
|
38
|
+
imports: [_1.HashModule.register({})],
|
|
39
|
+
}).compile();
|
|
40
|
+
const hashService = moduleRef.get(_1.HashService);
|
|
41
|
+
expect(hashService).toBeDefined();
|
|
42
|
+
const hashed = await hashService.hash("password");
|
|
43
|
+
expect(hashed).toContain("$argon2");
|
|
44
|
+
});
|
|
45
|
+
it("should throw error when secret is too short", async () => {
|
|
46
|
+
await expect(testing_1.Test.createTestingModule({
|
|
47
|
+
imports: [_1.HashModule.register({ secret: "short" })],
|
|
48
|
+
}).compile()).rejects.toThrow("Hash secret must be at least 32 characters long.");
|
|
49
|
+
});
|
|
50
|
+
it("should throw error when secret has low entropy", async () => {
|
|
51
|
+
// A secret that is 32 chars but low entropy (all same character)
|
|
52
|
+
const lowEntropySecret = "a".repeat(32);
|
|
53
|
+
await expect(testing_1.Test.createTestingModule({
|
|
54
|
+
imports: [_1.HashModule.register({ secret: lowEntropySecret })],
|
|
55
|
+
}).compile()).rejects.toThrow("Hash secret appears low-entropy.");
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
describe("registerAsync", () => {
|
|
59
|
+
it("should register module with async factory", async () => {
|
|
60
|
+
const moduleRef = await testing_1.Test.createTestingModule({
|
|
61
|
+
imports: [
|
|
62
|
+
_1.HashModule.registerAsync({
|
|
63
|
+
useFactory: () => ({
|
|
64
|
+
secret: TEST_SECRET,
|
|
65
|
+
}),
|
|
66
|
+
}),
|
|
67
|
+
],
|
|
68
|
+
}).compile();
|
|
69
|
+
const hashService = moduleRef.get(_1.HashService);
|
|
70
|
+
expect(hashService).toBeDefined();
|
|
71
|
+
const hashed = await hashService.hash("password");
|
|
72
|
+
expect(hashed).toContain("$argon2");
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
//# sourceMappingURL=hash.module.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash.module.spec.js","sourceRoot":"","sources":["../src/hash.module.spec.ts"],"names":[],"mappings":"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"}
|
package/dist/hash.service.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { HashModuleOptions } from "./hash-module-options.interface";
|
|
2
1
|
/**
|
|
3
2
|
* Service that provides password hashing and verification using Argon2 algorithm.
|
|
4
3
|
*
|
|
@@ -6,34 +5,97 @@ import { HashModuleOptions } from "./hash-module-options.interface";
|
|
|
6
5
|
* ```typescript
|
|
7
6
|
* import { HashService } from '@nest-boot/hash';
|
|
8
7
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* constructor(private readonly hashService: HashService) {}
|
|
8
|
+
* // Initialize at application startup
|
|
9
|
+
* HashService.init(process.env.HASH_SECRET);
|
|
12
10
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* async verifyPassword(hash: string, password: string): Promise<boolean> {
|
|
18
|
-
* return this.hashService.verify(hash, password);
|
|
19
|
-
* }
|
|
20
|
-
* }
|
|
11
|
+
* // Use static methods
|
|
12
|
+
* const hashed = await HashService.hash(password);
|
|
13
|
+
* const isValid = await HashService.verify(hashed, password);
|
|
21
14
|
* ```
|
|
22
15
|
*/
|
|
23
16
|
export declare class HashService {
|
|
17
|
+
private static _instance?;
|
|
18
|
+
/**
|
|
19
|
+
* Gets the static HashService instance.
|
|
20
|
+
* @throws Error if HashService has not been initialized via `init()`
|
|
21
|
+
* @returns The HashService instance
|
|
22
|
+
*/
|
|
23
|
+
static get instance(): HashService;
|
|
24
|
+
/**
|
|
25
|
+
* Initializes the static HashService instance with the given secret.
|
|
26
|
+
* Call this method at application startup to configure the default secret.
|
|
27
|
+
*
|
|
28
|
+
* @param secret - The secret key to use for hashing
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```typescript
|
|
32
|
+
* // In your application bootstrap
|
|
33
|
+
* HashService.init(process.env.HASH_SECRET);
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
static init(secret?: string): void;
|
|
37
|
+
/**
|
|
38
|
+
* Creates a hash from the given value using the static instance.
|
|
39
|
+
* @param value - The value to hash (password or other sensitive data)
|
|
40
|
+
* @param secret - Optional secret key to use instead of the default
|
|
41
|
+
* @returns The hashed string
|
|
42
|
+
* @throws Error if HashService has not been initialized via `init()`
|
|
43
|
+
*/
|
|
44
|
+
static hash(value: string | Buffer, secret?: string): Promise<string>;
|
|
45
|
+
/**
|
|
46
|
+
* Creates a hash synchronously from the given value using the static instance.
|
|
47
|
+
* @param value - The value to hash (password or other sensitive data)
|
|
48
|
+
* @param secret - Optional secret key to use instead of the default
|
|
49
|
+
* @returns The hashed string
|
|
50
|
+
* @throws Error if HashService has not been initialized via `init()`
|
|
51
|
+
*/
|
|
52
|
+
static hashSync(value: string | Buffer, secret?: string): string;
|
|
53
|
+
/**
|
|
54
|
+
* Verifies a value against a hash using the static instance.
|
|
55
|
+
* @param hashed - The hash to verify against
|
|
56
|
+
* @param value - The value to verify
|
|
57
|
+
* @param secret - Optional secret key to use instead of the default
|
|
58
|
+
* @returns True if the value matches the hash, false otherwise
|
|
59
|
+
* @throws Error if HashService has not been initialized via `init()`
|
|
60
|
+
*/
|
|
61
|
+
static verify(hashed: string | Buffer, value: string | Buffer, secret?: string): Promise<boolean>;
|
|
62
|
+
/**
|
|
63
|
+
* Verifies a value against a hash synchronously using the static instance.
|
|
64
|
+
* @param hashed - The hash to verify against
|
|
65
|
+
* @param value - The value to verify
|
|
66
|
+
* @param secret - Optional secret key to use instead of the default
|
|
67
|
+
* @returns True if the value matches the hash, false otherwise
|
|
68
|
+
* @throws Error if HashService has not been initialized via `init()`
|
|
69
|
+
*/
|
|
70
|
+
static verifySync(hashed: string | Buffer, value: string | Buffer, secret?: string): boolean;
|
|
24
71
|
private readonly secret?;
|
|
25
72
|
/**
|
|
26
73
|
* Creates an instance of HashService.
|
|
27
|
-
* @param
|
|
74
|
+
* @param secret - Optional secret key to use for hashing
|
|
28
75
|
*/
|
|
29
|
-
constructor(
|
|
76
|
+
constructor(secret?: string);
|
|
30
77
|
/**
|
|
31
78
|
* Creates a hash from the given value using Argon2.
|
|
32
79
|
* @param value - The value to hash (password or other sensitive data)
|
|
33
80
|
* @param secret - Optional secret key to use instead of the default
|
|
34
81
|
* @returns The hashed string
|
|
82
|
+
* @deprecated Use `hash` instead
|
|
35
83
|
*/
|
|
36
84
|
create(value: string | Buffer, secret?: string): Promise<string>;
|
|
85
|
+
/**
|
|
86
|
+
* Creates a hash from the given value using Argon2.
|
|
87
|
+
* @param value - The value to hash (password or other sensitive data)
|
|
88
|
+
* @param secret - Optional secret key to use instead of the default
|
|
89
|
+
* @returns The hashed string
|
|
90
|
+
*/
|
|
91
|
+
hash(value: string | Buffer, secret?: string): Promise<string>;
|
|
92
|
+
/**
|
|
93
|
+
* Creates a hash synchronously from the given value using Argon2.
|
|
94
|
+
* @param value - The value to hash (password or other sensitive data)
|
|
95
|
+
* @param secret - Optional secret key to use instead of the default
|
|
96
|
+
* @returns The hashed string
|
|
97
|
+
*/
|
|
98
|
+
hashSync(value: string | Buffer, secret?: string): string;
|
|
37
99
|
/**
|
|
38
100
|
* Verifies a value against a hash.
|
|
39
101
|
* @param hashed - The hash to verify against
|
|
@@ -42,4 +104,12 @@ export declare class HashService {
|
|
|
42
104
|
* @returns True if the value matches the hash, false otherwise
|
|
43
105
|
*/
|
|
44
106
|
verify(hashed: string | Buffer, value: string | Buffer, secret?: string): Promise<boolean>;
|
|
107
|
+
/**
|
|
108
|
+
* Verifies a value against a hash synchronously.
|
|
109
|
+
* @param hashed - The hash to verify against
|
|
110
|
+
* @param value - The value to verify
|
|
111
|
+
* @param secret - Optional secret key to use instead of the default
|
|
112
|
+
* @returns True if the value matches the hash, false otherwise
|
|
113
|
+
*/
|
|
114
|
+
verifySync(hashed: string | Buffer, value: string | Buffer, secret?: string): boolean;
|
|
45
115
|
}
|
package/dist/hash.service.js
CHANGED
|
@@ -1,21 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
-
};
|
|
8
|
-
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
-
};
|
|
11
|
-
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
-
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
-
};
|
|
14
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
3
|
exports.HashService = void 0;
|
|
16
|
-
const common_1 = require("@nestjs/common");
|
|
17
4
|
const argon2_1 = require("@node-rs/argon2");
|
|
18
|
-
const hash_module_definition_1 = require("./hash.module-definition");
|
|
19
5
|
/**
|
|
20
6
|
* Service that provides password hashing and verification using Argon2 algorithm.
|
|
21
7
|
*
|
|
@@ -23,42 +9,122 @@ const hash_module_definition_1 = require("./hash.module-definition");
|
|
|
23
9
|
* ```typescript
|
|
24
10
|
* import { HashService } from '@nest-boot/hash';
|
|
25
11
|
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* constructor(private readonly hashService: HashService) {}
|
|
12
|
+
* // Initialize at application startup
|
|
13
|
+
* HashService.init(process.env.HASH_SECRET);
|
|
29
14
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* async verifyPassword(hash: string, password: string): Promise<boolean> {
|
|
35
|
-
* return this.hashService.verify(hash, password);
|
|
36
|
-
* }
|
|
37
|
-
* }
|
|
15
|
+
* // Use static methods
|
|
16
|
+
* const hashed = await HashService.hash(password);
|
|
17
|
+
* const isValid = await HashService.verify(hashed, password);
|
|
38
18
|
* ```
|
|
39
19
|
*/
|
|
40
|
-
|
|
20
|
+
class HashService {
|
|
41
21
|
/**
|
|
42
|
-
*
|
|
43
|
-
* @
|
|
22
|
+
* Gets the static HashService instance.
|
|
23
|
+
* @throws Error if HashService has not been initialized via `init()`
|
|
24
|
+
* @returns The HashService instance
|
|
44
25
|
*/
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
this.secret = Buffer.from(secret);
|
|
26
|
+
static get instance() {
|
|
27
|
+
if (!this._instance) {
|
|
28
|
+
throw new Error("HashService not initialized");
|
|
49
29
|
}
|
|
30
|
+
return this._instance;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Initializes the static HashService instance with the given secret.
|
|
34
|
+
* Call this method at application startup to configure the default secret.
|
|
35
|
+
*
|
|
36
|
+
* @param secret - The secret key to use for hashing
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```typescript
|
|
40
|
+
* // In your application bootstrap
|
|
41
|
+
* HashService.init(process.env.HASH_SECRET);
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
static init(secret) {
|
|
45
|
+
this._instance = new HashService(secret);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Creates a hash from the given value using the static instance.
|
|
49
|
+
* @param value - The value to hash (password or other sensitive data)
|
|
50
|
+
* @param secret - Optional secret key to use instead of the default
|
|
51
|
+
* @returns The hashed string
|
|
52
|
+
* @throws Error if HashService has not been initialized via `init()`
|
|
53
|
+
*/
|
|
54
|
+
static hash(value, secret) {
|
|
55
|
+
return this.instance.hash(value, secret);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Creates a hash synchronously from the given value using the static instance.
|
|
59
|
+
* @param value - The value to hash (password or other sensitive data)
|
|
60
|
+
* @param secret - Optional secret key to use instead of the default
|
|
61
|
+
* @returns The hashed string
|
|
62
|
+
* @throws Error if HashService has not been initialized via `init()`
|
|
63
|
+
*/
|
|
64
|
+
static hashSync(value, secret) {
|
|
65
|
+
return this.instance.hashSync(value, secret);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Verifies a value against a hash using the static instance.
|
|
69
|
+
* @param hashed - The hash to verify against
|
|
70
|
+
* @param value - The value to verify
|
|
71
|
+
* @param secret - Optional secret key to use instead of the default
|
|
72
|
+
* @returns True if the value matches the hash, false otherwise
|
|
73
|
+
* @throws Error if HashService has not been initialized via `init()`
|
|
74
|
+
*/
|
|
75
|
+
static verify(hashed, value, secret) {
|
|
76
|
+
return this.instance.verify(hashed, value, secret);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Verifies a value against a hash synchronously using the static instance.
|
|
80
|
+
* @param hashed - The hash to verify against
|
|
81
|
+
* @param value - The value to verify
|
|
82
|
+
* @param secret - Optional secret key to use instead of the default
|
|
83
|
+
* @returns True if the value matches the hash, false otherwise
|
|
84
|
+
* @throws Error if HashService has not been initialized via `init()`
|
|
85
|
+
*/
|
|
86
|
+
static verifySync(hashed, value, secret) {
|
|
87
|
+
return this.instance.verifySync(hashed, value, secret);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Creates an instance of HashService.
|
|
91
|
+
* @param secret - Optional secret key to use for hashing
|
|
92
|
+
*/
|
|
93
|
+
constructor(secret) {
|
|
94
|
+
this.secret = secret ? Buffer.from(secret) : undefined;
|
|
50
95
|
}
|
|
51
96
|
/**
|
|
52
97
|
* Creates a hash from the given value using Argon2.
|
|
53
98
|
* @param value - The value to hash (password or other sensitive data)
|
|
54
99
|
* @param secret - Optional secret key to use instead of the default
|
|
55
100
|
* @returns The hashed string
|
|
101
|
+
* @deprecated Use `hash` instead
|
|
56
102
|
*/
|
|
57
103
|
async create(value, secret) {
|
|
104
|
+
return await this.hash(value, secret);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Creates a hash from the given value using Argon2.
|
|
108
|
+
* @param value - The value to hash (password or other sensitive data)
|
|
109
|
+
* @param secret - Optional secret key to use instead of the default
|
|
110
|
+
* @returns The hashed string
|
|
111
|
+
*/
|
|
112
|
+
async hash(value, secret) {
|
|
58
113
|
return await (0, argon2_1.hash)(value, {
|
|
59
114
|
secret: typeof secret !== "undefined" ? Buffer.from(secret) : this.secret,
|
|
60
115
|
});
|
|
61
116
|
}
|
|
117
|
+
/**
|
|
118
|
+
* Creates a hash synchronously from the given value using Argon2.
|
|
119
|
+
* @param value - The value to hash (password or other sensitive data)
|
|
120
|
+
* @param secret - Optional secret key to use instead of the default
|
|
121
|
+
* @returns The hashed string
|
|
122
|
+
*/
|
|
123
|
+
hashSync(value, secret) {
|
|
124
|
+
return (0, argon2_1.hashSync)(value, {
|
|
125
|
+
secret: typeof secret !== "undefined" ? Buffer.from(secret) : this.secret,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
62
128
|
/**
|
|
63
129
|
* Verifies a value against a hash.
|
|
64
130
|
* @param hashed - The hash to verify against
|
|
@@ -71,12 +137,18 @@ let HashService = class HashService {
|
|
|
71
137
|
secret: typeof secret !== "undefined" ? Buffer.from(secret) : this.secret,
|
|
72
138
|
});
|
|
73
139
|
}
|
|
74
|
-
|
|
140
|
+
/**
|
|
141
|
+
* Verifies a value against a hash synchronously.
|
|
142
|
+
* @param hashed - The hash to verify against
|
|
143
|
+
* @param value - The value to verify
|
|
144
|
+
* @param secret - Optional secret key to use instead of the default
|
|
145
|
+
* @returns True if the value matches the hash, false otherwise
|
|
146
|
+
*/
|
|
147
|
+
verifySync(hashed, value, secret) {
|
|
148
|
+
return (0, argon2_1.verifySync)(hashed, value, {
|
|
149
|
+
secret: typeof secret !== "undefined" ? Buffer.from(secret) : this.secret,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
}
|
|
75
153
|
exports.HashService = HashService;
|
|
76
|
-
exports.HashService = HashService = __decorate([
|
|
77
|
-
(0, common_1.Injectable)(),
|
|
78
|
-
__param(0, (0, common_1.Optional)()),
|
|
79
|
-
__param(0, (0, common_1.Inject)(hash_module_definition_1.MODULE_OPTIONS_TOKEN)),
|
|
80
|
-
__metadata("design:paramtypes", [Object])
|
|
81
|
-
], HashService);
|
|
82
154
|
//# sourceMappingURL=hash.service.js.map
|
package/dist/hash.service.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hash.service.js","sourceRoot":"","sources":["../src/hash.service.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"hash.service.js","sourceRoot":"","sources":["../src/hash.service.ts"],"names":[],"mappings":";;;AAAA,4CAAqE;AAErE;;;;;;;;;;;;;;GAcG;AAEH,MAAa,WAAW;IAGtB;;;;OAIG;IACH,MAAM,KAAK,QAAQ;QACjB,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;QACjD,CAAC;QAED,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,IAAI,CAAC,MAAe;QACzB,IAAI,CAAC,SAAS,GAAG,IAAI,WAAW,CAAC,MAAM,CAAC,CAAC;IAC3C,CAAC;IAED;;;;;;OAMG;IACH,MAAM,CAAC,IAAI,CAAC,KAAsB,EAAE,MAAe;QACjD,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAC3C,CAAC;IAED;;;;;;OAMG;IACH,MAAM,CAAC,QAAQ,CAAC,KAAsB,EAAE,MAAe;QACrD,OAAO,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAC/C,CAAC;IAED;;;;;;;OAOG;IACH,MAAM,CAAC,MAAM,CACX,MAAuB,EACvB,KAAsB,EACtB,MAAe;QAEf,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IACrD,CAAC;IAED;;;;;;;OAOG;IACH,MAAM,CAAC,UAAU,CACf,MAAuB,EACvB,KAAsB,EACtB,MAAe;QAEf,OAAO,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IACzD,CAAC;IAID;;;OAGG;IACH,YAAY,MAAe;QACzB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACzD,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,MAAM,CAAC,KAAsB,EAAE,MAAe;QAClD,OAAO,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACxC,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,IAAI,CAAC,KAAsB,EAAE,MAAe;QAChD,OAAO,MAAM,IAAA,aAAI,EAAC,KAAK,EAAE;YACvB,MAAM,EAAE,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM;SAC1E,CAAC,CAAC;IACL,CAAC;IAED;;;;;OAKG;IACH,QAAQ,CAAC,KAAsB,EAAE,MAAe;QAC9C,OAAO,IAAA,iBAAQ,EAAC,KAAK,EAAE;YACrB,MAAM,EAAE,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM;SAC1E,CAAC,CAAC;IACL,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,MAAM,CACV,MAAuB,EACvB,KAAsB,EACtB,MAAe;QAEf,OAAO,MAAM,IAAA,eAAM,EAAC,MAAM,EAAE,KAAK,EAAE;YACjC,MAAM,EAAE,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM;SAC1E,CAAC,CAAC;IACL,CAAC;IAED;;;;;;OAMG;IACH,UAAU,CACR,MAAuB,EACvB,KAAsB,EACtB,MAAe;QAEf,OAAO,IAAA,mBAAU,EAAC,MAAM,EAAE,KAAK,EAAE;YAC/B,MAAM,EAAE,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM;SAC1E,CAAC,CAAC;IACL,CAAC;CACF;AApKD,kCAoKC"}
|