@1auth/crypto 0.0.0-alpha.31 → 0.0.0-alpha.33

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.
Files changed (2) hide show
  1. package/index.js +241 -285
  2. package/package.json +3 -3
package/index.js CHANGED
@@ -5,26 +5,43 @@ import {
5
5
  createCipheriv,
6
6
  createDecipheriv,
7
7
  generateKeyPair as generateKeyPairCallback,
8
- sign,
9
- verify
8
+ sign as signCallback,
9
+ verify as verifyCallback
10
10
  } from 'node:crypto'
11
11
  // https://github.com/napi-rs/node-rs/tree/main/packages/argon2
12
12
  import { hash as secretHash, verify as secretVerify } from '@node-rs/argon2'
13
13
 
14
- const options = {
15
- // randomBytes(32).toString('hex') // 256 bits
16
- encryptionSharedKey: '',
17
- encryptionMethod: 'chacha20-poly1305', // AES-256 GCM (aes-256-gcm) or ChaCha20-Poly1305 (chacha20-poly1305)
18
-
14
+ const generateKeyPair = promisify(generateKeyPairCallback)
15
+ const sign = promisify(signCallback)
16
+ const verify = promisify(verifyCallback)
17
+
18
+ const defaults = {
19
+ // symetricEncryptionKey: randomBytes(32).toString('base64') // 256 bits
20
+ symetricEncryptionKey: undefined,
21
+ symetricEncryptionMethod: 'chacha20-poly1305', // 2024-05: AES-256 GCM (aes-256-gcm) or ChaCha20-Poly1305 (chacha20-poly1305)
22
+ symetricEncryptionEncoding: 'base64', // https://nodejs.org/api/buffer.html#buffers-and-character-encodings
23
+ asymetricKey: 'P-384',
19
24
  digestAlgorithm: 'sha3-384',
20
- digestSalt: ''
21
- }
22
-
23
- export default (params) => {
24
- Object.assign(options, params)
25
+ signatureEncoding: 'base64'
26
+ }
27
+ const symetricEncryptionEncodingLengths = {}
28
+ const options = {}
29
+ export default (opt = {}) => {
30
+ Object.assign(options, defaults, opt)
31
+ symetricEncryptionEncodingLengths.iv = randomBytes(12).toString(
32
+ options.symetricEncryptionEncoding
33
+ ).length
34
+ symetricEncryptionEncodingLengths.ivAndAuthTag =
35
+ symetricEncryptionEncodingLengths.iv +
36
+ randomBytes(16).toString(options.symetricEncryptionEncoding).length
37
+ if (!options.symetricEncryptionKey) {
38
+ console.warn(
39
+ "@1auth/crypto symetricEncryptionKey is empty, use a stored secret made from randomBytes(32).toString('base64'). Encryption disabled."
40
+ )
41
+ }
25
42
  }
26
43
 
27
- const generateKeyPair = promisify(generateKeyPairCallback)
44
+ export const getOptions = () => options
28
45
 
29
46
  // *** entropy *** //
30
47
  // export const characterPoolSize = (value) => {
@@ -42,188 +59,107 @@ const generateKeyPair = promisify(generateKeyPairCallback)
42
59
  // return max - min
43
60
  // }
44
61
 
45
- // *** Random generators *** //
46
- export const characterPoolSize = {
47
- keyboard: 94, // (26 + 10 + 11) * 2
48
- alphaNumeric: 62, // (26 + 10) * 2
49
- base64: 64, // (26 * 2 + 10 + 2
50
- hex: 16,
51
- numeric: 10
62
+ // *** Helpers *** //
63
+ // Ref: https://therootcompany.com/blog/how-many-bits-of-entropy-per-character/
64
+ export const entropyToCharacterLength = (bits, characterPoolSize) => {
65
+ // bits*ln(2)/ln(characterPoolSize)
66
+ return Math.ceil((bits * Math.LN2) / Math.log(characterPoolSize))
52
67
  }
53
- // Alt: https://github.com/sindresorhus/crypto-random-string/blob/main/core.js
54
- export const randomAlphaNumeric = (bits) => {
55
- const characterLength = entropyToCharacterLength(
56
- bits,
57
- characterPoolSize.alphaNumeric
58
- )
59
- return randomBytes(characterLength * 2)
60
- .toString('base64')
61
- .replace(/[^a-zA-Z0-9]/g, '')
62
- .substring(0, characterLength)
68
+ /* export const characterLengthToEntropy = (
69
+ characterLength,
70
+ characterPoolSize,
71
+ ) => {
72
+ // log_2(characterPoolSize^characterLength)
73
+ return Math.floor(Math.log2(characterPoolSize ** characterLength));
74
+ }; */
75
+
76
+ // *** Random generators *** //
77
+ // Ref: https://github.com/sindresorhus/crypto-random-string/blob/main/core.js
78
+ export const charactersAlphaNumeric = [
79
+ ...'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
80
+ ]
81
+ export const charactersDistinguishable = [...'CDEHKMPRTUWXY012458']
82
+ export const charactersNumeric = [...'0123456789']
83
+
84
+ export const randomCharacters = (
85
+ length,
86
+ characters = charactersAlphaNumeric
87
+ ) => {
88
+ // Generating entropy is faster than complex math operations, so we use the simplest way
89
+ const characterCount = characters.length
90
+ const maxValidSelector =
91
+ Math.floor(0x1_00_00 / characterCount) * characterCount - 1 // Using values above this will ruin distribution when using modular division
92
+ const entropyLength = 2 * Math.ceil(1.1 * length) // Generating a bit more than required so chances we need more than one pass will be really low
93
+ let string = ''
94
+ let stringLength = 0
95
+
96
+ while (stringLength < length) {
97
+ // In case we had many bad values, which may happen for character sets of size above 0x8000 but close to it
98
+ const entropy = new Uint8Array(randomBytes(entropyLength))
99
+ let entropyPosition = 0
100
+
101
+ while (entropyPosition < entropyLength && stringLength < length) {
102
+ const entropyValue =
103
+ entropy[entropyPosition] + (entropy[entropyPosition + 1] << 8) // eslint-disable-line no-bitwise
104
+ entropyPosition += 2
105
+ if (entropyValue > maxValidSelector) {
106
+ // Skip values which will ruin distribution when using modular division
107
+ continue
108
+ }
109
+
110
+ string += characters[entropyValue % characterCount]
111
+ stringLength++
112
+ }
113
+ }
114
+
115
+ return string
63
116
  }
64
117
 
65
- export const randomBase64 = (bits) => {
66
- const characterLength = entropyToCharacterLength(
67
- bits,
68
- characterPoolSize.base64
69
- )
70
- return randomBytes(characterLength + 1)
71
- .toString('base64')
72
- .replace('=', '')
118
+ export const randomAlphaNumeric = (characterLength) => {
119
+ return randomCharacters(characterLength, charactersAlphaNumeric)
73
120
  }
74
121
 
75
- export const randomNumeric = (bits) => {
76
- const characterLength = entropyToCharacterLength(
77
- bits,
78
- characterPoolSize.numeric
79
- )
80
- const max = 10 ** characterLength
81
- let value = Math.floor(Math.random() * max).toString()
82
- if (value === max.toString()) {
83
- return randomNumeric(bits)
84
- }
85
- while (value.length < characterLength) value = '0' + value
86
- return value
122
+ export const randomNumeric = (characterLength) => {
123
+ return randomCharacters(characterLength, charactersNumeric)
87
124
  }
88
125
 
89
- export const randomHex = (bits) => {
90
- const characterLength = entropyToCharacterLength(bits, characterPoolSize.hex)
91
- return randomBytes(characterLength).toString('hex')
126
+ export const randomSymetricEncryptionKey = () => {
127
+ return randomBytes(32).toString('base64') // 256 bits
92
128
  }
93
129
 
94
130
  // *** configs *** //
95
131
  export const randomId = {
96
132
  type: 'id',
97
- entropy: 64,
98
- charPool: characterPoolSize.alphaNumeric,
133
+ minLength: entropyToCharacterLength(64, charactersAlphaNumeric.length),
99
134
  // TODO update to use https://github.com/jetpack-io/typeid
100
- create: async (prefix) =>
101
- (prefix ? prefix + '_' : '') + randomAlphaNumeric(randomId.entropy)
102
- }
103
-
104
- export const subject = {
105
- type: 'id',
106
- entropy: 64,
107
- charPool: characterPoolSize.alphaNumeric,
108
- create: async (prefix) =>
109
- (prefix ? prefix + '_' : '') + randomAlphaNumeric(subject.entropy)
110
- }
111
-
112
- export const session = {
113
- type: 'id',
114
- entropy: 128, // ASVS 3.2.2
115
- charPool: characterPoolSize.alphaNumeric,
116
- expire: 15 * 60,
117
- create: async (prefix) =>
118
- (prefix ? prefix + '_' : '') + randomAlphaNumeric(session.entropy)
119
- }
120
-
121
- export const passwordSecret = {
122
- type: 'secret',
123
- entropy: 64,
124
- charPool: characterPoolSize.keyboard,
125
- otp: false,
126
- encode: async (value, encryptedKey, sub) =>
127
- createSecretHash(value).then((hash) => encrypt(hash, encryptedKey, sub)),
128
- decode: async (value, encryptedKey, sub) => decrypt(value, encryptedKey, sub),
129
- verify: async (value, hash) => verifySecretHash(hash, value)
130
- }
131
-
132
- // aka Password/Credential Recovery
133
- export const passwordToken = {
134
- type: 'token',
135
- entropy: 20,
136
- charPool: characterPoolSize.numeric,
137
- otp: true,
138
- expire: 30,
139
- create: async () => randomNumeric(passwordToken.entropy),
140
- encode: async (value, encryptedKey, sub) =>
141
- createSecretHash(value).then((hash) => encrypt(hash, encryptedKey, sub)),
142
- decode: async (value, encryptedKey, sub) => decrypt(value, encryptedKey, sub),
143
- verify: async (value, hash) => verifySecretHash(hash, value)
144
- }
145
-
146
- export const oneTimeSecret = {
147
- type: 'secret',
148
- entropy: 64, //
149
- charPool: characterPoolSize.base64,
150
- otp: false,
151
- expire: null,
152
- create: async () => randomBase64(oneTimeSecret.entropy),
153
- encode: async (value, encryptedKey, sub) => encrypt(value, encryptedKey, sub),
154
- decode: async (value, encryptedKey, sub) => decrypt(value, encryptedKey, sub)
155
- // create, hash, verify to be handled within
156
- }
157
- export const oneTimeToken = {
158
- type: 'token',
159
- entropy: 20,
160
- charPool: characterPoolSize.numeric,
161
- otp: true,
162
- expire: 30
163
- // create, hash, verify to be handled within
164
- }
165
-
166
- // aka lookup secret
167
- export const recoveryCode = {
168
- type: 'secret',
169
- entropy: 112,
170
- charPool: characterPoolSize.alphaNumeric,
171
- otp: true,
172
- create: async () => randomAlphaNumeric(recoveryCode.entropy),
173
- encode: async (value, encryptedKey, sub) =>
174
- createSecretHash(value).then((hash) => encrypt(hash, encryptedKey, sub)),
175
- decode: async (value, encryptedKey, sub) => decrypt(value, encryptedKey, sub),
176
- verify: async (value, hash) => verifySecretHash(hash, value)
177
- }
178
-
179
- export const outOfBandToken = {
180
- type: 'token',
181
- entropy: 20,
182
- charPool: characterPoolSize.numeric,
183
- otp: true,
184
- expire: 10 * 60,
185
- create: async () => randomNumeric(outOfBandToken.entropy),
186
- encode: async (value, encryptedKey, sub) =>
187
- createSecretHash(value).then((hash) => encrypt(hash, encryptedKey, sub)),
188
- decode: async (value, encryptedKey, sub) => decrypt(value, encryptedKey, sub),
189
- verify: async (value, hash) => verifySecretHash(hash, value)
190
- }
191
-
192
- export const accessToken = {
193
- type: 'secret',
194
- entropy: 112,
195
- charPool: characterPoolSize.alphaNumeric,
196
- otp: false,
197
- expire: 30 * 24 * 60 * 60, // allow override from user
198
- create: async () => randomAlphaNumeric(accessToken.entropy),
199
- encode: async (value, encryptedKey, sub) =>
200
- createSecretHash(value).then((hash) => encrypt(hash, encryptedKey, sub)),
201
- decode: async (value, encryptedKey, sub) => decrypt(value, encryptedKey, sub),
202
- verify: async (value, hash) => verifySecretHash(hash, value)
203
- }
204
-
205
- // *** Helpers *** //
206
- export const characterLengthToEntropy = (
207
- characterLength,
208
- characterPoolSize
209
- ) => {
210
- // log_2(characterPoolSize^characterLength)
211
- return Math.round(Math.log2(characterPoolSize ** characterLength))
212
- }
213
-
214
- export const entropyToCharacterLength = (bits, characterPoolSize) => {
215
- // bits*ln(2)/ln(characterPoolSize)
216
- return Math.round((bits * Math.LN2) / Math.log(characterPoolSize))
135
+ create: (prefix) =>
136
+ (prefix ? prefix + '_' : '') + randomAlphaNumeric(randomId.minLength)
217
137
  }
218
138
 
219
139
  // *** Digests *** //
220
- export const createDigest = async (value, { algorithm, salt } = {}) => {
140
+ export const createDigest = (value, { algorithm } = {}) => {
221
141
  algorithm ??= options.digestAlgorithm
222
- salt ??= options.digestSalt
223
- const hash = checksum(algorithm)
224
- .update(value + salt)
225
- .digest('hex')
226
- return `${algorithm}:${hash}`
142
+ const hash = checksum(algorithm).update(value).digest('hex')
143
+ const digest = `${algorithm}:${hash}`
144
+ return digest
145
+ }
146
+
147
+ export const createEncryptedDigest = (value, { algorithm } = {}) => {
148
+ const digest = createDigest(value, { algorithm })
149
+ // encrypting using the symetricEncryptionKey instread of
150
+ // the row encryptionKey to allow lookup, must have fixed iv
151
+ return symetricEncrypt(digest, {
152
+ encryptionKey: options.symetricEncryptionKey,
153
+ sub: '',
154
+ encoding: options.symetricEncryptionEncoding,
155
+ iv: Buffer.from(
156
+ options.symetricEncryptionKey.substring(
157
+ 0,
158
+ symetricEncryptionEncodingLengths.iv
159
+ ),
160
+ options.symetricEncryptionEncoding
161
+ )
162
+ })
227
163
  }
228
164
 
229
165
  // *** Hashing *** //
@@ -248,124 +184,156 @@ export const verifySecretHash = async (hash, value) => {
248
184
  // *** Encryption *** //
249
185
  const authTagLength = 16
250
186
 
251
- export const makeSymetricKey = (assocData) => {
252
- if (!options.encryptionSharedKey) {
187
+ export const makeSymetricKey = (sub) => {
188
+ if (!options.symetricEncryptionKey) {
253
189
  return { encryptionKey: '', encryptedKey: '' }
254
190
  }
255
- const encryptionKey = randomBytes(32)
256
- const encryptedKey = __encrypt(
257
- encryptionKey,
258
- Buffer.from(options.encryptionSharedKey, 'hex'),
259
- assocData,
260
- 'hex',
261
- 'hex'
262
- )
191
+ const encryptionKey = randomSymetricEncryptionKey()
192
+ const encryptedKey = symetricEncrypt(encryptionKey, {
193
+ encryptionKey: options.symetricEncryptionKey,
194
+ sub,
195
+ decoding: 'base64',
196
+ encoding: options.symetricEncryptionEncoding
197
+ })
263
198
  return { encryptionKey, encryptedKey }
264
199
  }
265
200
 
266
- // assocData = sub or id
267
- export const encryptFields = (values, encryptedKey, assocData, fields = []) => {
268
- // TODO optimize: don't decrypt encryptedKey more than once
201
+ // sub add context to encryption
202
+ export const symetricEncryptFields = (
203
+ values,
204
+ { encryptedKey, encryptionKey, sub },
205
+ fields = []
206
+ ) => {
207
+ if (encryptedKey) {
208
+ encryptionKey ??= symetricDecryptKey(encryptedKey, {
209
+ sub
210
+ })
211
+ }
212
+ if (!encryptionKey) return values
213
+ const encryptedValues = structuredClone(values)
269
214
  for (const key of fields) {
270
- values[key] &&= encrypt(values[key], encryptedKey, assocData)
215
+ encryptedValues[key] &&= symetricEncrypt(encryptedValues[key], {
216
+ encryptionKey,
217
+ sub
218
+ })
271
219
  }
272
- return values
220
+ return encryptedValues
273
221
  }
274
222
 
275
- export const encrypt = (data, encryptedKey, assocData) => {
276
- if (!encryptedKey) return data
277
-
278
- const encryptionKey = __decryptKey(encryptedKey, assocData)
279
- return __encrypt(
280
- data,
281
- Buffer.from(encryptionKey, 'hex'),
282
- assocData,
283
- 'utf8',
284
- 'hex'
285
- )
286
- }
287
-
288
- const __encrypt = (
223
+ export const symetricEncrypt = (
289
224
  data,
290
- encryptionKey,
291
- assocData,
292
- decoding = 'utf8',
293
- encoding = 'hex'
225
+ { encryptedKey, encryptionKey, sub, decoding, encoding, iv }
294
226
  ) => {
295
- const iv = randomBytes(12) // 96 bits
296
- const cipher = createCipheriv(options.encryptionMethod, encryptionKey, iv, {
297
- authTagLength
298
- })
299
- cipher.setAAD(Buffer.from(assocData, 'utf8'))
227
+ if (encryptedKey) {
228
+ encryptionKey ??= symetricDecryptKey(encryptedKey, {
229
+ sub
230
+ })
231
+ }
232
+ if (!encryptionKey) return data
233
+ decoding ??= 'utf8'
234
+ encoding ??= options.symetricEncryptionEncoding
235
+ iv ??= randomBytes(12) // 96 bits
236
+
237
+ const cipher = createCipheriv(
238
+ options.symetricEncryptionMethod,
239
+ Buffer.from(encryptionKey, 'base64'),
240
+ iv,
241
+ {
242
+ authTagLength
243
+ }
244
+ )
245
+ cipher.setAAD(Buffer.from(sub ?? '', 'utf8'))
300
246
  const encryptedData =
301
247
  cipher.update(data, decoding, encoding) + cipher.final(encoding)
302
248
  const authTag = cipher.getAuthTag()
303
- return (
304
- iv.toString(encoding) + // 24 char
305
- authTag.toString(encoding) + // 32 char
306
- encryptedData
307
- )
249
+
250
+ const encryptedDataPacket =
251
+ iv.toString(encoding) + authTag.toString(encoding) + encryptedData
252
+
253
+ return encryptedDataPacket
308
254
  }
309
255
 
310
- export const decryptFields = (values, encryptedKey, assocData, fields = []) => {
311
- // TODO optimize: don't decrypt encryptedKey more than once
256
+ export const symetricDecryptFields = (
257
+ encryptedValues,
258
+ { encryptedKey, encryptionKey, sub },
259
+ fields = []
260
+ ) => {
261
+ if (encryptedKey) {
262
+ encryptionKey ??= symetricDecryptKey(encryptedKey, {
263
+ sub
264
+ })
265
+ }
266
+ if (!encryptionKey) return encryptedValues
267
+ const values = structuredClone(encryptedValues)
312
268
  for (const key of fields) {
313
- values[key] &&= decrypt(values[key], encryptedKey, assocData)
269
+ values[key] &&= symetricDecrypt(values[key], {
270
+ encryptionKey,
271
+ sub
272
+ })
314
273
  }
315
274
  return values
316
275
  }
317
276
 
318
- export const decrypt = (encryptedData, encryptedKey, assocData) => {
319
- if (!options.encryptionSharedKey || !encryptedKey) return encryptedData
320
- const encryptionKey = __decryptKey(encryptedKey, assocData)
321
- const data = __decrypt(
322
- encryptedData,
323
- Buffer.from(encryptionKey, 'hex'),
324
- assocData,
325
- 'hex',
326
- 'utf8'
327
- )
328
- return data
277
+ export const symetricDecryptKey = (encryptedKey, { sub } = {}) => {
278
+ return symetricDecrypt(encryptedKey, {
279
+ encryptionKey: options.symetricEncryptionKey,
280
+ sub,
281
+ decoding: options.symetricEncryptionEncoding,
282
+ encoding: 'base64'
283
+ })
329
284
  }
330
285
 
331
- const __decryptKey = (encryptedKey, assocData) =>
332
- __decrypt(
333
- encryptedKey,
334
- Buffer.from(options.encryptionSharedKey, 'hex'),
335
- assocData,
336
- 'hex',
337
- 'hex'
338
- )
339
-
340
- const __decrypt = (
341
- data,
342
- encryptionKey,
343
- assocData,
344
- decoding = 'hex',
345
- encoding = 'utf8'
286
+ export const symetricDecrypt = (
287
+ encryptedDataPacket,
288
+ { encryptedKey, encryptionKey, sub, decoding, encoding }
346
289
  ) => {
347
- const iv = Buffer.from(data.substring(0, 24), decoding)
348
- const authTag = Buffer.from(data.substring(24, 56), decoding)
349
- const encryptedData = Buffer.from(data.substring(56), decoding)
290
+ if (encryptedKey) {
291
+ encryptionKey ??= symetricDecryptKey(encryptedKey, {
292
+ sub
293
+ })
294
+ }
295
+ if (!encryptionKey) return encryptedDataPacket
296
+ decoding ??= options.symetricEncryptionEncoding
297
+ encoding ??= 'utf8'
298
+
299
+ const iv = Buffer.from(
300
+ encryptedDataPacket.substring(0, symetricEncryptionEncodingLengths.iv),
301
+ decoding
302
+ )
303
+ const authTag = Buffer.from(
304
+ encryptedDataPacket.substring(
305
+ symetricEncryptionEncodingLengths.iv,
306
+ symetricEncryptionEncodingLengths.ivAndAuthTag
307
+ ),
308
+ decoding
309
+ )
310
+ const encryptedData = Buffer.from(
311
+ encryptedDataPacket.substring(
312
+ symetricEncryptionEncodingLengths.ivAndAuthTag
313
+ ),
314
+ decoding
315
+ )
350
316
 
351
317
  const decipher = createDecipheriv(
352
- options.encryptionMethod,
353
- encryptionKey,
318
+ options.symetricEncryptionMethod,
319
+ Buffer.from(encryptionKey, 'base64'),
354
320
  iv,
355
321
  {
356
322
  authTagLength
357
323
  }
358
324
  )
359
- decipher.setAAD(Buffer.from(assocData, 'utf8'))
325
+ decipher.setAAD(Buffer.from(sub ?? '', 'utf8'))
326
+
360
327
  decipher.setAuthTag(authTag)
361
- return (
328
+ const data =
362
329
  decipher.update(encryptedData, decoding, encoding) +
363
330
  decipher.final(encoding)
364
- )
331
+ return data
365
332
  }
366
333
 
367
334
  // *** Signatures *** //
368
- export const makeAsymmetricKeys = async (encryptionKey) => {
335
+ // asymmetricKeyPairType
336
+ export const makeAsymmetricKeys = async () => {
369
337
  const { publicKey, privateKey } = await generateKeyPair('ec', {
370
338
  namedCurve: 'P-384', // P-512
371
339
  paramEncoding: 'named',
@@ -375,44 +343,32 @@ export const makeAsymmetricKeys = async (encryptionKey) => {
375
343
  },
376
344
  privateKeyEncoding: {
377
345
  type: 'sec1',
378
- format: 'pem',
379
- // TODO remove encryption for other with sub check?
380
- cipher: options.encryptionMethod,
381
- passphrase: encryptionKey
346
+ format: 'pem'
347
+ // Encryption done at another level for consistency
348
+ // cipher: options.asymetricEncryptionMethod,
349
+ // passphrase: encryptionKey,
382
350
  }
383
351
  })
384
352
  return { publicKey, privateKey }
385
353
  }
386
354
 
387
- export const makeSignature = (data, privateKey, algorithm = 'SHA3-384') => {
388
- return sign(algorithm, Buffer.from(data), privateKey).toString('base64')
355
+ export const makeSignature = async (data, privateKey, { algorithm } = {}) => {
356
+ algorithm ??= options.digestAlgorithm
357
+ return (await sign(algorithm, Buffer.from(data), privateKey)).toString(
358
+ options.signatureEncoding
359
+ )
389
360
  }
390
- export const verifySignature = (
361
+ export const verifySignature = async (
391
362
  data,
392
363
  publicKey,
393
364
  signature,
394
- algorithm = 'SHA3-384'
365
+ { algorithm } = {}
395
366
  ) => {
396
- return verify(
367
+ algorithm ??= options.digestAlgorithm
368
+ return await verify(
397
369
  algorithm,
398
370
  Buffer.from(data),
399
371
  publicKey,
400
- Buffer.from(signature, 'base64')
372
+ Buffer.from(signature, options.signatureEncoding)
401
373
  )
402
374
  }
403
- // const assocData = 'sub'
404
- // const input = 'data'
405
- //
406
- // const {encryptedKey} = makeSymetricKey(assocData)
407
- // const encryptedData = encrypt(input, encryptedKey, assocData)
408
- // const output = decrypt(encryptedData, encryptedKey, assocData)
409
- // console.log(assocData, input, output, encryptedData)
410
-
411
- // const assocData = 'tlSIcVp1XEF'
412
- // const encryptionKey =
413
- // 'b9ebfdab6603dd8e151138ec8298aaf8b49bf6d38480f9864e9e72e65c4d8b59.b9f9bc89d7f3ce4aa1e1af469d10508b.aa1b6a682fcc186e867a9cfd'
414
- // const value =
415
- // '76ebdea75ea529c16f1645d5435413934cbb97378293776cb446331e6d8323865a808b7f0822cd4f36ef6cca57354ea7c955c94d232a55038321184f4294971315fda4b8dc2f33422bbd3a5c978edc0f5bf019f818f0c92f7c570bdc49fe2f71df3856655198b6723fa52697b9225b2e79f04ed80cd35ef61a8e1e06c3751d3f9caa40aa9a41528ce5ab1bfae8ecff0feab784497ccbf2c7dca4461c6b9a74d1ded6233dc38ad75d0fe2f57cfda2bd1d59ed1f8c53de911cf8071dc7cefde7870c303137586bc0c5f85fe93505d9056994a4d8e59df2027b564c303aa723e98ae5934b15039f90d21827ac22b824593f334466622582a2857f04d8bf450310a9924060d113d2ece0259da68376b31a3c2e8a0b79e81f8efe96bf2b7a6b5b1841edca2566a0a89ab80ee6d6ac2ed24e788ad318a1238dfa5b9e965d256935d3aeafe52f986a530b2f9225bbe7a73b43e6515ce789701f501546239460bccc46285f3fcff0c54c2b6df820334a974abea81460fd4ac99a13cb88e296a2275f80f4c783757319417078458977461dd5e101f9f9b7d303578379dc15ee1b549e3fcceffffba895ecc8291d1f82e150ce8e10640fd79f2e0666167ef7d529cd28cb76a72bf2b3e239dbb845bedd39f42c938bbe711542231fb835edb547d919b3c695272f4cd43640eb3bed2b86948278e5aeeb67ef932ef08332730e75752fd5bd247e2dd30470fc493362d2ecac72237dfbf0a1694f8e6b8c18ab24c71eb723a3f610a056a73fea90f4f8660bfc6dec46fa52a55a3d72a5c9b97770bff7d52ea91b97cc643d915341642e201918fcb088986e9134e133519c6575048e3f840622e569fc5fa66e4f0c31681c9de4b1b1f6acb179728bc0a9f9950bf2e0c8d49da835298013977a2f97d7052bcbedbc39b875bbf9a0622ede589810175ab2455ea72a8274659af7066a2c97ba3aacce84531d8685d08b15d3619038997ae459ac916a88bedaf619f574236d1b86b02f29edaf78684c91c6ee45199b861359ee374fecb95be8a85dc012991d22564adeb2ec95f160574858fa010c40ce74077a08f0e681eb4b10a0093e885f115a12469a82b07012ad4e20b836d5711358c47969af89d09c9299edc540321fe897312ca49c9e8f93d50dc68394d0cc1d108f38e3534821b979c405c1f526a3b57651897873aeeb0909b176fb2034f9fdb1d43a8003809af29ff0bdc456a593029c4526b270908ac94b620a7cb8b7da20a6421e0f2671c899c20d78e1e0a1c3ab0b92948c90fca3c36d21a5e53143bc7e061773251364f8ce3b8992b6313c9604dc19c018b9efc6ca8f7c1fe039077fd76775461d1fa3968f51be7e340e3f09b40d6b44c77a7cbf7d71cad2ddea1121b31d27470a38cda8f8d38170a0d8f0b02d56f8e97b2134597d6111ea6670545bd4f7b4e4d6d7cf2fb5b787a68ba8ee84775f06db195f47282d9646dfbdbb57701e2ef5a432b621cb54a70e94de6b7a3f95bfe3c50793e08a27f76f832070fb2d23ed19dcd75f798aeff0c3e76d8215d43e1a8b7e643bffa243691adf2abcd52f465390e92e0344e2f452673f12d50e2ead0496ba76504ae0f78c81f2a2b5a64b39d3fb35f39f178b9a1587d1f07ed28e7696bfc8740f429f6cc35c964ae04ef39c1070eab6415be3aab887ff6192ac4d49ba9b169221b47d73c55f6010dda07a77cbcf54b779d380591786ba70c6d7000af57034539487f801aeb5c097939682e1530bc26c0b030bcab327ddaaaac5c9b969301b6d4ed7f601a46e8431e8cae3800c80c42686fee3b7625742798ced5976d163d2c8aad1bdac36c001e4e246fdb7b4c6850ed99554cfc0c07b7c7acc7659fd042989cc291ec2bd03a59e439860a5c48e430780f9d85c9acb3e85e741e73163f29afb7c43f143e7ada99a4670cbbe2210bfce8d36ee86.a5237f2d798c9f98b26a676794d3c3f6.0f15d0f53657150aeb1462d5'
416
- // const output = decrypt(value, encryptionKey, assocData)
417
- // console.log(output)
418
- // *** TOTP *** //
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@1auth/crypto",
3
- "version": "0.0.0-alpha.31",
3
+ "version": "0.0.0-alpha.33",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "engines": {
7
- "node": ">=16"
7
+ "node": ">=20"
8
8
  },
9
9
  "engineStrict": true,
10
10
  "publishConfig": {
@@ -44,7 +44,7 @@
44
44
  "url": "https://github.com/willfarrell/1auth/issues"
45
45
  },
46
46
  "homepage": "https://github.com/willfarrell/1auth",
47
- "gitHead": "246b0b521e6d136d8f37ee7d9781ffc8ccc987bd",
47
+ "gitHead": "14b8c5bd83728c460fdcc4c3af5ae5c3c2bb9007",
48
48
  "dependencies": {
49
49
  "@node-rs/argon2": "1.8.3"
50
50
  }