@cardanowall/crypto-core 0.0.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 (81) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +192 -0
  3. package/dist/aead.cjs +44 -0
  4. package/dist/aead.cjs.map +1 -0
  5. package/dist/aead.d.cts +38 -0
  6. package/dist/aead.d.ts +38 -0
  7. package/dist/aead.js +38 -0
  8. package/dist/aead.js.map +1 -0
  9. package/dist/cbor.cjs +69 -0
  10. package/dist/cbor.cjs.map +1 -0
  11. package/dist/cbor.d.cts +17 -0
  12. package/dist/cbor.d.ts +17 -0
  13. package/dist/cbor.js +64 -0
  14. package/dist/cbor.js.map +1 -0
  15. package/dist/cose.cjs +430 -0
  16. package/dist/cose.cjs.map +1 -0
  17. package/dist/cose.d.cts +72 -0
  18. package/dist/cose.d.ts +72 -0
  19. package/dist/cose.js +398 -0
  20. package/dist/cose.js.map +1 -0
  21. package/dist/hash.cjs +165 -0
  22. package/dist/hash.cjs.map +1 -0
  23. package/dist/hash.d.cts +30 -0
  24. package/dist/hash.d.ts +30 -0
  25. package/dist/hash.js +155 -0
  26. package/dist/hash.js.map +1 -0
  27. package/dist/index.cjs +1856 -0
  28. package/dist/index.cjs.map +1 -0
  29. package/dist/index.d.cts +12 -0
  30. package/dist/index.d.ts +12 -0
  31. package/dist/index.js +1759 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/kdf.cjs +26 -0
  34. package/dist/kdf.cjs.map +1 -0
  35. package/dist/kdf.d.cts +25 -0
  36. package/dist/kdf.d.ts +25 -0
  37. package/dist/kdf.js +23 -0
  38. package/dist/kdf.js.map +1 -0
  39. package/dist/kem.cjs +86 -0
  40. package/dist/kem.cjs.map +1 -0
  41. package/dist/kem.d.cts +47 -0
  42. package/dist/kem.d.ts +47 -0
  43. package/dist/kem.js +73 -0
  44. package/dist/kem.js.map +1 -0
  45. package/dist/merkle.cjs +284 -0
  46. package/dist/merkle.cjs.map +1 -0
  47. package/dist/merkle.d.cts +24 -0
  48. package/dist/merkle.d.ts +24 -0
  49. package/dist/merkle.js +279 -0
  50. package/dist/merkle.js.map +1 -0
  51. package/dist/recipient.cjs +141 -0
  52. package/dist/recipient.cjs.map +1 -0
  53. package/dist/recipient.d.cts +16 -0
  54. package/dist/recipient.d.ts +16 -0
  55. package/dist/recipient.js +135 -0
  56. package/dist/recipient.js.map +1 -0
  57. package/dist/sealed-poe.cjs +851 -0
  58. package/dist/sealed-poe.cjs.map +1 -0
  59. package/dist/sealed-poe.d.cts +134 -0
  60. package/dist/sealed-poe.d.ts +134 -0
  61. package/dist/sealed-poe.js +838 -0
  62. package/dist/sealed-poe.js.map +1 -0
  63. package/dist/seed-derive.cjs +129 -0
  64. package/dist/seed-derive.cjs.map +1 -0
  65. package/dist/seed-derive.d.cts +28 -0
  66. package/dist/seed-derive.d.ts +28 -0
  67. package/dist/seed-derive.js +101 -0
  68. package/dist/seed-derive.js.map +1 -0
  69. package/dist/sig.cjs +77 -0
  70. package/dist/sig.cjs.map +1 -0
  71. package/dist/sig.d.cts +17 -0
  72. package/dist/sig.d.ts +17 -0
  73. package/dist/sig.js +53 -0
  74. package/dist/sig.js.map +1 -0
  75. package/dist/util.cjs +36 -0
  76. package/dist/util.cjs.map +1 -0
  77. package/dist/util.d.cts +5 -0
  78. package/dist/util.d.ts +5 -0
  79. package/dist/util.js +33 -0
  80. package/dist/util.js.map +1 -0
  81. package/package.json +122 -0
