simple-hpke 0.0.9 → 0.1.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.
- package/README.md +43 -35
- package/dist/constants.cjs +1788 -0
- package/dist/constants.cjs.map +7 -0
- package/dist/constants.d.ts +14 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +1771 -0
- package/dist/constants.js.map +7 -0
- package/dist/constants.min.cjs +2 -0
- package/dist/constants.min.cjs.map +7 -0
- package/dist/constants.min.js +2 -0
- package/dist/constants.min.js.map +7 -0
- package/dist/index.cjs +229 -203
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +37 -105
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +229 -203
- package/dist/index.js.map +4 -4
- package/dist/index.min.cjs +1 -1
- package/dist/index.min.cjs.map +4 -4
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +4 -4
- package/dist/meta.json +299 -4
- package/dist/util.cjs +1787 -0
- package/dist/util.cjs.map +7 -0
- package/dist/util.d.ts +90 -0
- package/dist/util.d.ts.map +1 -0
- package/dist/util.js +1770 -0
- package/dist/util.js.map +7 -0
- package/dist/util.min.cjs +2 -0
- package/dist/util.min.cjs.map +7 -0
- package/dist/util.min.js +2 -0
- package/dist/util.min.js.map +7 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
// src/index.ts
|
|
22
22
|
var index_exports = {};
|
|
23
23
|
__export(index_exports, {
|
|
24
|
+
create: () => create2,
|
|
24
25
|
decrypt: () => decrypt,
|
|
25
26
|
encrypt: () => encrypt,
|
|
26
27
|
open: () => open,
|
|
@@ -1306,8 +1307,7 @@ function toString2(array, encoding = "utf8") {
|
|
|
1306
1307
|
}
|
|
1307
1308
|
__name(toString2, "toString");
|
|
1308
1309
|
|
|
1309
|
-
// src/
|
|
1310
|
-
var subtle = globalThis.crypto.subtle;
|
|
1310
|
+
// src/constants.ts
|
|
1311
1311
|
var KEM_ID = 32;
|
|
1312
1312
|
var KDF_ID = 1;
|
|
1313
1313
|
var AEAD_ID = 2;
|
|
@@ -1318,6 +1318,7 @@ var ENC_LENGTH = 32;
|
|
|
1318
1318
|
var AEAD_TAG_LENGTH = 16;
|
|
1319
1319
|
var MODE_BASE = 0;
|
|
1320
1320
|
var HPKE_V1 = new TextEncoder().encode("HPKE-v1");
|
|
1321
|
+
var WRAPPED_LEN_PREFIX = 2;
|
|
1321
1322
|
var KEM_SUITE_ID = concat2(
|
|
1322
1323
|
new TextEncoder().encode("KEM"),
|
|
1323
1324
|
i2osp(KEM_ID, 2)
|
|
@@ -1328,174 +1329,68 @@ var HPKE_SUITE_ID = concat2(
|
|
|
1328
1329
|
i2osp(KDF_ID, 2),
|
|
1329
1330
|
i2osp(AEAD_ID, 2)
|
|
1330
1331
|
);
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
keyBytes = aesKey;
|
|
1337
|
-
} else if (aesKey) {
|
|
1338
|
-
keyBytes = await exportAesKeyBytes(aesKey);
|
|
1339
|
-
validateRawKeyBytes(keyBytes);
|
|
1340
|
-
} else {
|
|
1341
|
-
const keysize = opts?.keysize ?? 256;
|
|
1342
|
-
validateKeysize(keysize);
|
|
1343
|
-
keyBytes = globalThis.crypto.getRandomValues(
|
|
1344
|
-
new Uint8Array(keysize / 8)
|
|
1345
|
-
);
|
|
1346
|
-
}
|
|
1347
|
-
const publicKey = await resolveRecipientPublicKey(recipient);
|
|
1348
|
-
const { sharedSecret, enc } = await encap(publicKey);
|
|
1349
|
-
const { key, baseNonce } = await keySchedule(sharedSecret, info);
|
|
1350
|
-
const ciphertext = await aeadSeal(key, baseNonce, keyBytes);
|
|
1351
|
-
const wrapped = concat2(enc, ciphertext);
|
|
1352
|
-
const aesGcmKey = await importAesKey(keyBytes);
|
|
1353
|
-
return { wrapped, key: aesGcmKey };
|
|
1354
|
-
}
|
|
1355
|
-
__name(seal, "seal");
|
|
1356
|
-
async function openBytes(keypair, wrapped, opts) {
|
|
1357
|
-
const keyBytes = await openRawBytes(keypair, wrapped, opts);
|
|
1358
|
-
return importAesKey(keyBytes);
|
|
1359
|
-
}
|
|
1360
|
-
__name(openBytes, "openBytes");
|
|
1361
|
-
async function openRawBytes(keypair, wrapped, opts) {
|
|
1362
|
-
if (wrapped.byteLength < ENC_LENGTH + AEAD_TAG_LENGTH) {
|
|
1363
|
-
throw new Error("malformed envelope: too short");
|
|
1364
|
-
}
|
|
1365
|
-
const info = normalizeInfo(opts?.info);
|
|
1366
|
-
const enc = wrapped.slice(0, ENC_LENGTH);
|
|
1367
|
-
const ciphertext = wrapped.slice(ENC_LENGTH);
|
|
1368
|
-
const sharedSecret = await decap(enc, keypair);
|
|
1369
|
-
const { key, baseNonce } = await keySchedule(sharedSecret, info);
|
|
1370
|
-
return aeadOpen(key, baseNonce, ciphertext);
|
|
1371
|
-
}
|
|
1372
|
-
__name(openRawBytes, "openRawBytes");
|
|
1373
|
-
var open = Object.assign(openBytes, {
|
|
1374
|
-
raw: openRawBytes
|
|
1375
|
-
});
|
|
1376
|
-
var WRAPPED_LEN_PREFIX = 2;
|
|
1377
|
-
var encrypt = Object.assign(encryptBytes, {
|
|
1378
|
-
asString: encryptToString
|
|
1379
|
-
});
|
|
1380
|
-
var decrypt = Object.assign(decryptBytes, {
|
|
1381
|
-
asString: decryptToString,
|
|
1382
|
-
fromString: decryptFromString
|
|
1383
|
-
});
|
|
1384
|
-
async function decryptBytes(keypair, message, opts) {
|
|
1385
|
-
if (message.byteLength < WRAPPED_LEN_PREFIX) {
|
|
1386
|
-
throw new Error("malformed message: too short");
|
|
1387
|
-
}
|
|
1388
|
-
const wrappedLen = message[0] << 8 | message[1];
|
|
1389
|
-
const ivStart = WRAPPED_LEN_PREFIX + wrappedLen;
|
|
1390
|
-
const ctStart = ivStart + NN;
|
|
1391
|
-
if (message.byteLength < ctStart + AEAD_TAG_LENGTH) {
|
|
1392
|
-
throw new Error("malformed message: too short");
|
|
1393
|
-
}
|
|
1394
|
-
const wrapped = message.slice(WRAPPED_LEN_PREFIX, ivStart);
|
|
1395
|
-
const iv = message.slice(ivStart, ctStart);
|
|
1396
|
-
const ciphertext = message.slice(ctStart);
|
|
1397
|
-
const keyBytes = await openRawBytes(
|
|
1398
|
-
keypair,
|
|
1399
|
-
wrapped,
|
|
1400
|
-
opts?.info !== void 0 ? { info: opts.info } : void 0
|
|
1401
|
-
);
|
|
1402
|
-
const key = await importAesKeyDecryptOnly(keyBytes);
|
|
1403
|
-
const pt = await subtle.decrypt(
|
|
1404
|
-
{ name: "AES-GCM", iv },
|
|
1405
|
-
key,
|
|
1406
|
-
ciphertext
|
|
1407
|
-
);
|
|
1408
|
-
return new Uint8Array(pt);
|
|
1409
|
-
}
|
|
1410
|
-
__name(decryptBytes, "decryptBytes");
|
|
1411
|
-
async function decryptToString(keypair, message, opts) {
|
|
1412
|
-
const bytes = await decryptBytes(keypair, message, opts);
|
|
1413
|
-
return new TextDecoder().decode(bytes);
|
|
1414
|
-
}
|
|
1415
|
-
__name(decryptToString, "decryptToString");
|
|
1416
|
-
async function decryptFromString(keypair, message, opts) {
|
|
1417
|
-
const bytes = fromString2(message, "base64url");
|
|
1418
|
-
const plaintext = await decryptBytes(
|
|
1419
|
-
keypair,
|
|
1420
|
-
bytes,
|
|
1421
|
-
opts?.info !== void 0 ? { info: opts.info } : void 0
|
|
1422
|
-
);
|
|
1423
|
-
return opts?.buffer ? plaintext : new TextDecoder().decode(plaintext);
|
|
1424
|
-
}
|
|
1425
|
-
__name(decryptFromString, "decryptFromString");
|
|
1426
|
-
function validateKeysize(keysize) {
|
|
1427
|
-
if (keysize !== 128 && keysize !== 256) {
|
|
1428
|
-
throw new Error(
|
|
1429
|
-
`invalid keysize: ${keysize} (expected 128 or 256)`
|
|
1430
|
-
);
|
|
1431
|
-
}
|
|
1432
|
-
}
|
|
1433
|
-
__name(validateKeysize, "validateKeysize");
|
|
1434
|
-
function validateRawKeyBytes(raw) {
|
|
1435
|
-
if (raw.length !== 16 && raw.length !== 32) {
|
|
1436
|
-
throw new Error(
|
|
1437
|
-
`invalid aesKey length: ${raw.length} bytes (expected 16 or 32)`
|
|
1438
|
-
);
|
|
1439
|
-
}
|
|
1440
|
-
}
|
|
1441
|
-
__name(validateRawKeyBytes, "validateRawKeyBytes");
|
|
1442
|
-
function normalizeInfo(info) {
|
|
1443
|
-
if (info === void 0 || info === null) return new Uint8Array(0);
|
|
1444
|
-
if (typeof info === "string") return new TextEncoder().encode(info);
|
|
1445
|
-
return info;
|
|
1446
|
-
}
|
|
1447
|
-
__name(normalizeInfo, "normalizeInfo");
|
|
1448
|
-
async function exportAesKeyBytes(key) {
|
|
1449
|
-
if (!key.extractable) {
|
|
1450
|
-
throw new Error(
|
|
1451
|
-
"aesKey must be extractable: its raw bytes are what get sealed"
|
|
1452
|
-
);
|
|
1453
|
-
}
|
|
1454
|
-
return new Uint8Array(await subtle.exportKey("raw", key));
|
|
1455
|
-
}
|
|
1456
|
-
__name(exportAesKeyBytes, "exportAesKeyBytes");
|
|
1457
|
-
async function importAesKey(raw) {
|
|
1458
|
-
return subtle.importKey(
|
|
1332
|
+
|
|
1333
|
+
// src/util.ts
|
|
1334
|
+
var subtle = globalThis.crypto.subtle;
|
|
1335
|
+
async function aeadSeal(key, nonce, plaintext) {
|
|
1336
|
+
const k = await subtle.importKey(
|
|
1459
1337
|
"raw",
|
|
1460
|
-
|
|
1338
|
+
key,
|
|
1461
1339
|
{ name: "AES-GCM" },
|
|
1462
|
-
|
|
1463
|
-
["encrypt"
|
|
1340
|
+
false,
|
|
1341
|
+
["encrypt"]
|
|
1342
|
+
);
|
|
1343
|
+
const ct = await subtle.encrypt(
|
|
1344
|
+
{ name: "AES-GCM", iv: nonce },
|
|
1345
|
+
k,
|
|
1346
|
+
plaintext
|
|
1464
1347
|
);
|
|
1348
|
+
return new Uint8Array(ct);
|
|
1465
1349
|
}
|
|
1466
|
-
__name(
|
|
1467
|
-
async function
|
|
1468
|
-
|
|
1350
|
+
__name(aeadSeal, "aeadSeal");
|
|
1351
|
+
async function aeadOpen(key, nonce, ciphertext) {
|
|
1352
|
+
const k = await subtle.importKey(
|
|
1469
1353
|
"raw",
|
|
1470
|
-
|
|
1354
|
+
key,
|
|
1471
1355
|
{ name: "AES-GCM" },
|
|
1472
1356
|
false,
|
|
1473
1357
|
["decrypt"]
|
|
1474
1358
|
);
|
|
1359
|
+
const pt = await subtle.decrypt(
|
|
1360
|
+
{ name: "AES-GCM", iv: nonce },
|
|
1361
|
+
k,
|
|
1362
|
+
ciphertext
|
|
1363
|
+
);
|
|
1364
|
+
return new Uint8Array(pt);
|
|
1475
1365
|
}
|
|
1476
|
-
__name(
|
|
1477
|
-
function
|
|
1478
|
-
const
|
|
1479
|
-
let
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1366
|
+
__name(aeadOpen, "aeadOpen");
|
|
1367
|
+
async function encryptBytes(recipient, message, aesKey, opts) {
|
|
1368
|
+
const plaintext = typeof message === "string" ? new TextEncoder().encode(message) : message;
|
|
1369
|
+
let enc;
|
|
1370
|
+
let key;
|
|
1371
|
+
if (!aesKey) {
|
|
1372
|
+
const keys = await create2(recipient, opts);
|
|
1373
|
+
enc = keys.enc;
|
|
1374
|
+
key = keys.key;
|
|
1375
|
+
} else {
|
|
1376
|
+
const keys = await seal(recipient, aesKey, opts);
|
|
1377
|
+
enc = keys.enc;
|
|
1378
|
+
key = keys.key;
|
|
1483
1379
|
}
|
|
1484
|
-
|
|
1380
|
+
const iv = globalThis.crypto.getRandomValues(new Uint8Array(NN));
|
|
1381
|
+
const ct = new Uint8Array(await subtle.encrypt(
|
|
1382
|
+
{ name: "AES-GCM", iv },
|
|
1383
|
+
key,
|
|
1384
|
+
plaintext
|
|
1385
|
+
));
|
|
1386
|
+
return concat2(i2osp(enc.length, WRAPPED_LEN_PREFIX), enc, iv, ct);
|
|
1485
1387
|
}
|
|
1486
|
-
__name(
|
|
1487
|
-
function
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
const out = new Uint8Array(total);
|
|
1491
|
-
let offset = 0;
|
|
1492
|
-
for (const a of arrays) {
|
|
1493
|
-
out.set(a, offset);
|
|
1494
|
-
offset += a.length;
|
|
1495
|
-
}
|
|
1496
|
-
return out;
|
|
1388
|
+
__name(encryptBytes, "encryptBytes");
|
|
1389
|
+
async function encryptToString(recipient, message, aesKey, opts) {
|
|
1390
|
+
const envelope = await encryptBytes(recipient, message, aesKey, opts);
|
|
1391
|
+
return toString2(envelope, opts?.encoding ?? "base64url");
|
|
1497
1392
|
}
|
|
1498
|
-
__name(
|
|
1393
|
+
__name(encryptToString, "encryptToString");
|
|
1499
1394
|
async function hmac(key, data) {
|
|
1500
1395
|
const k = await subtle.importKey(
|
|
1501
1396
|
"raw",
|
|
@@ -1664,6 +1559,144 @@ async function decap(enc, keypair) {
|
|
|
1664
1559
|
return extractAndExpand(dhBytes, kemContext);
|
|
1665
1560
|
}
|
|
1666
1561
|
__name(decap, "decap");
|
|
1562
|
+
function i2osp(n, len) {
|
|
1563
|
+
const out = new Uint8Array(len);
|
|
1564
|
+
let v = n;
|
|
1565
|
+
for (let i = len - 1; i >= 0; i--) {
|
|
1566
|
+
out[i] = v & 255;
|
|
1567
|
+
v = Math.floor(v / 256);
|
|
1568
|
+
}
|
|
1569
|
+
return out;
|
|
1570
|
+
}
|
|
1571
|
+
__name(i2osp, "i2osp");
|
|
1572
|
+
function concat2(...arrays) {
|
|
1573
|
+
let total = 0;
|
|
1574
|
+
for (const a of arrays) total += a.length;
|
|
1575
|
+
const out = new Uint8Array(total);
|
|
1576
|
+
let offset = 0;
|
|
1577
|
+
for (const a of arrays) {
|
|
1578
|
+
out.set(a, offset);
|
|
1579
|
+
offset += a.length;
|
|
1580
|
+
}
|
|
1581
|
+
return out;
|
|
1582
|
+
}
|
|
1583
|
+
__name(concat2, "concat");
|
|
1584
|
+
|
|
1585
|
+
// src/index.ts
|
|
1586
|
+
var subtle2 = globalThis.crypto.subtle;
|
|
1587
|
+
async function create2(recipient, opts) {
|
|
1588
|
+
const { wrapped, key } = await encryptKey(recipient, null, opts);
|
|
1589
|
+
return { enc: wrapped, key };
|
|
1590
|
+
}
|
|
1591
|
+
__name(create2, "create");
|
|
1592
|
+
async function seal(recipient, aesKey, opts) {
|
|
1593
|
+
const { wrapped, key } = await encryptKey(recipient, aesKey, opts);
|
|
1594
|
+
return { enc: wrapped, key };
|
|
1595
|
+
}
|
|
1596
|
+
__name(seal, "seal");
|
|
1597
|
+
var open = Object.assign(openBytes, {
|
|
1598
|
+
raw: openRawBytes
|
|
1599
|
+
});
|
|
1600
|
+
var encrypt = Object.assign(encryptBytes, {
|
|
1601
|
+
asString: encryptToString
|
|
1602
|
+
});
|
|
1603
|
+
var decrypt = Object.assign(decryptBytes, {
|
|
1604
|
+
asString: decryptToString,
|
|
1605
|
+
fromString: decryptFromString
|
|
1606
|
+
});
|
|
1607
|
+
async function decryptBytes(keypair, message, opts) {
|
|
1608
|
+
if (message.byteLength < WRAPPED_LEN_PREFIX) {
|
|
1609
|
+
throw new Error("malformed message: too short");
|
|
1610
|
+
}
|
|
1611
|
+
const wrappedLen = message[0] << 8 | message[1];
|
|
1612
|
+
const ivStart = WRAPPED_LEN_PREFIX + wrappedLen;
|
|
1613
|
+
const ctStart = ivStart + NN;
|
|
1614
|
+
if (message.byteLength < ctStart + AEAD_TAG_LENGTH) {
|
|
1615
|
+
throw new Error("malformed message: too short");
|
|
1616
|
+
}
|
|
1617
|
+
const wrapped = message.slice(WRAPPED_LEN_PREFIX, ivStart);
|
|
1618
|
+
const iv = message.slice(ivStart, ctStart);
|
|
1619
|
+
const ciphertext = message.slice(ctStart);
|
|
1620
|
+
const keyBytes = await openRawBytes(
|
|
1621
|
+
keypair,
|
|
1622
|
+
wrapped,
|
|
1623
|
+
opts?.info !== void 0 ? { info: opts.info } : void 0
|
|
1624
|
+
);
|
|
1625
|
+
const key = await importAesKeyDecryptOnly(keyBytes);
|
|
1626
|
+
const pt = await subtle2.decrypt(
|
|
1627
|
+
{ name: "AES-GCM", iv },
|
|
1628
|
+
key,
|
|
1629
|
+
ciphertext
|
|
1630
|
+
);
|
|
1631
|
+
return new Uint8Array(pt);
|
|
1632
|
+
}
|
|
1633
|
+
__name(decryptBytes, "decryptBytes");
|
|
1634
|
+
async function decryptToString(keypair, message, opts) {
|
|
1635
|
+
const bytes = await decryptBytes(keypair, message, opts);
|
|
1636
|
+
return new TextDecoder().decode(bytes);
|
|
1637
|
+
}
|
|
1638
|
+
__name(decryptToString, "decryptToString");
|
|
1639
|
+
async function decryptFromString(keypair, message, opts) {
|
|
1640
|
+
const bytes = fromString2(message, "base64url");
|
|
1641
|
+
const plaintext = await decryptBytes(
|
|
1642
|
+
keypair,
|
|
1643
|
+
bytes,
|
|
1644
|
+
opts?.info !== void 0 ? { info: opts.info } : void 0
|
|
1645
|
+
);
|
|
1646
|
+
return opts?.buffer ? plaintext : new TextDecoder().decode(plaintext);
|
|
1647
|
+
}
|
|
1648
|
+
__name(decryptFromString, "decryptFromString");
|
|
1649
|
+
function validateKeysize(keysize) {
|
|
1650
|
+
if (keysize !== 128 && keysize !== 256) {
|
|
1651
|
+
throw new Error(
|
|
1652
|
+
`invalid keysize: ${keysize} (expected 128 or 256)`
|
|
1653
|
+
);
|
|
1654
|
+
}
|
|
1655
|
+
}
|
|
1656
|
+
__name(validateKeysize, "validateKeysize");
|
|
1657
|
+
function validateRawKeyBytes(raw) {
|
|
1658
|
+
if (raw.length !== 16 && raw.length !== 32) {
|
|
1659
|
+
throw new Error(
|
|
1660
|
+
`invalid aesKey length: ${raw.length} bytes (expected 16 or 32)`
|
|
1661
|
+
);
|
|
1662
|
+
}
|
|
1663
|
+
}
|
|
1664
|
+
__name(validateRawKeyBytes, "validateRawKeyBytes");
|
|
1665
|
+
function normalizeInfo(info) {
|
|
1666
|
+
if (info === void 0 || info === null) return new Uint8Array(0);
|
|
1667
|
+
if (typeof info === "string") return new TextEncoder().encode(info);
|
|
1668
|
+
return info;
|
|
1669
|
+
}
|
|
1670
|
+
__name(normalizeInfo, "normalizeInfo");
|
|
1671
|
+
async function exportAesKeyBytes(key) {
|
|
1672
|
+
if (!key.extractable) {
|
|
1673
|
+
throw new Error(
|
|
1674
|
+
"aesKey must be extractable: its raw bytes are what get sealed"
|
|
1675
|
+
);
|
|
1676
|
+
}
|
|
1677
|
+
return new Uint8Array(await subtle2.exportKey("raw", key));
|
|
1678
|
+
}
|
|
1679
|
+
__name(exportAesKeyBytes, "exportAesKeyBytes");
|
|
1680
|
+
async function importAesKey(raw) {
|
|
1681
|
+
return subtle2.importKey(
|
|
1682
|
+
"raw",
|
|
1683
|
+
raw,
|
|
1684
|
+
{ name: "AES-GCM" },
|
|
1685
|
+
true,
|
|
1686
|
+
["encrypt", "decrypt"]
|
|
1687
|
+
);
|
|
1688
|
+
}
|
|
1689
|
+
__name(importAesKey, "importAesKey");
|
|
1690
|
+
async function importAesKeyDecryptOnly(raw) {
|
|
1691
|
+
return subtle2.importKey(
|
|
1692
|
+
"raw",
|
|
1693
|
+
raw,
|
|
1694
|
+
{ name: "AES-GCM" },
|
|
1695
|
+
false,
|
|
1696
|
+
["decrypt"]
|
|
1697
|
+
);
|
|
1698
|
+
}
|
|
1699
|
+
__name(importAesKeyDecryptOnly, "importAesKeyDecryptOnly");
|
|
1667
1700
|
async function keySchedule(sharedSecret, info) {
|
|
1668
1701
|
const empty2 = new Uint8Array(0);
|
|
1669
1702
|
const pskIdHash = await labeledExtract(
|
|
@@ -1702,53 +1735,46 @@ async function keySchedule(sharedSecret, info) {
|
|
|
1702
1735
|
return { key, baseNonce };
|
|
1703
1736
|
}
|
|
1704
1737
|
__name(keySchedule, "keySchedule");
|
|
1705
|
-
async function
|
|
1706
|
-
|
|
1707
|
-
"
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
);
|
|
1713
|
-
const
|
|
1714
|
-
|
|
1715
|
-
k,
|
|
1716
|
-
plaintext
|
|
1717
|
-
);
|
|
1718
|
-
return new Uint8Array(ct);
|
|
1719
|
-
}
|
|
1720
|
-
__name(aeadSeal, "aeadSeal");
|
|
1721
|
-
async function aeadOpen(key, nonce, ciphertext) {
|
|
1722
|
-
const k = await subtle.importKey(
|
|
1723
|
-
"raw",
|
|
1724
|
-
key,
|
|
1725
|
-
{ name: "AES-GCM" },
|
|
1726
|
-
false,
|
|
1727
|
-
["decrypt"]
|
|
1728
|
-
);
|
|
1729
|
-
const pt = await subtle.decrypt(
|
|
1730
|
-
{ name: "AES-GCM", iv: nonce },
|
|
1731
|
-
k,
|
|
1732
|
-
ciphertext
|
|
1733
|
-
);
|
|
1734
|
-
return new Uint8Array(pt);
|
|
1738
|
+
async function openRawBytes(keypair, wrapped, opts) {
|
|
1739
|
+
if (wrapped.byteLength < ENC_LENGTH + AEAD_TAG_LENGTH) {
|
|
1740
|
+
throw new Error("malformed envelope: too short");
|
|
1741
|
+
}
|
|
1742
|
+
const info = normalizeInfo(opts?.info);
|
|
1743
|
+
const enc = wrapped.slice(0, ENC_LENGTH);
|
|
1744
|
+
const ciphertext = wrapped.slice(ENC_LENGTH);
|
|
1745
|
+
const sharedSecret = await decap(enc, keypair);
|
|
1746
|
+
const { key, baseNonce } = await keySchedule(sharedSecret, info);
|
|
1747
|
+
return aeadOpen(key, baseNonce, ciphertext);
|
|
1735
1748
|
}
|
|
1736
|
-
__name(
|
|
1737
|
-
async function
|
|
1738
|
-
const
|
|
1739
|
-
|
|
1740
|
-
const iv = globalThis.crypto.getRandomValues(new Uint8Array(NN));
|
|
1741
|
-
const ct = new Uint8Array(await subtle.encrypt(
|
|
1742
|
-
{ name: "AES-GCM", iv },
|
|
1743
|
-
key,
|
|
1744
|
-
plaintext
|
|
1745
|
-
));
|
|
1746
|
-
return concat2(i2osp(wrapped.length, WRAPPED_LEN_PREFIX), wrapped, iv, ct);
|
|
1749
|
+
__name(openRawBytes, "openRawBytes");
|
|
1750
|
+
async function openBytes(keypair, wrapped, opts) {
|
|
1751
|
+
const keyBytes = await openRawBytes(keypair, wrapped, opts);
|
|
1752
|
+
return importAesKey(keyBytes);
|
|
1747
1753
|
}
|
|
1748
|
-
__name(
|
|
1749
|
-
async function
|
|
1750
|
-
const
|
|
1751
|
-
|
|
1754
|
+
__name(openBytes, "openBytes");
|
|
1755
|
+
async function encryptKey(recipient, aesKey, opts) {
|
|
1756
|
+
const info = normalizeInfo(opts?.info);
|
|
1757
|
+
let keyBytes;
|
|
1758
|
+
if (aesKey instanceof Uint8Array) {
|
|
1759
|
+
validateRawKeyBytes(aesKey);
|
|
1760
|
+
keyBytes = aesKey;
|
|
1761
|
+
} else if (aesKey) {
|
|
1762
|
+
keyBytes = await exportAesKeyBytes(aesKey);
|
|
1763
|
+
validateRawKeyBytes(keyBytes);
|
|
1764
|
+
} else {
|
|
1765
|
+
const keysize = opts?.size ?? 256;
|
|
1766
|
+
validateKeysize(keysize);
|
|
1767
|
+
keyBytes = globalThis.crypto.getRandomValues(
|
|
1768
|
+
new Uint8Array(keysize / 8)
|
|
1769
|
+
);
|
|
1770
|
+
}
|
|
1771
|
+
const publicKey = await resolveRecipientPublicKey(recipient);
|
|
1772
|
+
const { sharedSecret, enc } = await encap(publicKey);
|
|
1773
|
+
const { key, baseNonce } = await keySchedule(sharedSecret, info);
|
|
1774
|
+
const ciphertext = await aeadSeal(key, baseNonce, keyBytes);
|
|
1775
|
+
const wrapped = concat2(enc, ciphertext);
|
|
1776
|
+
const aesGcmKey = await importAesKey(keyBytes);
|
|
1777
|
+
return { wrapped, key: aesGcmKey };
|
|
1752
1778
|
}
|
|
1753
|
-
__name(
|
|
1779
|
+
__name(encryptKey, "encryptKey");
|
|
1754
1780
|
//# sourceMappingURL=index.cjs.map
|