aegis-aead 0.1.1 → 0.2.1

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 (48) hide show
  1. package/README.md +195 -89
  2. package/dist/aegis128l-bs.d.ts +194 -0
  3. package/dist/aegis128l-bs.d.ts.map +1 -0
  4. package/dist/aegis128l-bs.js +549 -0
  5. package/dist/aegis128l-bs.js.map +1 -0
  6. package/dist/aegis128l.d.ts +74 -5
  7. package/dist/aegis128l.d.ts.map +1 -1
  8. package/dist/aegis128l.js +173 -5
  9. package/dist/aegis128l.js.map +1 -1
  10. package/dist/aegis128x.d.ts +109 -12
  11. package/dist/aegis128x.d.ts.map +1 -1
  12. package/dist/aegis128x.js +202 -9
  13. package/dist/aegis128x.js.map +1 -1
  14. package/dist/aegis256-bs.d.ts +183 -0
  15. package/dist/aegis256-bs.d.ts.map +1 -0
  16. package/dist/aegis256-bs.js +477 -0
  17. package/dist/aegis256-bs.js.map +1 -0
  18. package/dist/aegis256.d.ts +74 -5
  19. package/dist/aegis256.d.ts.map +1 -1
  20. package/dist/aegis256.js +158 -5
  21. package/dist/aegis256.js.map +1 -1
  22. package/dist/aegis256x.d.ts +109 -12
  23. package/dist/aegis256x.d.ts.map +1 -1
  24. package/dist/aegis256x.js +193 -9
  25. package/dist/aegis256x.js.map +1 -1
  26. package/dist/aes-bs.d.ts +71 -0
  27. package/dist/aes-bs.d.ts.map +1 -0
  28. package/dist/aes-bs.js +399 -0
  29. package/dist/aes-bs.js.map +1 -0
  30. package/dist/index.d.ts +6 -4
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +6 -4
  33. package/dist/index.js.map +1 -1
  34. package/dist/random.d.ts +22 -0
  35. package/dist/random.d.ts.map +1 -0
  36. package/dist/random.js +36 -0
  37. package/dist/random.js.map +1 -0
  38. package/package.json +1 -1
  39. package/src/aegis128l-bs.ts +709 -0
  40. package/src/aegis128l.ts +238 -5
  41. package/src/aegis128x.ts +342 -15
  42. package/src/aegis256-bs.ts +625 -0
  43. package/src/aegis256.ts +223 -5
  44. package/src/aegis256x.ts +329 -15
  45. package/src/aes-bs.ts +459 -0
  46. package/src/index.ts +86 -0
  47. package/src/random.ts +41 -0
  48. package/README.md~ +0 -154
package/src/aegis128l.ts CHANGED
@@ -8,6 +8,7 @@ import {
8
8
  xorBlocksTo,
9
9
  zeroPad,
10
10
  } from "./aes.js";
11
+ import { randomBytes } from "./random.js";
11
12
 
