@1auth/crypto 0.0.0-alpha.4 → 0.0.0-alpha.40

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 (3) hide show
  1. package/index.js +271 -270
  2. package/package.json +4 -8
  3. package/LICENSE +0 -21
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
-
19
- digestAlgorithm: 'sha3-256',
20
- digestSalt: ''
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',
24
+ digestAlgorithm: 'sha3-384',
25
+ signatureEncoding: 'base64'
21
26
  }
22
-
23
- export default (params) => {
24
- Object.assign(options, params)
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,184 +59,134 @@ 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 + 10) * 2 + 2
50
- hex: 16,
51
- numeric: 10
52
- }
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)
63
- }
64
-
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('=', '')
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))
73
67
  }
68
+ /* export const characterLengthToEntropy = (
69
+ characterLength,
70
+ characterPoolSize,
71
+ ) => {
72
+ // log_2(characterPoolSize^characterLength)
73
+ return Math.floor(Math.log2(characterPoolSize ** characterLength));
74
+ }; */
74
75
 
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)
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
+ }
84
113
  }
85
- while (value.length < characterLength) value = '0' + value
86
- return value
87
- }
88
114
 
89
- export const randomHex = (bits) => {
90
- const characterLength = entropyToCharacterLength(bits, characterPoolSize.hex)
91
- return randomBytes(characterLength).toString('hex')
115
+ return string
92
116
  }
93
117
 