@@ -0,0 +1,135 @@
1
+ // src/recipient/bech32.ts
2
+ var BECH32_ALPHABET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
3
+ var POLYMOD_GENERATORS = [996825010, 642813549, 513874426, 1027748829, 705979059];
4
+ var ENCODING_CONST = 1;
5
+ function polymodStep(pre) {
6
+ const b = pre >> 25;
7
+ let chk = (pre & 33554431) << 5;
8
+ for (let i = 0; i < POLYMOD_GENERATORS.length; i++) {
9
+ if ((b >> i & 1) === 1) chk ^= POLYMOD_GENERATORS[i];
10
+ }
11
+ return chk;
12
+ }
13
+ function bytesToWords(bytes) {
14
+ const words = [];
15
+ let carry = 0;
16
+ let pos = 0;
17
+ const mask = (1 << 5) - 1;
18
+ for (const n of bytes) {
19
+ carry = carry << 8 | n;
20
+ pos += 8;
21
+ for (; pos >= 5; pos -= 5) words.push(carry >> pos - 5 & mask);
22
+ carry &= (1 << pos) - 1;
23
+ }
24
+ if (pos > 0) words.push(carry << 5 - pos & mask);
25
+ return words;
26
+ }
27
+ function checksum(prefix, words) {
28
+ let chk = 1;
29
+ for (let i = 0; i < prefix.length; i++) {
30
+ const c = prefix.charCodeAt(i);
31
+ if (c < 33 || c > 126) throw new Error(`bech32: invalid prefix (${prefix})`);
32
+ chk = polymodStep(chk) ^ c >> 5;
33
+ }
34
+ chk = polymodStep(chk);
35
+ for (let i = 0; i < prefix.length; i++) chk = polymodStep(chk) ^ prefix.charCodeAt(i) & 31;
36
+ for (const v of words) chk = polymodStep(chk) ^ v;
37
+ for (let i = 0; i < 6; i++) chk = polymodStep(chk);
38
+ chk ^= ENCODING_CONST;
39
+ let out = "";
40
+ for (let i = 0; i < 6; i++) out += BECH32_ALPHABET[chk >> 5 * (5 - i) & 31];
41
+ return out;
42
+ }
43
+ function bech32EncodeNoLimit(prefix, bytes) {
44
+ if (prefix.length === 0) throw new Error("bech32: empty prefix");
45
+ const words = bytesToWords(bytes);
46
+ let payload = "";
47
+ for (const w of words) payload += BECH32_ALPHABET[w];
48
+ const lowered = prefix.toLowerCase();
49
+ return `${lowered}1${payload}${checksum(lowered, words)}`;
50
+ }
51
+ function checksumValid(prefix, words) {
52
+ let chk = 1;
53
+ for (let i = 0; i < prefix.length; i++) chk = polymodStep(chk) ^ prefix.charCodeAt(i) >> 5;
54
+ chk = polymodStep(chk);
55
+ for (let i = 0; i < prefix.length; i++) chk = polymodStep(chk) ^ prefix.charCodeAt(i) & 31;
56
+ for (const v of words) chk = polymodStep(chk) ^ v;
57
+ return chk === ENCODING_CONST;
58
+ }
59
+ function wordsToBytes(words) {
60
+ const out = [];
61
+ let carry = 0;
62
+ let pos = 0;
63
+ for (const w of words) {
64
+ carry = carry << 5 | w;
65
+ pos += 5;
66
+ for (; pos >= 8; pos -= 8) out.push(carry >> pos - 8 & 255);
67
+ carry &= (1 << pos) - 1;
68
+ }
69
+ if (pos >= 5 || carry !== 0) throw new Error("bech32: non-canonical padding");
70
+ return Uint8Array.from(out);
71
+ }
72
+ function bech32DecodeNoLimit(input) {
73
+ if (input.length === 0) throw new Error("bech32: empty string");
74
+ const hasLower = input !== input.toUpperCase();
75
+ const hasUpper = input !== input.toLowerCase();
76
+ if (hasLower && hasUpper) throw new Error("bech32: mixed-case string");
77
+ const s = input.toLowerCase();
78
+ const sep = s.lastIndexOf("1");
79
+ if (sep < 1) throw new Error("bech32: missing human-readable prefix");
80
+ if (s.length - sep - 1 < 6) throw new Error("bech32: data too short for checksum");
81
+ const hrp = s.slice(0, sep);
82
+ for (let i = 0; i < hrp.length; i++) {
83
+ const c = hrp.charCodeAt(i);
84
+ if (c < 33 || c > 126) throw new Error("bech32: invalid prefix character");
85
+ }
86
+ const words = [];
87
+ for (let i = sep + 1; i < s.length; i++) {
88
+ const v = BECH32_ALPHABET.indexOf(s[i]);
89
+ if (v === -1) throw new Error("bech32: invalid data character");
90
+ words.push(v);
91
+ }
92
+ if (!checksumValid(hrp, words)) throw new Error("bech32: bad checksum");
93
+ return { hrp, bytes: wordsToBytes(words.slice(0, words.length - 6)) };
94
+ }
95
+
96
+ // src/recipient/age-recipient.ts
97
+ var X25519_HRP = "age";
98
+ var XWING_HRP = "age1pqc";
99
+ var X25519_PUBLIC_KEY_BYTES = 32;
100
+ var XWING_PUBLIC_KEY_BYTES = 1216;
101
+ function encodeAgeX25519Recipient(publicKey) {
102
+ if (publicKey.length !== X25519_PUBLIC_KEY_BYTES) {
103
+ throw new Error("encodeAgeX25519Recipient: publicKey must be exactly 32 bytes");
104
+ }
105
+ return bech32EncodeNoLimit(X25519_HRP, publicKey);
106
+ }
107
+ function encodeAgeXWingRecipient(publicKey) {
108
+ if (publicKey.length !== XWING_PUBLIC_KEY_BYTES) {
109
+ throw new Error("encodeAgeXWingRecipient: publicKey must be exactly 1216 bytes");
110
+ }
111
+ return bech32EncodeNoLimit(XWING_HRP, publicKey);
112
+ }
113
+ function parseAgeRecipient(recipient) {
114
+ if (typeof recipient !== "string") {
115
+ throw new Error("parseAgeRecipient: recipient must be a string");
116
+ }
117
+ const { hrp, bytes } = bech32DecodeNoLimit(recipient.trim());
118
+ if (hrp === X25519_HRP) {
119
+ if (bytes.length !== X25519_PUBLIC_KEY_BYTES) {
120
+ throw new Error("parseAgeRecipient: age recipient must carry a 32-byte X25519 key");
121
+ }
122
+ return { kem: "x25519", publicKey: bytes };
123
+ }
124
+ if (hrp === XWING_HRP) {
125
+ if (bytes.length !== XWING_PUBLIC_KEY_BYTES) {
126
+ throw new Error("parseAgeRecipient: age1pqc recipient must carry a 1216-byte X-Wing key");
127
+ }
128
+ return { kem: "mlkem768x25519", publicKey: bytes };
129
+ }
130
+ throw new Error(`parseAgeRecipient: unrecognized recipient prefix "${hrp}"`);
131
+ }
132
+
133
+ export { bech32DecodeNoLimit, bech32EncodeNoLimit, encodeAgeX25519Recipient, encodeAgeXWingRecipient, parseAgeRecipient };
134
+ //# sourceMappingURL=recipient.js.map
135
+ //# sourceMappingURL=recipient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/recipient/bech32.ts","../src/recipient/age-recipient.ts"],"names":[],"mappings":";AAUA,IAAM,eAAA,GAAkB,kCAAA;AACxB,IAAM,qBAAqB,CAAC,SAAA,EAAY,SAAA,EAAY,SAAA,EAAY,YAAY,SAAU,CAAA;AACtF,IAAM,cAAA,GAAiB,CAAA;AAEvB,SAAS,YAAY,GAAA,EAAqB;AACxC,EAAA,MAAM,IAAI,GAAA,IAAO,EAAA;AACjB,EAAA,IAAI,GAAA,GAAA,CAAO,MAAM,QAAA,KAAc,CAAA;AAC/B,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,kBAAA,CAAmB,QAAQ,CAAA,EAAA,EAAK;AAClD,IAAA,IAAA,CAAM,KAAK,CAAA,GAAK,CAAA,MAAO,CAAA,EAAG,GAAA,IAAO,mBAAmB,CAAC,CAAA;AAAA,EACvD;AACA,EAAA,OAAO,GAAA;AACT;AAGA,SAAS,aAAa,KAAA,EAA6B;AACjD,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,EAAA,IAAI,GAAA,GAAM,CAAA;AACV,EAAA,MAAM,IAAA,GAAA,CAAQ,KAAK,CAAA,IAAK,CAAA;AACxB,EAAA,KAAA,MAAW,KAAK,KAAA,EAAO;AACrB,IAAA,KAAA,GAAS,SAAS,CAAA,GAAK,CAAA;AACvB,IAAA,GAAA,IAAO,CAAA;AACP,IAAA,OAAO,GAAA,IAAO,GAAG,GAAA,IAAO,CAAA,QAAS,IAAA,CAAM,KAAA,IAAU,GAAA,GAAM,CAAA,GAAM,IAAI,CAAA;AACjE,IAAA,KAAA,IAAA,CAAU,KAAK,GAAA,IAAO,CAAA;AAAA,EACxB;AACA,EAAA,IAAI,MAAM,CAAA,EAAG,KAAA,CAAM,KAAM,KAAA,IAAU,CAAA,GAAI,MAAQ,IAAI,CAAA;AACnD,EAAA,OAAO,KAAA;AACT;AAEA,SAAS,QAAA,CAAS,QAAgB,KAAA,EAAyB;AACzD,EAAA,IAAI,GAAA,GAAM,CAAA;AACV,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,MAAA,CAAO,QAAQ,CAAA,EAAA,EAAK;AACtC,IAAA,MAAM,CAAA,GAAI,MAAA,CAAO,UAAA,CAAW,CAAC,CAAA;AAC7B,IAAA,IAAI,CAAA,GAAI,MAAM,CAAA,GAAI,GAAA,QAAW,IAAI,KAAA,CAAM,CAAA,wBAAA,EAA2B,MAAM,CAAA,CAAA,CAAG,CAAA;AAC3E,IAAA,GAAA,GAAM,WAAA,CAAY,GAAG,CAAA,GAAK,CAAA,IAAK,CAAA;AAAA,EACjC;AACA,EAAA,GAAA,GAAM,YAAY,GAAG,CAAA;AACrB,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,MAAA,CAAO,MAAA,EAAQ,CAAA,EAAA,EAAK,GAAA,GAAM,WAAA,CAAY,GAAG,CAAA,GAAK,MAAA,CAAO,UAAA,CAAW,CAAC,CAAA,GAAI,EAAA;AACzF,EAAA,KAAA,MAAW,CAAA,IAAK,KAAA,EAAO,GAAA,GAAM,WAAA,CAAY,GAAG,CAAA,GAAI,CAAA;AAChD,EAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,GAAG,CAAA,EAAA,EAAK,GAAA,GAAM,YAAY,GAAG,CAAA;AACjD,EAAA,GAAA,IAAO,cAAA;AACP,EAAA,IAAI,GAAA,GAAM,EAAA;AACV,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,CAAA,EAAG,CAAA,EAAA,EAAK,GAAA,IAAO,eAAA,CAAiB,GAAA,IAAQ,CAAA,IAAK,CAAA,GAAI,CAAA,CAAA,GAAO,EAAE,CAAA;AAC9E,EAAA,OAAO,GAAA;AACT;AAGO,SAAS,mBAAA,CAAoB,QAAgB,KAAA,EAA2B;AAC7E,EAAA,IAAI,OAAO,MAAA,KAAW,CAAA,EAAG,MAAM,IAAI,MAAM,sBAAsB,CAAA;AAC/D,EAAA,MAAM,KAAA,GAAQ,aAAa,KAAK,CAAA;AAChC,EAAA,IAAI,OAAA,GAAU,EAAA;AACd,EAAA,KAAA,MAAW,CAAA,IAAK,KAAA,EAAO,OAAA,IAAW,eAAA,CAAgB,CAAC,CAAA;AACnD,EAAA,MAAM,OAAA,GAAU,OAAO,WAAA,EAAY;AACnC,EAAA,OAAO,CAAA,EAAG,OAAO,CAAA,CAAA,EAAI,OAAO,GAAG,QAAA,CAAS,OAAA,EAAS,KAAK,CAAC,CAAA,CAAA;AACzD;AAKA,SAAS,aAAA,CAAc,QAAgB,KAAA,EAA0B;AAC/D,EAAA,IAAI,GAAA,GAAM,CAAA;AACV,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,MAAA,CAAO,MAAA,EAAQ,CAAA,EAAA,EAAK,GAAA,GAAM,WAAA,CAAY,GAAG,CAAA,GAAK,MAAA,CAAO,UAAA,CAAW,CAAC,CAAA,IAAK,CAAA;AAC1F,EAAA,GAAA,GAAM,YAAY,GAAG,CAAA;AACrB,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,MAAA,CAAO,MAAA,EAAQ,CAAA,EAAA,EAAK,GAAA,GAAM,WAAA,CAAY,GAAG,CAAA,GAAK,MAAA,CAAO,UAAA,CAAW,CAAC,CAAA,GAAI,EAAA;AACzF,EAAA,KAAA,MAAW,CAAA,IAAK,KAAA,EAAO,GAAA,GAAM,WAAA,CAAY,GAAG,CAAA,GAAI,CAAA;AAChD,EAAA,OAAO,GAAA,KAAQ,cAAA;AACjB;AAKA,SAAS,aAAa,KAAA,EAA6B;AACjD,EAAA,MAAM,MAAgB,EAAC;AACvB,EAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,EAAA,IAAI,GAAA,GAAM,CAAA;AACV,EAAA,KAAA,MAAW,KAAK,KAAA,EAAO;AACrB,IAAA,KAAA,GAAS,SAAS,CAAA,GAAK,CAAA;AACvB,IAAA,GAAA,IAAO,CAAA;AACP,IAAA,OAAO,GAAA,IAAO,GAAG,GAAA,IAAO,CAAA,MAAO,IAAA,CAAM,KAAA,IAAU,GAAA,GAAM,CAAA,GAAM,GAAI,CAAA;AAC/D,IAAA,KAAA,IAAA,CAAU,KAAK,GAAA,IAAO,CAAA;AAAA,EACxB;AACA,EAAA,IAAI,OAAO,CAAA,IAAK,KAAA,KAAU,GAAG,MAAM,IAAI,MAAM,+BAA+B,CAAA;AAC5E,EAAA,OAAO,UAAA,CAAW,KAAK,GAAG,CAAA;AAC5B;AAOO,SAAS,oBAAoB,KAAA,EAAmD;AACrF,EAAA,IAAI,MAAM,MAAA,KAAW,CAAA,EAAG,MAAM,IAAI,MAAM,sBAAsB,CAAA;AAC9D,EAAA,MAAM,QAAA,GAAW,KAAA,KAAU,KAAA,CAAM,WAAA,EAAY;AAC7C,EAAA,MAAM,QAAA,GAAW,KAAA,KAAU,KAAA,CAAM,WAAA,EAAY;AAC7C,EAAA,IAAI,QAAA,IAAY,QAAA,EAAU,MAAM,IAAI,MAAM,2BAA2B,CAAA;AACrE,EAAA,MAAM,CAAA,GAAI,MAAM,WAAA,EAAY;AAC5B,EAAA,MAAM,GAAA,GAAM,CAAA,CAAE,WAAA,CAAY,GAAG,CAAA;AAC7B,EAAA,IAAI,GAAA,GAAM,CAAA,EAAG,MAAM,IAAI,MAAM,uCAAuC,CAAA;AACpE,EAAA,IAAI,CAAA,CAAE,SAAS,GAAA,GAAM,CAAA,GAAI,GAAG,MAAM,IAAI,MAAM,qCAAqC,CAAA;AACjF,EAAA,MAAM,GAAA,GAAM,CAAA,CAAE,KAAA,CAAM,CAAA,EAAG,GAAG,CAAA;AAC1B,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,GAAA,CAAI,QAAQ,CAAA,EAAA,EAAK;AACnC,IAAA,MAAM,CAAA,GAAI,GAAA,CAAI,UAAA,CAAW,CAAC,CAAA;AAC1B,IAAA,IAAI,IAAI,EAAA,IAAM,CAAA,GAAI,KAAK,MAAM,IAAI,MAAM,kCAAkC,CAAA;AAAA,EAC3E;AACA,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,KAAA,IAAS,IAAI,GAAA,GAAM,CAAA,EAAG,CAAA,GAAI,CAAA,CAAE,QAAQ,CAAA,EAAA,EAAK;AACvC,IAAA,MAAM,CAAA,GAAI,eAAA,CAAgB,OAAA,CAAQ,CAAA,CAAE,CAAC,CAAE,CAAA;AACvC,IAAA,IAAI,CAAA,KAAM,EAAA,EAAI,MAAM,IAAI,MAAM,gCAAgC,CAAA;AAC9D,IAAA,KAAA,CAAM,KAAK,CAAC,CAAA;AAAA,EACd;AACA,EAAA,IAAI,CAAC,cAAc,GAAA,EAAK,KAAK,GAAG,MAAM,IAAI,MAAM,sBAAsB,CAAA;AACtE,EAAA,OAAO,EAAE,GAAA,EAAK,KAAA,EAAO,YAAA,CAAa,KAAA,CAAM,KAAA,CAAM,CAAA,EAAG,KAAA,CAAM,MAAA,GAAS,CAAC,CAAC,CAAA,EAAE;AACtE;;;ACxGA,IAAM,UAAA,GAAa,KAAA;AACnB,IAAM,SAAA,GAAY,SAAA;AAClB,IAAM,uBAAA,GAA0B,EAAA;AAChC,IAAM,sBAAA,GAAyB,IAAA;AAUxB,SAAS,yBAAyB,SAAA,EAA+B;AACtE,EAAA,IAAI,SAAA,CAAU,WAAW,uBAAA,EAAyB;AAChD,IAAA,MAAM,IAAI,MAAM,8DAA8D,CAAA;AAAA,EAChF;AACA,EAAA,OAAO,mBAAA,CAAoB,YAAY,SAAS,CAAA;AAClD;AAEO,SAAS,wBAAwB,SAAA,EAA+B;AACrE,EAAA,IAAI,SAAA,CAAU,WAAW,sBAAA,EAAwB;AAC/C,IAAA,MAAM,IAAI,MAAM,+DAA+D,CAAA;AAAA,EACjF;AACA,EAAA,OAAO,mBAAA,CAAoB,WAAW,SAAS,CAAA;AACjD;AASO,SAAS,kBAAkB,SAAA,EAAuC;AACvE,EAAA,IAAI,OAAO,cAAc,QAAA,EAAU;AACjC,IAAA,MAAM,IAAI,MAAM,+CAA+C,CAAA;AAAA,EACjE;AACA,EAAA,MAAM,EAAE,GAAA,EAAK,KAAA,KAAU,mBAAA,CAAoB,SAAA,CAAU,MAAM,CAAA;AAC3D,EAAA,IAAI,QAAQ,UAAA,EAAY;AACtB,IAAA,IAAI,KAAA,CAAM,WAAW,uBAAA,EAAyB;AAC5C,MAAA,MAAM,IAAI,MAAM,kEAAkE,CAAA;AAAA,IACpF;AACA,IAAA,OAAO,EAAE,GAAA,EAAK,QAAA,EAAU,SAAA,EAAW,KAAA,EAAM;AAAA,EAC3C;AACA,EAAA,IAAI,QAAQ,SAAA,EAAW;AACrB,IAAA,IAAI,KAAA,CAAM,WAAW,sBAAA,EAAwB;AAC3C,MAAA,MAAM,IAAI,MAAM,wEAAwE,CAAA;AAAA,IAC1F;AACA,IAAA,OAAO,EAAE,GAAA,EAAK,gBAAA,EAAkB,SAAA,EAAW,KAAA,EAAM;AAAA,EACnD;AACA,EAAA,MAAM,IAAI,KAAA,CAAM,CAAA,kDAAA,EAAqD,GAAG,CAAA,CAAA,CAAG,CAAA;AAC7E","file":"recipient.js","sourcesContent":["// Minimal BIP-173 bech32 encoder used to format age-style recipient strings.\n//\n// This package's dependency policy keeps the runtime import graph to a small,\n// audited set of cryptographic libraries, so we inline the exact bech32\n// algorithm here rather than pull in a general-purpose base-encoding library.\n// Output is byte-identical to the no-length-limit form of a standard bech32\n// encoder (`encode(hrp, toWords(bytes))` with the 90-char BIP-173 cap\n// disabled): age recipients exceed that cap — an X-Wing recipient is ~1960\n// characters — so the limit must be off.\n\nconst BECH32_ALPHABET = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l';\nconst POLYMOD_GENERATORS = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3];\nconst ENCODING_CONST = 1; // BIP-173 bech32 (not bech32m).\n\nfunction polymodStep(pre: number): number {\n const b = pre >> 25;\n let chk = (pre & 0x1ffffff) << 5;\n for (let i = 0; i < POLYMOD_GENERATORS.length; i++) {\n if (((b >> i) & 1) === 1) chk ^= POLYMOD_GENERATORS[i]!;\n }\n return chk;\n}\n\n// 8-bit bytes → 5-bit words, padding the final partial group with zero bits.\nfunction bytesToWords(bytes: Uint8Array): number[] {\n const words: number[] = [];\n let carry = 0;\n let pos = 0;\n const mask = (1 << 5) - 1;\n for (const n of bytes) {\n carry = (carry << 8) | n;\n pos += 8;\n for (; pos >= 5; pos -= 5) words.push((carry >> (pos - 5)) & mask);\n carry &= (1 << pos) - 1;\n }\n if (pos > 0) words.push((carry << (5 - pos)) & mask);\n return words;\n}\n\nfunction checksum(prefix: string, words: number[]): string {\n let chk = 1;\n for (let i = 0; i < prefix.length; i++) {\n const c = prefix.charCodeAt(i);\n if (c < 33 || c > 126) throw new Error(`bech32: invalid prefix (${prefix})`);\n chk = polymodStep(chk) ^ (c >> 5);\n }\n chk = polymodStep(chk);\n for (let i = 0; i < prefix.length; i++) chk = polymodStep(chk) ^ (prefix.charCodeAt(i) & 0x1f);\n for (const v of words) chk = polymodStep(chk) ^ v;\n for (let i = 0; i < 6; i++) chk = polymodStep(chk);\n chk ^= ENCODING_CONST;\n let out = '';\n for (let i = 0; i < 6; i++) out += BECH32_ALPHABET[(chk >> (5 * (5 - i))) & 31];\n return out;\n}\n\n// Encode raw bytes to a bech32 string with NO length limit. `prefix` is the HRP.\nexport function bech32EncodeNoLimit(prefix: string, bytes: Uint8Array): string {\n if (prefix.length === 0) throw new Error('bech32: empty prefix');\n const words = bytesToWords(bytes);\n let payload = '';\n for (const w of words) payload += BECH32_ALPHABET[w];\n const lowered = prefix.toLowerCase();\n return `${lowered}1${payload}${checksum(lowered, words)}`;\n}\n\n// Recompute the polymod over the HRP + every data word (the trailing six being\n// the checksum) and test it against the encoding constant. True iff the string\n// carries a valid bech32 checksum.\nfunction checksumValid(prefix: string, words: number[]): boolean {\n let chk = 1;\n for (let i = 0; i < prefix.length; i++) chk = polymodStep(chk) ^ (prefix.charCodeAt(i) >> 5);\n chk = polymodStep(chk);\n for (let i = 0; i < prefix.length; i++) chk = polymodStep(chk) ^ (prefix.charCodeAt(i) & 0x1f);\n for (const v of words) chk = polymodStep(chk) ^ v;\n return chk === ENCODING_CONST;\n}\n\n// 5-bit words → 8-bit bytes (the inverse of `bytesToWords`). Rejects\n// non-canonical padding: any leftover must be fewer than 5 bits and all zero,\n// matching the zero-fill `bytesToWords` applies to a final partial group.\nfunction wordsToBytes(words: number[]): Uint8Array {\n const out: number[] = [];\n let carry = 0;\n let pos = 0;\n for (const w of words) {\n carry = (carry << 5) | w;\n pos += 5;\n for (; pos >= 8; pos -= 8) out.push((carry >> (pos - 8)) & 0xff);\n carry &= (1 << pos) - 1;\n }\n if (pos >= 5 || carry !== 0) throw new Error('bech32: non-canonical padding');\n return Uint8Array.from(out);\n}\n\n// Decode a bech32 string with NO length limit, verifying the checksum. Returns\n// the lower-cased HRP and the decoded data bytes. The inverse of\n// `bech32EncodeNoLimit`. The separator is the last `1` in the string, so HRPs\n// that themselves contain a `1` (e.g. the `age1pqc` recipient prefix) round-trip\n// correctly.\nexport function bech32DecodeNoLimit(input: string): { hrp: string; bytes: Uint8Array } {\n if (input.length === 0) throw new Error('bech32: empty string');\n const hasLower = input !== input.toUpperCase();\n const hasUpper = input !== input.toLowerCase();\n if (hasLower && hasUpper) throw new Error('bech32: mixed-case string');\n const s = input.toLowerCase();\n const sep = s.lastIndexOf('1');\n if (sep < 1) throw new Error('bech32: missing human-readable prefix');\n if (s.length - sep - 1 < 6) throw new Error('bech32: data too short for checksum');\n const hrp = s.slice(0, sep);\n for (let i = 0; i < hrp.length; i++) {\n const c = hrp.charCodeAt(i);\n if (c < 33 || c > 126) throw new Error('bech32: invalid prefix character');\n }\n const words: number[] = [];\n for (let i = sep + 1; i < s.length; i++) {\n const v = BECH32_ALPHABET.indexOf(s[i]!);\n if (v === -1) throw new Error('bech32: invalid data character');\n words.push(v);\n }\n if (!checksumValid(hrp, words)) throw new Error('bech32: bad checksum');\n return { hrp, bytes: wordsToBytes(words.slice(0, words.length - 6)) };\n}\n","// Encodes a raw KEM public key to a bech32 age-style recipient string — the\n// form a sender uses to address a sealed PoE record.\n//\n// • X25519 (32 bytes) → \"age1…\"\n// • X-Wing / ML-KEM-768 + X25519 (1216 bytes) → \"age1pqc…\"\n//\n// The two HRPs make a recipient self-describing: a parser routes to the right\n// KEM purely from the bech32 prefix. We use the `age1pqc` HRP for the hybrid\n// key (upstream age v1.3.0 claims the shorter `age1pq` HRP for the same X-Wing\n// primitive; `age1pqc` avoids colliding with that wire identifier).\n//\n// The X-Wing public key derives for free from the same identity seed via\n// `deriveMlKem768X25519KeypairFromSeed`, so every identity always has one and\n// can RECEIVE hybrid sealed records even when it publishes via the classical\n// X25519 path.\n\nimport { bech32DecodeNoLimit, bech32EncodeNoLimit } from './bech32';\n\nconst X25519_HRP = 'age';\nconst XWING_HRP = 'age1pqc';\nconst X25519_PUBLIC_KEY_BYTES = 32;\nconst XWING_PUBLIC_KEY_BYTES = 1216;\n\n// The KEM a recipient string addresses, inferred from its bech32 HRP.\nexport type RecipientKem = 'x25519' | 'mlkem768x25519';\n\nexport interface ParsedAgeRecipient {\n readonly kem: RecipientKem;\n readonly publicKey: Uint8Array;\n}\n\nexport function encodeAgeX25519Recipient(publicKey: Uint8Array): string {\n if (publicKey.length !== X25519_PUBLIC_KEY_BYTES) {\n throw new Error('encodeAgeX25519Recipient: publicKey must be exactly 32 bytes');\n }\n return bech32EncodeNoLimit(X25519_HRP, publicKey);\n}\n\nexport function encodeAgeXWingRecipient(publicKey: Uint8Array): string {\n if (publicKey.length !== XWING_PUBLIC_KEY_BYTES) {\n throw new Error('encodeAgeXWingRecipient: publicKey must be exactly 1216 bytes');\n }\n return bech32EncodeNoLimit(XWING_HRP, publicKey);\n}\n\n// Decode an age-style recipient string back to its raw KEM public key, routing\n// on the bech32 HRP. The inverse of `encodeAgeX25519Recipient` /\n// `encodeAgeXWingRecipient`: a sender can take a recipient string a peer shared\n// and recover the exact public key (and which KEM it belongs to) needed to seal\n// a record to them. Surrounding whitespace is tolerated so pasted strings parse.\n// Throws on an unknown HRP, a bad checksum, or a key length that does not match\n// the HRP's KEM.\nexport function parseAgeRecipient(recipient: string): ParsedAgeRecipient {\n if (typeof recipient !== 'string') {\n throw new Error('parseAgeRecipient: recipient must be a string');\n }\n const { hrp, bytes } = bech32DecodeNoLimit(recipient.trim());\n if (hrp === X25519_HRP) {\n if (bytes.length !== X25519_PUBLIC_KEY_BYTES) {\n throw new Error('parseAgeRecipient: age recipient must carry a 32-byte X25519 key');\n }\n return { kem: 'x25519', publicKey: bytes };\n }\n if (hrp === XWING_HRP) {\n if (bytes.length !== XWING_PUBLIC_KEY_BYTES) {\n throw new Error('parseAgeRecipient: age1pqc recipient must carry a 1216-byte X-Wing key');\n }\n return { kem: 'mlkem768x25519', publicKey: bytes };\n }\n throw new Error(`parseAgeRecipient: unrecognized recipient prefix \"${hrp}\"`);\n}\n"]}