12
13
  /**
13
14
  * AEGIS-128L cipher state.
@@ -203,6 +204,37 @@ export class Aegis128LState {
203
204
  return out;
204
205
  }
205
206
 
207
+ /**
208
+ * Encrypts a 32-byte plaintext block in-place.
209
+ * @param block - 32-byte buffer (plaintext in, ciphertext out)
210
+ */
211
+ encInPlace(block: Uint8Array): void {
212
+ const z0 = this.z0;
213
+ const z1 = this.z1;
214
+ const tmp = this.tmp0;
215
+
216
+ xorBlocksTo(this.s1, this.s6, z0);
217
+ andBlocksTo(this.s2, this.s3, tmp);
218
+ for (let i = 0; i < 16; i++) z0[i] ^= tmp[i]!;
219
+
220
+ xorBlocksTo(this.s2, this.s5, z1);
221
+ andBlocksTo(this.s6, this.s7, tmp);
222
+ for (let i = 0; i < 16; i++) z1[i] ^= tmp[i]!;
223
+
224
+ this.update(block.subarray(0, 16), block.subarray(16, 32));
225
+
226
+ for (let i = 0; i < 16; i++) block[i] ^= z0[i]!;
227
+ for (let i = 0; i < 16; i++) block[16 + i] ^= z1[i]!;
228
+ }
229
+
230
+ /**
231
+ * Decrypts a 32-byte ciphertext block in-place.
232
+ * @param block - 32-byte buffer (ciphertext in, plaintext out)
233
+ */
234
+ decInPlace(block: Uint8Array): void {
235
+ this.decTo(block, block);
236
+ }
237
+
206
238
  /**
207
239
  * Decrypts a partial (final) ciphertext block smaller than 32 bytes.
208
240
  * @param cn - Partial ciphertext block (1-31 bytes)
@@ -285,15 +317,15 @@ export class Aegis128LState {
285
317
  }
286
318
 
287
319
  /**
288
- * Encrypts a message using AEGIS-128L.
320
+ * Encrypts a message using AEGIS-128L (detached mode).
289
321
  * @param msg - Plaintext message
290
322
  * @param ad - Associated data (authenticated but not encrypted)
291
323
  * @param key - 16-byte encryption key
292
324
  * @param nonce - 16-byte nonce (must be unique per message with the same key)
293
325
  * @param tagLen - Authentication tag length: 16 or 32 bytes (default: 16)
294
- * @returns Object containing ciphertext and authentication tag
326
+ * @returns Object containing ciphertext and authentication tag separately
295
327
  */
