@1auth/crypto 0.0.0-alpha.32 → 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 -286
  2. package/package.json +3 -3
package/index.js CHANGED
@@ -5,27 +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
- encryptionContextKey: null,
17
- encryptionSharedKey: '',
18
- encryptionMethod: 'chacha20-poly1305', // AES-256 GCM (aes-256-gcm) or ChaCha20-Poly1305 (chacha20-poly1305)
19
-
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',
20
24
  digestAlgorithm: 'sha3-384',
21
- digestSalt: ''
22
- }
23
-
24
- export default (params) => {
25
- 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
+ }
26
42
  }
27
43
 
28
- const generateKeyPair = promisify(generateKeyPairCallback)
44
+ export const getOptions = () => options
29
45
 
30
46
  // *** entropy *** //
31
47
  // export const characterPoolSize = (value) => {
@@ -43,188 +59,107 @@ const generateKeyPair = promisify(generateKeyPairCallback)
43
59
  // return max - min
44
60
  // }
45
61
 
46
- // *** Random generators *** //
47
- export const characterPoolSize = {
48
- keyboard: 94, // (26 + 10 + 11) * 2
49
- alphaNumeric: 62, // (26 + 10) * 2
50
- base64: 64, // (26 * 2 + 10 + 2
51
- hex: 16,
52
- 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))
53
67
  }
54
- // Alt: https://github.com/sindresorhus/crypto-random-string/blob/main/core.js
55
- export const randomAlphaNumeric = (bits) => {
56
- const characterLength = entropyToCharacterLength(
57
- bits,
58
- characterPoolSize.alphaNumeric
59
- )
60
- return randomBytes(characterLength * 2)
61
- .toString('base64')
62
- .replace(/[^a-zA-Z0-9]/g, '')
63
- .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
64
116
  }
65
117
 
