@1auth/crypto 0.0.0-alpha.32 → 0.0.0-alpha.34

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 +265 -283
  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,134 @@ 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)
135
+ create: (prefix) =>
136
+ (prefix ? prefix + '_' : '') + randomAlphaNumeric(randomId.minLength)
178
137
  }
179
138
 
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)
139
+ // *** Digests *** //
140
+ export const createChecksum = (value, { algorithm } = {}) => {
141
+ algorithm ??= options.digestAlgorithm
142
+ return checksum(algorithm).update(value).digest('hex')
191
143
  }
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)
144
+ export const createDigest = (value, { algorithm } = {}) => {
145
+ algorithm ??= options.digestAlgorithm
146
+ const checksum = createChecksum(value, { algorithm })
147
+ return `${algorithm}:${checksum}`
148
+ }
149
+
150
+ // TODO evaluate non-iv encryption approach?
151
+ // Use encryption as pepper to allow easier rotation of pepper
152
+ export const createEncryptedDigest = (value, { algorithm } = {}) => {
153
+ const digest = createDigest(value, { algorithm })
154
+ // encrypting using the symetricEncryptionKey instread of
155
+ // the row encryptionKey to allow lookup, must have fixed iv
156
+ return symetricEncrypt(digest, {
157
+ encryptionKey: options.symetricEncryptionKey,
158
+ sub: '',
159
+ encoding: options.symetricEncryptionEncoding,
160
+ iv: Buffer.from(
161
+ options.symetricEncryptionKey.substring(
162
+ 0,
163
+ symetricEncryptionEncodingLengths.iv
164
+ ),
165
+ options.symetricEncryptionEncoding
166
+ )
167
+ })
204
168
  }
205
169
 
206
- // *** Helpers *** //
207
- export const characterLengthToEntropy = (
208
- characterLength,
209
- characterPoolSize
170
+ export const rotateDigestEncryption = (
171
+ encryptedValue,
172
+ encryptionKey,
173
+ newEncryptionKey
210
174
  ) => {
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))
218
- }
175
+ const digest = symetricDecrypt(encryptedValue, {
176
+ encryptionKey,
177
+ sub: '',
178
+ encoding: options.symetricEncryptionEncoding
179
+ })
219
180
 
220
- // *** Digests *** //
221
- export const createDigest = async (value, { algorithm, salt } = {}) => {
222
- algorithm ??= options.digestAlgorithm
223
- salt ??= options.digestSalt
224
- const hash = checksum(algorithm)
225
- .update(value + salt)
226
- .digest('hex')
227
- return `${algorithm}:${hash}`
181
+ return symetricEncrypt(digest, {
182
+ encryptionKey: newEncryptionKey,
183
+ sub: '',
184
+ encoding: options.symetricEncryptionEncoding,
185
+ iv: Buffer.from(
186
+ newEncryptionKey.substring(0, symetricEncryptionEncodingLengths.iv),
187
+ options.symetricEncryptionEncoding
188
+ )
189
+ })
228
190
  }
229
191
 
230
192
  // *** Hashing *** //