94
- // *** configs *** //
95
- export const randomId = {
96
- type: 'id',
97
- entropy: 64,
98
- charPool: characterPoolSize.alphaNumeric,
99
- create: async () => randomAlphaNumeric(randomId.entropy)
118
+ export const randomAlphaNumeric = (characterLength) => {
119
+ return randomCharacters(characterLength, charactersAlphaNumeric)
100
120
  }
101
121
 
102
- export const subject = {
103
- type: 'id',
104
- entropy: 64,
105
- charPool: characterPoolSize.alphaNumeric,
106
- create: async () => randomAlphaNumeric(subject.entropy)
107
- }
108
-
109
- export const session = {
110
- type: 'id',
111
- entropy: 128, // ASVS 3.2.2
112
- charPool: characterPoolSize.alphaNumeric,
113
- expire: 15 * 60,
114
- create: async () => randomAlphaNumeric(session.entropy)
115
- }
116
-
117
- export const passwordSecret = {
118
- type: 'secret',
119
- entropy: 64,
120
- charPool: characterPoolSize.keyboard,
121
- otp: false,
122
- encode: async (value, encryptedKey, sub) =>
123
- createSecretHash(value).then((hash) => encrypt(hash, encryptedKey, sub)),
124
- decode: async (value, encryptedKey, sub) => decrypt(value, encryptedKey, sub),
125
- verify: async (value, hash) => verifySecretHash(hash, value)
122
+ export const randomNumeric = (characterLength) => {
123
+ return randomCharacters(characterLength, charactersNumeric)
126
124
  }
127
125
 
128
- // aka Password/Credential Recovery
129
- export const passwordToken = {
130
- type: 'token',
131
- entropy: 20,
132
- charPool: characterPoolSize.numeric,
133
- otp: true,
134
- expire: 30,
135
- create: async () => randomNumeric(passwordToken.entropy),
136
- encode: async (value, encryptedKey, sub) =>
137
- createSecretHash(value).then((hash) => encrypt(hash, encryptedKey, sub)),
138
- decode: async (value, encryptedKey, sub) => decrypt(value, encryptedKey, sub),
139
- verify: async (value, hash) => verifySecretHash(hash, value)
126
+ export const randomSymetricEncryptionKey = () => {
127
+ return randomBytes(32).toString('base64') // 256 bits
140
128
  }
141
129
 
142
- export const oneTimeSecret = {
143
- type: 'secret',
144
- entropy: 64, //
145
- charPool: characterPoolSize.base64,
146
- otp: false,
147
- expire: null,
148
- create: async () => randomBase64(oneTimeSecret.entropy),
149
- encode: async (value, encryptedKey, sub) => encrypt(value, encryptedKey, sub),
150
- decode: async (value, encryptedKey, sub) => decrypt(value, encryptedKey, sub)
151
- // create, hash, verify to be handled within
152
- }
153
- export const oneTimeToken = {
154
- type: 'token',
155
- entropy: 20,
156
- charPool: characterPoolSize.numeric,
157
- otp: true,
158
- expire: 30
159
- // create, hash, verify to be handled within
130
+ // *** configs *** //
131
+ export const randomId = {
132
+ type: 'id',
133
+ minLength: entropyToCharacterLength(64, charactersAlphaNumeric.length),
134
+ // TODO update to use https://github.com/jetpack-io/typeid
135
+ create: (prefix) =>
136
+ (prefix ? prefix + '_' : '') + randomAlphaNumeric(randomId.minLength)
160
137
  }
161
138
 
162
- // aka lookup secret
163
- export const recoveryCode = {
164
- type: 'secret',
165
- entropy: 112,
166
- charPool: characterPoolSize.alphaNumeric,
167
- otp: true,
168
- create: async () => randomAlphaNumeric(recoveryCode.entropy),
169
- encode: async (value, encryptedKey, sub) =>
170
- createSecretHash(value).then((hash) => encrypt(hash, encryptedKey, sub)),
171
- decode: async (value, encryptedKey, sub) => decrypt(value, encryptedKey, sub),
172
- 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')
173
143
  }
174
-
175
- export const outOfBandToken = {
176
- type: 'token',
177
- entropy: 20,
178
- charPool: characterPoolSize.numeric,
179
- otp: true,
180
- expire: 10 * 60,
181
- create: async () => randomNumeric(outOfBandToken.entropy),
182
- encode: async (value, encryptedKey, sub) =>
183
- createSecretHash(value).then((hash) => encrypt(hash, encryptedKey, sub)),
184
- decode: async (value, encryptedKey, sub) => decrypt(value, encryptedKey, sub),
185
- 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}`
186
148
  }
187
149
 
188
- export const accessToken = {
189
- type: 'secret',
190
- entropy: 112,
191
- charPool: characterPoolSize.alphaNumeric,
192
- otp: false,
193
- expire: 30 * 24 * 60 * 60, // allow override from user
194
- create: async () => randomAlphaNumeric(accessToken.entropy),
195
- encode: async (value, encryptedKey, sub) =>
196
- createSecretHash(value).then((hash) => encrypt(hash, encryptedKey, sub)),
197
- decode: async (value, encryptedKey, sub) => decrypt(value, encryptedKey, sub),
198
- verify: async (value, hash) => verifySecretHash(hash, value)
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
+ })
199
168
  }
200
169
 
201
- // *** Helpers *** //
202
- export const characterLengthToEntropy = (
203
- characterLength,
204
- characterPoolSize
170
+ export const rotateDigestEncryption = (
171
+ encryptedValue,
172
+ encryptionKey,
173
+ newEncryptionKey
205
174
  ) => {
206
- // log_2(characterPoolSize^characterLength)
207
- return Math.round(Math.log2(characterPoolSize ** characterLength))
208
- }
209
-
210
- export const entropyToCharacterLength = (bits, characterPoolSize) => {
211
- // bits*ln(2)/ln(characterPoolSize)
212
- return Math.round((bits * Math.LN2) / Math.log(characterPoolSize))
213
- }
175
+ const digest = symetricDecrypt(encryptedValue, {
176
+ encryptionKey,
177
+ sub: '',
178
+ encoding: options.symetricEncryptionEncoding
179
+ })
214
180
 
215
- // *** Digests *** //
216
- export const createDigest = async (value, { algorithm, salt } = {}) => {
217
- algorithm ??= options.digestAlgorithm
218
- salt ??= options.digestSalt
219
- const hash = checksum(algorithm)
220
- .update(value + salt)
221
- .digest('hex')
222
- 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
+ })
223
190
  }
224
191
 
225
192
  // *** Hashing *** //
@@ -244,110 +211,156 @@ export const verifySecretHash = async (hash, value) => {
244
211
  // *** Encryption *** //
245
212
  const authTagLength = 16
246
213
 
247
- export const makeSymetricKey = (assocData) => {
248
- if (!options.encryptionSharedKey) {
214
+ export const makeSymetricKey = (sub) => {
215
+ if (!options.symetricEncryptionKey) {
249
216
  return { encryptionKey: '', encryptedKey: '' }
250
217
  }
251
- const encryptionKey = randomBytes(32)
252
- const encryptedKey = __encrypt(
253
- encryptionKey,
254
- Buffer.from(options.encryptionSharedKey, 'hex'),
255
- assocData,
256
- 'hex',
257
- 'hex'
258
- )
218
+ const encryptionKey = randomSymetricEncryptionKey()
219
+ const encryptedKey = symetricEncrypt(encryptionKey, {
220
+ encryptionKey: options.symetricEncryptionKey,
221
+ sub,
222
+ decoding: 'base64',
223
+ encoding: options.symetricEncryptionEncoding
224
+ })
259
225
  return { encryptionKey, encryptedKey }
260
226
  }
261
227
 
262
- export const encrypt = (data, encryptedKey, assocData) => {
263
- if (!encryptedKey) return data
264
-
265
- const encryptionKey = __decrypt(
266
- encryptedKey,
267
- Buffer.from(options.encryptionSharedKey, 'hex'),
268
- assocData,
269
- 'hex',
270
- 'hex'
271
- )
272
- return __encrypt(
273
- data,
274
- Buffer.from(encryptionKey, 'hex'),
275
- assocData,
276
- 'utf8',
277
- 'hex'
278
- )
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)
241
+ for (const key of fields) {
242
+ encryptedValues[key] &&= symetricEncrypt(encryptedValues[key], {
243
+ encryptionKey,
244
+ sub
245
+ })
246
+ }
247
+ return encryptedValues
279
248
  }
280
249
 
281
- const __encrypt = (
250
+ export const symetricEncrypt = (
282
251
  data,
283
- encryptionKey,
284
- assocData,
285
- decoding = 'utf8',
286
- encoding = 'hex'
252
+ { encryptedKey, encryptionKey, sub, decoding, encoding, iv }
287
253
  ) => {
288
- const iv = randomBytes(12) // 96 bits
289
- const cipher = createCipheriv(options.encryptionMethod, encryptionKey, iv, {
290
- authTagLength
291
- })
292
- cipher.setAAD(Buffer.from(assocData, 'utf8'))
254
+ if (encryptedKey) {
255
+ encryptionKey ??= symetricDecryptKey(encryptedKey, {
256
+ sub
257
+ })
258
+ }
259
+ if (!encryptionKey || !data) 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'))
293
273
  const encryptedData =
294
274
  cipher.update(data, decoding, encoding) + cipher.final(encoding)
295
275
  const authTag = cipher.getAuthTag()
296
- return (
297
- iv.toString(encoding) + // 24 char
298
- authTag.toString(encoding) + // 32 char
299
- encryptedData
300
- )
276
+
277
+ const encryptedDataPacket =
278
+ iv.toString(encoding) + authTag.toString(encoding) + encryptedData
279
+
280
+ return encryptedDataPacket
301
281
  }
302
282
 
303
- export const decrypt = (encryptedData, encryptedKey, assocData) => {
304
- if (!options.encryptionSharedKey || !encryptedKey) return encryptedData
305
- const encryptionKey = __decrypt(
306
- encryptedKey,
307
- Buffer.from(options.encryptionSharedKey, 'hex'),
308
- assocData,
309
- 'hex',
310
- 'hex'
311
- )
312
- const data = __decrypt(
313
- encryptedData,
314
- Buffer.from(encryptionKey, 'hex'),
315
- assocData,
316
- 'hex',
317
- 'utf8'
318
- )
319
- return data
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)
295
+ for (const key of fields) {
296
+ values[key] &&= symetricDecrypt(values[key], {
297
+ encryptionKey,
298
+ sub
299
+ })
300
+ }
301
+ return values
320
302
  }
321
303
 
322
- const __decrypt = (
323
- data,
324
- encryptionKey,
325
- assocData,
326
- decoding = 'hex',
327
- encoding = 'utf8'
304
+ export const symetricDecryptKey = (encryptedKey, { sub } = {}) => {
305
+ return symetricDecrypt(encryptedKey, {
306
+ encryptionKey: options.symetricEncryptionKey,
307
+ sub,
308
+ decoding: options.symetricEncryptionEncoding,
309
+ encoding: 'base64'
310
+ })
311
+ }
312
+
313
+ export const symetricDecrypt = (
314
+ encryptedDataPacket,
315
+ { encryptedKey, encryptionKey, sub, decoding, encoding }
328
316
  ) => {
329
- const iv = Buffer.from(data.substring(0, 24), decoding)
330
- const authTag = Buffer.from(data.substring(24, 56), decoding)
331
- const encryptedData = Buffer.from(data.substring(56), decoding)
317
+ if (encryptedKey) {
318
+ encryptionKey ??= symetricDecryptKey(encryptedKey, {
319
+ sub
320
+ })
321
+ }
322
+ if (!encryptionKey || !encryptedDataPacket) 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
+ )
332
343
 
333
344
  const decipher = createDecipheriv(
334
- options.encryptionMethod,
335
- encryptionKey,
345
+ options.symetricEncryptionMethod,
346
+ Buffer.from(encryptionKey, 'base64'),
336
347
  iv,
337
348
  {
338
349
  authTagLength
339
350
  }
340
351
  )
341
- decipher.setAAD(Buffer.from(assocData, 'utf8'))
352
+ decipher.setAAD(Buffer.from(sub ?? '', 'utf8'))
353
+
342
354
  decipher.setAuthTag(authTag)
343
- return (
355
+ const data =
344
356
  decipher.update(encryptedData, decoding, encoding) +
345
357
  decipher.final(encoding)
346
- )
358
+ return data
347
359
  }
348
360
 
349
361
  // *** Signatures *** //
350
- export const makeAsymmetricKeys = async (encryptionKey) => {
362
+ // asymmetricKeyPairType
363
+ export const makeAsymmetricKeys = async () => {
351
364
  const { publicKey, privateKey } = await generateKeyPair('ec', {
352
365
  namedCurve: 'P-384', // P-512
353
366
  paramEncoding: 'named',
@@ -357,44 +370,32 @@ export const makeAsymmetricKeys = async (encryptionKey) => {
357
370
  },
358
371
  privateKeyEncoding: {
359
372
  type: 'sec1',
360
- format: 'pem',
361
- // TODO remove encryption for other with sub check?
362
- cipher: options.encryptionMethod,
363
- passphrase: encryptionKey
373
+ format: 'pem'
374
+ // Encryption done at another level for consistency
375
+ // cipher: options.asymetricEncryptionMethod,
376
+ // passphrase: encryptionKey,
364
377
  }
365
378
  })
366
379
  return { publicKey, privateKey }
367
380
  }
368
381
 
369
- export const makeSignature = (data, privateKey, algorithm = 'SHA3-256') => {
370
- 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
+ )
371
387
  }
372
- export const verifySignature = (
388
+ export const verifySignature = async (
373
389
  data,
374
390
  publicKey,
375
391
  signature,
376
- algorithm = 'SHA3-256'
392
+ { algorithm } = {}
377
393
  ) => {
378
- return verify(
394
+ algorithm ??= options.digestAlgorithm
395
+ return await verify(
379
396
  algorithm,
380
397
  Buffer.from(data),
381
398
  publicKey,
382
- Buffer.from(signature, 'base64')
399
+ Buffer.from(signature, options.signatureEncoding)
383
400
  )
384
401
  }
385
- // const assocData = 'sub'
386
- // const input = 'data'
387
- //
388
- // const {encryptedKey} = makeSymetricKey(assocData)
389
- // const encryptedData = encrypt(input, encryptedKey, assocData)
390
- // const output = decrypt(encryptedData, encryptedKey, assocData)
391
- // console.log(assocData, input, output, encryptedData)
392
-
393
- // const assocData = 'tlSIcVp1XEF'
394
- // const encryptionKey =
395
- // 'b9ebfdab6603dd8e151138ec8298aaf8b49bf6d38480f9864e9e72e65c4d8b59.b9f9bc89d7f3ce4aa1e1af469d10508b.aa1b6a682fcc186e867a9cfd'
396
- // const value =
397
- // '76ebdea75ea529c16f1645d5435413934cbb97378293776cb446331e6d8323865a808b7f0822cd4f36ef6cca57354ea7c955c94d232a55038321184f4294971315fda4b8dc2f33422bbd3a5c978edc0f5bf019f818f0c92f7c570bdc49fe2f71df3856655198b6723fa52697b9225b2e79f04ed80cd35ef61a8e1e06c3751d3f9caa40aa9a41528ce5ab1bfae8ecff0feab784497ccbf2c7dca4461c6b9a74d1ded6233dc38ad75d0fe2f57cfda2bd1d59ed1f8c53de911cf8071dc7cefde7870c303137586bc0c5f85fe93505d9056994a4d8e59df2027b564c303aa723e98ae5934b15039f90d21827ac22b824593f334466622582a2857f04d8bf450310a9924060d113d2ece0259da68376b31a3c2e8a0b79e81f8efe96bf2b7a6b5b1841edca2566a0a89ab80ee6d6ac2ed24e788ad318a1238dfa5b9e965d256935d3aeafe52f986a530b2f9225bbe7a73b43e6515ce789701f501546239460bccc46285f3fcff0c54c2b6df820334a974abea81460fd4ac99a13cb88e296a2275f80f4c783757319417078458977461dd5e101f9f9b7d303578379dc15ee1b549e3fcceffffba895ecc8291d1f82e150ce8e10640fd79f2e0666167ef7d529cd28cb76a72bf2b3e239dbb845bedd39f42c938bbe711542231fb835edb547d919b3c695272f4cd43640eb3bed2b86948278e5aeeb67ef932ef08332730e75752fd5bd247e2dd30470fc493362d2ecac72237dfbf0a1694f8e6b8c18ab24c71eb723a3f610a056a73fea90f4f8660bfc6dec46fa52a55a3d72a5c9b97770bff7d52ea91b97cc643d915341642e201918fcb088986e9134e133519c6575048e3f840622e569fc5fa66e4f0c31681c9de4b1b1f6acb179728bc0a9f9950bf2e0c8d49da835298013977a2f97d7052bcbedbc39b875bbf9a0622ede589810175ab2455ea72a8274659af7066a2c97ba3aacce84531d8685d08b15d3619038997ae459ac916a88bedaf619f574236d1b86b02f29edaf78684c91c6ee45199b861359ee374fecb95be8a85dc012991d22564adeb2ec95f160574858fa010c40ce74077a08f0e681eb4b10a0093e885f115a12469a82b07012ad4e20b836d5711358c47969af89d09c9299edc540321fe897312ca49c9e8f93d50dc68394d0cc1d108f38e3534821b979c405c1f526a3b57651897873aeeb0909b176fb2034f9fdb1d43a8003809af29ff0bdc456a593029c4526b270908ac94b620a7cb8b7da20a6421e0f2671c899c20d78e1e0a1c3ab0b92948c90fca3c36d21a5e53143bc7e061773251364f8ce3b8992b6313c9604dc19c018b9efc6ca8f7c1fe039077fd76775461d1fa3968f51be7e340e3f09b40d6b44c77a7cbf7d71cad2ddea1121b31d27470a38cda8f8d38170a0d8f0b02d56f8e97b2134597d6111ea6670545bd4f7b4e4d6d7cf2fb5b787a68ba8ee84775f06db195f47282d9646dfbdbb57701e2ef5a432b621cb54a70e94de6b7a3f95bfe3c50793e08a27f76f832070fb2d23ed19dcd75f798aeff0c3e76d8215d43e1a8b7e643bffa243691adf2abcd52f465390e92e0344e2f452673f12d50e2ead0496ba76504ae0f78c81f2a2b5a64b39d3fb35f39f178b9a1587d1f07ed28e7696bfc8740f429f6cc35c964ae04ef39c1070eab6415be3aab887ff6192ac4d49ba9b169221b47d73c55f6010dda07a77cbcf54b779d380591786ba70c6d7000af57034539487f801aeb5c097939682e1530bc26c0b030bcab327ddaaaac5c9b969301b6d4ed7f601a46e8431e8cae3800c80c42686fee3b7625742798ced5976d163d2c8aad1bdac36c001e4e246fdb7b4c6850ed99554cfc0c07b7c7acc7659fd042989cc291ec2bd03a59e439860a5c48e430780f9d85c9acb3e85e741e73163f29afb7c43f143e7ada99a4670cbbe2210bfce8d36ee86.a5237f2d798c9f98b26a676794d3c3f6.0f15d0f53657150aeb1462d5'
398
- // const output = decrypt(value, encryptionKey, assocData)
399
- // console.log(output)
400
- // *** TOTP *** //
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@1auth/crypto",
3
- "version": "0.0.0-alpha.4",
3
+ "version": "0.0.0-alpha.40",
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": {
@@ -25,10 +25,6 @@
25
25
  "index.js",
26
26
  "index.d.ts"
27
27
  ],
28
- "scripts": {
29
- "test": "npm run test:unit",
30
- "test:unit": "ava"
31
- },
32
28
  "license": "MIT",
33
29
  "funding": {
34
30
  "type": "github",
@@ -48,8 +44,8 @@
48
44
  "url": "https://github.com/willfarrell/1auth/issues"
49
45
  },
50
46
  "homepage": "https://github.com/willfarrell/1auth",
51
- "gitHead": "47894073ee5f1b6754cef5e482f123dc81575b1c",
47
+ "gitHead": "7a6c0fbb8ab71d6a2171e678697de9f237568431",
52
48
  "dependencies": {
53
- "@node-rs/argon2": "1.5.0"
49
+ "@node-rs/argon2": "2.0.0"
54
50
  }
55
51
  }
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2023 will Farrell
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.