@yielded/crypto 0.0.0-stage → 0.1.0-beta.20

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 (88) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +39 -2
  3. package/THIRD_PARTY_NOTICES.md +378 -0
  4. package/dist/Aead.d.mts +34 -0
  5. package/dist/Aead.mjs +28 -0
  6. package/dist/Aead.mjs.map +1 -0
  7. package/dist/Errors.d.mts +20 -0
  8. package/dist/Errors.mjs +19 -0
  9. package/dist/Errors.mjs.map +1 -0
  10. package/dist/Hmac.d.mts +39 -0
  11. package/dist/Hmac.mjs +26 -0
  12. package/dist/Hmac.mjs.map +1 -0
  13. package/dist/Kdf.d.mts +54 -0
  14. package/dist/Kdf.mjs +78 -0
  15. package/dist/Kdf.mjs.map +1 -0
  16. package/dist/KdfAdmission.d.mts +24 -0
  17. package/dist/KdfAdmission.mjs +48 -0
  18. package/dist/KdfAdmission.mjs.map +1 -0
  19. package/dist/Portable.d.mts +11 -0
  20. package/dist/Portable.mjs +13 -0
  21. package/dist/Portable.mjs.map +1 -0
  22. package/dist/Signature.d.mts +70 -0
  23. package/dist/Signature.mjs +73 -0
  24. package/dist/Signature.mjs.map +1 -0
  25. package/dist/WebCrypto.d.mts +20 -0
  26. package/dist/WebCrypto.mjs +33 -0
  27. package/dist/WebCrypto.mjs.map +1 -0
  28. package/dist/index.d.mts +7 -0
  29. package/dist/index.mjs +7 -0
  30. package/dist/internal/aead.mjs +81 -0
  31. package/dist/internal/aead.mjs.map +1 -0
  32. package/dist/internal/argon2-core.mjs +293 -0
  33. package/dist/internal/argon2-core.mjs.map +1 -0
  34. package/dist/internal/argon2.mjs +16 -0
  35. package/dist/internal/argon2.mjs.map +1 -0
  36. package/dist/internal/blake2b.mjs +359 -0
  37. package/dist/internal/blake2b.mjs.map +1 -0
  38. package/dist/internal/common.mjs +20 -0
  39. package/dist/internal/common.mjs.map +1 -0
  40. package/dist/internal/hmac.mjs +68 -0
  41. package/dist/internal/hmac.mjs.map +1 -0
  42. package/dist/internal/kdf.mjs +99 -0
  43. package/dist/internal/kdf.mjs.map +1 -0
  44. package/dist/internal/layer.mjs +26 -0
  45. package/dist/internal/layer.mjs.map +1 -0
  46. package/dist/internal/node.d.mts +11 -0
  47. package/dist/internal/node.mjs +34 -0
  48. package/dist/internal/node.mjs.map +1 -0
  49. package/dist/internal/poly1305.mjs +247 -0
  50. package/dist/internal/poly1305.mjs.map +1 -0
  51. package/dist/internal/signature.mjs +140 -0
  52. package/dist/internal/signature.mjs.map +1 -0
  53. package/dist/internal/word64.mjs +25 -0
  54. package/dist/internal/word64.mjs.map +1 -0
  55. package/dist/internal/xchacha-core.mjs +285 -0
  56. package/dist/internal/xchacha-core.mjs.map +1 -0
  57. package/dist/internal/xchacha.mjs +21 -0
  58. package/dist/internal/xchacha.mjs.map +1 -0
  59. package/dist/platform-bun.d.mts +2 -0
  60. package/dist/platform-bun.mjs +2 -0
  61. package/dist/platform-node.d.mts +2 -0
  62. package/dist/platform-node.mjs +2 -0
  63. package/package.json +1 -6
  64. package/src/Aead.ts +39 -0
  65. package/src/Errors.ts +27 -0
  66. package/src/Hmac.ts +41 -0
  67. package/src/Kdf.ts +87 -0
  68. package/src/KdfAdmission.ts +87 -0
  69. package/src/Portable.ts +8 -0
  70. package/src/Signature.ts +87 -0
  71. package/src/WebCrypto.ts +46 -0
  72. package/src/index.ts +6 -0
  73. package/src/internal/aead.ts +119 -0
  74. package/src/internal/argon2-core.ts +470 -0
  75. package/src/internal/argon2.ts +23 -0
  76. package/src/internal/blake2b.ts +230 -0
  77. package/src/internal/common.ts +44 -0
  78. package/src/internal/hmac.ts +111 -0
  79. package/src/internal/kdf.ts +150 -0
  80. package/src/internal/layer.ts +32 -0
  81. package/src/internal/node.ts +46 -0
  82. package/src/internal/poly1305.ts +289 -0
  83. package/src/internal/signature.ts +188 -0
  84. package/src/internal/word64.ts +48 -0
  85. package/src/internal/xchacha-core.ts +397 -0
  86. package/src/internal/xchacha.ts +26 -0
  87. package/src/platform-bun.ts +2 -0
  88. package/src/platform-node.ts +2 -0