296
- export function aegis128LEncrypt(
328
+ export function aegis128LEncryptDetached(
297
329
  msg: Uint8Array,
298
330
  ad: Uint8Array,
299
331
  key: Uint8Array,
@@ -325,7 +357,7 @@ export function aegis128LEncrypt(
325
357
  }
326
358
 
327
359
  /**
328
- * Decrypts a message using AEGIS-128L.
360
+ * Decrypts a message using AEGIS-128L (detached mode).
329
361
  * @param ct - Ciphertext
330
362
  * @param tag - Authentication tag (16 or 32 bytes)
331
363
  * @param ad - Associated data (must match what was used during encryption)
@@ -333,7 +365,7 @@ export function aegis128LEncrypt(
333
365
  * @param nonce - 16-byte nonce (must match what was used during encryption)
334
366
  * @returns Decrypted plaintext, or null if authentication fails
335
367
  */
336
- export function aegis128LDecrypt(
368
+ export function aegis128LDecryptDetached(
337
369
  ct: Uint8Array,
338
370
  tag: Uint8Array,
339
371
  ad: Uint8Array,
@@ -375,6 +407,189 @@ export function aegis128LDecrypt(
375
407
  return msg;
376
408
  }
377
409
 
410
+ /**
411
+ * Encrypts a message in-place using AEGIS-128L (detached mode).
412
+ * The input buffer is modified to contain the ciphertext.
413
+ * @param data - Buffer containing plaintext (will be overwritten with ciphertext)
414
+ * @param ad - Associated data (authenticated but not encrypted)
415
+ * @param key - 16-byte encryption key
416
+ * @param nonce - 16-byte nonce (must be unique per message with the same key)
417
+ * @param tagLen - Authentication tag length: 16 or 32 bytes (default: 16)
418
+ * @returns Authentication tag
419
+ */
420
+ export function aegis128LEncryptDetachedInPlace(
421
+ data: Uint8Array,
422
+ ad: Uint8Array,
423
+ key: Uint8Array,
424
+ nonce: Uint8Array,
425
+ tagLen: 16 | 32 = 16,
426
+ ): Uint8Array {
427
+ const state = new Aegis128LState();
428
+ state.init(key, nonce);
429
+
430
+ const adPadded = zeroPad(ad, 32);
431
+ for (let i = 0; i + 32 <= adPadded.length; i += 32) {
432
+ state.absorb(adPadded.subarray(i, i + 32));
433
+ }
434
+
435
+ const msgLen = data.length;
436
+ const fullBlocksLen = Math.floor(msgLen / 32) * 32;
437
+
438
+ for (let i = 0; i < fullBlocksLen; i += 32) {
439
+ state.encInPlace(data.subarray(i, i + 32));
440
+ }
441
+
442
+ if (msgLen > fullBlocksLen) {
443
+ const lastPartial = data.subarray(fullBlocksLen);
444
+ const lastBlock = zeroPad(lastPartial, 32);
445
+ const encBlock = state.enc(lastBlock);
446
+ lastPartial.set(encBlock.subarray(0, lastPartial.length));
447
+ }
448
+
449
+ return state.finalize(BigInt(ad.length * 8), BigInt(msgLen * 8), tagLen);
450
+ }
451
+
452
+ /**
453
+ * Decrypts a message in-place using AEGIS-128L (detached mode).
454
+ * The input buffer is modified to contain the plaintext (or zeroed on failure).
455
+ * @param data - Buffer containing ciphertext (will be overwritten with plaintext)
456
+ * @param tag - Authentication tag (16 or 32 bytes)
457
+ * @param ad - Associated data (must match what was used during encryption)
458
+ * @param key - 16-byte encryption key
459
+ * @param nonce - 16-byte nonce (must match what was used during encryption)
460
+ * @returns True if authentication succeeds, false otherwise
461
+ */
462
+ export function aegis128LDecryptDetachedInPlace(
463
+ data: Uint8Array,
464
+ tag: Uint8Array,
465
+ ad: Uint8Array,
466
+ key: Uint8Array,
467
+ nonce: Uint8Array,
468
+ ): boolean {
469
+ const tagLen = tag.length as 16 | 32;
470
+ const state = new Aegis128LState();
471
+ state.init(key, nonce);
472
+
473
+ const adPadded = zeroPad(ad, 32);
474
+ for (let i = 0; i + 32 <= adPadded.length; i += 32) {
475
+ state.absorb(adPadded.subarray(i, i + 32));
476
+ }
477
+
478
+ const msgLen = data.length;
479
+ const fullBlocksLen = Math.floor(msgLen / 32) * 32;
480
+
481
+ for (let i = 0; i < fullBlocksLen; i += 32) {
482
+ state.decInPlace(data.subarray(i, i + 32));
483
+ }
484
+
485
+ if (msgLen > fullBlocksLen) {
486
+ const lastPartial = data.subarray(fullBlocksLen);
487
+ const decrypted = state.decPartial(lastPartial);
488
+ lastPartial.set(decrypted);
489
+ }
490
+
491
+ const expectedTag = state.finalize(
492
+ BigInt(ad.length * 8),
493
+ BigInt(msgLen * 8),
494
+ tagLen,
495
+ );
496
+
497
+ if (!constantTimeEqual(tag, expectedTag)) {
498
+ data.fill(0);
499
+ return false;
500
+ }
501
+
502
+ return true;
503
+ }
504
+
505
+ /** Nonce size for AEGIS-128L in bytes. */
506
+ export const AEGIS_128L_NONCE_SIZE = 16;
507
+
508
+ /** Key size for AEGIS-128L in bytes. */
509
+ export const AEGIS_128L_KEY_SIZE = 16;
510
+
511
+ /**
512
+ * Encrypts a message using AEGIS-128L.
513
+ * Returns a single buffer containing nonce || ciphertext || tag.
514
+ * @param msg - Plaintext message
515
+ * @param ad - Associated data (authenticated but not encrypted)
516
+ * @param key - 16-byte encryption key
517
+ * @param nonce - 16-byte nonce (optional, generates random nonce if not provided)
518
+ * @param tagLen - Authentication tag length: 16 or 32 bytes (default: 16)
519
+ * @returns Concatenated nonce || ciphertext || tag
520
+ */
521
+ export function aegis128LEncrypt(
522
+ msg: Uint8Array,
523
+ ad: Uint8Array,
524
+ key: Uint8Array,
525
+ nonce: Uint8Array | null = null,
526
+ tagLen: 16 | 32 = 16,
527
+ ): Uint8Array {
528
+ const actualNonce = nonce ?? randomBytes(AEGIS_128L_NONCE_SIZE);
529
+ const state = new Aegis128LState();
530
+ state.init(key, actualNonce);
531
+
532
+ const adPadded = zeroPad(ad, 32);
533
+ for (let i = 0; i + 32 <= adPadded.length; i += 32) {
534
+ state.absorb(adPadded.subarray(i, i + 32));
535
+ }
536
+
537
+ const nonceSize = AEGIS_128L_NONCE_SIZE;
538
+ const result = new Uint8Array(nonceSize + msg.length + tagLen);
539
+ result.set(actualNonce, 0);
540
+
541
+ const fullBlocks = Math.floor(msg.length / 32) * 32;
542
+ for (let i = 0; i < fullBlocks; i += 32) {
543
+ state.encTo(
544
+ msg.subarray(i, i + 32),
545
+ result.subarray(nonceSize + i, nonceSize + i + 32),
546
+ );
547
+ }
548
+
549
+ if (msg.length > fullBlocks) {
550
+ const lastBlock = zeroPad(msg.subarray(fullBlocks), 32);
551
+ const encBlock = state.enc(lastBlock);
552
+ result.set(
553
+ encBlock.subarray(0, msg.length - fullBlocks),
554
+ nonceSize + fullBlocks,
555
+ );
556
+ }
557
+
558
+ const tag = state.finalize(
559
+ BigInt(ad.length * 8),
560
+ BigInt(msg.length * 8),
561
+ tagLen,
562
+ );
563
+ result.set(tag, nonceSize + msg.length);
564
+
565
+ return result;
566
+ }
567
+
568
+ /**
569
+ * Decrypts a message using AEGIS-128L.
570
+ * Expects input as nonce || ciphertext || tag.
571
+ * @param sealed - Concatenated nonce || ciphertext || tag
572
+ * @param ad - Associated data (must match what was used during encryption)
573
+ * @param key - 16-byte encryption key
574
+ * @param tagLen - Authentication tag length: 16 or 32 bytes (default: 16)
575
+ * @returns Decrypted plaintext, or null if authentication fails
576
+ */
577
+ export function aegis128LDecrypt(
578
+ sealed: Uint8Array,
579
+ ad: Uint8Array,
580
+ key: Uint8Array,
581
+ tagLen: 16 | 32 = 16,
582
+ ): Uint8Array | null {
583
+ const nonceSize = AEGIS_128L_NONCE_SIZE;
584
+ if (sealed.length < nonceSize + tagLen) {
585
+ return null;
586
+ }
587
+ const nonce = sealed.subarray(0, nonceSize);
588
+ const ct = sealed.subarray(nonceSize, sealed.length - tagLen);
589
+ const tag = sealed.subarray(sealed.length - tagLen);
590
+ return aegis128LDecryptDetached(ct, tag, ad, key, nonce);
591
+ }
592
+
378
593
  /**
379
594
  * Computes a MAC (Message Authentication Code) using AEGIS-128L.
380
595
  * @param data - Data to authenticate
@@ -418,3 +633,21 @@ export function aegis128LMacVerify(
418
633
  const expectedTag = aegis128LMac(data, key, nonce, tagLen);
419
634
  return constantTimeEqual(tag, expectedTag);
420
635
  }
636
+
637
+ /**
638
+ * Generates a random 16-byte key for AEGIS-128L.
639
+ * @returns 16-byte encryption key
640
+ * @throws Error if no cryptographic random source is available
641
+ */
642
+ export function aegis128LCreateKey(): Uint8Array {
643
+ return randomBytes(AEGIS_128L_KEY_SIZE);
644
+ }
645
+
646
+ /**
647
+ * Generates a random 16-byte nonce for AEGIS-128L.
648
+ * @returns 16-byte nonce
649
+ * @throws Error if no cryptographic random source is available
650
+ */
651
+ export function aegis128LCreateNonce(): Uint8Array {
652
+ return randomBytes(AEGIS_128L_NONCE_SIZE);
653
+ }