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.
- package/README.md +195 -89
- package/dist/aegis128l-bs.d.ts +194 -0
- package/dist/aegis128l-bs.d.ts.map +1 -0
- package/dist/aegis128l-bs.js +549 -0
- package/dist/aegis128l-bs.js.map +1 -0
- package/dist/aegis128l.d.ts +74 -5
- package/dist/aegis128l.d.ts.map +1 -1
- package/dist/aegis128l.js +173 -5
- package/dist/aegis128l.js.map +1 -1
- package/dist/aegis128x.d.ts +109 -12
- package/dist/aegis128x.d.ts.map +1 -1
- package/dist/aegis128x.js +202 -9
- package/dist/aegis128x.js.map +1 -1
- package/dist/aegis256-bs.d.ts +183 -0
- package/dist/aegis256-bs.d.ts.map +1 -0
- package/dist/aegis256-bs.js +477 -0
- package/dist/aegis256-bs.js.map +1 -0
- package/dist/aegis256.d.ts +74 -5
- package/dist/aegis256.d.ts.map +1 -1
- package/dist/aegis256.js +158 -5
- package/dist/aegis256.js.map +1 -1
- package/dist/aegis256x.d.ts +109 -12
- package/dist/aegis256x.d.ts.map +1 -1
- package/dist/aegis256x.js +193 -9
- package/dist/aegis256x.js.map +1 -1
- package/dist/aes-bs.d.ts +71 -0
- package/dist/aes-bs.d.ts.map +1 -0
- package/dist/aes-bs.js +399 -0
- package/dist/aes-bs.js.map +1 -0
- package/dist/index.d.ts +6 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -4
- package/dist/index.js.map +1 -1
- package/dist/random.d.ts +22 -0
- package/dist/random.d.ts.map +1 -0
- package/dist/random.js +36 -0
- package/dist/random.js.map +1 -0
- package/package.json +1 -1
- package/src/aegis128l-bs.ts +709 -0
- package/src/aegis128l.ts +238 -5
- package/src/aegis128x.ts +342 -15
- package/src/aegis256-bs.ts +625 -0
- package/src/aegis256.ts +223 -5
- package/src/aegis256x.ts +329 -15
- package/src/aes-bs.ts +459 -0
- package/src/index.ts +86 -0
- package/src/random.ts +41 -0
- 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
|
|
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
|
|
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
|
+
}
|