aegis-aead 0.1.1 → 0.2.0

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 +241 -60
  2. package/dist/aegis128l-bs.d.ts +162 -0
  3. package/dist/aegis128l-bs.d.ts.map +1 -0
  4. package/dist/aegis128l-bs.js +470 -0
  5. package/dist/aegis128l-bs.js.map +1 -0
  6. package/dist/aegis128l.d.ts +42 -5
  7. package/dist/aegis128l.d.ts.map +1 -1
  8. package/dist/aegis128l.js +79 -5
  9. package/dist/aegis128l.js.map +1 -1
  10. package/dist/aegis128x.d.ts +67 -12
  11. package/dist/aegis128x.d.ts.map +1 -1
  12. package/dist/aegis128x.js +102 -9
  13. package/dist/aegis128x.js.map +1 -1
  14. package/dist/aegis256-bs.d.ts +151 -0
  15. package/dist/aegis256-bs.d.ts.map +1 -0
  16. package/dist/aegis256-bs.js +398 -0
  17. package/dist/aegis256-bs.js.map +1 -0
  18. package/dist/aegis256.d.ts +42 -5
  19. package/dist/aegis256.d.ts.map +1 -1
  20. package/dist/aegis256.js +79 -5
  21. package/dist/aegis256.js.map +1 -1
  22. package/dist/aegis256x.d.ts +67 -12
  23. package/dist/aegis256x.d.ts.map +1 -1
  24. package/dist/aegis256x.js +102 -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 +602 -0
  40. package/src/aegis128l.ts +112 -5
  41. package/src/aegis128x.ts +174 -15
  42. package/src/aegis256-bs.ts +518 -0
  43. package/src/aegis256.ts +112 -5
  44. package/src/aegis256x.ts +174 -15
  45. package/src/aes-bs.ts +459 -0
  46. package/src/index.ts +66 -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.
@@ -285,15 +286,15 @@ export class Aegis128LState {
285
286
  }
286
287
 
287
288
  /**
288
- * Encrypts a message using AEGIS-128L.
289
+ * Encrypts a message using AEGIS-128L (detached mode).
289
290
  * @param msg - Plaintext message
290
291
  * @param ad - Associated data (authenticated but not encrypted)
291
292
  * @param key - 16-byte encryption key
292
293
  * @param nonce - 16-byte nonce (must be unique per message with the same key)
293
294
  * @param tagLen - Authentication tag length: 16 or 32 bytes (default: 16)
294
- * @returns Object containing ciphertext and authentication tag
295
+ * @returns Object containing ciphertext and authentication tag separately
295
296
  */
