simple-hpke 0.2.0 → 0.3.3
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 +207 -27
- package/dist/constants.cjs +188 -47
- package/dist/constants.cjs.map +4 -4
- package/dist/constants.d.ts +2 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +188 -47
- package/dist/constants.js.map +4 -4
- package/dist/constants.min.cjs +1 -1
- package/dist/constants.min.cjs.map +4 -4
- package/dist/constants.min.js +1 -1
- package/dist/constants.min.js.map +4 -4
- package/dist/errors.cjs +38 -0
- package/dist/errors.cjs.map +7 -0
- package/dist/errors.d.ts +22 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +19 -0
- package/dist/errors.js.map +7 -0
- package/dist/errors.min.cjs +2 -0
- package/dist/errors.min.cjs.map +7 -0
- package/dist/errors.min.js +2 -0
- package/dist/errors.min.js.map +7 -0
- package/dist/index.cjs +231 -50
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +34 -21
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +231 -50
- 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 +81 -20
- package/dist/util.cjs +228 -48
- package/dist/util.cjs.map +4 -4
- package/dist/util.d.ts +56 -3
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +228 -48
- package/dist/util.js.map +4 -4
- package/dist/util.min.cjs +1 -1
- package/dist/util.min.cjs.map +4 -4
- package/dist/util.min.js +1 -1
- package/dist/util.min.js.map +4 -4
- package/package.json +6 -5
package/dist/constants.cjs
CHANGED
|
@@ -29,6 +29,8 @@ __export(constants_exports, {
|
|
|
29
29
|
KDF_ID: () => KDF_ID,
|
|
30
30
|
KEM_ID: () => KEM_ID,
|
|
31
31
|
KEM_SUITE_ID: () => KEM_SUITE_ID,
|
|
32
|
+
KEY_ID_LABEL: () => KEY_ID_LABEL,
|
|
33
|
+
KEY_ID_NONCE_LENGTH: () => KEY_ID_NONCE_LENGTH,
|
|
32
34
|
MODE_BASE: () => MODE_BASE,
|
|
33
35
|
NK: () => NK,
|
|
34
36
|
NN: () => NN,
|
|
@@ -1315,6 +1317,19 @@ function toString2(array, encoding = "utf8") {
|
|
|
1315
1317
|
}
|
|
1316
1318
|
__name(toString2, "toString");
|
|
1317
1319
|
|
|
1320
|
+
// src/errors.ts
|
|
1321
|
+
var HpkeError = class extends Error {
|
|
1322
|
+
static {
|
|
1323
|
+
__name(this, "HpkeError");
|
|
1324
|
+
}
|
|
1325
|
+
code;
|
|
1326
|
+
constructor(code2, message, opts) {
|
|
1327
|
+
super(message, opts);
|
|
1328
|
+
this.name = "HpkeError";
|
|
1329
|
+
this.code = code2;
|
|
1330
|
+
}
|
|
1331
|
+
};
|
|
1332
|
+
|
|
1318
1333
|
// src/index.ts
|
|
1319
1334
|
var subtle = globalThis.crypto.subtle;
|
|
1320
1335
|
var open = Object.assign(openBytes, {
|
|
@@ -1329,13 +1344,19 @@ var decrypt = Object.assign(decryptBytes, {
|
|
|
1329
1344
|
});
|
|
1330
1345
|
async function decryptBytes(keypair, message, opts) {
|
|
1331
1346
|
if (message.byteLength < WRAPPED_LEN_PREFIX) {
|
|
1332
|
-
throw new
|
|
1347
|
+
throw new HpkeError(
|
|
1348
|
+
"ERR_MALFORMED_MESSAGE",
|
|
1349
|
+
"malformed message: too short"
|
|
1350
|
+
);
|
|
1333
1351
|
}
|
|
1334
1352
|
const wrappedLen = message[0] << 8 | message[1];
|
|
1335
1353
|
const ivStart = WRAPPED_LEN_PREFIX + wrappedLen;
|
|
1336
1354
|
const ctStart = ivStart + NN;
|
|
1337
1355
|
if (message.byteLength < ctStart + AEAD_TAG_LENGTH) {
|
|
1338
|
-
throw new
|
|
1356
|
+
throw new HpkeError(
|
|
1357
|
+
"ERR_MALFORMED_MESSAGE",
|
|
1358
|
+
"malformed message: too short"
|
|
1359
|
+
);
|
|
1339
1360
|
}
|
|
1340
1361
|
const wrapped = message.slice(WRAPPED_LEN_PREFIX, ivStart);
|
|
1341
1362
|
const iv = message.slice(ivStart, ctStart);
|
|
@@ -1346,11 +1367,20 @@ async function decryptBytes(keypair, message, opts) {
|
|
|
1346
1367
|
opts?.info !== void 0 ? { info: opts.info } : void 0
|
|
1347
1368
|
);
|
|
1348
1369
|
const key = await importAesKeyDecryptOnly(keyBytes);
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1370
|
+
let pt;
|
|
1371
|
+
try {
|
|
1372
|
+
pt = await subtle.decrypt(
|
|
1373
|
+
{ name: "AES-GCM", iv },
|
|
1374
|
+
key,
|
|
1375
|
+
ciphertext
|
|
1376
|
+
);
|
|
1377
|
+
} catch (err) {
|
|
1378
|
+
throw new HpkeError(
|
|
1379
|
+
"ERR_DECRYPT_FAILED",
|
|
1380
|
+
"failed to decrypt the message: tampered ciphertext",
|
|
1381
|
+
{ cause: err }
|
|
1382
|
+
);
|
|
1383
|
+
}
|
|
1354
1384
|
return new Uint8Array(pt);
|
|
1355
1385
|
}
|
|
1356
1386
|
__name(decryptBytes, "decryptBytes");
|
|
@@ -1360,7 +1390,16 @@ async function decryptToString(keypair, message, opts) {
|
|
|
1360
1390
|
}
|
|
1361
1391
|
__name(decryptToString, "decryptToString");
|
|
1362
1392
|
async function decryptFromString(keypair, message, opts) {
|
|
1363
|
-
|
|
1393
|
+
let bytes;
|
|
1394
|
+
try {
|
|
1395
|
+
bytes = fromString2(message, "base64url");
|
|
1396
|
+
} catch (err) {
|
|
1397
|
+
throw new HpkeError(
|
|
1398
|
+
"ERR_MALFORMED_MESSAGE",
|
|
1399
|
+
"malformed message: not base64url",
|
|
1400
|
+
{ cause: err }
|
|
1401
|
+
);
|
|
1402
|
+
}
|
|
1364
1403
|
const plaintext = await decryptBytes(
|
|
1365
1404
|
keypair,
|
|
1366
1405
|
bytes,
|
|
@@ -1371,7 +1410,8 @@ async function decryptFromString(keypair, message, opts) {
|
|
|
1371
1410
|
__name(decryptFromString, "decryptFromString");
|
|
1372
1411
|
function validateKeysize(keysize) {
|
|
1373
1412
|
if (keysize !== 128 && keysize !== 256) {
|
|
1374
|
-
throw new
|
|
1413
|
+
throw new HpkeError(
|
|
1414
|
+
"ERR_INVALID_KEYSIZE",
|
|
1375
1415
|
`invalid keysize: ${keysize} (expected 128 or 256)`
|
|
1376
1416
|
);
|
|
1377
1417
|
}
|
|
@@ -1379,7 +1419,8 @@ function validateKeysize(keysize) {
|
|
|
1379
1419
|
__name(validateKeysize, "validateKeysize");
|
|
1380
1420
|
function validateRawKeyBytes(raw) {
|
|
1381
1421
|
if (raw.length !== 16 && raw.length !== 32) {
|
|
1382
|
-
throw new
|
|
1422
|
+
throw new HpkeError(
|
|
1423
|
+
"ERR_INVALID_AES_KEY",
|
|
1383
1424
|
`invalid aesKey length: ${raw.length} bytes (expected 16 or 32)`
|
|
1384
1425
|
);
|
|
1385
1426
|
}
|
|
@@ -1393,19 +1434,20 @@ function normalizeInfo(info) {
|
|
|
1393
1434
|
__name(normalizeInfo, "normalizeInfo");
|
|
1394
1435
|
async function exportAesKeyBytes(key) {
|
|
1395
1436
|
if (!key.extractable) {
|
|
1396
|
-
throw new
|
|
1437
|
+
throw new HpkeError(
|
|
1438
|
+
"ERR_INVALID_AES_KEY",
|
|
1397
1439
|
"aesKey must be extractable: its raw bytes are what get sealed"
|
|
1398
1440
|
);
|
|
1399
1441
|
}
|
|
1400
1442
|
return new Uint8Array(await subtle.exportKey("raw", key));
|
|
1401
1443
|
}
|
|
1402
1444
|
__name(exportAesKeyBytes, "exportAesKeyBytes");
|
|
1403
|
-
async function importAesKey(raw) {
|
|
1445
|
+
async function importAesKey(raw, extractable) {
|
|
1404
1446
|
return subtle.importKey(
|
|
1405
1447
|
"raw",
|
|
1406
1448
|
raw,
|
|
1407
1449
|
{ name: "AES-GCM" },
|
|
1408
|
-
|
|
1450
|
+
extractable,
|
|
1409
1451
|
["encrypt", "decrypt"]
|
|
1410
1452
|
);
|
|
1411
1453
|
}
|
|
@@ -1460,7 +1502,10 @@ async function keySchedule(sharedSecret, info) {
|
|
|
1460
1502
|
__name(keySchedule, "keySchedule");
|
|
1461
1503
|
async function openRawBytes(keypair, wrapped, opts) {
|
|
1462
1504
|
if (wrapped.byteLength < ENC_LENGTH + AEAD_TAG_LENGTH) {
|
|
1463
|
-
throw new
|
|
1505
|
+
throw new HpkeError(
|
|
1506
|
+
"ERR_MALFORMED_ENVELOPE",
|
|
1507
|
+
"malformed envelope: too short"
|
|
1508
|
+
);
|
|
1464
1509
|
}
|
|
1465
1510
|
const info = normalizeInfo(opts?.info);
|
|
1466
1511
|
const enc = wrapped.slice(0, ENC_LENGTH);
|
|
@@ -1472,7 +1517,7 @@ async function openRawBytes(keypair, wrapped, opts) {
|
|
|
1472
1517
|
__name(openRawBytes, "openRawBytes");
|
|
1473
1518
|
async function openBytes(keypair, wrapped, opts) {
|
|
1474
1519
|
const keyBytes = await openRawBytes(keypair, wrapped, opts);
|
|
1475
|
-
return importAesKey(keyBytes);
|
|
1520
|
+
return importAesKey(keyBytes, opts?.extractable ?? false);
|
|
1476
1521
|
}
|
|
1477
1522
|
__name(openBytes, "openBytes");
|
|
1478
1523
|
async function encryptKey(recipient, aesKey, opts) {
|
|
@@ -1482,6 +1527,12 @@ async function encryptKey(recipient, aesKey, opts) {
|
|
|
1482
1527
|
validateRawKeyBytes(aesKey);
|
|
1483
1528
|
keyBytes = aesKey;
|
|
1484
1529
|
} else if (aesKey) {
|
|
1530
|
+
if (aesKey.algorithm.name !== "AES-GCM") {
|
|
1531
|
+
throw new HpkeError(
|
|
1532
|
+
"ERR_INVALID_AES_KEY",
|
|
1533
|
+
"aesKey must be an AES-GCM key, got " + aesKey.algorithm.name
|
|
1534
|
+
);
|
|
1535
|
+
}
|
|
1485
1536
|
keyBytes = await exportAesKeyBytes(aesKey);
|
|
1486
1537
|
validateRawKeyBytes(keyBytes);
|
|
1487
1538
|
} else {
|
|
@@ -1496,8 +1547,12 @@ async function encryptKey(recipient, aesKey, opts) {
|
|
|
1496
1547
|
const { key, baseNonce } = await keySchedule(sharedSecret, info);
|
|
1497
1548
|
const ciphertext = await aeadSeal(key, baseNonce, keyBytes);
|
|
1498
1549
|
const wrapped = concat2(enc, ciphertext);
|
|
1499
|
-
|
|
1500
|
-
|
|
1550
|
+
if (aesKey instanceof CryptoKey) return { wrapped, key: aesKey };
|
|
1551
|
+
const aesGcmKey = await importAesKey(
|
|
1552
|
+
keyBytes,
|
|
1553
|
+
opts?.extractable ?? false
|
|
1554
|
+
);
|
|
1555
|
+
return { wrapped, key: aesGcmKey };
|
|
1501
1556
|
}
|
|
1502
1557
|
__name(encryptKey, "encryptKey");
|
|
1503
1558
|
|
|
@@ -1527,24 +1582,44 @@ async function aeadOpen(key, nonce, ciphertext) {
|
|
|
1527
1582
|
false,
|
|
1528
1583
|
["decrypt"]
|
|
1529
1584
|
);
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1585
|
+
let pt;
|
|
1586
|
+
try {
|
|
1587
|
+
pt = await subtle2.decrypt(
|
|
1588
|
+
{ name: "AES-GCM", iv: nonce },
|
|
1589
|
+
k,
|
|
1590
|
+
ciphertext
|
|
1591
|
+
);
|
|
1592
|
+
} catch (err) {
|
|
1593
|
+
throw new HpkeError(
|
|
1594
|
+
"ERR_DECRYPT_FAILED",
|
|
1595
|
+
"failed to decrypt the wrapped key: wrong keypair, wrong info, or a tampered envelope",
|
|
1596
|
+
{ cause: err }
|
|
1597
|
+
);
|
|
1598
|
+
}
|
|
1535
1599
|
return new Uint8Array(pt);
|
|
1536
1600
|
}
|
|
1537
1601
|
__name(aeadOpen, "aeadOpen");
|
|
1538
1602
|
async function encryptBytes(recipient, message, aesKey, opts) {
|
|
1603
|
+
if (aesKey instanceof CryptoKey && !aesKey.usages.includes("encrypt")) {
|
|
1604
|
+
throw new HpkeError(
|
|
1605
|
+
"ERR_INVALID_AES_KEY",
|
|
1606
|
+
'aesKey is missing the "encrypt" usage, which encrypt needs to encrypt the message'
|
|
1607
|
+
);
|
|
1608
|
+
}
|
|
1539
1609
|
const plaintext = typeof message === "string" ? new TextEncoder().encode(message) : message;
|
|
1540
|
-
const {
|
|
1610
|
+
const { wrapped, key } = await encryptKey(recipient, aesKey, opts);
|
|
1541
1611
|
const iv = globalThis.crypto.getRandomValues(new Uint8Array(NN));
|
|
1542
1612
|
const ct = new Uint8Array(await subtle2.encrypt(
|
|
1543
1613
|
{ name: "AES-GCM", iv },
|
|
1544
1614
|
key,
|
|
1545
1615
|
plaintext
|
|
1546
1616
|
));
|
|
1547
|
-
return concat2(
|
|
1617
|
+
return concat2(
|
|
1618
|
+
i2osp(wrapped.length, WRAPPED_LEN_PREFIX),
|
|
1619
|
+
wrapped,
|
|
1620
|
+
iv,
|
|
1621
|
+
ct
|
|
1622
|
+
);
|
|
1548
1623
|
}
|
|
1549
1624
|
__name(encryptBytes, "encryptBytes");
|
|
1550
1625
|
async function encryptToString(recipient, message, aesKey, opts) {
|
|
@@ -1610,7 +1685,8 @@ async function exportRawPublic(key) {
|
|
|
1610
1685
|
__name(exportRawPublic, "exportRawPublic");
|
|
1611
1686
|
async function importRawPublic(raw) {
|
|
1612
1687
|
if (raw.length !== ENC_LENGTH) {
|
|
1613
|
-
throw new
|
|
1688
|
+
throw new HpkeError(
|
|
1689
|
+
"ERR_INVALID_RECIPIENT_KEY",
|
|
1614
1690
|
`invalid public key length: ${raw.length} bytes (expected ${ENC_LENGTH})`
|
|
1615
1691
|
);
|
|
1616
1692
|
}
|
|
@@ -1628,44 +1704,83 @@ async function resolveRecipientPublicKey(recipient) {
|
|
|
1628
1704
|
return importRawPublic(recipient);
|
|
1629
1705
|
}
|
|
1630
1706
|
if (recipient instanceof CryptoKey) {
|
|
1631
|
-
|
|
1632
|
-
throw new Error("recipient CryptoKey must be a public key");
|
|
1633
|
-
}
|
|
1634
|
-
assertX25519Algorithm(recipient, "recipient CryptoKey");
|
|
1635
|
-
return recipient;
|
|
1707
|
+
return assertRecipientPublicKey(recipient, "recipient CryptoKey");
|
|
1636
1708
|
}
|
|
1637
1709
|
if (typeof recipient.publicKey === "string") {
|
|
1638
1710
|
const { publicKey, encoding } = recipient;
|
|
1639
|
-
|
|
1711
|
+
let decoded;
|
|
1712
|
+
try {
|
|
1713
|
+
decoded = fromString2(publicKey, encoding ?? "base64url");
|
|
1714
|
+
} catch (err) {
|
|
1715
|
+
throw new HpkeError(
|
|
1716
|
+
"ERR_INVALID_RECIPIENT_KEY",
|
|
1717
|
+
`recipient publicKey string does not decode as ${encoding ?? "base64url"}`,
|
|
1718
|
+
{ cause: err }
|
|
1719
|
+
);
|
|
1720
|
+
}
|
|
1721
|
+
return importRawPublic(decoded);
|
|
1640
1722
|
}
|
|
1641
1723
|
const pair = recipient;
|
|
1642
1724
|
if (pair.publicKey instanceof CryptoKey) {
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
return pair.publicKey;
|
|
1725
|
+
return assertRecipientPublicKey(
|
|
1726
|
+
pair.publicKey,
|
|
1727
|
+
"recipient keypair publicKey"
|
|
1728
|
+
);
|
|
1648
1729
|
}
|
|
1649
|
-
throw new
|
|
1730
|
+
throw new HpkeError(
|
|
1731
|
+
"ERR_INVALID_RECIPIENT_KEY",
|
|
1732
|
+
"unrecognized recipient key form"
|
|
1733
|
+
);
|
|
1650
1734
|
}
|
|
1651
1735
|
__name(resolveRecipientPublicKey, "resolveRecipientPublicKey");
|
|
1652
|
-
function
|
|
1736
|
+
function assertRecipientPublicKey(key, context) {
|
|
1737
|
+
if (key.type !== "public") {
|
|
1738
|
+
throw new HpkeError(
|
|
1739
|
+
"ERR_INVALID_RECIPIENT_KEY",
|
|
1740
|
+
`${context} must be a public key`
|
|
1741
|
+
);
|
|
1742
|
+
}
|
|
1743
|
+
assertX25519Algorithm(key, context, "ERR_INVALID_RECIPIENT_KEY");
|
|
1744
|
+
if (!key.extractable) {
|
|
1745
|
+
throw new HpkeError(
|
|
1746
|
+
"ERR_INVALID_RECIPIENT_KEY",
|
|
1747
|
+
`${context} must be extractable (the KEM exports it)`
|
|
1748
|
+
);
|
|
1749
|
+
}
|
|
1750
|
+
return key;
|
|
1751
|
+
}
|
|
1752
|
+
__name(assertRecipientPublicKey, "assertRecipientPublicKey");
|
|
1753
|
+
function assertX25519Algorithm(key, context, code2) {
|
|
1653
1754
|
if (key.algorithm.name !== "X25519") {
|
|
1654
|
-
throw new
|
|
1755
|
+
throw new HpkeError(
|
|
1756
|
+
code2,
|
|
1655
1757
|
`${context} must be an X25519 key (got ${key.algorithm.name})`
|
|
1656
1758
|
);
|
|
1657
1759
|
}
|
|
1658
1760
|
}
|
|
1659
1761
|
__name(assertX25519Algorithm, "assertX25519Algorithm");
|
|
1660
1762
|
async function dh(priv, pub) {
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1763
|
+
let bits;
|
|
1764
|
+
try {
|
|
1765
|
+
bits = await subtle2.deriveBits(
|
|
1766
|
+
{ name: "X25519", public: pub },
|
|
1767
|
+
priv,
|
|
1768
|
+
256
|
|
1769
|
+
);
|
|
1770
|
+
} catch (err) {
|
|
1771
|
+
if (err?.name === "OperationError") {
|
|
1772
|
+
throw new HpkeError(
|
|
1773
|
+
"ERR_SMALL_ORDER_KEY",
|
|
1774
|
+
"X25519 deriveBits rejected a small-order public key",
|
|
1775
|
+
{ cause: err }
|
|
1776
|
+
);
|
|
1777
|
+
}
|
|
1778
|
+
throw err;
|
|
1779
|
+
}
|
|
1666
1780
|
const bytes = new Uint8Array(bits);
|
|
1667
1781
|
if (bytes.every((b) => b === 0)) {
|
|
1668
|
-
throw new
|
|
1782
|
+
throw new HpkeError(
|
|
1783
|
+
"ERR_SMALL_ORDER_KEY",
|
|
1669
1784
|
"X25519 shared secret is all-zero (small-order public key?)"
|
|
1670
1785
|
);
|
|
1671
1786
|
}
|
|
@@ -1704,9 +1819,33 @@ async function encap(pkR) {
|
|
|
1704
1819
|
__name(encap, "encap");
|
|
1705
1820
|
async function decap(enc, keypair) {
|
|
1706
1821
|
if (keypair.privateKey.type !== "private") {
|
|
1707
|
-
throw new
|
|
1822
|
+
throw new HpkeError(
|
|
1823
|
+
"ERR_INVALID_KEYPAIR",
|
|
1824
|
+
"keypair.privateKey must be a private key"
|
|
1825
|
+
);
|
|
1708
1826
|
}
|
|
1709
|
-
assertX25519Algorithm(
|
|
1827
|
+
assertX25519Algorithm(
|
|
1828
|
+
keypair.privateKey,
|
|
1829
|
+
"keypair.privateKey",
|
|
1830
|
+
"ERR_INVALID_KEYPAIR"
|
|
1831
|
+
);
|
|
1832
|
+
if (!keypair.privateKey.usages.includes("deriveBits")) {
|
|
1833
|
+
throw new HpkeError(
|
|
1834
|
+
"ERR_INVALID_KEYPAIR",
|
|
1835
|
+
"keypair.privateKey must have the deriveBits usage"
|
|
1836
|
+
);
|
|
1837
|
+
}
|
|
1838
|
+
if (keypair.publicKey.type !== "public" || !keypair.publicKey.extractable) {
|
|
1839
|
+
throw new HpkeError(
|
|
1840
|
+
"ERR_INVALID_KEYPAIR",
|
|
1841
|
+
"keypair.publicKey must be an extractable public key"
|
|
1842
|
+
);
|
|
1843
|
+
}
|
|
1844
|
+
assertX25519Algorithm(
|
|
1845
|
+
keypair.publicKey,
|
|
1846
|
+
"keypair.publicKey",
|
|
1847
|
+
"ERR_INVALID_KEYPAIR"
|
|
1848
|
+
);
|
|
1710
1849
|
const pkE = await subtle2.importKey(
|
|
1711
1850
|
"raw",
|
|
1712
1851
|
enc,
|
|
@@ -1765,4 +1904,6 @@ var HPKE_SUITE_ID = concat2(
|
|
|
1765
1904
|
i2osp(KDF_ID, 2),
|
|
1766
1905
|
i2osp(AEAD_ID, 2)
|
|
1767
1906
|
);
|
|
1907
|
+
var KEY_ID_LABEL = new TextEncoder().encode("simple-hpke/keyId/v1");
|
|
1908
|
+
var KEY_ID_NONCE_LENGTH = 12;
|
|
1768
1909
|
//# sourceMappingURL=constants.cjs.map
|