@@ -0,0 +1,285 @@
1
+ import { Poly1305 } from "./poly1305.mjs";
2
+ //#region src/internal/xchacha-core.ts
3
+ /**
4
+ * Adapted from noble-ciphers, Copyright (c) 2022 Paul Miller.
5
+ * MIT; source revision 785181b0772ba84afbe812025714163e4e48262f.
6
+ * Poly1305 arithmetic derives from the public-domain poly1305-donna implementation.
7
+ * See ../../THIRD_PARTY_NOTICES.md for source mapping and licenses.
8
+ */
9
+ const rotl = (word, shift) => word << shift | word >>> 32 - shift;
10
+ function chachaCore(s, k, n, out, cnt, rounds = 20) {
11
+ let y00 = s[0], y01 = s[1], y02 = s[2], y03 = s[3], y04 = k[0], y05 = k[1], y06 = k[2], y07 = k[3], y08 = k[4], y09 = k[5], y10 = k[6], y11 = k[7], y12 = cnt, y13 = n[0], y14 = n[1], y15 = n[2];
12
+ let x00 = y00, x01 = y01, x02 = y02, x03 = y03, x04 = y04, x05 = y05, x06 = y06, x07 = y07, x08 = y08, x09 = y09, x10 = y10, x11 = y11, x12 = y12, x13 = y13, x14 = y14, x15 = y15;
13
+ for (let r = 0; r < rounds; r += 2) {
14
+ x00 = x00 + x04 | 0;
15
+ x12 = rotl(x12 ^ x00, 16);
16
+ x08 = x08 + x12 | 0;
17
+ x04 = rotl(x04 ^ x08, 12);
18
+ x00 = x00 + x04 | 0;
19
+ x12 = rotl(x12 ^ x00, 8);
20
+ x08 = x08 + x12 | 0;
21
+ x04 = rotl(x04 ^ x08, 7);
22
+ x01 = x01 + x05 | 0;
23
+ x13 = rotl(x13 ^ x01, 16);
24
+ x09 = x09 + x13 | 0;
25
+ x05 = rotl(x05 ^ x09, 12);
26
+ x01 = x01 + x05 | 0;
27
+ x13 = rotl(x13 ^ x01, 8);
28
+ x09 = x09 + x13 | 0;
29
+ x05 = rotl(x05 ^ x09, 7);
30
+ x02 = x02 + x06 | 0;
31
+ x14 = rotl(x14 ^ x02, 16);
32
+ x10 = x10 + x14 | 0;
33
+ x06 = rotl(x06 ^ x10, 12);
34
+ x02 = x02 + x06 | 0;
35
+ x14 = rotl(x14 ^ x02, 8);
36
+ x10 = x10 + x14 | 0;
37
+ x06 = rotl(x06 ^ x10, 7);
38
+ x03 = x03 + x07 | 0;
39
+ x15 = rotl(x15 ^ x03, 16);
40
+ x11 = x11 + x15 | 0;
41
+ x07 = rotl(x07 ^ x11, 12);
42
+ x03 = x03 + x07 | 0;
43
+ x15 = rotl(x15 ^ x03, 8);
44
+ x11 = x11 + x15 | 0;
45
+ x07 = rotl(x07 ^ x11, 7);
46
+ x00 = x00 + x05 | 0;
47
+ x15 = rotl(x15 ^ x00, 16);
48
+ x10 = x10 + x15 | 0;
49
+ x05 = rotl(x05 ^ x10, 12);
50
+ x00 = x00 + x05 | 0;
51
+ x15 = rotl(x15 ^ x00, 8);
52
+ x10 = x10 + x15 | 0;
53
+ x05 = rotl(x05 ^ x10, 7);
54
+ x01 = x01 + x06 | 0;
55
+ x12 = rotl(x12 ^ x01, 16);
56
+ x11 = x11 + x12 | 0;
57
+ x06 = rotl(x06 ^ x11, 12);
58
+ x01 = x01 + x06 | 0;
59
+ x12 = rotl(x12 ^ x01, 8);
60
+ x11 = x11 + x12 | 0;
61
+ x06 = rotl(x06 ^ x11, 7);
62
+ x02 = x02 + x07 | 0;
63
+ x13 = rotl(x13 ^ x02, 16);
64
+ x08 = x08 + x13 | 0;
65
+ x07 = rotl(x07 ^ x08, 12);
66
+ x02 = x02 + x07 | 0;
67
+ x13 = rotl(x13 ^ x02, 8);
68
+ x08 = x08 + x13 | 0;
69
+ x07 = rotl(x07 ^ x08, 7);
70
+ x03 = x03 + x04 | 0;
71
+ x14 = rotl(x14 ^ x03, 16);
72
+ x09 = x09 + x14 | 0;
73
+ x04 = rotl(x04 ^ x09, 12);
74
+ x03 = x03 + x04 | 0;
75
+ x14 = rotl(x14 ^ x03, 8);
76
+ x09 = x09 + x14 | 0;
77
+ x04 = rotl(x04 ^ x09, 7);
78
+ }
79
+ let oi = 0;
80
+ out[oi++] = y00 + x00 | 0;
81
+ out[oi++] = y01 + x01 | 0;
82
+ out[oi++] = y02 + x02 | 0;
83
+ out[oi++] = y03 + x03 | 0;
84
+ out[oi++] = y04 + x04 | 0;
85
+ out[oi++] = y05 + x05 | 0;
86
+ out[oi++] = y06 + x06 | 0;
87
+ out[oi++] = y07 + x07 | 0;
88
+ out[oi++] = y08 + x08 | 0;
89
+ out[oi++] = y09 + x09 | 0;
90
+ out[oi++] = y10 + x10 | 0;
91
+ out[oi++] = y11 + x11 | 0;
92
+ out[oi++] = y12 + x12 | 0;
93
+ out[oi++] = y13 + x13 | 0;
94
+ out[oi++] = y14 + x14 | 0;
95
+ out[oi++] = y15 + x15 | 0;
96
+ }
97
+ /**
98
+ * hchacha hashes key and nonce into key' and nonce' for xchacha20.
99
+ */
100
+ function hchacha(s, k, i, out) {
101
+ let x00 = s[0], x01 = s[1], x02 = s[2], x03 = s[3], x04 = k[0], x05 = k[1], x06 = k[2], x07 = k[3], x08 = k[4], x09 = k[5], x10 = k[6], x11 = k[7], x12 = i[0], x13 = i[1], x14 = i[2], x15 = i[3];
102
+ for (let r = 0; r < 20; r += 2) {
103
+ x00 = x00 + x04 | 0;
104
+ x12 = rotl(x12 ^ x00, 16);
105
+ x08 = x08 + x12 | 0;
106
+ x04 = rotl(x04 ^ x08, 12);
107
+ x00 = x00 + x04 | 0;
108
+ x12 = rotl(x12 ^ x00, 8);
109
+ x08 = x08 + x12 | 0;
110
+ x04 = rotl(x04 ^ x08, 7);
111
+ x01 = x01 + x05 | 0;
112
+ x13 = rotl(x13 ^ x01, 16);
113
+ x09 = x09 + x13 | 0;
114
+ x05 = rotl(x05 ^ x09, 12);
115
+ x01 = x01 + x05 | 0;
116
+ x13 = rotl(x13 ^ x01, 8);
117
+ x09 = x09 + x13 | 0;
118
+ x05 = rotl(x05 ^ x09, 7);
119
+ x02 = x02 + x06 | 0;
120
+ x14 = rotl(x14 ^ x02, 16);
121
+ x10 = x10 + x14 | 0;
122
+ x06 = rotl(x06 ^ x10, 12);
123
+ x02 = x02 + x06 | 0;
124
+ x14 = rotl(x14 ^ x02, 8);
125
+ x10 = x10 + x14 | 0;
126
+ x06 = rotl(x06 ^ x10, 7);
127
+ x03 = x03 + x07 | 0;
128
+ x15 = rotl(x15 ^ x03, 16);
129
+ x11 = x11 + x15 | 0;
130
+ x07 = rotl(x07 ^ x11, 12);
131
+ x03 = x03 + x07 | 0;
132
+ x15 = rotl(x15 ^ x03, 8);
133
+ x11 = x11 + x15 | 0;
134
+ x07 = rotl(x07 ^ x11, 7);
135
+ x00 = x00 + x05 | 0;
136
+ x15 = rotl(x15 ^ x00, 16);
137
+ x10 = x10 + x15 | 0;
138
+ x05 = rotl(x05 ^ x10, 12);
139
+ x00 = x00 + x05 | 0;
140
+ x15 = rotl(x15 ^ x00, 8);
141
+ x10 = x10 + x15 | 0;
142
+ x05 = rotl(x05 ^ x10, 7);
143
+ x01 = x01 + x06 | 0;
144
+ x12 = rotl(x12 ^ x01, 16);
145
+ x11 = x11 + x12 | 0;
146
+ x06 = rotl(x06 ^ x11, 12);
147
+ x01 = x01 + x06 | 0;
148
+ x12 = rotl(x12 ^ x01, 8);
149
+ x11 = x11 + x12 | 0;
150
+ x06 = rotl(x06 ^ x11, 7);
151
+ x02 = x02 + x07 | 0;
152
+ x13 = rotl(x13 ^ x02, 16);
153
+ x08 = x08 + x13 | 0;
154
+ x07 = rotl(x07 ^ x08, 12);
155
+ x02 = x02 + x07 | 0;
156
+ x13 = rotl(x13 ^ x02, 8);
157
+ x08 = x08 + x13 | 0;
158
+ x07 = rotl(x07 ^ x08, 7);
159
+ x03 = x03 + x04 | 0;
160
+ x14 = rotl(x14 ^ x03, 16);
161
+ x09 = x09 + x14 | 0;
162
+ x04 = rotl(x04 ^ x09, 12);
163
+ x03 = x03 + x04 | 0;
164
+ x14 = rotl(x14 ^ x03, 8);
165
+ x09 = x09 + x14 | 0;
166
+ x04 = rotl(x04 ^ x09, 7);
167
+ }
168
+ let oi = 0;
169
+ out[oi++] = x00;
170
+ out[oi++] = x01;
171
+ out[oi++] = x02;
172
+ out[oi++] = x03;
173
+ out[oi++] = x12;
174
+ out[oi++] = x13;
175
+ out[oi++] = x14;
176
+ out[oi++] = x15;
177
+ }
178
+ const sigma = Uint32Array.from([
179
+ 1634760805,
180
+ 857760878,
181
+ 2036477234,
182
+ 1797285236
183
+ ]);
184
+ const padding = /* @__PURE__ */ new Uint8Array(16);
185
+ const readWords = (data, words) => {
186
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
187
+ for (let i = 0; i < words.length; i++) words[i] = view.getUint32(i * 4, true);
188
+ };
189
+ function withState(key, nonce, operation) {
190
+ const original = /* @__PURE__ */ new Uint32Array(8);
191
+ const extendedNonce = /* @__PURE__ */ new Uint32Array(4);
192
+ const state = {
193
+ key: /* @__PURE__ */ new Uint32Array(8),
194
+ nonce: /* @__PURE__ */ new Uint32Array(3),
195
+ words: /* @__PURE__ */ new Uint32Array(16),
196
+ stream: /* @__PURE__ */ new Uint8Array(64)
197
+ };
198
+ try {
199
+ readWords(key, original);
200
+ readWords(nonce.subarray(0, 16), extendedNonce);
201
+ hchacha(sigma, original, extendedNonce, state.key);
202
+ const view = new DataView(nonce.buffer, nonce.byteOffset, nonce.byteLength);
203
+ state.nonce[1] = view.getUint32(16, true);
204
+ state.nonce[2] = view.getUint32(20, true);
205
+ return operation(state);
206
+ } finally {
207
+ original.fill(0);
208
+ extendedNonce.fill(0);
209
+ state.key.fill(0);
210
+ state.nonce.fill(0);
211
+ state.words.fill(0);
212
+ state.stream.fill(0);
213
+ }
214
+ }
215
+ const blockAt = (state, counter) => {
216
+ chachaCore(sigma, state.key, state.nonce, state.words, counter);
217
+ const view = new DataView(state.stream.buffer, state.stream.byteOffset, state.stream.byteLength);
218
+ for (let i = 0; i < 16; i++) view.setUint32(i * 4, state.words[i], true);
219
+ };
220
+ const xor = (state, data, out) => {
221
+ for (let offset = 0, counter = 1; offset < data.length; offset += 64, counter++) {
222
+ blockAt(state, counter);
223
+ const length = Math.min(64, data.length - offset);
224
+ for (let i = 0; i < length; i++) out[offset + i] = data[offset + i] ^ state.stream[i];
225
+ }
226
+ };
227
+ const padded = (mac, data) => {
228
+ mac.update(data);
229
+ const remainder = data.length % 16;
230
+ if (remainder !== 0) mac.update(padding.subarray(remainder));
231
+ };
232
+ const tag = (state, ciphertext, additionalData) => {
233
+ const lengths = /* @__PURE__ */ new Uint8Array(16);
234
+ const view = new DataView(lengths.buffer);
235
+ view.setUint32(0, additionalData.length >>> 0, true);
236
+ view.setUint32(4, Math.floor(additionalData.length / 4294967296), true);
237
+ view.setUint32(8, ciphertext.length >>> 0, true);
238
+ view.setUint32(12, Math.floor(ciphertext.length / 4294967296), true);
239
+ blockAt(state, 0);
240
+ const mac = new Poly1305(state.stream.subarray(0, 32));
241
+ try {
242
+ padded(mac, additionalData);
243
+ padded(mac, ciphertext);
244
+ return mac.update(lengths).digest();
245
+ } finally {
246
+ mac.destroy();
247
+ lengths.fill(0);
248
+ state.stream.fill(0);
249
+ }
250
+ };
251
+ const encrypt = (key, nonce, additionalData, plaintext) => withState(key, nonce, (state) => {
252
+ const out = new Uint8Array(plaintext.length + 16);
253
+ const ciphertext = out.subarray(0, plaintext.length);
254
+ try {
255
+ xor(state, plaintext, ciphertext);
256
+ const authentication = tag(state, ciphertext, additionalData);
257
+ out.set(authentication, plaintext.length);
258
+ authentication.fill(0);
259
+ return out;
260
+ } catch (error) {
261
+ out.fill(0);
262
+ throw error;
263
+ }
264
+ });
265
+ /** Authenticate the complete input before allocating or producing plaintext. */
266
+ const decrypt = (key, nonce, additionalData, sealed) => withState(key, nonce, (state) => {
267
+ const ciphertext = sealed.subarray(0, -16);
268
+ const authentication = tag(state, ciphertext, additionalData);
269
+ let difference = 0;
270
+ for (let i = 0; i < 16; i++) difference |= authentication[i] ^ sealed[ciphertext.length + i];
271
+ authentication.fill(0);
272
+ if (difference !== 0) return void 0;
273
+ const out = new Uint8Array(ciphertext.length);
274
+ try {
275
+ xor(state, ciphertext, out);
276
+ return out;
277
+ } catch (error) {
278
+ out.fill(0);
279
+ throw error;
280
+ }
281
+ });
282
+ //#endregion
283
+ export { decrypt, encrypt };
284
+
285
+ //# sourceMappingURL=xchacha-core.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xchacha-core.mjs","names":[],"sources":["../../src/internal/xchacha-core.ts"],"sourcesContent":["/**\n * Adapted from noble-ciphers, Copyright (c) 2022 Paul Miller.\n * MIT; source revision 785181b0772ba84afbe812025714163e4e48262f.\n * Poly1305 arithmetic derives from the public-domain poly1305-donna implementation.\n * See ../../THIRD_PARTY_NOTICES.md for source mapping and licenses.\n */\nimport { Poly1305 } from \"./poly1305\";\n\nconst rotl = (word: number, shift: number): number => (word << shift) | (word >>> (32 - shift));\n\nfunction chachaCore(\n s: Uint32Array,\n k: Uint32Array,\n n: Uint32Array,\n out: Uint32Array,\n cnt: number,\n rounds = 20,\n): void {\n let y00 = s[0],\n y01 = s[1],\n y02 = s[2],\n y03 = s[3], // \"expa\" \"nd 3\" \"2-by\" \"te k\"\n y04 = k[0],\n y05 = k[1],\n y06 = k[2],\n y07 = k[3], // Key Key Key Key\n y08 = k[4],\n y09 = k[5],\n y10 = k[6],\n y11 = k[7], // Key Key Key Key\n y12 = cnt,\n y13 = n[0],\n y14 = n[1],\n y15 = n[2]; // Counter Counter\tNonce Nonce\n\n // Save state to temporary variables\n let x00 = y00,\n x01 = y01,\n x02 = y02,\n x03 = y03,\n x04 = y04,\n x05 = y05,\n x06 = y06,\n x07 = y07,\n x08 = y08,\n x09 = y09,\n x10 = y10,\n x11 = y11,\n x12 = y12,\n x13 = y13,\n x14 = y14,\n x15 = y15;\n\n for (let r = 0; r < rounds; r += 2) {\n x00 = (x00 + x04) | 0;\n x12 = rotl(x12 ^ x00, 16);\n x08 = (x08 + x12) | 0;\n x04 = rotl(x04 ^ x08, 12);\n x00 = (x00 + x04) | 0;\n x12 = rotl(x12 ^ x00, 8);\n x08 = (x08 + x12) | 0;\n x04 = rotl(x04 ^ x08, 7);\n\n x01 = (x01 + x05) | 0;\n x13 = rotl(x13 ^ x01, 16);\n x09 = (x09 + x13) | 0;\n x05 = rotl(x05 ^ x09, 12);\n x01 = (x01 + x05) | 0;\n x13 = rotl(x13 ^ x01, 8);\n x09 = (x09 + x13) | 0;\n x05 = rotl(x05 ^ x09, 7);\n\n x02 = (x02 + x06) | 0;\n x14 = rotl(x14 ^ x02, 16);\n x10 = (x10 + x14) | 0;\n x06 = rotl(x06 ^ x10, 12);\n x02 = (x02 + x06) | 0;\n x14 = rotl(x14 ^ x02, 8);\n x10 = (x10 + x14) | 0;\n x06 = rotl(x06 ^ x10, 7);\n\n x03 = (x03 + x07) | 0;\n x15 = rotl(x15 ^ x03, 16);\n x11 = (x11 + x15) | 0;\n x07 = rotl(x07 ^ x11, 12);\n x03 = (x03 + x07) | 0;\n x15 = rotl(x15 ^ x03, 8);\n x11 = (x11 + x15) | 0;\n x07 = rotl(x07 ^ x11, 7);\n\n x00 = (x00 + x05) | 0;\n x15 = rotl(x15 ^ x00, 16);\n x10 = (x10 + x15) | 0;\n x05 = rotl(x05 ^ x10, 12);\n x00 = (x00 + x05) | 0;\n x15 = rotl(x15 ^ x00, 8);\n x10 = (x10 + x15) | 0;\n x05 = rotl(x05 ^ x10, 7);\n\n x01 = (x01 + x06) | 0;\n x12 = rotl(x12 ^ x01, 16);\n x11 = (x11 + x12) | 0;\n x06 = rotl(x06 ^ x11, 12);\n x01 = (x01 + x06) | 0;\n x12 = rotl(x12 ^ x01, 8);\n x11 = (x11 + x12) | 0;\n x06 = rotl(x06 ^ x11, 7);\n\n x02 = (x02 + x07) | 0;\n x13 = rotl(x13 ^ x02, 16);\n x08 = (x08 + x13) | 0;\n x07 = rotl(x07 ^ x08, 12);\n x02 = (x02 + x07) | 0;\n x13 = rotl(x13 ^ x02, 8);\n x08 = (x08 + x13) | 0;\n x07 = rotl(x07 ^ x08, 7);\n\n x03 = (x03 + x04) | 0;\n x14 = rotl(x14 ^ x03, 16);\n x09 = (x09 + x14) | 0;\n x04 = rotl(x04 ^ x09, 12);\n x03 = (x03 + x04) | 0;\n x14 = rotl(x14 ^ x03, 8);\n x09 = (x09 + x14) | 0;\n x04 = rotl(x04 ^ x09, 7);\n }\n // Write output\n let oi = 0;\n\n out[oi++] = (y00 + x00) | 0;\n out[oi++] = (y01 + x01) | 0;\n out[oi++] = (y02 + x02) | 0;\n out[oi++] = (y03 + x03) | 0;\n out[oi++] = (y04 + x04) | 0;\n out[oi++] = (y05 + x05) | 0;\n out[oi++] = (y06 + x06) | 0;\n out[oi++] = (y07 + x07) | 0;\n out[oi++] = (y08 + x08) | 0;\n out[oi++] = (y09 + x09) | 0;\n out[oi++] = (y10 + x10) | 0;\n out[oi++] = (y11 + x11) | 0;\n out[oi++] = (y12 + x12) | 0;\n out[oi++] = (y13 + x13) | 0;\n out[oi++] = (y14 + x14) | 0;\n out[oi++] = (y15 + x15) | 0;\n}\n/**\n * hchacha hashes key and nonce into key' and nonce' for xchacha20.\n */\nfunction hchacha(s: Uint32Array, k: Uint32Array, i: Uint32Array, out: Uint32Array): void {\n let x00 = s[0],\n x01 = s[1],\n x02 = s[2],\n x03 = s[3],\n x04 = k[0],\n x05 = k[1],\n x06 = k[2],\n x07 = k[3],\n x08 = k[4],\n x09 = k[5],\n x10 = k[6],\n x11 = k[7],\n x12 = i[0],\n x13 = i[1],\n x14 = i[2],\n x15 = i[3];\n\n for (let r = 0; r < 20; r += 2) {\n x00 = (x00 + x04) | 0;\n x12 = rotl(x12 ^ x00, 16);\n x08 = (x08 + x12) | 0;\n x04 = rotl(x04 ^ x08, 12);\n x00 = (x00 + x04) | 0;\n x12 = rotl(x12 ^ x00, 8);\n x08 = (x08 + x12) | 0;\n x04 = rotl(x04 ^ x08, 7);\n\n x01 = (x01 + x05) | 0;\n x13 = rotl(x13 ^ x01, 16);\n x09 = (x09 + x13) | 0;\n x05 = rotl(x05 ^ x09, 12);\n x01 = (x01 + x05) | 0;\n x13 = rotl(x13 ^ x01, 8);\n x09 = (x09 + x13) | 0;\n x05 = rotl(x05 ^ x09, 7);\n\n x02 = (x02 + x06) | 0;\n x14 = rotl(x14 ^ x02, 16);\n x10 = (x10 + x14) | 0;\n x06 = rotl(x06 ^ x10, 12);\n x02 = (x02 + x06) | 0;\n x14 = rotl(x14 ^ x02, 8);\n x10 = (x10 + x14) | 0;\n x06 = rotl(x06 ^ x10, 7);\n\n x03 = (x03 + x07) | 0;\n x15 = rotl(x15 ^ x03, 16);\n x11 = (x11 + x15) | 0;\n x07 = rotl(x07 ^ x11, 12);\n x03 = (x03 + x07) | 0;\n x15 = rotl(x15 ^ x03, 8);\n x11 = (x11 + x15) | 0;\n x07 = rotl(x07 ^ x11, 7);\n\n x00 = (x00 + x05) | 0;\n x15 = rotl(x15 ^ x00, 16);\n x10 = (x10 + x15) | 0;\n x05 = rotl(x05 ^ x10, 12);\n x00 = (x00 + x05) | 0;\n x15 = rotl(x15 ^ x00, 8);\n x10 = (x10 + x15) | 0;\n x05 = rotl(x05 ^ x10, 7);\n\n x01 = (x01 + x06) | 0;\n x12 = rotl(x12 ^ x01, 16);\n x11 = (x11 + x12) | 0;\n x06 = rotl(x06 ^ x11, 12);\n x01 = (x01 + x06) | 0;\n x12 = rotl(x12 ^ x01, 8);\n x11 = (x11 + x12) | 0;\n x06 = rotl(x06 ^ x11, 7);\n\n x02 = (x02 + x07) | 0;\n x13 = rotl(x13 ^ x02, 16);\n x08 = (x08 + x13) | 0;\n x07 = rotl(x07 ^ x08, 12);\n x02 = (x02 + x07) | 0;\n x13 = rotl(x13 ^ x02, 8);\n x08 = (x08 + x13) | 0;\n x07 = rotl(x07 ^ x08, 7);\n\n x03 = (x03 + x04) | 0;\n x14 = rotl(x14 ^ x03, 16);\n x09 = (x09 + x14) | 0;\n x04 = rotl(x04 ^ x09, 12);\n x03 = (x03 + x04) | 0;\n x14 = rotl(x14 ^ x03, 8);\n x09 = (x09 + x14) | 0;\n x04 = rotl(x04 ^ x09, 7);\n }\n let oi = 0;\n\n out[oi++] = x00;\n out[oi++] = x01;\n out[oi++] = x02;\n out[oi++] = x03;\n out[oi++] = x12;\n out[oi++] = x13;\n out[oi++] = x14;\n out[oi++] = x15;\n}\n\nconst sigma = Uint32Array.from([0x61707865, 0x3320646e, 0x79622d32, 0x6b206574]);\nconst padding = new Uint8Array(16);\n\ninterface State {\n readonly key: Uint32Array;\n readonly nonce: Uint32Array;\n readonly words: Uint32Array;\n readonly stream: Uint8Array;\n}\n\nconst readWords = (data: Uint8Array, words: Uint32Array): void => {\n const view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n\n for (let i = 0; i < words.length; i++) words[i] = view.getUint32(i * 4, true);\n};\n\nfunction withState<A>(key: Uint8Array, nonce: Uint8Array, operation: (state: State) => A): A {\n const original = new Uint32Array(8);\n const extendedNonce = new Uint32Array(4);\n\n const state: State = {\n key: new Uint32Array(8),\n nonce: new Uint32Array(3),\n words: new Uint32Array(16),\n stream: new Uint8Array(64),\n };\n\n try {\n readWords(key, original);\n readWords(nonce.subarray(0, 16), extendedNonce);\n hchacha(sigma, original, extendedNonce, state.key);\n // XChaCha uses HChaCha(key, nonce[0..16]), then 0 || nonce[16..24].\n const view = new DataView(nonce.buffer, nonce.byteOffset, nonce.byteLength);\n\n state.nonce[1] = view.getUint32(16, true);\n state.nonce[2] = view.getUint32(20, true);\n\n return operation(state);\n } finally {\n original.fill(0);\n extendedNonce.fill(0);\n state.key.fill(0);\n state.nonce.fill(0);\n state.words.fill(0);\n state.stream.fill(0);\n }\n}\n\nconst blockAt = (state: State, counter: number): void => {\n chachaCore(sigma, state.key, state.nonce, state.words, counter);\n const view = new DataView(state.stream.buffer, state.stream.byteOffset, state.stream.byteLength);\n\n for (let i = 0; i < 16; i++) view.setUint32(i * 4, state.words[i], true);\n};\n\nconst xor = (state: State, data: Uint8Array, out: Uint8Array): void => {\n for (let offset = 0, counter = 1; offset < data.length; offset += 64, counter++) {\n blockAt(state, counter);\n const length = Math.min(64, data.length - offset);\n\n for (let i = 0; i < length; i++) out[offset + i] = data[offset + i] ^ state.stream[i];\n }\n};\n\nconst padded = (mac: Poly1305, data: Uint8Array): void => {\n mac.update(data);\n const remainder = data.length % 16;\n\n if (remainder !== 0) mac.update(padding.subarray(remainder));\n};\n\nconst tag = (state: State, ciphertext: Uint8Array, additionalData: Uint8Array): Uint8Array => {\n const lengths = new Uint8Array(16);\n const view = new DataView(lengths.buffer);\n\n // RFC 8439 authenticates little-endian 64-bit byte lengths, AAD first.\n view.setUint32(0, additionalData.length >>> 0, true);\n view.setUint32(4, Math.floor(additionalData.length / 0x100000000), true);\n view.setUint32(8, ciphertext.length >>> 0, true);\n view.setUint32(12, Math.floor(ciphertext.length / 0x100000000), true);\n blockAt(state, 0);\n const mac = new Poly1305(state.stream.subarray(0, 32));\n\n try {\n padded(mac, additionalData);\n padded(mac, ciphertext);\n\n return mac.update(lengths).digest();\n } finally {\n mac.destroy();\n lengths.fill(0);\n state.stream.fill(0);\n }\n};\n\nexport const encrypt = (\n key: Uint8Array,\n nonce: Uint8Array,\n additionalData: Uint8Array,\n plaintext: Uint8Array,\n): Uint8Array =>\n withState(key, nonce, (state) => {\n const out = new Uint8Array(plaintext.length + 16);\n const ciphertext = out.subarray(0, plaintext.length);\n\n try {\n xor(state, plaintext, ciphertext);\n const authentication = tag(state, ciphertext, additionalData);\n\n out.set(authentication, plaintext.length);\n authentication.fill(0);\n\n return out;\n } catch (error) {\n out.fill(0);\n throw error;\n }\n });\n\n/** Authenticate the complete input before allocating or producing plaintext. */\nexport const decrypt = (\n key: Uint8Array,\n nonce: Uint8Array,\n additionalData: Uint8Array,\n sealed: Uint8Array,\n): Uint8Array | undefined =>\n withState(key, nonce, (state) => {\n const ciphertext = sealed.subarray(0, -16);\n const authentication = tag(state, ciphertext, additionalData);\n let difference = 0;\n\n for (let i = 0; i < 16; i++) difference |= authentication[i] ^ sealed[ciphertext.length + i];\n authentication.fill(0);\n if (difference !== 0) return undefined;\n const out = new Uint8Array(ciphertext.length);\n\n try {\n xor(state, ciphertext, out);\n\n return out;\n } catch (error) {\n out.fill(0);\n throw error;\n }\n });\n"],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { AuthenticationFailed, InvalidInput } from "../Errors.mjs";
2
+ import { decrypt, encrypt } from "./xchacha-core.mjs";
3
+ import { Effect } from "effect";
4
+ //#region src/internal/xchacha.ts
5
+ const maximumPlaintextBytes = 274877906880;
6
+ const xchacha = {
7
+ encrypt: Effect.fnUntraced(function* ({ key, nonce, additionalData, data }) {
8
+ if (data.length > maximumPlaintextBytes) return yield* InvalidInput.make({ reason: "data" });
9
+ return encrypt(key, nonce, additionalData, data);
10
+ }),
11
+ decrypt: Effect.fnUntraced(function* ({ key, nonce, additionalData, data }) {
12
+ if (data.length - 16 > maximumPlaintextBytes) return yield* InvalidInput.make({ reason: "data" });
13
+ const plaintext = decrypt(key, nonce, additionalData, data);
14
+ if (plaintext === void 0) return yield* AuthenticationFailed.make({});
15
+ return plaintext;
16
+ })
17
+ };
18
+ //#endregion
19
+ export { xchacha };
20
+
21
+ //# sourceMappingURL=xchacha.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xchacha.mjs","names":[],"sources":["../../src/internal/xchacha.ts"],"sourcesContent":["import { Effect } from \"effect\";\n\nimport { AuthenticationFailed, InvalidInput } from \"../Errors\";\nimport type { XChaCha } from \"./aead\";\nimport { decrypt, encrypt } from \"./xchacha-core\";\n\n// Counter zero derives the MAC key; payload blocks use the remaining uint32 values.\nconst maximumPlaintextBytes = 0xffffffff * 64;\n\nexport const xchacha: XChaCha = {\n encrypt: Effect.fnUntraced(function* ({ key, nonce, additionalData, data }) {\n if (data.length > maximumPlaintextBytes) return yield* InvalidInput.make({ reason: \"data\" });\n\n return encrypt(key, nonce, additionalData, data);\n }),\n decrypt: Effect.fnUntraced(function* ({ key, nonce, additionalData, data }) {\n if (data.length - 16 > maximumPlaintextBytes)\n return yield* InvalidInput.make({ reason: \"data\" });\n\n const plaintext = decrypt(key, nonce, additionalData, data);\n\n if (plaintext === undefined) return yield* AuthenticationFailed.make({});\n\n return plaintext;\n }),\n};\n"],"mappings":";;;;AAOA,MAAM,wBAAwB;AAE9B,MAAa,UAAmB;CAC9B,SAAS,OAAO,WAAW,WAAW,EAAE,KAAK,OAAO,gBAAgB,QAAQ;EAC1E,IAAI,KAAK,SAAS,uBAAuB,OAAO,OAAO,aAAa,KAAK,EAAE,QAAQ,OAAO,CAAC;EAE3F,OAAO,QAAQ,KAAK,OAAO,gBAAgB,IAAI;CACjD,CAAC;CACD,SAAS,OAAO,WAAW,WAAW,EAAE,KAAK,OAAO,gBAAgB,QAAQ;EAC1E,IAAI,KAAK,SAAS,KAAK,uBACrB,OAAO,OAAO,aAAa,KAAK,EAAE,QAAQ,OAAO,CAAC;EAEpD,MAAM,YAAY,QAAQ,KAAK,OAAO,gBAAgB,IAAI;EAE1D,IAAI,cAAc,KAAA,GAAW,OAAO,OAAO,qBAAqB,KAAK,CAAC,CAAC;EAEvE,OAAO;CACT,CAAC;AACH"}
@@ -0,0 +1,2 @@
1
+ import { layer } from "./internal/node.mjs";
2
+ export { layer };
@@ -0,0 +1,2 @@
1
+ import { layer } from "./internal/node.mjs";
2
+ export { layer };
@@ -0,0 +1,2 @@
1
+ import { layer } from "./internal/node.mjs";
2
+ export { layer };
@@ -0,0 +1,2 @@
1
+ import { layer } from "./internal/node.mjs";
2
+ export { layer };
package/package.json CHANGED
@@ -1,6 +1 @@
1
- {
2
- "name": "@yielded/crypto",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
1
+ {"name":"@yielded/crypto","version":"0.1.0-beta.20","devDependencies":{"@effect/vitest":"4.0.0","@types/node":"26.1.2","effect":"4.0.0","typescript":"7.0.2","vite-plus":"0.3.3"},"peerDependencies":{"effect":"^4.0.0"},"exports":{".":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"},"./Aead":{"types":"./dist/Aead.d.mts","default":"./dist/Aead.mjs"},"./Errors":{"types":"./dist/Errors.d.mts","default":"./dist/Errors.mjs"},"./Hmac":{"types":"./dist/Hmac.d.mts","default":"./dist/Hmac.mjs"},"./Kdf":{"types":"./dist/Kdf.d.mts","default":"./dist/Kdf.mjs"},"./KdfAdmission":{"types":"./dist/KdfAdmission.d.mts","default":"./dist/KdfAdmission.mjs"},"./Signature":{"types":"./dist/Signature.d.mts","default":"./dist/Signature.mjs"},"./WebCrypto":{"types":"./dist/WebCrypto.d.mts","default":"./dist/WebCrypto.mjs"},"./platform-node":{"types":"./dist/platform-node.d.mts","default":"./dist/platform-node.mjs"},"./platform-bun":{"types":"./dist/platform-bun.d.mts","default":"./dist/platform-bun.mjs"},"./Portable":{"types":"./dist/Portable.d.mts","default":"./dist/Portable.mjs"}},"description":"Effect cryptography services with explicit native and portable backends.","homepage":"https://yielded.dev/auth/","bugs":{"url":"https://github.com/yielded-dev/auth/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/yielded-dev/auth.git","directory":"packages/crypto"},"files":["dist","src","THIRD_PARTY_NOTICES.md"],"type":"module","sideEffects":[],"publishConfig":{"access":"public"},"scripts":{"build":"vp pack","check":"tsc --noEmit -p tsconfig.json","test":"vp test"}}
package/src/Aead.ts ADDED
@@ -0,0 +1,39 @@
1
+ import { Context, type Effect, type Redacted, Schema } from "effect";
2
+
3
+ import type { AuthenticationFailed, OperationError } from "./Errors";
4
+
5
+ export const Algorithm = Schema.Literals(["AES-256-GCM", "XChaCha20-Poly1305"]);
6
+ export type Algorithm = typeof Algorithm.Type;
7
+
8
+ const context = {
9
+ algorithm: Algorithm,
10
+ key: Schema.Redacted(Schema.Uint8Array, { disallowJsonEncode: true }),
11
+ nonce: Schema.Uint8Array,
12
+ additionalData: Schema.optionalKey(Schema.Uint8Array),
13
+ };
14
+
15
+ export const EncryptInput = Schema.Struct({
16
+ ...context,
17
+ plaintext: Schema.Redacted(Schema.Uint8Array, { disallowJsonEncode: true }),
18
+ });
19
+
20
+ export type EncryptInput = typeof EncryptInput.Type;
21
+
22
+ export const DecryptInput = Schema.Struct({ ...context, ciphertext: Schema.Uint8Array });
23
+ export type DecryptInput = typeof DecryptInput.Type;
24
+
25
+ /**
26
+ * Both algorithms use a 32-byte key and append a 16-byte tag to ciphertext.
27
+ * AES-GCM uses a 12-byte nonce; XChaCha uses 24. The caller MUST supply a unique
28
+ * nonce for each encryption with a key. Obtain entropy from Effect Crypto.
29
+ * Envelope serialization and key selection belong to the caller.
30
+ */
31
+ export class Aead extends Context.Service<
32
+ Aead,
33
+ {
34
+ readonly encrypt: (input: EncryptInput) => Effect.Effect<Uint8Array, OperationError>;
35
+ readonly decrypt: (
36
+ input: DecryptInput,
37
+ ) => Effect.Effect<Redacted.Redacted<Uint8Array>, OperationError | AuthenticationFailed>;
38
+ }
39
+ >()("@yielded/crypto/Aead") {}
package/src/Errors.ts ADDED
@@ -0,0 +1,27 @@
1
+ import { Schema } from "effect";
2
+
3
+ /** Diagnostics contain only fixed classifications, never native causes or input. */
4
+ export class InvalidInput extends Schema.TaggedError<InvalidInput>()("CryptoInvalidInput", {
5
+ reason: Schema.Literals(["key", "nonce", "parameters", "data"]),
6
+ }) {}
7
+
8
+ export class UnsupportedAlgorithm extends Schema.TaggedError<UnsupportedAlgorithm>()(
9
+ "CryptoUnsupportedAlgorithm",
10
+ {},
11
+ ) {}
12
+
13
+ /** A native backend failed without a more specific classification. */
14
+ export class CryptoUnavailable extends Schema.TaggedError<CryptoUnavailable>()(
15
+ "CryptoUnavailable",
16
+ {},
17
+ ) {}
18
+
19
+ /** An authenticated decryption rejected the supplied ciphertext or context. */
20
+ export class AuthenticationFailed extends Schema.TaggedError<AuthenticationFailed>()(
21
+ "CryptoAuthenticationFailed",
22
+ {},
23
+ ) {}
24
+
25
+ export class KdfBusy extends Schema.TaggedError<KdfBusy>()("CryptoKdfBusy", {}) {}
26
+
27
+ export type OperationError = InvalidInput | UnsupportedAlgorithm | CryptoUnavailable;
package/src/Hmac.ts ADDED
@@ -0,0 +1,41 @@
1
+ import { Context, type Effect, Schema, type Scope } from "effect";
2
+
3
+ import type { OperationError } from "./Errors";
4
+
5
+ /** SHA-1 exists for interoperability with TOTP, not new signature designs. */
6
+ export const Algorithm = Schema.Literals(["SHA-1", "SHA-256", "SHA-384", "SHA-512"]);
7
+ export type Algorithm = typeof Algorithm.Type;
8
+
9
+ export const KeyInput = Schema.Struct({
10
+ algorithm: Algorithm,
11
+ key: Schema.Redacted(Schema.Uint8Array, { disallowJsonEncode: true }),
12
+ });
13
+
14
+ export type KeyInput = typeof KeyInput.Type;
15
+
16
+ export const Input = Schema.Struct({
17
+ ...KeyInput.fields,
18
+ data: Schema.Uint8Array,
19
+ });
20
+
21
+ export type Input = typeof Input.Type;
22
+
23
+ export const VerifyInput = Schema.Struct({ ...Input.fields, tag: Schema.Uint8Array });
24
+ export type VerifyInput = typeof VerifyInput.Type;
25
+
26
+ /** An imported, nonextractable key, usable only while its owning Scope is open. */
27
+ export interface Key {
28
+ readonly sign: (data: Uint8Array) => Effect.Effect<Uint8Array, OperationError>;
29
+ readonly verify: (data: Uint8Array, tag: Uint8Array) => Effect.Effect<boolean, OperationError>;
30
+ }
31
+
32
+ export class Hmac extends Context.Service<
33
+ Hmac,
34
+ {
35
+ /** Snapshot and validate once. Closing the Scope joins native work and releases the key. */
36
+ readonly importKey: (input: KeyInput) => Effect.Effect<Key, OperationError, Scope.Scope>;
37
+ readonly sign: (input: Input) => Effect.Effect<Uint8Array, OperationError>;
38
+ /** A wrong tag is false; a key or backend failure stays in the error channel. */
39
+ readonly verify: (input: VerifyInput) => Effect.Effect<boolean, OperationError>;
40
+ }
41
+ >()("@yielded/crypto/Hmac") {}
package/src/Kdf.ts ADDED
@@ -0,0 +1,87 @@
1
+ import { Context, type Effect, type Redacted, Schema } from "effect";
2
+
3
+ import type { KdfBusy, OperationError } from "./Errors";
4
+
5
+ const positive = Schema.Int.check(Schema.isGreaterThan(0));
6
+ const uint32 = Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 0xffffffff }));
7
+ const bytes = Schema.Uint8Array;
8
+ const secret = Schema.Redacted(bytes, { disallowJsonEncode: true });
9
+ const argon2Bytes = bytes.check(Schema.isMaxLength(0xffffffff));
10
+ const argon2Secret = Schema.Redacted(argon2Bytes, { disallowJsonEncode: true });
11
+
12
+ export const Argon2idInput = Schema.Struct({
13
+ password: argon2Secret,
14
+ salt: argon2Bytes.check(Schema.isMinLength(8)),
15
+ memoryKiB: uint32,
16
+ passes: uint32,
17
+ parallelism: Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 0xffffff })),
18
+ length: Schema.Int.check(Schema.isBetween({ minimum: 4, maximum: 0xffffffff })),
19
+ secret: Schema.optionalKey(argon2Secret),
20
+ associatedData: Schema.optionalKey(argon2Bytes),
21
+ });
22
+
23
+ export type Argon2idInput = typeof Argon2idInput.Type;
24
+
25
+ export const Pbkdf2Input = Schema.Struct({
26
+ password: secret,
27
+ salt: bytes,
28
+ // Native Node/Bun PBKDF2 accepts a positive signed 32-bit iteration count.
29
+ iterations: Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 0x7fffffff })),
30
+ // WebCrypto takes an unsigned 32-bit bit count; this API takes whole bytes.
31
+ length: Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 0x1fffffff })),
32
+ });
33
+
34
+ export type Pbkdf2Input = typeof Pbkdf2Input.Type;
35
+
36
+ export const HkdfInput = Schema.Struct({
37
+ key: secret,
38
+ salt: bytes,
39
+ info: bytes.check(Schema.isMaxLength(1024)),
40
+ length: Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 255 * 32 })),
41
+ });
42
+
43
+ export type HkdfInput = typeof HkdfInput.Type;
44
+
45
+ /** Resource ceilings, not a password-strength policy. Limits apply per permit. */
46
+ export const Limits = Schema.Struct({
47
+ maximumMemoryKiB: positive,
48
+ maximumPasses: positive,
49
+ maximumParallelism: positive,
50
+ maximumMemoryPasses: positive,
51
+ maximumIterations: positive,
52
+ maximumInputBytes: positive,
53
+ maximumOutputBytes: positive,
54
+ });
55
+
56
+ export type Limits = typeof Limits.Type;
57
+
58
+ export const defaultLimits: Limits = Object.freeze({
59
+ maximumMemoryKiB: 65536,
60
+ maximumPasses: 6,
61
+ maximumParallelism: 4,
62
+ maximumMemoryPasses: 131072,
63
+ maximumIterations: 1000000,
64
+ maximumInputBytes: 65536,
65
+ maximumOutputBytes: 1024,
66
+ });
67
+
68
+ /**
69
+ * Byte-preserving derivation; no text normalization, PHC parsing or password policy.
70
+ * Argon2id uses version 19; PBKDF2 and HKDF use SHA-256. A backend captures shared
71
+ * KdfAdmission when its Layer is built and retains admission until work and cleanup
72
+ * finish, including when a native operation cannot be cancelled.
73
+ */
74
+ export class Kdf extends Context.Service<
75
+ Kdf,
76
+ {
77
+ readonly argon2id: (
78
+ input: Argon2idInput,
79
+ ) => Effect.Effect<Redacted.Redacted<Uint8Array>, OperationError | KdfBusy>;
80
+ readonly pbkdf2: (
81
+ input: Pbkdf2Input,
82
+ ) => Effect.Effect<Redacted.Redacted<Uint8Array>, OperationError | KdfBusy>;
83
+ readonly hkdf: (
84
+ input: HkdfInput,
85
+ ) => Effect.Effect<Redacted.Redacted<Uint8Array>, OperationError | KdfBusy>;
86
+ }
87
+ >()("@yielded/crypto/Kdf") {}
@@ -0,0 +1,87 @@
1
+ import { Context, Effect, Layer, Option, Schema, Semaphore } from "effect";
2
+
3
+ import { InvalidInput, KdfBusy } from "./Errors";
4
+
5
+ export interface Options {
6
+ readonly concurrency?: number;
7
+ readonly maxQueued?: number;
8
+ readonly maxWaitMilliseconds?: number;
9
+ }
10
+
11
+ /** Share one Layer across all backend instances to bound actual KDF work. */
12
+ export class KdfAdmission extends Context.Service<
13
+ KdfAdmission,
14
+ {
15
+ readonly run: <A, E, R>(work: Effect.Effect<A, E, R>) => Effect.Effect<A, E | KdfBusy, R>;
16
+ }
17
+ >()("@yielded/crypto/KdfAdmission") {}
18
+
19
+ const Configuration = Schema.Struct({
20
+ concurrency: Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 32 })),
21
+ maxQueued: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),
22
+ maxWaitMilliseconds: Schema.Int.check(Schema.isGreaterThan(0)),
23
+ });
24
+
25
+ /**
26
+ * Waiting is interruptible and bounded. The permit covers work and its cleanup;
27
+ * backends protect nonabortable native calls until actual completion. Owned
28
+ * interruptible work can stop and release its resources without finishing a KDF.
29
+ * Nested work in the same fiber shares its permit through scoped cleanup; forked
30
+ * fibers must acquire their own. This covers preparation and cleanup around a KDF.
31
+ * Defaults: one running derivation, sixteen waiting, five-second acquisition wait.
32
+ */
33
+ export const layer = (options: Options = {}): Layer.Layer<KdfAdmission, InvalidInput> => {
34
+ const snapshot = {
35
+ concurrency: options.concurrency ?? 1,
36
+ maxQueued: options.maxQueued ?? 16,
37
+ maxWaitMilliseconds: options.maxWaitMilliseconds ?? 5000,
38
+ };
39
+
40
+ return Layer.effect(
41
+ KdfAdmission,
42
+ Effect.gen(function* () {
43
+ const config = yield* Schema.decodeEffect(Configuration)(snapshot).pipe(
44
+ Effect.mapError(() => InvalidInput.make({ reason: "parameters" })),
45
+ );
46
+
47
+ const capacity = yield* Schema.decodeEffect(Schema.Int)(
48
+ config.concurrency + config.maxQueued,
49
+ ).pipe(Effect.mapError(() => InvalidInput.make({ reason: "parameters" })));
50
+
51
+ const active = yield* Semaphore.make(config.concurrency);
52
+ const admitted = yield* Semaphore.make(capacity);
53
+ const owners = new Set<number>();
54
+
55
+ const acquire = Effect.acquireRelease(active.take(1), () => active.release(1), {
56
+ interruptible: true,
57
+ }).pipe(
58
+ Effect.timeoutOrElse({
59
+ duration: config.maxWaitMilliseconds,
60
+ orElse: () => Effect.fail(KdfBusy.make({})),
61
+ }),
62
+ );
63
+
64
+ return KdfAdmission.of({
65
+ run: <A, E, R>(work: Effect.Effect<A, E, R>) =>
66
+ Effect.withFiber((fiber) => {
67
+ if (owners.has(fiber.id)) return work;
68
+
69
+ const owned = Effect.acquireRelease(
70
+ Effect.sync(() => owners.add(fiber.id)),
71
+ () => Effect.sync(() => owners.delete(fiber.id)),
72
+ ).pipe(Effect.andThen(work));
73
+
74
+ return admitted
75
+ .withPermitsIfAvailable(1)(Effect.scoped(Effect.andThen(acquire, owned)))
76
+ .pipe(
77
+ Effect.flatMap((result) =>
78
+ Option.isSome(result)
79
+ ? Effect.succeed(result.value)
80
+ : Effect.fail(KdfBusy.make({})),
81
+ ),
82
+ );
83
+ }),
84
+ });
85
+ }),
86
+ );
87
+ };