@1auth/crypto 0.0.0-alpha.57 → 0.0.0-alpha.58
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/index.js +227 -111
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { promisify } from 'node:util'
|
|
2
2
|
import {
|
|
3
3
|
randomBytes,
|
|
4
|
-
createHash
|
|
4
|
+
createHash,
|
|
5
5
|
createCipheriv,
|
|
6
6
|
createDecipheriv,
|
|
7
7
|
createHmac,
|
|
@@ -18,39 +18,63 @@ const sign = promisify(signCallback)
|
|
|
18
18
|
const verify = promisify(verifyCallback)
|
|
19
19
|
|
|
20
20
|
const defaults = {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
symmetricSignatureSecret: undefined,
|
|
21
|
+
symmetricEncryptionKey: undefined, // symmetricRandomEncryptionKey()
|
|
22
|
+
symmetricEncryptionAlgorithm: 'chacha20-poly1305', // 2024-05: AES-256 GCM (aes-256-gcm) or ChaCha20-Poly1305 (chacha20-poly1305)
|
|
23
|
+
symmetricEncryptionEncoding: undefined, // https://nodejs.org/api/buffer.html#buffers-and-character-encodings
|
|
24
|
+
symmetricSignatureHashAlgorithm: undefined, // fallback to defaultHashAlgorithm
|
|
25
|
+
symmetricSignatureSecret: undefined, // symmetricRandomSignatureSecret()
|
|
26
|
+
symmetricSignatureEncoding: undefined, // fallback to defaultEncoding
|
|
28
27
|
asymmetricKeyNamedCurve: 'P-384', // P-512
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
28
|
+
asymmetricSignatureHashAlgorithm: undefined, // fallback to defaultHashAlgorithm
|
|
29
|
+
asymmetricSignatureEncoding: undefined, // fallback to defaultEncoding
|
|
30
|
+
digestChecksumAlgorithm: undefined, // fallback to defaultHashAlgorithm
|
|
31
|
+
digestChecksumEncoding: undefined,
|
|
32
|
+
digestChecksumSalt: undefined, // randomChecksumSalt()
|
|
33
|
+
digestChecksumPepper: undefined, // randomChecksumPepper()
|
|
34
|
+
defaultEncoding: 'base64',
|
|
35
|
+
defaultHashAlgorithm: 'sha3-384'
|
|
33
36
|
}
|
|
34
37
|
const symmetricEncryptionEncodingLengths = {}
|
|
35
38
|
const options = {}
|
|
36
39
|
export default (opt = {}) => {
|
|
37
40
|
Object.assign(options, defaults, opt)
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
).length
|
|
41
|
-
symmetricEncryptionEncodingLengths.ivAndAuthTag =
|
|
42
|
-
symmetricEncryptionEncodingLengths.iv +
|
|
43
|
-
randomBytes(16).toString(options.symmetricEncryptionEncoding).length
|
|
41
|
+
|
|
42
|
+
// Check options, set defaults
|
|
44
43
|
if (!options.symmetricEncryptionKey) {
|
|
45
44
|
console.warn(
|
|
46
|
-
|
|
45
|
+
'@1auth/crypto symmetricEncryptionKey is empty, use a stored secret made from randomBytes(32) Encryption disabled.'
|
|
47
46
|
)
|
|
48
47
|
}
|
|
48
|
+
options.symmetricEncryptionEncoding ??= options.defaultEncoding
|
|
49
|
+
options.symmetricSignatureHashAlgorithm ??= options.defaultHashAlgorithm
|
|
49
50
|
if (!options.symmetricSignatureSecret) {
|
|
50
51
|
console.warn(
|
|
51
|
-
|
|
52
|
+
'@1auth/crypto symmetricSignatureSecret is empty, use a stored secret made from randomBytes(32). Signature disabled.'
|
|
52
53
|
)
|
|
53
54
|
}
|
|
55
|
+
options.symmetricSignatureEncoding ??= options.defaultEncoding
|
|
56
|
+
options.asymmetricSignatureHashAlgorithm ??= options.defaultHashAlgorithm
|
|
57
|
+
options.asymmetricSignatureEncoding ??= options.defaultEncoding
|
|
58
|
+
if (!options.digestChecksumSalt) {
|
|
59
|
+
console.warn(
|
|
60
|
+
'@1auth/crypto digestChecksumSalt is empty, use a stored secret made from randomBytes(32). Checksum salting disabled.'
|
|
61
|
+
)
|
|
62
|
+
}
|
|
63
|
+
if (!options.digestChecksumPepper) {
|
|
64
|
+
console.warn(
|
|
65
|
+
'@1auth/crypto digestChecksumPepper is empty, use a stored secret made from randomBytes(12). Checksum peppering disabled.'
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
options.digestChecksumAlgorithm ??= options.defaultHashAlgorithm
|
|
69
|
+
options.digestChecksumEncoding ??= options.defaultEncoding
|
|
70
|
+
|
|
71
|
+
// Lengths
|
|
72
|
+
symmetricEncryptionEncodingLengths.iv = randomIV().toString(
|
|
73
|
+
options.symmetricEncryptionEncoding
|
|
74
|
+
).length
|
|
75
|
+
symmetricEncryptionEncodingLengths.ivAndAuthTag =
|
|
76
|
+
symmetricEncryptionEncodingLengths.iv +
|
|
77
|
+
randomBytes(16).toString(options.symmetricEncryptionEncoding).length
|
|
54
78
|
}
|
|
55
79
|
|
|
56
80
|
export const getOptions = () => options
|
|
@@ -86,13 +110,13 @@ export const entropyToCharacterLength = (bits, characterPoolSize) => {
|
|
|
86
110
|
}; */
|
|
87
111
|
|
|
88
112
|
// *** Random generators *** //
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
...'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
|
|
113
|
+
export const charactersAlpha = [
|
|
114
|
+
...'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
|
|
92
115
|
]
|
|
93
|
-
export const charactersDistinguishable = [...'CDEHKMPRTUWXY012458']
|
|
94
116
|
export const charactersNumeric = [...'0123456789']
|
|
117
|
+
export const charactersAlphaNumeric = charactersAlpha.concat(charactersNumeric)
|
|
95
118
|
|
|
119
|
+
// Ref: https://github.com/sindresorhus/crypto-random-string/blob/main/core.js
|
|
96
120
|
export const randomCharacters = (
|
|
97
121
|
length,
|
|
98
122
|
characters = charactersAlphaNumeric
|
|
@@ -145,58 +169,101 @@ export const randomId = {
|
|
|
145
169
|
}
|
|
146
170
|
|
|
147
171
|
// *** Digests *** //
|
|
148
|
-
export const
|
|
149
|
-
|
|
150
|
-
encoding ??= options.digestEncoding
|
|
151
|
-
return checksum(algorithm).update(value).digest(encoding)
|
|
172
|
+
export const randomChecksumSalt = () => {
|
|
173
|
+
return randomBytes(32) // 256 bits
|
|
152
174
|
}
|
|
153
|
-
export const
|
|
154
|
-
|
|
155
|
-
const checksum = createChecksum(value, { algorithm })
|
|
156
|
-
return `${algorithm}:${checksum}`
|
|
175
|
+
export const randomChecksumPepper = () => {
|
|
176
|
+
return randomIV() // 96
|
|
157
177
|
}
|
|
158
178
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
return symmetricEncrypt(digest, {
|
|
167
|
-
encryptionKey: options.symmetricEncryptionKey,
|
|
168
|
-
sub: '',
|
|
169
|
-
encoding: options.symmetricEncryptionEncoding,
|
|
170
|
-
iv: Buffer.from(
|
|
171
|
-
options.symmetricEncryptionKey.substring(
|
|
172
|
-
0,
|
|
173
|
-
symmetricEncryptionEncodingLengths.iv
|
|
174
|
-
),
|
|
175
|
-
options.symmetricEncryptionEncoding
|
|
176
|
-
)
|
|
177
|
-
})
|
|
179
|
+
export const createSaltedValue = (value, { checksumSalt } = {}) => {
|
|
180
|
+
checksumSalt ??= options.digestChecksumSalt
|
|
181
|
+
if (!checksumSalt) {
|
|
182
|
+
return value
|
|
183
|
+
}
|
|
184
|
+
const newValue = value + checksumSalt
|
|
185
|
+
return newValue
|
|
178
186
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
encryptionKey,
|
|
183
|
-
newEncryptionKey
|
|
187
|
+
export const createPepperedValue = (
|
|
188
|
+
value,
|
|
189
|
+
{ checksumPepper, encryptionKey } = {}
|
|
184
190
|
) => {
|
|
185
|
-
|
|
191
|
+
checksumPepper ??= options.digestChecksumPepper
|
|
192
|
+
encryptionKey ??= options.symmetricEncryptionKey
|
|
193
|
+
if (!checksumPepper || !encryptionKey) {
|
|
194
|
+
return value
|
|
195
|
+
}
|
|
196
|
+
const newValue = symmetricEncrypt(value, {
|
|
186
197
|
encryptionKey,
|
|
187
198
|
sub: '',
|
|
188
|
-
|
|
199
|
+
iv: checksumPepper
|
|
189
200
|
})
|
|
201
|
+
return newValue
|
|
202
|
+
}
|
|
190
203
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
204
|
+
export const createChecksum = (value, { algorithm, encoding } = {}) => {
|
|
205
|
+
algorithm ??= options.digestChecksumAlgorithm
|
|
206
|
+
encoding ??= options.digestChecksumEncoding
|
|
207
|
+
return createHash(algorithm).update(value).digest(encoding)
|
|
208
|
+
}
|
|
209
|
+
export const createSeasonedChecksum = (
|
|
210
|
+
value,
|
|
211
|
+
{ algorithm, encoding, checksumSalt, checksumPepper } = {}
|
|
212
|
+
) => {
|
|
213
|
+
return createChecksum(
|
|
214
|
+
createPepperedValue(createSaltedValue(value, { checksumSalt }), {
|
|
215
|
+
checksumPepper
|
|
216
|
+
}),
|
|
217
|
+
{
|
|
218
|
+
algorithm,
|
|
219
|
+
encoding
|
|
220
|
+
}
|
|
221
|
+
)
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export const createDigest = (value, { algorithm, encoding } = {}) => {
|
|
225
|
+
algorithm ??= options.digestChecksumAlgorithm
|
|
226
|
+
const checksum = createChecksum(value, { algorithm, encoding })
|
|
227
|
+
return `${algorithm}:${checksum}`
|
|
228
|
+
}
|
|
229
|
+
export const createSaltedDigest = (
|
|
230
|
+
value,
|
|
231
|
+
{ algorithm, encoding, checksumSalt } = {}
|
|
232
|
+
) => {
|
|
233
|
+
algorithm ??= options.digestChecksumAlgorithm
|
|
234
|
+
const checksum = createChecksum(createSaltedValue(value, { checksumSalt }), {
|
|
235
|
+
algorithm,
|
|
236
|
+
encoding
|
|
199
237
|
})
|
|
238
|
+
return `${algorithm}:${checksum}`
|
|
239
|
+
}
|
|
240
|
+
export const createPepperedDigest = (
|
|
241
|
+
value,
|
|
242
|
+
{ algorithm, encoding, checksumPepper, encryptionKey } = {}
|
|
243
|
+
) => {
|
|
244
|
+
algorithm ??= options.digestChecksumAlgorithm
|
|
245
|
+
const checksum = createChecksum(
|
|
246
|
+
createPepperedValue(value, { checksumPepper, encryptionKey }),
|
|
247
|
+
{
|
|
248
|
+
algorithm,
|
|
249
|
+
encoding
|
|
250
|
+
}
|
|
251
|
+
)
|
|
252
|
+
return `${algorithm}:${checksum}`
|
|
253
|
+
}
|
|
254
|
+
export const createSeasonedDigest = (
|
|
255
|
+
value,
|
|
256
|
+
{ algorithm, encoding, checksumSalt, checksumPepper, encryptionKey } = {}
|
|
257
|
+
) => {
|
|
258
|
+
algorithm ??= options.digestChecksumAlgorithm
|
|
259
|
+
const checksum = createSeasonedChecksum(value, {
|
|
260
|
+
algorithm,
|
|
261
|
+
encoding,
|
|
262
|
+
checksumSalt,
|
|
263
|
+
checksumPepper,
|
|
264
|
+
encryptionKey
|
|
265
|
+
})
|
|
266
|
+
return `${algorithm}:${checksum}`
|
|
200
267
|
}
|
|
201
268
|
|
|
202
269
|
// *** Hashing *** //
|
|
@@ -222,31 +289,41 @@ export const verifySecretHash = async (hash, value) => {
|
|
|
222
289
|
const authTagLength = 16
|
|
223
290
|
|
|
224
291
|
export const symmetricRandomEncryptionKey = () => {
|
|
225
|
-
return randomBytes(32)
|
|
292
|
+
return randomBytes(32) // 256 bits
|
|
226
293
|
}
|
|
227
294
|
|
|
228
|
-
export const
|
|
229
|
-
|
|
295
|
+
export const randomIV = () => {
|
|
296
|
+
return randomBytes(12) // 96 bits
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
export const symmetricGenerateEncryptionKey = (
|
|
300
|
+
sub,
|
|
301
|
+
{ encryptionKey, signatureSecret } = {}
|
|
302
|
+
) => {
|
|
303
|
+
encryptionKey ??= options.symmetricEncryptionKey
|
|
304
|
+
signatureSecret ??= options.symemeticSignatureSecret
|
|
305
|
+
|
|
306
|
+
if (!encryptionKey) {
|
|
230
307
|
return { encryptionKey: '', encryptedKey: '' }
|
|
231
308
|
}
|
|
232
|
-
const
|
|
233
|
-
const
|
|
234
|
-
encryptionKey
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
encoding: options.symmetricEncryptionEncoding
|
|
309
|
+
const rowEncryptionKey = symmetricRandomEncryptionKey()
|
|
310
|
+
const rowEncryptedKey = symmetricEncrypt(rowEncryptionKey, {
|
|
311
|
+
encryptionKey,
|
|
312
|
+
signatureSecret,
|
|
313
|
+
sub
|
|
238
314
|
})
|
|
239
|
-
return { encryptionKey, encryptedKey }
|
|
315
|
+
return { encryptionKey: rowEncryptionKey, encryptedKey: rowEncryptedKey }
|
|
240
316
|
}
|
|
241
317
|
|
|
242
318
|
// sub add context to encryption
|
|
243
319
|
export const symmetricEncryptFields = (
|
|
244
320
|
values,
|
|
245
|
-
{ encryptedKey, encryptionKey, sub },
|
|
321
|
+
{ encryptedKey, encryptionKey, signatureSecret, sub },
|
|
246
322
|
fields = []
|
|
247
323
|
) => {
|
|
248
324
|
if (encryptedKey) {
|
|
249
325
|
encryptionKey ??= symmetricDecryptKey(encryptedKey, {
|
|
326
|
+
signatureSecret,
|
|
250
327
|
sub
|
|
251
328
|
})
|
|
252
329
|
}
|
|
@@ -255,6 +332,7 @@ export const symmetricEncryptFields = (
|
|
|
255
332
|
for (const key of fields) {
|
|
256
333
|
encryptedValues[key] &&= symmetricEncrypt(encryptedValues[key], {
|
|
257
334
|
encryptionKey,
|
|
335
|
+
signatureSecret,
|
|
258
336
|
sub
|
|
259
337
|
})
|
|
260
338
|
}
|
|
@@ -267,23 +345,23 @@ export const symmetricEncrypt = (
|
|
|
267
345
|
) => {
|
|
268
346
|
if (encryptedKey) {
|
|
269
347
|
encryptionKey ??= symmetricDecryptKey(encryptedKey, {
|
|
348
|
+
signatureSecret,
|
|
270
349
|
sub
|
|
271
350
|
})
|
|
272
351
|
}
|
|
273
352
|
if (!encryptionKey || !data) return data
|
|
274
353
|
decoding ??= 'utf8'
|
|
275
354
|
encoding ??= options.symmetricEncryptionEncoding
|
|
276
|
-
iv ??=
|
|
277
|
-
|
|
355
|
+
iv ??= randomIV()
|
|
278
356
|
const cipher = createCipheriv(
|
|
279
|
-
options.
|
|
280
|
-
|
|
357
|
+
options.symmetricEncryptionAlgorithm,
|
|
358
|
+
encryptionKey,
|
|
281
359
|
iv,
|
|
282
360
|
{
|
|
283
361
|
authTagLength
|
|
284
362
|
}
|
|
285
363
|
)
|
|
286
|
-
cipher.setAAD(
|
|
364
|
+
cipher.setAAD(sub)
|
|
287
365
|
const encryptedData =
|
|
288
366
|
cipher.update(data, decoding, encoding) + cipher.final(encoding)
|
|
289
367
|
const authTag = cipher.getAuthTag()
|
|
@@ -302,6 +380,7 @@ export const symmetricDecryptFields = (
|
|
|
302
380
|
) => {
|
|
303
381
|
if (encryptedKey) {
|
|
304
382
|
encryptionKey ??= symmetricDecryptKey(encryptedKey, {
|
|
383
|
+
signatureSecret,
|
|
305
384
|
sub
|
|
306
385
|
})
|
|
307
386
|
}
|
|
@@ -310,19 +389,28 @@ export const symmetricDecryptFields = (
|
|
|
310
389
|
for (const key of fields) {
|
|
311
390
|
values[key] &&= symmetricDecrypt(values[key], {
|
|
312
391
|
encryptionKey,
|
|
392
|
+
signatureSecret,
|
|
313
393
|
sub
|
|
314
394
|
})
|
|
315
395
|
}
|
|
316
396
|
return values
|
|
317
397
|
}
|
|
318
398
|
|
|
319
|
-
export const symmetricDecryptKey = (
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
399
|
+
export const symmetricDecryptKey = (
|
|
400
|
+
encryptedKey,
|
|
401
|
+
{ sub, encryptionKey, signatureSecret } = {}
|
|
402
|
+
) => {
|
|
403
|
+
encryptionKey ??= options.symmetricEncryptionKey
|
|
404
|
+
signatureSecret ??= options.symemeticSignatureSecret
|
|
405
|
+
return Buffer.from(
|
|
406
|
+
symmetricDecrypt(encryptedKey, {
|
|
407
|
+
encryptionKey,
|
|
408
|
+
signatureSecret,
|
|
409
|
+
sub,
|
|
410
|
+
encoding: options.symmetricEncryptionEncoding
|
|
411
|
+
}),
|
|
412
|
+
options.symmetricEncryptionEncoding
|
|
413
|
+
)
|
|
326
414
|
}
|
|
327
415
|
|
|
328
416
|
export const symmetricDecrypt = (
|
|
@@ -331,6 +419,7 @@ export const symmetricDecrypt = (
|
|
|
331
419
|
) => {
|
|
332
420
|
if (encryptedKey) {
|
|
333
421
|
encryptionKey ??= symmetricDecryptKey(encryptedKey, {
|
|
422
|
+
signatureSecret,
|
|
334
423
|
sub
|
|
335
424
|
})
|
|
336
425
|
}
|
|
@@ -347,7 +436,6 @@ export const symmetricDecrypt = (
|
|
|
347
436
|
if (encryptedDataPacket === false) {
|
|
348
437
|
throw new Error('Signature incorrect')
|
|
349
438
|
}
|
|
350
|
-
|
|
351
439
|
const iv = Buffer.from(
|
|
352
440
|
encryptedDataPacket.substring(0, symmetricEncryptionEncodingLengths.iv),
|
|
353
441
|
decoding
|
|
@@ -367,14 +455,14 @@ export const symmetricDecrypt = (
|
|
|
367
455
|
)
|
|
368
456
|
|
|
369
457
|
const decipher = createDecipheriv(
|
|
370
|
-
options.
|
|
371
|
-
|
|
458
|
+
options.symmetricEncryptionAlgorithm,
|
|
459
|
+
encryptionKey,
|
|
372
460
|
iv,
|
|
373
461
|
{
|
|
374
462
|
authTagLength
|
|
375
463
|
}
|
|
376
464
|
)
|
|
377
|
-
decipher.setAAD(Buffer.from(sub
|
|
465
|
+
decipher.setAAD(Buffer.from(sub, 'utf8'))
|
|
378
466
|
|
|
379
467
|
decipher.setAuthTag(authTag)
|
|
380
468
|
const data =
|
|
@@ -385,10 +473,10 @@ export const symmetricDecrypt = (
|
|
|
385
473
|
|
|
386
474
|
// *** Symmetric Signatures *** //
|
|
387
475
|
export const symmetricRandomSignatureSecret = () => {
|
|
388
|
-
return randomBytes(32)
|
|
476
|
+
return randomBytes(32) // 256 bits
|
|
389
477
|
}
|
|
390
478
|
|
|
391
|
-
export const symmetricGenerateSignatureSecret = (
|
|
479
|
+
export const symmetricGenerateSignatureSecret = () => {
|
|
392
480
|
if (!options.symmetricSignatureSecret) {
|
|
393
481
|
return { signatureSecret: '' }
|
|
394
482
|
}
|
|
@@ -401,12 +489,11 @@ export const symmetricSignatureSign = (
|
|
|
401
489
|
signatureSecret,
|
|
402
490
|
{ algorithm } = {}
|
|
403
491
|
) => {
|
|
404
|
-
// if (typeof data !== 'string') throw new TypeError('data must me a string')
|
|
405
492
|
signatureSecret ??= options.symmetricSignatureSecret
|
|
406
|
-
algorithm ??= options.
|
|
493
|
+
algorithm ??= options.symmetricSignatureHashAlgorithm
|
|
407
494
|
const signature = createHmac(algorithm, signatureSecret)
|
|
408
495
|
.update(data)
|
|
409
|
-
.digest(options.
|
|
496
|
+
.digest(options.symmetricSignatureEncoding)
|
|
410
497
|
.replace(/=+$/, '')
|
|
411
498
|
|
|
412
499
|
const signedData = data + '.' + signature
|
|
@@ -423,19 +510,48 @@ export const symmetricSignatureVerify = (
|
|
|
423
510
|
const signedDataExpected = symmetricSignatureSign(data, signatureSecret, {
|
|
424
511
|
algorithm
|
|
425
512
|
})
|
|
426
|
-
|
|
427
513
|
return safeEqual(signedData, signedDataExpected) && data
|
|
428
514
|
}
|
|
429
515
|
|
|
516
|
+
// Allow rotation of global encryption key, global signature secret, and row encryption key
|
|
430
517
|
export const symmetricRotation = (
|
|
431
|
-
|
|
432
|
-
oldOptions, // {
|
|
433
|
-
|
|
434
|
-
|
|
518
|
+
oldEncryptedValues,
|
|
519
|
+
oldOptions, // { encryptionKey, signatureSecret, sub, decoding, encoding }, // old
|
|
520
|
+
oldFields = [],
|
|
521
|
+
newOptions, // { encryptionKey, signatureSecret, sub, decoding, encoding }, // new
|
|
522
|
+
newFields = [],
|
|
523
|
+
transform = (data) => {
|
|
524
|
+
return data
|
|
525
|
+
}
|
|
435
526
|
) => {
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
527
|
+
if (oldOptions.sub !== newOptions.sub) throw new Error('Mismatching `sub`')
|
|
528
|
+
|
|
529
|
+
// decrypt old encryption key
|
|
530
|
+
const { encryptionKey: oldEncryptedKey } = oldEncryptedValues
|
|
531
|
+
delete oldEncryptedValues.encryptionKey
|
|
532
|
+
|
|
533
|
+
oldOptions.encryptionKey = symmetricDecryptKey(oldEncryptedKey, oldOptions)
|
|
534
|
+
|
|
535
|
+
// decrypt
|
|
536
|
+
const data = transform(
|
|
537
|
+
symmetricDecryptFields(oldEncryptedValues, oldOptions, oldFields)
|
|
538
|
+
)
|
|
539
|
+
|
|
540
|
+
// rotate encryptionKey
|
|
541
|
+
const { encryptionKey: newEncryptionKey, encryptedKey: newEncryptedKey } =
|
|
542
|
+
symmetricGenerateEncryptionKey(oldOptions.sub, newOptions)
|
|
543
|
+
|
|
544
|
+
newOptions.encryptionKey = newEncryptionKey
|
|
545
|
+
|
|
546
|
+
// encrypt
|
|
547
|
+
const newEncryptedValues = symmetricEncryptFields(
|
|
548
|
+
data,
|
|
549
|
+
newOptions,
|
|
550
|
+
newFields
|
|
551
|
+
)
|
|
552
|
+
newEncryptedValues.encryptionKey = newEncryptedKey
|
|
553
|
+
|
|
554
|
+
return newEncryptedValues
|
|
439
555
|
}
|
|
440
556
|
|
|
441
557
|
// *** Asymmetric Signatures *** //
|
|
@@ -452,7 +568,7 @@ export const makeAsymmetricKeys = async () => {
|
|
|
452
568
|
type: 'sec1',
|
|
453
569
|
format: 'pem'
|
|
454
570
|
// Encryption done at another level for consistency
|
|
455
|
-
// cipher: options.
|
|
571
|
+
// cipher: options.asymmetricEncryptionAlgorithm,
|
|
456
572
|
// passphrase: encryptionKey,
|
|
457
573
|
}
|
|
458
574
|
})
|
|
@@ -464,9 +580,9 @@ export const makeAsymmetricSignature = async (
|
|
|
464
580
|
privateKey,
|
|
465
581
|
{ algorithm } = {}
|
|
466
582
|
) => {
|
|
467
|
-
algorithm ??= options.
|
|
583
|
+
algorithm ??= options.asymmetricSignatureHashAlgorithm
|
|
468
584
|
return (await sign(algorithm, Buffer.from(data), privateKey)).toString(
|
|
469
|
-
options.
|
|
585
|
+
options.asymmetricSignatureEncoding
|
|
470
586
|
)
|
|
471
587
|
}
|
|
472
588
|
export const verifyAsymmetricSignature = async (
|
|
@@ -475,12 +591,12 @@ export const verifyAsymmetricSignature = async (
|
|
|
475
591
|
signature,
|
|
476
592
|
{ algorithm } = {}
|
|
477
593
|
) => {
|
|
478
|
-
algorithm ??= options.
|
|
594
|
+
algorithm ??= options.asymmetricSignatureHashAlgorithm
|
|
479
595
|
return await verify(
|
|
480
596
|
algorithm,
|
|
481
597
|
Buffer.from(data),
|
|
482
598
|
publicKey,
|
|
483
|
-
Buffer.from(signature, options.
|
|
599
|
+
Buffer.from(signature, options.asymmetricSignatureEncoding)
|
|
484
600
|
)
|
|
485
601
|
}
|
|
486
602
|
|