@@ -249,124 +211,156 @@ export const verifySecretHash = async (hash, value) => {
249
211
  // *** Encryption *** //
250
212
  const authTagLength = 16
251
213
 
252
- export const makeSymetricKey = (assocData) => {
253
- if (!options.encryptionSharedKey) {
214
+ export const makeSymetricKey = (sub) => {
215
+ if (!options.symetricEncryptionKey) {
254
216
  return { encryptionKey: '', encryptedKey: '' }
255
217
  }
256
- const encryptionKey = randomBytes(32)
257
- const encryptedKey = __encrypt(
258
- encryptionKey,
259
- Buffer.from(options.encryptionSharedKey, 'hex'),
260
- assocData,
261
- 'hex',
262
- 'hex'
263
- )
218
+ const encryptionKey = randomSymetricEncryptionKey()
219
+ const encryptedKey = symetricEncrypt(encryptionKey, {
220
+ encryptionKey: options.symetricEncryptionKey,
221
+ sub,
222
+ decoding: 'base64',
223
+ encoding: options.symetricEncryptionEncoding
224
+ })
264
225
  return { encryptionKey, encryptedKey }
265
226
  }
266
227
 
267
- // assocData = sub or id
268
- export const encryptFields = (values, encryptedKey, assocData, fields = []) => {
269
- // TODO optimize: don't decrypt encryptedKey more than once
228
+ // sub add context to encryption
229
+ export const symetricEncryptFields = (
230
+ values,
231
+ { encryptedKey, encryptionKey, sub },
232
+ fields = []
233
+ ) => {
234
+ if (encryptedKey) {
235
+ encryptionKey ??= symetricDecryptKey(encryptedKey, {
236
+ sub
237
+ })
238
+ }
239
+ if (!encryptionKey) return values
240
+ const encryptedValues = structuredClone(values)
270
241
  for (const key of fields) {
271
- values[key] &&= encrypt(values[key], encryptedKey, assocData)
242
+ encryptedValues[key] &&= symetricEncrypt(encryptedValues[key], {
243
+ encryptionKey,
244
+ sub
245
+ })
272
246
  }
273
- return values
247
+ return encryptedValues
274
248
  }
275
249
 
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 = (
250
+ export const symetricEncrypt = (
290
251
  data,
291
- encryptionKey,
292
- assocData,
293
- decoding = 'utf8',
294
- encoding = 'hex'
252
+ { encryptedKey, encryptionKey, sub, decoding, encoding, iv }
295
253
  ) => {
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'))
254
+ if (encryptedKey) {
255
+ encryptionKey ??= symetricDecryptKey(encryptedKey, {
256
+ sub
257
+ })
258
+ }
259
+ if (!encryptionKey) return data
260
+ decoding ??= 'utf8'
261
+ encoding ??= options.symetricEncryptionEncoding
262
+ iv ??= randomBytes(12) // 96 bits
263
+
264
+ const cipher = createCipheriv(
265
+ options.symetricEncryptionMethod,
266
+ Buffer.from(encryptionKey, 'base64'),
267
+ iv,
268
+ {
269
+ authTagLength
270
+ }
271
+ )
272
+ cipher.setAAD(Buffer.from(sub ?? '', 'utf8'))
301
273
  const encryptedData =
302
274
  cipher.update(data, decoding, encoding) + cipher.final(encoding)
303
275
  const authTag = cipher.getAuthTag()
304
- return (
305
- iv.toString(encoding) + // 24 char
306
- authTag.toString(encoding) + // 32 char
307
- encryptedData
308
- )
276
+
277
+ const encryptedDataPacket =
278
+ iv.toString(encoding) + authTag.toString(encoding) + encryptedData
279
+
280
+ return encryptedDataPacket
309
281
  }
310
282
 
311
- export const decryptFields = (values, encryptedKey, assocData, fields = []) => {
312
- // TODO optimize: don't decrypt encryptedKey more than once
283
+ export const symetricDecryptFields = (
284
+ encryptedValues,
285
+ { encryptedKey, encryptionKey, sub },
286
+ fields = []
287
+ ) => {
288
+ if (encryptedKey) {
289
+ encryptionKey ??= symetricDecryptKey(encryptedKey, {
290
+ sub
291
+ })
292
+ }
293
+ if (!encryptionKey) return encryptedValues
294
+ const values = structuredClone(encryptedValues)
313
295
  for (const key of fields) {
314
- values[key] &&= decrypt(values[key], encryptedKey, assocData)
296
+ values[key] &&= symetricDecrypt(values[key], {
297
+ encryptionKey,
298
+ sub
299
+ })
315
300
  }
316
301
  return values
317
302
  }
318
303
 
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
304
+ export const symetricDecryptKey = (encryptedKey, { sub } = {}) => {
305
+ return symetricDecrypt(encryptedKey, {
306
+ encryptionKey: options.symetricEncryptionKey,
307
+ sub,
308
+ decoding: options.symetricEncryptionEncoding,
309
+ encoding: 'base64'
310
+ })
330
311
  }
331
312
 
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'
313
+ export const symetricDecrypt = (
314
+ encryptedDataPacket,
315
+ { encryptedKey, encryptionKey, sub, decoding, encoding }
347
316
  ) => {
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)
317
+ if (encryptedKey) {
318
+ encryptionKey ??= symetricDecryptKey(encryptedKey, {
319
+ sub
320
+ })
321
+ }
322
+ if (!encryptionKey) return encryptedDataPacket
323
+ decoding ??= options.symetricEncryptionEncoding
324
+ encoding ??= 'utf8'
325
+
326
+ const iv = Buffer.from(
327
+ encryptedDataPacket.substring(0, symetricEncryptionEncodingLengths.iv),
328
+ decoding
329
+ )
330
+ const authTag = Buffer.from(
331
+ encryptedDataPacket.substring(
332
+ symetricEncryptionEncodingLengths.iv,
333
+ symetricEncryptionEncodingLengths.ivAndAuthTag
334
+ ),
335
+ decoding
336
+ )
337
+ const encryptedData = Buffer.from(
338
+ encryptedDataPacket.substring(
339
+ symetricEncryptionEncodingLengths.ivAndAuthTag
340
+ ),
341
+ decoding
342
+ )
351
343
 
352
344
  const decipher = createDecipheriv(
353
- options.encryptionMethod,
354
- encryptionKey,
345
+ options.symetricEncryptionMethod,
346
+ Buffer.from(encryptionKey, 'base64'),
355
347
  iv,
356
348
  {
357
349
  authTagLength
358
350
  }
359
351
  )
360
- decipher.setAAD(Buffer.from(assocData, 'utf8'))
352
+ decipher.setAAD(Buffer.from(sub ?? '', 'utf8'))
353
+
361
354
  decipher.setAuthTag(authTag)
362
- return (
355
+ const data =
363
356
  decipher.update(encryptedData, decoding, encoding) +
364
357
  decipher.final(encoding)
365
- )
358
+ return data
366
359
  }
367
360
 
368
361
  // *** Signatures *** //
369
- export const makeAsymmetricKeys = async (encryptionKey) => {
362
+ // asymmetricKeyPairType
363
+ export const makeAsymmetricKeys = async () => {
370
364
  const { publicKey, privateKey } = await generateKeyPair('ec', {
371
365
  namedCurve: 'P-384', // P-512
372
366
  paramEncoding: 'named',
@@ -376,44 +370,32 @@ export const makeAsymmetricKeys = async (encryptionKey) => {
376
370
  },
377
371
  privateKeyEncoding: {
378
372
  type: 'sec1',
379
- format: 'pem',
380
- // TODO remove encryption for other with sub check?
381
- cipher: options.encryptionMethod,
382
- passphrase: encryptionKey
373
+ format: 'pem'
374
+ // Encryption done at another level for consistency
375
+ // cipher: options.asymetricEncryptionMethod,
376
+ // passphrase: encryptionKey,
383
377
  }
384
378
  })
385
379
  return { publicKey, privateKey }
386
380
  }
387
381
 
388
- export const makeSignature = (data, privateKey, algorithm = 'SHA3-384') => {
389
- return sign(algorithm, Buffer.from(data), privateKey).toString('base64')
382
+ export const makeSignature = async (data, privateKey, { algorithm } = {}) => {
383
+ algorithm ??= options.digestAlgorithm
384
+ return (await sign(algorithm, Buffer.from(data), privateKey)).toString(
385
+ options.signatureEncoding
386
+ )
390
387
  }
391
- export const verifySignature = (
388
+ export const verifySignature = async (
392
389
  data,
393
390
  publicKey,
394
391
  signature,
395
- algorithm = 'SHA3-384'
392
+ { algorithm } = {}
396
393
  ) => {
397
- return verify(
394
+ algorithm ??= options.digestAlgorithm
395
+ return await verify(
398
396
  algorithm,
399
397
  Buffer.from(data),
400
398
  publicKey,
401
- Buffer.from(signature, 'base64')
399
+ Buffer.from(signature, options.signatureEncoding)
402
400
  )
403
401
  }
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.34",
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": "c88105a99efd7f3de80795736d6194e52ef465b4",
48
48
  "dependencies": {
49
49
  "@node-rs/argon2": "1.8.3"
50
50
  }