296
- export function aegis128LEncrypt(
297
+ export function aegis128LEncryptDetached(
297
298
  msg: Uint8Array,
298
299
  ad: Uint8Array,
299
300
  key: Uint8Array,
@@ -325,7 +326,7 @@ export function aegis128LEncrypt(
325
326
  }
326
327
 
327
328
  /**
328
- * Decrypts a message using AEGIS-128L.
329
+ * Decrypts a message using AEGIS-128L (detached mode).
329
330
  * @param ct - Ciphertext
330
331
  * @param tag - Authentication tag (16 or 32 bytes)
331
332
  * @param ad - Associated data (must match what was used during encryption)
@@ -333,7 +334,7 @@ export function aegis128LEncrypt(
333
334
  * @param nonce - 16-byte nonce (must match what was used during encryption)
334
335
  * @returns Decrypted plaintext, or null if authentication fails
335
336
  */
336
- export function aegis128LDecrypt(
337
+ export function aegis128LDecryptDetached(
337
338
  ct: Uint8Array,
338
339
  tag: Uint8Array,
339
340
  ad: Uint8Array,
@@ -375,6 +376,94 @@ export function aegis128LDecrypt(
375
376
  return msg;
376
377
  }
377
378
 
379
+ /** Nonce size for AEGIS-128L in bytes. */
380
+ export const AEGIS_128L_NONCE_SIZE = 16;
381
+
382
+ /** Key size for AEGIS-128L in bytes. */
383
+ export const AEGIS_128L_KEY_SIZE = 16;
384
+
385
+ /**
386
+ * Encrypts a message using AEGIS-128L.
387
+ * Returns a single buffer containing nonce || ciphertext || tag.
388
+ * @param msg - Plaintext message
389
+ * @param ad - Associated data (authenticated but not encrypted)
390
+ * @param key - 16-byte encryption key
391
+ * @param nonce - 16-byte nonce (optional, generates random nonce if not provided)
392
+ * @param tagLen - Authentication tag length: 16 or 32 bytes (default: 16)
393
+ * @returns Concatenated nonce || ciphertext || tag
394
+ */
395
+ export function aegis128LEncrypt(
396
+ msg: Uint8Array,
397
+ ad: Uint8Array,
398
+ key: Uint8Array,
399
+ nonce: Uint8Array | null = null,
400
+ tagLen: 16 | 32 = 16,
401
+ ): Uint8Array {
402
+ const actualNonce = nonce ?? randomBytes(AEGIS_128L_NONCE_SIZE);
403
+ const state = new Aegis128LState();
404
+ state.init(key, actualNonce);
405
+
406
+ const adPadded = zeroPad(ad, 32);
407
+ for (let i = 0; i + 32 <= adPadded.length; i += 32) {
408
+ state.absorb(adPadded.subarray(i, i + 32));
409
+ }
410
+
411
+ const nonceSize = AEGIS_128L_NONCE_SIZE;
412
+ const result = new Uint8Array(nonceSize + msg.length + tagLen);
413
+ result.set(actualNonce, 0);
414
+
415
+ const fullBlocks = Math.floor(msg.length / 32) * 32;
416
+ for (let i = 0; i < fullBlocks; i += 32) {
417
+ state.encTo(
418
+ msg.subarray(i, i + 32),
419
+ result.subarray(nonceSize + i, nonceSize + i + 32),
420
+ );
421
+ }
422
+
423
+ if (msg.length > fullBlocks) {
424
+ const lastBlock = zeroPad(msg.subarray(fullBlocks), 32);
425
+ const encBlock = state.enc(lastBlock);
426
+ result.set(
427
+ encBlock.subarray(0, msg.length - fullBlocks),
428
+ nonceSize + fullBlocks,
429
+ );
430
+ }
431
+
432
+ const tag = state.finalize(
433
+ BigInt(ad.length * 8),
434
+ BigInt(msg.length * 8),
435
+ tagLen,
436
+ );
437
+ result.set(tag, nonceSize + msg.length);
438
+
439
+ return result;
440
+ }
441
+
442
+ /**
443
+ * Decrypts a message using AEGIS-128L.
444
+ * Expects input as nonce || ciphertext || tag.
445
+ * @param sealed - Concatenated nonce || ciphertext || tag
446
+ * @param ad - Associated data (must match what was used during encryption)
447
+ * @param key - 16-byte encryption key
448
+ * @param tagLen - Authentication tag length: 16 or 32 bytes (default: 16)
449
+ * @returns Decrypted plaintext, or null if authentication fails
450
+ */
451
+ export function aegis128LDecrypt(
452
+ sealed: Uint8Array,
453
+ ad: Uint8Array,
454
+ key: Uint8Array,
455
+ tagLen: 16 | 32 = 16,
456
+ ): Uint8Array | null {
457
+ const nonceSize = AEGIS_128L_NONCE_SIZE;
458
+ if (sealed.length < nonceSize + tagLen) {
459
+ return null;
460
+ }
461
+ const nonce = sealed.subarray(0, nonceSize);
462
+ const ct = sealed.subarray(nonceSize, sealed.length - tagLen);
463
+ const tag = sealed.subarray(sealed.length - tagLen);
464
+ return aegis128LDecryptDetached(ct, tag, ad, key, nonce);
465
+ }
466
+
378
467
  /**
379
468
  * Computes a MAC (Message Authentication Code) using AEGIS-128L.
380
469
  * @param data - Data to authenticate
@@ -418,3 +507,21 @@ export function aegis128LMacVerify(
418
507
  const expectedTag = aegis128LMac(data, key, nonce, tagLen);
419
508
  return constantTimeEqual(tag, expectedTag);
420
509
  }
510
+
511
+ /**
512
+ * Generates a random 16-byte key for AEGIS-128L.
513
+ * @returns 16-byte encryption key
514
+ * @throws Error if no cryptographic random source is available
515
+ */
516
+ export function aegis128LCreateKey(): Uint8Array {
517
+ return randomBytes(AEGIS_128L_KEY_SIZE);
518
+ }
519
+
520
+ /**
521
+ * Generates a random 16-byte nonce for AEGIS-128L.
522
+ * @returns 16-byte nonce
523
+ * @throws Error if no cryptographic random source is available
524
+ */
525
+ export function aegis128LCreateNonce(): Uint8Array {
526
+ return randomBytes(AEGIS_128L_NONCE_SIZE);
527
+ }
package/src/aegis128x.ts CHANGED
@@ -10,6 +10,7 @@ import {
10
10
  xorBlocksTo,
11
11
  zeroPad,
12
12
  } from "./aes.js";
13
+ import { randomBytes } from "./random.js";
13
14
 
14
15
  /**
15
16
  * AEGIS-128X cipher state with configurable parallelism degree.
@@ -385,16 +386,16 @@ export class Aegis128XState {
385
386
  }
386
387
 
387
388
  /**
388
- * Encrypts a message using AEGIS-128X.
389
+ * Encrypts a message using AEGIS-128X (detached mode).
389
390
  * @param msg - Plaintext message
390
391
  * @param ad - Associated data (authenticated but not encrypted)
391
392
  * @param key - 16-byte encryption key
392
393
  * @param nonce - 16-byte nonce (must be unique per message with the same key)
393
394
  * @param tagLen - Authentication tag length: 16 or 32 bytes (default: 16)
394
395
  * @param degree - Parallelism degree (default: 2)
395
- * @returns Object containing ciphertext and authentication tag
396
+ * @returns Object containing ciphertext and authentication tag separately
396
397
  */
397
- export function aegis128XEncrypt(
398
+ export function aegis128XEncryptDetached(
398
399
  msg: Uint8Array,
399
400
  ad: Uint8Array,
400
401
  key: Uint8Array,
@@ -432,7 +433,7 @@ export function aegis128XEncrypt(
432
433
  }
433
434
 
434
435
  /**
435
- * Decrypts a message using AEGIS-128X.
436
+ * Decrypts a message using AEGIS-128X (detached mode).
436
437
  * @param ct - Ciphertext
437
438
  * @param tag - Authentication tag (16 or 32 bytes)
438
439
  * @param ad - Associated data (must match what was used during encryption)
@@ -441,7 +442,7 @@ export function aegis128XEncrypt(
441
442
  * @param degree - Parallelism degree (default: 2)
442
443
  * @returns Decrypted plaintext, or null if authentication fails
443
444
  */
444
- export function aegis128XDecrypt(
445
+ export function aegis128XDecryptDetached(
445
446
  ct: Uint8Array,
446
447
  tag: Uint8Array,
447
448
  ad: Uint8Array,
@@ -486,41 +487,169 @@ export function aegis128XDecrypt(
486
487
  return msg;
487
488
  }
488
489
 
490
+ /** Nonce size for AEGIS-128X in bytes. */
491
+ export const AEGIS_128X_NONCE_SIZE = 16;
492
+
493
+ /** Key size for AEGIS-128X in bytes. */
494
+ export const AEGIS_128X_KEY_SIZE = 16;
495
+
496
+ /**
497
+ * Encrypts a message using AEGIS-128X.
498
+ * Returns a single buffer containing nonce || ciphertext || tag.
499
+ * @param msg - Plaintext message
500
+ * @param ad - Associated data (authenticated but not encrypted)
501
+ * @param key - 16-byte encryption key
502
+ * @param nonce - 16-byte nonce (optional, generates random nonce if not provided)
503
+ * @param tagLen - Authentication tag length: 16 or 32 bytes (default: 16)
504
+ * @param degree - Parallelism degree (default: 2)
505
+ * @returns Concatenated nonce || ciphertext || tag
506
+ */
507
+ export function aegis128XEncrypt(
508
+ msg: Uint8Array,
509
+ ad: Uint8Array,
510
+ key: Uint8Array,
511
+ nonce: Uint8Array | null = null,
512
+ tagLen: 16 | 32 = 16,
513
+ degree: number = 2,
514
+ ): Uint8Array {
515
+ const actualNonce = nonce ?? randomBytes(AEGIS_128X_NONCE_SIZE);
516
+ const state = new Aegis128XState(degree);
517
+ const rateBytes = (256 * degree) / 8;
518
+
519
+ state.init(key, actualNonce);
520
+
521
+ const adPadded = zeroPad(ad, rateBytes);
522
+ for (let i = 0; i + rateBytes <= adPadded.length; i += rateBytes) {
523
+ state.absorb(adPadded.subarray(i, i + rateBytes));
524
+ }
525
+
526
+ const nonceSize = AEGIS_128X_NONCE_SIZE;
527
+ const result = new Uint8Array(nonceSize + msg.length + tagLen);
528
+ result.set(actualNonce, 0);
529
+
530
+ const fullBlocks = Math.floor(msg.length / rateBytes) * rateBytes;
531
+ for (let i = 0; i < fullBlocks; i += rateBytes) {
532
+ state.encTo(
533
+ msg.subarray(i, i + rateBytes),
534
+ result.subarray(nonceSize + i, nonceSize + i + rateBytes),
535
+ );
536
+ }
537
+
538
+ if (msg.length > fullBlocks) {
539
+ const lastBlock = zeroPad(msg.subarray(fullBlocks), rateBytes);
540
+ const encBlock = state.enc(lastBlock);
541
+ result.set(
542
+ encBlock.subarray(0, msg.length - fullBlocks),
543
+ nonceSize + fullBlocks,
544
+ );
545
+ }
546
+
547
+ const tag = state.finalize(
548
+ BigInt(ad.length * 8),
549
+ BigInt(msg.length * 8),
550
+ tagLen,
551
+ );
552
+ result.set(tag, nonceSize + msg.length);
553
+
554
+ return result;
555
+ }
556
+
557
+ /**
558
+ * Decrypts a message using AEGIS-128X.
559
+ * Expects input as nonce || ciphertext || tag.
560
+ * @param sealed - Concatenated nonce || ciphertext || tag
561
+ * @param ad - Associated data (must match what was used during encryption)
562
+ * @param key - 16-byte encryption key
563
+ * @param tagLen - Authentication tag length: 16 or 32 bytes (default: 16)
564
+ * @param degree - Parallelism degree (default: 2)
565
+ * @returns Decrypted plaintext, or null if authentication fails
566
+ */
567
+ export function aegis128XDecrypt(
568
+ sealed: Uint8Array,
569
+ ad: Uint8Array,
570
+ key: Uint8Array,
571
+ tagLen: 16 | 32 = 16,
572
+ degree: number = 2,
573
+ ): Uint8Array | null {
574
+ const nonceSize = AEGIS_128X_NONCE_SIZE;
575
+ if (sealed.length < nonceSize + tagLen) {
576
+ return null;
577
+ }
578
+ const nonce = sealed.subarray(0, nonceSize);
579
+ const ct = sealed.subarray(nonceSize, sealed.length - tagLen);
580
+ const tag = sealed.subarray(sealed.length - tagLen);
581
+ return aegis128XDecryptDetached(ct, tag, ad, key, nonce, degree);
582
+ }
583
+
584
+ /** AEGIS-128X2 encryption - detached mode (degree=2). */
585
+ export const aegis128X2EncryptDetached = (
586
+ msg: Uint8Array,
587
+ ad: Uint8Array,
588
+ key: Uint8Array,
589
+ nonce: Uint8Array,
590
+ tagLen: 16 | 32 = 16,
591
+ ) => aegis128XEncryptDetached(msg, ad, key, nonce, tagLen, 2);
592
+
593
+ /** AEGIS-128X2 decryption - detached mode (degree=2). */
594
+ export const aegis128X2DecryptDetached = (
595
+ ct: Uint8Array,
596
+ tag: Uint8Array,
597
+ ad: Uint8Array,
598
+ key: Uint8Array,
599
+ nonce: Uint8Array,
600
+ ) => aegis128XDecryptDetached(ct, tag, ad, key, nonce, 2);
601
+
602
+ /** AEGIS-128X4 encryption - detached mode (degree=4). */
603
+ export const aegis128X4EncryptDetached = (
604
+ msg: Uint8Array,
605
+ ad: Uint8Array,
606
+ key: Uint8Array,
607
+ nonce: Uint8Array,
608
+ tagLen: 16 | 32 = 16,
609
+ ) => aegis128XEncryptDetached(msg, ad, key, nonce, tagLen, 4);
610
+
611
+ /** AEGIS-128X4 decryption - detached mode (degree=4). */
612
+ export const aegis128X4DecryptDetached = (
613
+ ct: Uint8Array,
614
+ tag: Uint8Array,
615
+ ad: Uint8Array,
616
+ key: Uint8Array,
617
+ nonce: Uint8Array,
618
+ ) => aegis128XDecryptDetached(ct, tag, ad, key, nonce, 4);
619
+
489
620
  /** AEGIS-128X2 encryption (degree=2). */
490
621
  export const aegis128X2Encrypt = (
491
622
  msg: Uint8Array,
492
623
  ad: Uint8Array,
493
624
  key: Uint8Array,
494
- nonce: Uint8Array,
625
+ nonce: Uint8Array | null = null,
495
626
  tagLen: 16 | 32 = 16,
496
627
  ) => aegis128XEncrypt(msg, ad, key, nonce, tagLen, 2);
497
628
 
498
629
  /** AEGIS-128X2 decryption (degree=2). */
499
630
  export const aegis128X2Decrypt = (
500
- ct: Uint8Array,
501
- tag: Uint8Array,
631
+ sealed: Uint8Array,
502
632
  ad: Uint8Array,
503
633
  key: Uint8Array,
504
- nonce: Uint8Array,
505
- ) => aegis128XDecrypt(ct, tag, ad, key, nonce, 2);
634
+ tagLen: 16 | 32 = 16,
635
+ ) => aegis128XDecrypt(sealed, ad, key, tagLen, 2);
506
636
 
507
637
  /** AEGIS-128X4 encryption (degree=4). */
508
638
  export const aegis128X4Encrypt = (
509
639
  msg: Uint8Array,
510
640
  ad: Uint8Array,
511
641
  key: Uint8Array,
512
- nonce: Uint8Array,
642
+ nonce: Uint8Array | null = null,
513
643
  tagLen: 16 | 32 = 16,
514
644
  ) => aegis128XEncrypt(msg, ad, key, nonce, tagLen, 4);
515
645
 
516
646
  /** AEGIS-128X4 decryption (degree=4). */
517
647
  export const aegis128X4Decrypt = (
518
- ct: Uint8Array,
519
- tag: Uint8Array,
648
+ sealed: Uint8Array,
520
649
  ad: Uint8Array,
521
650
  key: Uint8Array,
522
- nonce: Uint8Array,
523
- ) => aegis128XDecrypt(ct, tag, ad, key, nonce, 4);
651
+ tagLen: 16 | 32 = 16,
652
+ ) => aegis128XDecrypt(sealed, ad, key, tagLen, 4);
524
653
 
525
654
  /**
526
655
  * Computes a MAC (Message Authentication Code) using AEGIS-128X.
@@ -603,3 +732,33 @@ export const aegis128X4MacVerify = (
603
732
  key: Uint8Array,
604
733
  nonce: Uint8Array | null = null,
605
734
  ) => aegis128XMacVerify(data, tag, key, nonce, 4);
735
+
736
+ /**
737
+ * Generates a random 16-byte key for AEGIS-128X.
738
+ * @returns 16-byte encryption key
739
+ * @throws Error if no cryptographic random source is available
740
+ */
741
+ export function aegis128XCreateKey(): Uint8Array {
742
+ return randomBytes(AEGIS_128X_KEY_SIZE);
743
+ }
744
+
745
+ /**
746
+ * Generates a random 16-byte nonce for AEGIS-128X.
747
+ * @returns 16-byte nonce
748
+ * @throws Error if no cryptographic random source is available
749
+ */
750
+ export function aegis128XCreateNonce(): Uint8Array {
751
+ return randomBytes(AEGIS_128X_NONCE_SIZE);
752
+ }
753
+
754
+ /** AEGIS-128X2 key generation (degree=2). */
755
+ export const aegis128X2CreateKey = aegis128XCreateKey;
756
+
757
+ /** AEGIS-128X2 nonce generation (degree=2). */
758
+ export const aegis128X2CreateNonce = aegis128XCreateNonce;
759
+
760
+ /** AEGIS-128X4 key generation (degree=4). */
761
+ export const aegis128X4CreateKey = aegis128XCreateKey;
762
+
763
+ /** AEGIS-128X4 nonce generation (degree=4). */
764
+ export const aegis128X4CreateNonce = aegis128XCreateNonce;