66
- export const randomBase64 = (bits) => {
67
- const characterLength = entropyToCharacterLength(
68
- bits,
69
- characterPoolSize.base64
70
- )
71
- return randomBytes(characterLength + 1)
72
- .toString('base64')
73
- .replace('=', '')
118
+ export const randomAlphaNumeric = (characterLength) => {
119
+ return randomCharacters(characterLength, charactersAlphaNumeric)
74
120
  }
75
121
 
76
- export const randomNumeric = (bits) => {
77
- const characterLength = entropyToCharacterLength(
78
- bits,
79
- characterPoolSize.numeric
80
- )
81
- const max = 10 ** characterLength
82
- let value = Math.floor(Math.random() * max).toString()
83
- if (value === max.toString()) {
84
- return randomNumeric(bits)
85
- }
86
- while (value.length < characterLength) value = '0' + value
87
- return value
122
+ export const randomNumeric = (characterLength) => {
123
+ return randomCharacters(characterLength, charactersNumeric)
88
124
  }
89
125
 
90
- export const randomHex = (bits) => {
91
- const characterLength = entropyToCharacterLength(bits, characterPoolSize.hex)
92
- return randomBytes(characterLength).toString('hex')
126
+ export const randomSymetricEncryptionKey = () => {
127
+ return randomBytes(32).toString('base64') // 256 bits
93
128
  }
94
129
 
95
130
  // *** configs *** //
96
131
  export const randomId = {
97
132
  type: 'id',
98
- entropy: 64,
99
- charPool: characterPoolSize.alphaNumeric,
133
+ minLength: entropyToCharacterLength(64, charactersAlphaNumeric.length),
100
134
  // TODO update to use https://github.com/jetpack-io/typeid
101
- create: async (prefix) =>
102
- (prefix ? prefix + '_' : '') + randomAlphaNumeric(randomId.entropy)
103
- }
104
-
105
- export const subject = {
106
- type: 'id',
107
- entropy: 64,
108
- charPool: characterPoolSize.alphaNumeric,
109
- create: async (prefix) =>
110
- (prefix ? prefix + '_' : '') + randomAlphaNumeric(subject.entropy)
111
- }
112
-
113
- export const session = {
114
- type: 'id',
115
- entropy: 128, // ASVS 3.2.2
116
- charPool: characterPoolSize.alphaNumeric,
117
- expire: 15 * 60,
118
- create: async (prefix) =>
119
- (prefix ? prefix + '_' : '') + randomAlphaNumeric(session.entropy)
120
- }
121
-
122
- export const passwordSecret = {
123
- type: 'secret',
124
- entropy: 64,
125
- charPool: characterPoolSize.keyboard,
126
- otp: false,
127
- encode: async (value, encryptedKey, sub) =>
128
- createSecretHash(value).then((hash) => encrypt(hash, encryptedKey, sub)),
129
- decode: async (value, encryptedKey, sub) => decrypt(value, encryptedKey, sub),
130
- verify: async (value, hash) => verifySecretHash(hash, value)
131
- }
132
-
133
- // aka Password/Credential Recovery
134
- export const passwordToken = {
135
- type: 'token',
136
- entropy: 20,
137
- charPool: characterPoolSize.numeric,
138
- otp: true,
139
- expire: 30,
140
- create: async () => randomNumeric(passwordToken.entropy),
141
- encode: async (value, encryptedKey, sub) =>
142
- createSecretHash(value).then((hash) => encrypt(hash, encryptedKey, sub)),
143
- decode: async (value, encryptedKey, sub) => decrypt(value, encryptedKey, sub),
144
- verify: async (value, hash) => verifySecretHash(hash, value)
145
- }
146
-
147
- export const oneTimeSecret = {
148
- type: 'secret',
149
- entropy: 64, //
150
- charPool: characterPoolSize.base64,
151
- otp: false,
152
- expire: null,
153
- create: async () => randomBase64(oneTimeSecret.entropy),
154
- encode: async (value, encryptedKey, sub) => encrypt(value, encryptedKey, sub),
155
- decode: async (value, encryptedKey, sub) => decrypt(value, encryptedKey, sub)
156
- // create, hash, verify to be handled within
157
- }
158
- export const oneTimeToken = {
159
- type: 'token',
160
- entropy: 20,
161
- charPool: characterPoolSize.numeric,
162
- otp: true,
163
- expire: 30
164
- // create, hash, verify to be handled within
165
- }
166
-
167
- // aka lookup secret
168
- export const recoveryCode = {
169
- type: 'secret',
170
- entropy: 112,
171
- charPool: characterPoolSize.alphaNumeric,
172
- otp: true,
173
- create: async () => randomAlphaNumeric(recoveryCode.entropy),
174
- encode: async (value, encryptedKey, sub) =>
175
- createSecretHash(value).then((hash) => encrypt(hash, encryptedKey, sub)),
176
- decode: async (value, encryptedKey, sub) => decrypt(value, encryptedKey, sub),
177
- verify: async (value, hash) => verifySecretHash(hash, value)
178
- }
179
-
180
- export const outOfBandToken = {
181
- type: 'token',
182
- entropy: 20,
183
- charPool: characterPoolSize.numeric,
184
- otp: true,
185
- expire: 10 * 60,
186
- create: async () => randomNumeric(outOfBandToken.entropy),
187
- encode: async (value, encryptedKey, sub) =>
188
- createSecretHash(value).then((hash) => encrypt(hash, encryptedKey, sub)),
189
- decode: async (value, encryptedKey, sub) => decrypt(value, encryptedKey, sub),
190
- verify: async (value, hash) => verifySecretHash(hash, value)
191
- }
192
-
193
- export const accessToken = {
194
- type: 'secret',
195
- entropy: 112,
196
- charPool: characterPoolSize.alphaNumeric,
197
- otp: false,
198
- expire: 30 * 24 * 60 * 60, // allow override from user
199
- create: async () => randomAlphaNumeric(accessToken.entropy),
200
- encode: async (value, encryptedKey, sub) =>
201
- createSecretHash(value).then((hash) => encrypt(hash, encryptedKey, sub)),
202
- decode: async (value, encryptedKey, sub) => decrypt(value, encryptedKey, sub),
203
- verify: async (value, hash) => verifySecretHash(hash, value)
204
- }
205
-
206
- // *** Helpers *** //
207
- export const characterLengthToEntropy = (
208
- characterLength,
209
- characterPoolSize
210
- ) => {
211
- // log_2(characterPoolSize^characterLength)
212
- return Math.round(Math.log2(characterPoolSize ** characterLength))
213
- }
214
-
215
- export const entropyToCharacterLength = (bits, characterPoolSize) => {
216
- // bits*ln(2)/ln(characterPoolSize)
217
- return Math.round((bits * Math.LN2) / Math.log(characterPoolSize))
135
+ create: (prefix) =>
136
+ (prefix ? prefix + '_' : '') + randomAlphaNumeric(randomId.minLength)
218
137
  }
219
138
 
220
139
  // *** Digests *** //
221
- export const createDigest = async (value, { algorithm, salt } = {}) => {
140
+ export const createDigest = (value, { algorithm } = {}) => {
222
141
  algorithm ??= options.digestAlgorithm
223
- salt ??= options.digestSalt
224
- const hash = checksum(algorithm)
225
- .update(value + salt)
226
- .digest('hex')
227
- 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
+ })
228
163
  }
229
164
 
230
165
  // *** Hashing *** //
@@ -249,124 +184,156 @@ export const verifySecretHash = async (hash, value) => {
249
184
  // *** Encryption *** //
250
185
  const authTagLength = 16
251
186
 
252
- export const makeSymetricKey = (assocData) => {
253
- if (!options.encryptionSharedKey) {
187
+ export const makeSymetricKey = (sub) => {
188
+ if (!options.symetricEncryptionKey) {
254
189
  return { encryptionKey: '', encryptedKey: '' }
255
190
  }
256
- const encryptionKey = randomBytes(32)
257
- const encryptedKey = __encrypt(
258
- encryptionKey,
259
- Buffer.from(options.encryptionSharedKey, 'hex'),
260
- assocData,
261
- 'hex',
262
- 'hex'
263
- )
191
+ const encryptionKey = randomSymetricEncryptionKey()
192
+ const encryptedKey = symetricEncrypt(encryptionKey, {
193
+ encryptionKey: options.symetricEncryptionKey,
194
+ sub,
195
+ decoding: 'base64',
196
+ encoding: options.symetricEncryptionEncoding
197
+ })
264
198
  return { encryptionKey, encryptedKey }
265
199
  }
266
200
 
267
- // assocData = sub or id
268
- export const encryptFields = (values, encryptedKey, assocData, fields = []) => {
269
- // 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)
270
214
  for (const key of fields) {
271
- values[key] &&= encrypt(values[key], encryptedKey, assocData)
215
+ encryptedValues[key] &&= symetricEncrypt(encryptedValues[key], {
216
+ encryptionKey,
217
+ sub
218
+ })
272
219
  }
273
- return values
220
+ return encryptedValues
274
221
  }
275
222
 
276
- export const encrypt = (data, encryptedKey, assocData) => {
277
- if (!encryptedKey) return data
278
-
279
- const encryptionKey = __decryptKey(encryptedKey, assocData)
280
- return __encrypt(
281
- data,
282
- Buffer.from(encryptionKey, 'hex'),
283
- assocData,
284
- 'utf8',
285
- 'hex'
286
- )
287
- }
288
-
289
- const __encrypt = (
223
+ export const symetricEncrypt = (
290
224
  data,
291
- encryptionKey,
292
- assocData,
293
- decoding = 'utf8',
294
- encoding = 'hex'
225
+ { encryptedKey, encryptionKey, sub, decoding, encoding, iv }
295
226
  ) => {
296
- const iv = randomBytes(12) // 96 bits
297
- const cipher = createCipheriv(options.encryptionMethod, encryptionKey, iv, {
298
- authTagLength
299
- })
300
- 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'))
301
246
  const encryptedData =
302
247
  cipher.update(data, decoding, encoding) + cipher.final(encoding)
303
248
  const authTag = cipher.getAuthTag()
304
- return (
305
- iv.toString(encoding) + // 24 char
306
- authTag.toString(encoding) + // 32 char
307
- encryptedData
308
- )
249
+
250
+ const encryptedDataPacket =
251
+ iv.toString(encoding) + authTag.toString(encoding) + encryptedData
252
+
253
+ return encryptedDataPacket
309
254
  }
310
255
 
311
- export const decryptFields = (values, encryptedKey, assocData, fields = []) => {
312
- // 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)
313
268
  for (const key of fields) {
314
- values[key] &&= decrypt(values[key], encryptedKey, assocData)
269
+ values[key] &&= symetricDecrypt(values[key], {
270
+ encryptionKey,
271
+ sub
272
+ })
315
273
  }
316
274
  return values
317
275
  }
318
276
 
319
- export const decrypt = (encryptedData, encryptedKey, assocData) => {
320
- if (!options.encryptionSharedKey || !encryptedKey) return encryptedData
321
- const encryptionKey = __decryptKey(encryptedKey, assocData)
322
- const data = __decrypt(
323
- encryptedData,
324
- Buffer.from(encryptionKey, 'hex'),
325
- assocData,
326
- 'hex',
327
- 'utf8'
328
- )
329
- 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
+ })
330
284
  }
331
285
 
332
- const __decryptKey = (encryptedKey, assocData) =>
333
- __decrypt(
334
- encryptedKey,
335
- Buffer.from(options.encryptionSharedKey, 'hex'),
336
- assocData,
337
- 'hex',
338
- 'hex'
339
- )
340
-
341
- const __decrypt = (
342
- data,
343
- encryptionKey,
344
- assocData,
345
- decoding = 'hex',
346
- encoding = 'utf8'
286
+ export const symetricDecrypt = (
287
+ encryptedDataPacket,
288
+ { encryptedKey, encryptionKey, sub, decoding, encoding }
347
289
  ) => {
348
- const iv = Buffer.from(data.substring(0, 24), decoding)
349
- const authTag = Buffer.from(data.substring(24, 56), decoding)
350
- 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
+ )
351
316
 
352
317
  const decipher = createDecipheriv(
353
- options.encryptionMethod,
354
- encryptionKey,
318
+ options.symetricEncryptionMethod,
319
+ Buffer.from(encryptionKey, 'base64'),
355
320
  iv,
356
321
  {
357
322
  authTagLength
358
323
  }
359
324
  )
360
- decipher.setAAD(Buffer.from(assocData, 'utf8'))
325
+ decipher.setAAD(Buffer.from(sub ?? '', 'utf8'))
326
+
361
327
  decipher.setAuthTag(authTag)
362
- return (
328
+ const data =
363
329
  decipher.update(encryptedData, decoding, encoding) +
364
330
  decipher.final(encoding)
365
- )
331
+ return data
366
332
  }
367
333
 
368
334
  // *** Signatures *** //
369
- export const makeAsymmetricKeys = async (encryptionKey) => {
335
+ // asymmetricKeyPairType
336
+ export const makeAsymmetricKeys = async () => {
370
337
  const { publicKey, privateKey } = await generateKeyPair('ec', {
371
338
  namedCurve: 'P-384', // P-512
372
339
  paramEncoding: 'named',
@@ -376,44 +343,32 @@ export const makeAsymmetricKeys = async (encryptionKey) => {
376
343
  },
377
344
  privateKeyEncoding: {
378
345
  type: 'sec1',
379
- format: 'pem',
380
- // TODO remove encryption for other with sub check?
381
- cipher: options.encryptionMethod,
382
- passphrase: encryptionKey
346
+ format: 'pem'
347
+ // Encryption done at another level for consistency
348
+ // cipher: options.asymetricEncryptionMethod,
349
+ // passphrase: encryptionKey,
383
350
  }
384
351
  })
385
352
  return { publicKey, privateKey }
386
353
  }
387
354
 
388
- export const makeSignature = (data, privateKey, algorithm = 'SHA3-384') => {
389
- 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
+ )
390
360
  }
391
- export const verifySignature = (
361
+ export const verifySignature = async (
392
362
  data,
393
363
  publicKey,
394
364
  signature,
395
- algorithm = 'SHA3-384'
365
+ { algorithm } = {}
396
366
  ) => {
397
- return verify(
367
+ algorithm ??= options.digestAlgorithm
368
+ return await verify(
398
369
  algorithm,
399
370
  Buffer.from(data),
400
371
  publicKey,
401
- Buffer.from(signature, 'base64')
372
+ Buffer.from(signature, options.signatureEncoding)
402
373
  )
403
374
  }
404
- // const assocData = 'sub'
405
- // const input = 'data'
406
- //
407
- // const {encryptedKey} = makeSymetricKey(assocData)
408
- // const encryptedData = encrypt(input, encryptedKey, assocData)
409
- // const output = decrypt(encryptedData, encryptedKey, assocData)
410
- // console.log(assocData, input, output, encryptedData)
411
-
412
- // const assocData = 'tlSIcVp1XEF'
413
- // const encryptionKey =
414
- // 'b9ebfdab6603dd8e151138ec8298aaf8b49bf6d38480f9864e9e72e65c4d8b59.b9f9bc89d7f3ce4aa1e1af469d10508b.aa1b6a682fcc186e867a9cfd'
415
- // const value =
416
- // '76ebdea75ea529c16f1645d5435413934cbb97378293776cb446331e6d8323865a808b7f0822cd4f36ef6cca57354ea7c955c94d232a55038321184f4294971315fda4b8dc2f33422bbd3a5c978edc0f5bf019f818f0c92f7c570bdc49fe2f71df3856655198b6723fa52697b9225b2e79f04ed80cd35ef61a8e1e06c3751d3f9caa40aa9a41528ce5ab1bfae8ecff0feab784497ccbf2c7dca4461c6b9a74d1ded6233dc38ad75d0fe2f57cfda2bd1d59ed1f8c53de911cf8071dc7cefde7870c303137586bc0c5f85fe93505d9056994a4d8e59df2027b564c303aa723e98ae5934b15039f90d21827ac22b824593f334466622582a2857f04d8bf450310a9924060d113d2ece0259da68376b31a3c2e8a0b79e81f8efe96bf2b7a6b5b1841edca2566a0a89ab80ee6d6ac2ed24e788ad318a1238dfa5b9e965d256935d3aeafe52f986a530b2f9225bbe7a73b43e6515ce789701f501546239460bccc46285f3fcff0c54c2b6df820334a974abea81460fd4ac99a13cb88e296a2275f80f4c783757319417078458977461dd5e101f9f9b7d303578379dc15ee1b549e3fcceffffba895ecc8291d1f82e150ce8e10640fd79f2e0666167ef7d529cd28cb76a72bf2b3e239dbb845bedd39f42c938bbe711542231fb835edb547d919b3c695272f4cd43640eb3bed2b86948278e5aeeb67ef932ef08332730e75752fd5bd247e2dd30470fc493362d2ecac72237dfbf0a1694f8e6b8c18ab24c71eb723a3f610a056a73fea90f4f8660bfc6dec46fa52a55a3d72a5c9b97770bff7d52ea91b97cc643d915341642e201918fcb088986e9134e133519c6575048e3f840622e569fc5fa66e4f0c31681c9de4b1b1f6acb179728bc0a9f9950bf2e0c8d49da835298013977a2f97d7052bcbedbc39b875bbf9a0622ede589810175ab2455ea72a8274659af7066a2c97ba3aacce84531d8685d08b15d3619038997ae459ac916a88bedaf619f574236d1b86b02f29edaf78684c91c6ee45199b861359ee374fecb95be8a85dc012991d22564adeb2ec95f160574858fa010c40ce74077a08f0e681eb4b10a0093e885f115a12469a82b07012ad4e20b836d5711358c47969af89d09c9299edc540321fe897312ca49c9e8f93d50dc68394d0cc1d108f38e3534821b979c405c1f526a3b57651897873aeeb0909b176fb2034f9fdb1d43a8003809af29ff0bdc456a593029c4526b270908ac94b620a7cb8b7da20a6421e0f2671c899c20d78e1e0a1c3ab0b92948c90fca3c36d21a5e53143bc7e061773251364f8ce3b8992b6313c9604dc19c018b9efc6ca8f7c1fe039077fd76775461d1fa3968f51be7e340e3f09b40d6b44c77a7cbf7d71cad2ddea1121b31d27470a38cda8f8d38170a0d8f0b02d56f8e97b2134597d6111ea6670545bd4f7b4e4d6d7cf2fb5b787a68ba8ee84775f06db195f47282d9646dfbdbb57701e2ef5a432b621cb54a70e94de6b7a3f95bfe3c50793e08a27f76f832070fb2d23ed19dcd75f798aeff0c3e76d8215d43e1a8b7e643bffa243691adf2abcd52f465390e92e0344e2f452673f12d50e2ead0496ba76504ae0f78c81f2a2b5a64b39d3fb35f39f178b9a1587d1f07ed28e7696bfc8740f429f6cc35c964ae04ef39c1070eab6415be3aab887ff6192ac4d49ba9b169221b47d73c55f6010dda07a77cbcf54b779d380591786ba70c6d7000af57034539487f801aeb5c097939682e1530bc26c0b030bcab327ddaaaac5c9b969301b6d4ed7f601a46e8431e8cae3800c80c42686fee3b7625742798ced5976d163d2c8aad1bdac36c001e4e246fdb7b4c6850ed99554cfc0c07b7c7acc7659fd042989cc291ec2bd03a59e439860a5c48e430780f9d85c9acb3e85e741e73163f29afb7c43f143e7ada99a4670cbbe2210bfce8d36ee86.a5237f2d798c9f98b26a676794d3c3f6.0f15d0f53657150aeb1462d5'
417
- // const output = decrypt(value, encryptionKey, assocData)
418
- // console.log(output)
419
- // *** TOTP *** //
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@1auth/crypto",
3
- "version": "0.0.0-alpha.32",
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": "3750bef3d7e376c48f7d680e5f2181ee809213b9",
47
+ "gitHead": "14b8c5bd83728c460fdcc4c3af5ae5c3c2bb9007",
48
48
  "dependencies": {
49
49
  "@node-rs/argon2": "1.8.3"
50
50
  }