nestjs-cryptography 2.2.3 → 3.0.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/README.md +6 -1
- package/dist/cryptography.service.d.ts +21 -23
- package/dist/cryptography.service.js +82 -82
- package/dist/interfaces/cryptography-options.interface.d.ts +1 -1
- package/dist/interfaces/generic-options.interface.d.ts +5 -0
- package/dist/interfaces/generic-options.interface.js +2 -0
- package/dist/interfaces/index.d.ts +1 -0
- package/dist/interfaces/index.js +1 -0
- package/package.json +16 -15
- package/wiki/README.md +41 -0
- package/wiki/babel.config.js +3 -0
- package/wiki/docs/Internals/_category_.json +7 -0
- package/wiki/docs/Internals/create-safe-random-data.mdx +41 -0
- package/wiki/docs/Internals/create-secure-hmac.mdx +31 -0
- package/wiki/docs/Internals/symmetric-data-encrypt.mdx +103 -0
- package/wiki/docs/Internals/symmetric-secure-data-encrypt.mdx +161 -0
- package/wiki/docs/api-reference/_category_.json +7 -0
- package/wiki/docs/api-reference/settings.mdx +199 -0
- package/wiki/docs/guides/_category_.json +7 -0
- package/wiki/docs/guides/generics.mdx +170 -0
- package/wiki/docs/guides/hashing.mdx +258 -0
- package/wiki/docs/guides/hmac.mdx +271 -0
- package/wiki/docs/guides/key-derivation.mdx +101 -0
- package/wiki/docs/guides/password-hashing.mdx +136 -0
- package/wiki/docs/guides/symmetric-encryption.mdx +272 -0
- package/wiki/docs/intro.mdx +148 -0
- package/wiki/docusaurus.config.ts +138 -0
- package/wiki/package.json +48 -0
- package/wiki/sidebars.ts +20 -0
- package/wiki/src/common/timing-attack.mdx +3 -0
- package/wiki/src/common/tips.mdx +18 -0
- package/wiki/src/components/GenerateHexButton/index.tsx +35 -0
- package/wiki/src/components/GenerateHexButton/styles.module.css +10 -0
- package/wiki/src/components/GenericLabel/index.tsx +19 -0
- package/wiki/src/components/HomepageFeatures/index.tsx +70 -0
- package/wiki/src/components/HomepageFeatures/styles.module.css +11 -0
- package/wiki/src/components/RecommendedLabel/index.tsx +19 -0
- package/wiki/src/components/RequiredLabel/index.tsx +12 -0
- package/wiki/src/css/custom.css +30 -0
- package/wiki/src/pages/index.module.css +23 -0
- package/wiki/src/pages/index.tsx +43 -0
- package/wiki/src/pages/markdown-page.md +7 -0
- package/wiki/static/.nojekyll +0 -0
- package/wiki/static/img/gear_api.png +0 -0
- package/wiki/static/img/logo.svg +1 -0
- package/wiki/static/img/nestjs_favicon.ico +0 -0
- package/wiki/static/img/node_crypto.png +0 -0
- package/wiki/static/img/phc_logo.png +0 -0
- package/wiki/static/img/profile.png +0 -0
- package/wiki/versioned_docs/version-2.x/Internals/_category_.json +8 -0
- package/wiki/versioned_docs/version-2.x/Internals/create-secure-hmac.mdx +30 -0
- package/wiki/versioned_docs/version-2.x/Internals/symmetric-secure-data-encrypt.mdx +160 -0
- package/wiki/versioned_docs/version-2.x/api-reference/_category_.json +8 -0
- package/wiki/versioned_docs/version-2.x/api-reference/settings.mdx +197 -0
- package/wiki/versioned_docs/version-2.x/guides/_category_.json +7 -0
- package/wiki/versioned_docs/version-2.x/guides/generics.mdx +133 -0
- package/wiki/versioned_docs/version-2.x/guides/hashing.mdx +229 -0
- package/wiki/versioned_docs/version-2.x/guides/hmac.mdx +198 -0
- package/wiki/versioned_docs/version-2.x/guides/key-derivation.mdx +98 -0
- package/wiki/versioned_docs/version-2.x/guides/password-hashing.mdx +132 -0
- package/wiki/versioned_docs/version-2.x/guides/symmetric-encryption.mdx +107 -0
- package/wiki/versioned_docs/version-2.x/intro.mdx +148 -0
- package/wiki/versioned_sidebars/version-2.x-sidebars.json +8 -0
- package/wiki/versions.json +3 -0
package/README.md
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
[](https://codecov.io/github/mjorgegulab/nestjs-cryptography)
|
|
2
2
|
[](https://app.codacy.com/gh/mjorgegulab/nestjs-cryptography/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
|
|
3
3
|
[](https://github.com/mjorgegulab/nestjs-cryptography/actions/workflows/github-code-scanning/codeql)
|
|
4
|
+
[](https://nestjs-cryptography.thewolfx41.dev)
|
|
4
5
|
|
|
5
6
|
# NestJS - Cryptography
|
|
6
|
-
|
|
7
|
+
|
|
8
|
+
<p align="center">
|
|
9
|
+
<a href="http://nestjs.com/" target="blank"><img src="https://nestjs.com/img/logo-small.svg" width="120" alt="Nest Logo" /></a>
|
|
10
|
+
</p>
|
|
11
|
+
|
|
7
12
|
|
|
8
13
|
## Quick Start
|
|
9
14
|
|
|
@@ -1,36 +1,34 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
|
-
/// <reference types="node" />
|
|
3
1
|
import * as crypto from 'node:crypto';
|
|
4
|
-
import { CryptographyOptionsInterface } from './interfaces';
|
|
2
|
+
import { CryptographyOptionsInterface, GenericOptionsInterface } from './interfaces';
|
|
5
3
|
export declare class CryptographyService {
|
|
6
4
|
private options;
|
|
7
5
|
constructor(options: CryptographyOptionsInterface);
|
|
8
|
-
private
|
|
6
|
+
private convertInputData;
|
|
9
7
|
private extractIV;
|
|
10
8
|
private extractAuthTagFromCypheredData;
|
|
11
9
|
private extractCipheredData;
|
|
12
10
|
private extractSalt;
|
|
11
|
+
private extractSaltFromHmac;
|
|
13
12
|
private extractCipheredDEK;
|
|
14
13
|
private extractCipheredDataWithDEK;
|
|
15
|
-
private
|
|
16
|
-
|
|
14
|
+
private createHmacSecureKey;
|
|
15
|
+
createSafeRandomData(length: number): Buffer;
|
|
17
16
|
genUUID(secure?: boolean): string;
|
|
18
|
-
genRandomPassword(length: number
|
|
17
|
+
genRandomPassword(length: number): string;
|
|
19
18
|
generateSymmetricKey(length?: number): crypto.KeyObject;
|
|
20
|
-
deriveMasterKey(masterKey: string | Buffer, salt: Buffer, length
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
createCustomHash(algorithm: string, data: string,
|
|
24
|
-
verifyCustomHash(algorithm: string, data: string, oldHash: string | Buffer,
|
|
25
|
-
createSecureHash(data: string): Buffer;
|
|
26
|
-
verifySecureHash(data: string, oldHash: string | Buffer): boolean;
|
|
27
|
-
createCustomHmac(algorithm: string, key: Buffer, data: string): Buffer;
|
|
28
|
-
verifyCustomHmac(algorithm: string, key: Buffer, data: string, oldHmac: string | Buffer): boolean;
|
|
29
|
-
createSecureHmac(data: string): Buffer;
|
|
30
|
-
verifySecureHmac(data: string, oldHmac:
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
symmetricSecureDataDecrypt(data: string | Buffer): Promise<Buffer>;
|
|
19
|
+
deriveMasterKey(masterKey: string | Buffer, salt: Buffer, length?: number): Promise<Buffer>;
|
|
20
|
+
createArgon2HashFromPassword(data: string | Buffer): Promise<Buffer>;
|
|
21
|
+
verifyArgon2HashFromPassword(hash: string, data: string | Buffer): Promise<boolean>;
|
|
22
|
+
createCustomHash(algorithm: string, data: string | Buffer, options?: GenericOptionsInterface): Buffer;
|
|
23
|
+
verifyCustomHash(algorithm: string, data: string | Buffer, oldHash: string | Buffer, options?: GenericOptionsInterface): boolean;
|
|
24
|
+
createSecureHash(data: string | Buffer, options?: GenericOptionsInterface): Buffer;
|
|
25
|
+
verifySecureHash(data: string | Buffer, oldHash: string | Buffer, options?: GenericOptionsInterface): boolean;
|
|
26
|
+
createCustomHmac(algorithm: string, key: string | Buffer, data: string | Buffer, options?: GenericOptionsInterface): Buffer;
|
|
27
|
+
verifyCustomHmac(algorithm: string, key: string | Buffer, data: string | Buffer, oldHmac: string | Buffer, options?: GenericOptionsInterface): boolean;
|
|
28
|
+
createSecureHmac(data: string | Buffer, options?: GenericOptionsInterface): Buffer;
|
|
29
|
+
verifySecureHmac(data: string | Buffer, oldHmac: string | Buffer, options?: GenericOptionsInterface): boolean;
|
|
30
|
+
symmetricDataEncrypt(data: string | Buffer, key: string | Buffer, options?: GenericOptionsInterface): Promise<Buffer>;
|
|
31
|
+
symmetricDataDecrypt(data: string | Buffer, key: string | Buffer, options?: GenericOptionsInterface): Promise<Buffer>;
|
|
32
|
+
symmetricSecureDataEncrypt(data: string | Buffer, options?: GenericOptionsInterface): Promise<Buffer>;
|
|
33
|
+
symmetricSecureDataDecrypt(data: string | Buffer, options?: GenericOptionsInterface): Promise<Buffer>;
|
|
36
34
|
}
|
|
@@ -44,8 +44,16 @@ let CryptographyService = class CryptographyService {
|
|
|
44
44
|
constructor(options) {
|
|
45
45
|
this.options = options;
|
|
46
46
|
}
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
convertInputData(data, inputEncoding) {
|
|
48
|
+
if (Buffer.isBuffer(data)) {
|
|
49
|
+
return data;
|
|
50
|
+
}
|
|
51
|
+
else if (typeof data === 'string') {
|
|
52
|
+
return Buffer.from(data, inputEncoding ?? 'utf8');
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
throw new Error('Unsupported input type');
|
|
56
|
+
}
|
|
49
57
|
}
|
|
50
58
|
extractIV(data) {
|
|
51
59
|
return data.subarray(0, 12);
|
|
@@ -59,32 +67,35 @@ let CryptographyService = class CryptographyService {
|
|
|
59
67
|
extractSalt(data) {
|
|
60
68
|
return data.subarray(12, 76);
|
|
61
69
|
}
|
|
70
|
+
extractSaltFromHmac(data) {
|
|
71
|
+
return data.subarray(0, 16);
|
|
72
|
+
}
|
|
62
73
|
extractCipheredDEK(data) {
|
|
63
74
|
return data.subarray(0, 124);
|
|
64
75
|
}
|
|
65
76
|
extractCipheredDataWithDEK(data) {
|
|
66
77
|
return data.subarray(124, data.length);
|
|
67
78
|
}
|
|
68
|
-
|
|
69
|
-
return Buffer.from(crypto.hkdfSync('sha3-256', crypto.createSecretKey(
|
|
79
|
+
createHmacSecureKey(key, salt) {
|
|
80
|
+
return Buffer.from(crypto.hkdfSync('sha3-256', crypto.createSecretKey(key), salt, Buffer.alloc(0), 64));
|
|
70
81
|
}
|
|
71
|
-
|
|
72
|
-
return crypto.createSecretKey(
|
|
82
|
+
createSafeRandomData(length) {
|
|
83
|
+
return Buffer.from(crypto.hkdfSync('sha3-256', crypto.createSecretKey(crypto.randomBytes(64)), crypto.randomBytes(64), Buffer.alloc(0), length));
|
|
73
84
|
}
|
|
74
85
|
genUUID(secure = false) {
|
|
75
86
|
return crypto.randomUUID({
|
|
76
87
|
disableEntropyCache: secure,
|
|
77
88
|
});
|
|
78
89
|
}
|
|
79
|
-
genRandomPassword(length
|
|
80
|
-
return crypto.randomBytes(length).toString(
|
|
90
|
+
genRandomPassword(length) {
|
|
91
|
+
return crypto.randomBytes(length).toString('base64').slice(0, length);
|
|
81
92
|
}
|
|
82
93
|
generateSymmetricKey(length = 256) {
|
|
83
94
|
return crypto.generateKeySync('hmac', { length });
|
|
84
95
|
}
|
|
85
96
|
async deriveMasterKey(masterKey, salt, length) {
|
|
86
97
|
return await argon2.hash(masterKey, {
|
|
87
|
-
hashLength: length
|
|
98
|
+
hashLength: length ?? this.options.kdf.outputKeyLength,
|
|
88
99
|
salt: salt,
|
|
89
100
|
type: this.options.kdf.argon2Type,
|
|
90
101
|
memoryCost: this.options.kdf.memoryCost,
|
|
@@ -92,7 +103,7 @@ let CryptographyService = class CryptographyService {
|
|
|
92
103
|
raw: true,
|
|
93
104
|
});
|
|
94
105
|
}
|
|
95
|
-
async
|
|
106
|
+
async createArgon2HashFromPassword(data) {
|
|
96
107
|
const tmpData = await argon2.hash(data, {
|
|
97
108
|
hashLength: this.options.hashing.password.outputKeyLength,
|
|
98
109
|
type: this.options.hashing.password.argon2Type,
|
|
@@ -102,113 +113,102 @@ let CryptographyService = class CryptographyService {
|
|
|
102
113
|
});
|
|
103
114
|
return Buffer.isBuffer(tmpData) ? tmpData : Buffer.from(tmpData);
|
|
104
115
|
}
|
|
105
|
-
async
|
|
116
|
+
async verifyArgon2HashFromPassword(hash, data) {
|
|
106
117
|
return await argon2.verify(hash, data);
|
|
107
118
|
}
|
|
108
|
-
createCustomHash(algorithm, data,
|
|
119
|
+
createCustomHash(algorithm, data, options) {
|
|
120
|
+
const inputData = this.convertInputData(data, options?.inputDataEncoding);
|
|
109
121
|
const hash = crypto.createHash(algorithm, {
|
|
110
|
-
...(outputLength && { outputLength }),
|
|
122
|
+
...(options?.outputLength && { outputLength: options?.outputLength }),
|
|
111
123
|
});
|
|
112
|
-
hash.update(
|
|
124
|
+
hash.update(inputData);
|
|
113
125
|
return hash.digest();
|
|
114
126
|
}
|
|
115
|
-
verifyCustomHash(algorithm, data, oldHash,
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}
|
|
120
|
-
else {
|
|
121
|
-
return crypto.timingSafeEqual(Buffer.from(oldHash, 'hex'), hash);
|
|
122
|
-
}
|
|
127
|
+
verifyCustomHash(algorithm, data, oldHash, options) {
|
|
128
|
+
const inputOldHashData = this.convertInputData(oldHash, options?.inputDataEncoding);
|
|
129
|
+
const hash = this.createCustomHash(algorithm, data, options);
|
|
130
|
+
return crypto.timingSafeEqual(hash, inputOldHashData);
|
|
123
131
|
}
|
|
124
|
-
createSecureHash(data) {
|
|
125
|
-
return this.createCustomHash('shake256', data,
|
|
132
|
+
createSecureHash(data, options) {
|
|
133
|
+
return this.createCustomHash('shake256', data, {
|
|
134
|
+
...options,
|
|
135
|
+
outputLength: 48,
|
|
136
|
+
});
|
|
126
137
|
}
|
|
127
|
-
verifySecureHash(data, oldHash) {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
return crypto.timingSafeEqual(hash, buffOldHash);
|
|
138
|
+
verifySecureHash(data, oldHash, options) {
|
|
139
|
+
return this.verifyCustomHash('shake256', data, oldHash, {
|
|
140
|
+
...options,
|
|
141
|
+
outputLength: 48,
|
|
142
|
+
});
|
|
133
143
|
}
|
|
134
|
-
createCustomHmac(algorithm, key, data) {
|
|
135
|
-
const
|
|
136
|
-
|
|
144
|
+
createCustomHmac(algorithm, key, data, options) {
|
|
145
|
+
const inputKey = this.convertInputData(key, options?.inputKeyEncoding);
|
|
146
|
+
const inputData = this.convertInputData(data, options?.inputDataEncoding);
|
|
147
|
+
const hmac = crypto.createHmac(algorithm, crypto.createSecretKey(inputKey));
|
|
148
|
+
hmac.update(inputData);
|
|
137
149
|
key = null;
|
|
138
150
|
return hmac.digest();
|
|
139
151
|
}
|
|
140
|
-
verifyCustomHmac(algorithm, key, data, oldHmac) {
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}
|
|
145
|
-
else {
|
|
146
|
-
return crypto.timingSafeEqual(Buffer.from(oldHmac, 'hex'), hmac);
|
|
147
|
-
}
|
|
152
|
+
verifyCustomHmac(algorithm, key, data, oldHmac, options) {
|
|
153
|
+
const inputOldHmacData = this.convertInputData(oldHmac, options?.inputDataEncoding);
|
|
154
|
+
const hmac = this.createCustomHmac(algorithm, key, data, options);
|
|
155
|
+
return crypto.timingSafeEqual(hmac, inputOldHmacData);
|
|
148
156
|
}
|
|
149
|
-
createSecureHmac(data) {
|
|
157
|
+
createSecureHmac(data, options) {
|
|
150
158
|
const key = Buffer.from(this.options.hashing.hmac.masterKey, 'hex');
|
|
151
159
|
const salt = crypto.randomBytes(16);
|
|
152
|
-
const secureKey =
|
|
153
|
-
const hmac = this.createCustomHmac('sha3-256', secureKey, data);
|
|
154
|
-
return Buffer.concat([
|
|
160
|
+
const secureKey = this.createHmacSecureKey(key, salt);
|
|
161
|
+
const hmac = this.createCustomHmac('sha3-256', secureKey, data, options);
|
|
162
|
+
return Buffer.concat([salt, hmac], salt.length + hmac.length);
|
|
155
163
|
}
|
|
156
|
-
verifySecureHmac(data, oldHmac) {
|
|
164
|
+
verifySecureHmac(data, oldHmac, options) {
|
|
157
165
|
const key = Buffer.from(this.options.hashing.hmac.masterKey, 'hex');
|
|
158
|
-
const buffOldHmac =
|
|
159
|
-
|
|
160
|
-
: Buffer.from(oldHmac, 'hex');
|
|
161
|
-
const saltOldHmac = buffOldHmac.subarray(0, 16);
|
|
166
|
+
const buffOldHmac = this.convertInputData(oldHmac, options?.inputDataEncoding);
|
|
167
|
+
const saltOldHmac = this.extractSaltFromHmac(buffOldHmac);
|
|
162
168
|
const hashOldHmac = buffOldHmac.subarray(16, buffOldHmac.length);
|
|
163
|
-
const secureKey =
|
|
164
|
-
const hmac = this.createCustomHmac('sha3-256', secureKey, data);
|
|
169
|
+
const secureKey = this.createHmacSecureKey(key, saltOldHmac);
|
|
170
|
+
const hmac = this.createCustomHmac('sha3-256', secureKey, data, options);
|
|
165
171
|
return crypto.timingSafeEqual(hmac, hashOldHmac);
|
|
166
172
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
const
|
|
172
|
-
const
|
|
173
|
-
const secureEncryptionKey = await this.deriveMasterKey(key, salt, 32);
|
|
173
|
+
async symmetricDataEncrypt(data, key, options) {
|
|
174
|
+
const inputData = this.convertInputData(data, options?.inputDataEncoding);
|
|
175
|
+
const inputKey = this.convertInputData(key, options?.inputKeyEncoding);
|
|
176
|
+
const iv = this.createSafeRandomData(12);
|
|
177
|
+
const salt = this.createSafeRandomData(64);
|
|
178
|
+
const secureEncryptionKey = await this.deriveMasterKey(inputKey, salt, 32);
|
|
174
179
|
const cipher = crypto.createCipheriv('aes-256-gcm', crypto.createSecretKey(secureEncryptionKey), iv, {
|
|
175
180
|
authTagLength: 16,
|
|
176
181
|
});
|
|
177
|
-
let cipheredData = cipher.update(
|
|
178
|
-
cipheredData = Buffer.concat([
|
|
179
|
-
Buffer.from(cipheredData),
|
|
180
|
-
Buffer.from(cipher.final()),
|
|
181
|
-
]);
|
|
182
|
+
let cipheredData = cipher.update(inputData);
|
|
183
|
+
cipheredData = Buffer.concat([cipheredData, cipher.final()]);
|
|
182
184
|
return Buffer.concat([iv, salt, cipher.getAuthTag(), cipheredData]);
|
|
183
185
|
}
|
|
184
|
-
async symmetricDataDecrypt(data, key) {
|
|
185
|
-
|
|
186
|
-
const
|
|
187
|
-
const
|
|
188
|
-
const
|
|
189
|
-
const
|
|
190
|
-
const
|
|
186
|
+
async symmetricDataDecrypt(data, key, options) {
|
|
187
|
+
const inputData = this.convertInputData(data, options?.inputDataEncoding);
|
|
188
|
+
const inputKey = this.convertInputData(key, options?.inputKeyEncoding);
|
|
189
|
+
const iv = this.extractIV(inputData);
|
|
190
|
+
const salt = this.extractSalt(inputData);
|
|
191
|
+
const authTag = this.extractAuthTagFromCypheredData(inputData);
|
|
192
|
+
const cipheredData = this.extractCipheredData(inputData);
|
|
193
|
+
const decryptionKey = await this.deriveMasterKey(inputKey, salt, 32);
|
|
191
194
|
const decipher = crypto.createDecipheriv('aes-256-gcm', crypto.createSecretKey(decryptionKey), iv, {
|
|
192
195
|
authTagLength: 16,
|
|
193
196
|
});
|
|
194
197
|
decipher.setAuthTag(authTag);
|
|
195
198
|
let decipheredData = decipher.update(cipheredData);
|
|
196
|
-
decipheredData = Buffer.concat([
|
|
197
|
-
Buffer.from(decipheredData),
|
|
198
|
-
Buffer.from(decipher.final()),
|
|
199
|
-
]);
|
|
199
|
+
decipheredData = Buffer.concat([decipheredData, decipher.final()]);
|
|
200
200
|
return decipheredData;
|
|
201
201
|
}
|
|
202
|
-
async symmetricSecureDataEncrypt(data) {
|
|
203
|
-
const dek = this.
|
|
204
|
-
const cipheredData = await this.symmetricDataEncrypt(data, dek);
|
|
202
|
+
async symmetricSecureDataEncrypt(data, options) {
|
|
203
|
+
const dek = this.createSafeRandomData(32);
|
|
204
|
+
const cipheredData = await this.symmetricDataEncrypt(data, dek, options);
|
|
205
205
|
const cipheredDek = await this.symmetricDataEncrypt(dek, this.options.encryption.symmetric.masterKey);
|
|
206
206
|
return Buffer.concat([cipheredDek, cipheredData]);
|
|
207
207
|
}
|
|
208
|
-
async symmetricSecureDataDecrypt(data) {
|
|
209
|
-
|
|
210
|
-
const cipheredDek = this.extractCipheredDEK(
|
|
211
|
-
const cipheredData = this.extractCipheredDataWithDEK(
|
|
208
|
+
async symmetricSecureDataDecrypt(data, options) {
|
|
209
|
+
const inputData = this.convertInputData(data, options?.inputDataEncoding);
|
|
210
|
+
const cipheredDek = this.extractCipheredDEK(inputData);
|
|
211
|
+
const cipheredData = this.extractCipheredDataWithDEK(inputData);
|
|
212
212
|
const decipheredDek = await this.symmetricDataDecrypt(cipheredDek, this.options.encryption.symmetric.masterKey);
|
|
213
213
|
return await this.symmetricDataDecrypt(cipheredData, decipheredDek);
|
|
214
214
|
}
|
package/dist/interfaces/index.js
CHANGED
|
@@ -15,3 +15,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./cryptography-options.interface"), exports);
|
|
18
|
+
__exportStar(require("./generic-options.interface"), exports);
|
package/package.json
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nestjs-cryptography",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"author": {
|
|
5
5
|
"name": "Marc Jorge Gonzalez",
|
|
6
6
|
"url": "https://github.com/mjorgegulab"
|
|
7
7
|
},
|
|
8
8
|
"license": "MIT",
|
|
9
9
|
"description": "Secure NestJS cryptography module 🔐",
|
|
10
|
-
"publishConfig": {
|
|
11
|
-
"registry": "https://npm.pkg.github.com/"
|
|
12
|
-
},
|
|
13
10
|
"homepage": "https://nestjs-cryptography.thewolfx41.dev",
|
|
14
11
|
"repository": {
|
|
15
12
|
"type": "git",
|
|
@@ -24,17 +21,18 @@
|
|
|
24
21
|
"lint": "eslint --fix",
|
|
25
22
|
"publish:npm": "npm publish --access=public",
|
|
26
23
|
"prepublish": "yarn run build",
|
|
27
|
-
"prepack": "yarn run build"
|
|
24
|
+
"prepack": "yarn run build",
|
|
25
|
+
"test": "jest",
|
|
26
|
+
"test:cov": "jest --coverage",
|
|
27
|
+
"all": "yarn format && yarn lint && yarn test && yarn prepack"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"argon2": "^0.41.1"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
|
+
"@nestjs/cli": "^10.4.5",
|
|
33
34
|
"@nestjs/common": "^10.4.1",
|
|
34
35
|
"@nestjs/core": "^10.4.1",
|
|
35
|
-
"@nestjs/cli": "^10.4.5",
|
|
36
|
-
"reflect-metadata": "^0.2.2",
|
|
37
|
-
"rxjs": "^7.8.1",
|
|
38
36
|
"@nestjs/platform-express": "^10.4.1",
|
|
39
37
|
"@nestjs/schematics": "^10.1.4",
|
|
40
38
|
"@nestjs/testing": "^10.4.1",
|
|
@@ -46,17 +44,19 @@
|
|
|
46
44
|
"@typescript-eslint/parser": "^7.12.0",
|
|
47
45
|
"eslint": "^8.57.0",
|
|
48
46
|
"eslint-config-prettier": "^9.1.0",
|
|
49
|
-
"eslint-plugin-prettier": "^5.1
|
|
47
|
+
"eslint-plugin-prettier": "^5.2.1",
|
|
50
48
|
"jest": "29.7.0",
|
|
51
49
|
"prettier": "^3.3.3",
|
|
50
|
+
"reflect-metadata": "^0.2.2",
|
|
51
|
+
"rimraf": "^6.0.1",
|
|
52
|
+
"rxjs": "^7.8.1",
|
|
52
53
|
"source-map-support": "^0.5.21",
|
|
53
54
|
"supertest": "^7.0.0",
|
|
54
55
|
"ts-jest": "29.2.5",
|
|
55
56
|
"ts-loader": "^9.5.1",
|
|
56
57
|
"ts-node": "^10.9.2",
|
|
57
58
|
"tsconfig-paths": "4.2.0",
|
|
58
|
-
"typescript": "^5.
|
|
59
|
-
"rimraf": "^5.0.7"
|
|
59
|
+
"typescript": "^5.6.2"
|
|
60
60
|
},
|
|
61
61
|
"peerDependencies": {
|
|
62
62
|
"@nestjs/common": "^9.0.0 || ^10.0.0",
|
|
@@ -68,15 +68,16 @@
|
|
|
68
68
|
"json",
|
|
69
69
|
"ts"
|
|
70
70
|
],
|
|
71
|
-
"rootDir": "
|
|
72
|
-
"
|
|
71
|
+
"rootDir": "./",
|
|
72
|
+
"testMatch": [
|
|
73
|
+
"**/test/**/?(*.)+(spec|test).[tj]s?(x)"
|
|
74
|
+
],
|
|
73
75
|
"transform": {
|
|
74
76
|
"^.+\\.(t|j)s$": "ts-jest"
|
|
75
77
|
},
|
|
76
78
|
"collectCoverageFrom": [
|
|
77
|
-
"**/*.
|
|
79
|
+
"**/*.service.ts"
|
|
78
80
|
],
|
|
79
|
-
"coverageDirectory": "../coverage",
|
|
80
81
|
"testEnvironment": "node"
|
|
81
82
|
}
|
|
82
83
|
}
|
package/wiki/README.md
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Website
|
|
2
|
+
|
|
3
|
+
This website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator.
|
|
4
|
+
|
|
5
|
+
### Installation
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
$ yarn
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
### Local Development
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
$ yarn start
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.
|
|
18
|
+
|
|
19
|
+
### Build
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
$ yarn build
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
This command generates static content into the `build` directory and can be served using any static contents hosting service.
|
|
26
|
+
|
|
27
|
+
### Deployment
|
|
28
|
+
|
|
29
|
+
Using SSH:
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
$ USE_SSH=true yarn deploy
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Not using SSH:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
$ GIT_USER=<Your GitHub username> yarn deploy
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Create Safe Random Data
|
|
3
|
+
sidebar_label: Create Safe Random Data
|
|
4
|
+
sidebar_position: 2
|
|
5
|
+
description: Internals of createSafeRandomData
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
In the following section, you will see a diagram of the cryptographic operations performed when calling the method [`createSafeRandomData`][1]
|
|
9
|
+
|
|
10
|
+
This method generate a cryptographically secure random bytes of the desired lengths using **HKDF**
|
|
11
|
+
with `sha3-256` digest algorithm using the following params:
|
|
12
|
+
- Generate a random key using the secure random bytes' generator.
|
|
13
|
+
- Generate a salt using the secure random bytes' generator.
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
<div style={{ textAlign: 'center' }}>
|
|
17
|
+
```mermaid
|
|
18
|
+
graph TD
|
|
19
|
+
A[Key Length: length]
|
|
20
|
+
|
|
21
|
+
A --> CRB[Create Random Bytes: 64 bytes]
|
|
22
|
+
CRB --> CSK[Create Secret Key]
|
|
23
|
+
CSK ==> SK(SECRET_KEY)
|
|
24
|
+
|
|
25
|
+
A --> CRB2[Create Random Bytes: 64 bytes]
|
|
26
|
+
CRB2 ==> RB[RANDOM_BYTES]
|
|
27
|
+
|
|
28
|
+
SK -.-> HKDF["HKDF ( sha3-256 + SECRET_KEY + RANDOM_BYTES + length )"]
|
|
29
|
+
RB -.-> HKDF --> F([Return Secure Random Bytes])
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
style CRB fill:#f9f,stroke:#333,stroke-width:2px
|
|
33
|
+
style CRB2 fill:#f9f,stroke:#333,stroke-width:2px
|
|
34
|
+
style SK fill:#bbf,stroke:#333,stroke-width:2px
|
|
35
|
+
style RB fill:#bbf,stroke:#333,stroke-width:2px
|
|
36
|
+
style HKDF fill:#bfb,stroke:#333,stroke-width:2px
|
|
37
|
+
style F fill:#00f0f0,stroke:#F0000,stroke-width:2px
|
|
38
|
+
```
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
[1]: ../guides/generics#generate-secure-random-data
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Create Secure HMAC
|
|
3
|
+
sidebar_label: Create Secure HMAC
|
|
4
|
+
sidebar_position: 1
|
|
5
|
+
description: Internals of createSecureHmac
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
In the following section, you will see a diagram of the cryptographic operations performed when calling the method [`createSecureHmac`][1]
|
|
9
|
+
|
|
10
|
+
This method performs several cryptographic operations, including generating a salt,
|
|
11
|
+
deriving a secure key using HKDF with the sha3-256 hashing algorithm, creating an HMAC,
|
|
12
|
+
and returning the concatenated salt and HMAC result. The diagram will illustrate these steps clearly.
|
|
13
|
+
|
|
14
|
+
<div style={{ textAlign: 'center' }}>
|
|
15
|
+
```mermaid
|
|
16
|
+
graph TD
|
|
17
|
+
A[Input Data: data] --> B[Generate Master Key from Options]
|
|
18
|
+
B --> C[Generate Random Salt: 16 bytes]
|
|
19
|
+
C --> D[Use HKDF with sha3-256, Master Key, and Salt]
|
|
20
|
+
D --> E[Generate Secure Key: 64 bytes]
|
|
21
|
+
E --> F[Create HMAC with sha3-256, Secure Key, and Data]
|
|
22
|
+
F --> G[Concatenate Salt and HMAC]
|
|
23
|
+
G --> H[Return Combined Buffer: Salt + HMAC]
|
|
24
|
+
|
|
25
|
+
style B fill:#f9f,stroke:#333,stroke-width:2px
|
|
26
|
+
style D fill:#bbf,stroke:#333,stroke-width:2px
|
|
27
|
+
style F fill:#bfb,stroke:#333,stroke-width:2px
|
|
28
|
+
```
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
[1]: ../guides/hmac#create-a-secure-hmac
|