@smonn/ids 0.5.0 → 0.7.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 +555 -18
- package/dist/adapter-types-oHCCSgOO.d.mts +12 -0
- package/dist/adapter-types-oHCCSgOO.d.mts.map +1 -0
- package/dist/cli.mjs +246 -63
- package/dist/cli.mjs.map +1 -1
- package/dist/{codec-shell-dWpxoFmy.mjs → codec-shell-DH-UO4UR.mjs} +8 -8
- package/dist/codec-shell-DH-UO4UR.mjs.map +1 -0
- package/dist/drizzle-CeSni5PB.d.mts +44 -0
- package/dist/drizzle-CeSni5PB.d.mts.map +1 -0
- package/dist/drizzle.d.mts +3 -0
- package/dist/drizzle.mjs +43 -0
- package/dist/drizzle.mjs.map +1 -0
- package/dist/error-Cp5qYZcv.mjs +52 -0
- package/dist/error-Cp5qYZcv.mjs.map +1 -0
- package/dist/error-DTr4i6Ic.d.mts +44 -0
- package/dist/error-DTr4i6Ic.d.mts.map +1 -0
- package/dist/express.d.mts +85 -0
- package/dist/express.d.mts.map +1 -0
- package/dist/express.mjs +90 -0
- package/dist/express.mjs.map +1 -0
- package/dist/fastify.d.mts +88 -0
- package/dist/fastify.d.mts.map +1 -0
- package/dist/fastify.mjs +91 -0
- package/dist/fastify.mjs.map +1 -0
- package/dist/hono.d.mts +68 -0
- package/dist/hono.d.mts.map +1 -0
- package/dist/hono.mjs +63 -0
- package/dist/hono.mjs.map +1 -0
- package/dist/index.d.mts +2 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +3 -2
- package/dist/kysely.d.mts +56 -0
- package/dist/kysely.d.mts.map +1 -0
- package/dist/kysely.mjs +43 -0
- package/dist/kysely.mjs.map +1 -0
- package/dist/{opaque-B4ps7Pqk.mjs → opaque-uvjOFY_0.mjs} +37 -20
- package/dist/opaque-uvjOFY_0.mjs.map +1 -0
- package/dist/opaque.d.mts +34 -9
- package/dist/opaque.d.mts.map +1 -1
- package/dist/opaque.mjs +3 -2
- package/dist/prisma.d.mts +85 -0
- package/dist/prisma.d.mts.map +1 -0
- package/dist/prisma.mjs +54 -0
- package/dist/prisma.mjs.map +1 -0
- package/dist/reverse-BgFU6JHw.mjs +87 -0
- package/dist/reverse-BgFU6JHw.mjs.map +1 -0
- package/dist/reverse.d.mts +77 -0
- package/dist/reverse.d.mts.map +1 -0
- package/dist/reverse.mjs +3 -0
- package/dist/signed.d.mts +56 -0
- package/dist/signed.d.mts.map +1 -0
- package/dist/signed.mjs +100 -0
- package/dist/signed.mjs.map +1 -0
- package/dist/{timestamp-Bgzxx8bE.mjs → timestamp-B5_UCzc6.mjs} +3 -3
- package/dist/{timestamp-Bgzxx8bE.mjs.map → timestamp-B5_UCzc6.mjs.map} +1 -1
- package/dist/{timestamp-bytes-B57RM7Ho.mjs → timestamp-bytes-BBY7JI33.mjs} +2 -2
- package/dist/{timestamp-bytes-B57RM7Ho.mjs.map → timestamp-bytes-BBY7JI33.mjs.map} +1 -1
- package/dist/wrapped-0vL72Nje.mjs +361 -0
- package/dist/wrapped-0vL72Nje.mjs.map +1 -0
- package/dist/wrapped.d.mts +89 -9
- package/dist/wrapped.d.mts.map +1 -1
- package/dist/wrapped.mjs +3 -336
- package/package.json +45 -3
- package/dist/codec-shell-dWpxoFmy.mjs.map +0 -1
- package/dist/opaque-B4ps7Pqk.mjs.map +0 -1
- package/dist/wrapped.mjs.map +0 -1
package/dist/wrapped.mjs
CHANGED
|
@@ -1,336 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { i as
|
|
3
|
-
|
|
4
|
-
const zeroIv = new Uint8Array(16);
|
|
5
|
-
const pkcsPad = 16;
|
|
6
|
-
const laneByteLength = 8;
|
|
7
|
-
const tagByteLength = 8;
|
|
8
|
-
function writeU32Lane(value, lane) {
|
|
9
|
-
lane[0] = 0;
|
|
10
|
-
lane[1] = 0;
|
|
11
|
-
lane[2] = 0;
|
|
12
|
-
lane[3] = 0;
|
|
13
|
-
lane[4] = value >>> 24 & 255;
|
|
14
|
-
lane[5] = value >>> 16 & 255;
|
|
15
|
-
lane[6] = value >>> 8 & 255;
|
|
16
|
-
lane[7] = value & 255;
|
|
17
|
-
}
|
|
18
|
-
function readU32Lane(lane) {
|
|
19
|
-
for (let i = 0; i < 4; i++) if (lane[i] !== 0) return null;
|
|
20
|
-
return (lane[4] << 24 | lane[5] << 16 | lane[6] << 8 | lane[7]) >>> 0;
|
|
21
|
-
}
|
|
22
|
-
function writeI32Lane(value, lane) {
|
|
23
|
-
lane.fill(value < 0 ? 255 : 0, 0, 4);
|
|
24
|
-
new DataView(lane.buffer, lane.byteOffset, lane.byteLength).setInt32(4, value, false);
|
|
25
|
-
}
|
|
26
|
-
function readI32Lane(lane) {
|
|
27
|
-
const signExtension = (lane[4] & 128) === 0 ? 0 : 255;
|
|
28
|
-
for (let i = 0; i < 4; i++) if (lane[i] !== signExtension) return null;
|
|
29
|
-
return new DataView(lane.buffer, lane.byteOffset, lane.byteLength).getInt32(4, false);
|
|
30
|
-
}
|
|
31
|
-
function writeU64Lane(value, lane) {
|
|
32
|
-
new DataView(lane.buffer, lane.byteOffset, lane.byteLength).setBigUint64(0, value, false);
|
|
33
|
-
}
|
|
34
|
-
function readU64Lane(lane) {
|
|
35
|
-
return new DataView(lane.buffer, lane.byteOffset, lane.byteLength).getBigUint64(0, false);
|
|
36
|
-
}
|
|
37
|
-
function writeI64Lane(value, lane) {
|
|
38
|
-
new DataView(lane.buffer, lane.byteOffset, lane.byteLength).setBigInt64(0, value, false);
|
|
39
|
-
}
|
|
40
|
-
function readI64Lane(lane) {
|
|
41
|
-
return new DataView(lane.buffer, lane.byteOffset, lane.byteLength).getBigInt64(0, false);
|
|
42
|
-
}
|
|
43
|
-
function writeLane(kind, value, lane) {
|
|
44
|
-
if (kind === "i32") {
|
|
45
|
-
writeI32Lane(value, lane);
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
if (kind === "u64") {
|
|
49
|
-
writeU64Lane(value, lane);
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
if (kind === "i64") {
|
|
53
|
-
writeI64Lane(value, lane);
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
writeU32Lane(value, lane);
|
|
57
|
-
}
|
|
58
|
-
function readLane(kind, lane) {
|
|
59
|
-
if (kind === "u64") return readU64Lane(lane);
|
|
60
|
-
if (kind === "i64") return readI64Lane(lane);
|
|
61
|
-
return kind === "i32" ? readI32Lane(lane) : readU32Lane(lane);
|
|
62
|
-
}
|
|
63
|
-
function hmacMessage(brand, kind, lane) {
|
|
64
|
-
const prefix = new TextEncoder().encode(`${brand}:${kind}:`);
|
|
65
|
-
const message = new Uint8Array(prefix.length + lane.length);
|
|
66
|
-
message.set(prefix, 0);
|
|
67
|
-
message.set(lane, prefix.length);
|
|
68
|
-
return message;
|
|
69
|
-
}
|
|
70
|
-
async function computeTag(key, brand, kind, lane) {
|
|
71
|
-
return new Uint8Array(await crypto.subtle.sign("HMAC", key.hmacKey, hmacMessage(brand, kind, lane))).subarray(0, tagByteLength);
|
|
72
|
-
}
|
|
73
|
-
function tagsEqual(a, b) {
|
|
74
|
-
let diff = 0;
|
|
75
|
-
for (let i = 0; i < a.length; i++) diff |= a[i] ^ b[i];
|
|
76
|
-
return diff === 0;
|
|
77
|
-
}
|
|
78
|
-
async function encryptPayload(key, plaintext) {
|
|
79
|
-
return new Uint8Array(await crypto.subtle.encrypt({
|
|
80
|
-
name: "AES-CBC",
|
|
81
|
-
iv: zeroIv
|
|
82
|
-
}, key.aesKey, plaintext)).subarray(0, 16);
|
|
83
|
-
}
|
|
84
|
-
async function decryptPayload(key, c1) {
|
|
85
|
-
const c2Input = new Uint8Array(16);
|
|
86
|
-
for (let i = 0; i < 16; i++) c2Input[i] = pkcsPad ^ c1[i];
|
|
87
|
-
const c2Encrypted = new Uint8Array(await crypto.subtle.encrypt({
|
|
88
|
-
name: "AES-CBC",
|
|
89
|
-
iv: zeroIv
|
|
90
|
-
}, key.aesKey, c2Input));
|
|
91
|
-
const ciphertext = new Uint8Array(32);
|
|
92
|
-
ciphertext.set(c1, 0);
|
|
93
|
-
ciphertext.set(c2Encrypted.subarray(0, 16), 16);
|
|
94
|
-
return new Uint8Array(await crypto.subtle.decrypt({
|
|
95
|
-
name: "AES-CBC",
|
|
96
|
-
iv: zeroIv
|
|
97
|
-
}, key.aesKey, ciphertext));
|
|
98
|
-
}
|
|
99
|
-
function buildPlaintext(lane, tag) {
|
|
100
|
-
const plaintext = new Uint8Array(16);
|
|
101
|
-
plaintext.set(lane, 0);
|
|
102
|
-
plaintext.set(tag, laneByteLength);
|
|
103
|
-
return plaintext;
|
|
104
|
-
}
|
|
105
|
-
async function wrapLookupKey(prefix, brand, key, kind, lookupKey) {
|
|
106
|
-
const lane = new Uint8Array(laneByteLength);
|
|
107
|
-
writeLane(kind, lookupKey, lane);
|
|
108
|
-
return toWireId(prefix, await encryptPayload(key, buildPlaintext(lane, await computeTag(key, brand, kind, lane))));
|
|
109
|
-
}
|
|
110
|
-
async function tryUnwrapLookupKey(prefix, brand, key, kind, id) {
|
|
111
|
-
const plaintext = await decryptPayload(key, payloadBytesFromId(prefix, id));
|
|
112
|
-
const lane = plaintext.subarray(0, laneByteLength);
|
|
113
|
-
if (!tagsEqual(plaintext.subarray(laneByteLength, 16), await computeTag(key, brand, kind, lane))) return null;
|
|
114
|
-
return readLane(kind, lane);
|
|
115
|
-
}
|
|
116
|
-
function schemaExample(prefix) {
|
|
117
|
-
return prefix + "0".repeat(payloadBase32Length);
|
|
118
|
-
}
|
|
119
|
-
function createWrappedLayoutOps(prefix, brand, kind, keys) {
|
|
120
|
-
const wrapKey = keys[0];
|
|
121
|
-
return {
|
|
122
|
-
wrap: (lookupKey) => wrapLookupKey(prefix, brand, wrapKey, kind, lookupKey),
|
|
123
|
-
unwrap: async (id) => {
|
|
124
|
-
for (const key of keys) {
|
|
125
|
-
const lookupKey = await tryUnwrapLookupKey(prefix, brand, key, kind, id);
|
|
126
|
-
if (lookupKey !== null) return lookupKey;
|
|
127
|
-
}
|
|
128
|
-
throw new Error("verification failed");
|
|
129
|
-
},
|
|
130
|
-
tryUnwrap: async (id) => {
|
|
131
|
-
for (const key of keys) {
|
|
132
|
-
const lookupKey = await tryUnwrapLookupKey(prefix, brand, key, kind, id);
|
|
133
|
-
if (lookupKey !== null) return lookupKey;
|
|
134
|
-
}
|
|
135
|
-
return null;
|
|
136
|
-
},
|
|
137
|
-
exampleWireId: () => schemaExample(prefix)
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
//#endregion
|
|
141
|
-
//#region src/wrapping-key.ts
|
|
142
|
-
const validKeyByteLengths = new Set([
|
|
143
|
-
16,
|
|
144
|
-
24,
|
|
145
|
-
32
|
|
146
|
-
]);
|
|
147
|
-
const aesInfo = new TextEncoder().encode("@smonn/ids/wrapped/aes/v1");
|
|
148
|
-
const hmacInfo = new TextEncoder().encode("@smonn/ids/wrapped/hmac/v1");
|
|
149
|
-
const internals = /* @__PURE__ */ new WeakMap();
|
|
150
|
-
/**
|
|
151
|
-
* Imports raw operator secret bytes into a {@link WrappingKey} handle.
|
|
152
|
-
*
|
|
153
|
-
* @param bytes - 16, 24, or 32 raw key bytes (AES-128/192/256).
|
|
154
|
-
*/
|
|
155
|
-
async function importWrappingKey(bytes) {
|
|
156
|
-
assertValidKeyByteLength(bytes.length);
|
|
157
|
-
const aesKey = await deriveAesKey(bytes);
|
|
158
|
-
const hmacKey = await deriveHmacKey(bytes);
|
|
159
|
-
const key = Object.freeze({});
|
|
160
|
-
internals.set(key, {
|
|
161
|
-
rawBytes: bytes.slice(),
|
|
162
|
-
aesKey,
|
|
163
|
-
hmacKey
|
|
164
|
-
});
|
|
165
|
-
return key;
|
|
166
|
-
}
|
|
167
|
-
/**
|
|
168
|
-
* Encodes raw wrapping operator secret bytes for storage in env vars or secret managers.
|
|
169
|
-
*/
|
|
170
|
-
function encodeWrappingKey(bytes, format) {
|
|
171
|
-
assertWrappingKeyFormat(format);
|
|
172
|
-
assertValidKeyByteLength(bytes.length);
|
|
173
|
-
if (format === "hex") return encodeHex(bytes);
|
|
174
|
-
return encodeBase64Url(bytes);
|
|
175
|
-
}
|
|
176
|
-
/**
|
|
177
|
-
* Decodes key material emitted by {@link encodeWrappingKey} back to raw bytes.
|
|
178
|
-
*/
|
|
179
|
-
function decodeWrappingKey(encoded, format) {
|
|
180
|
-
assertWrappingKeyFormat(format);
|
|
181
|
-
let bytes;
|
|
182
|
-
if (format === "hex") {
|
|
183
|
-
if (encoded.length === 0 || encoded.length % 2 !== 0) throw new Error("invalid hex key: length must be a positive even number of characters");
|
|
184
|
-
if (!/^[0-9a-fA-F]+$/.test(encoded)) throw new Error("invalid hex key: expected [0-9a-fA-F] only");
|
|
185
|
-
bytes = decodeHex(encoded);
|
|
186
|
-
} else try {
|
|
187
|
-
bytes = decodeBase64Url(encoded);
|
|
188
|
-
} catch {
|
|
189
|
-
throw new Error("invalid base64url key");
|
|
190
|
-
}
|
|
191
|
-
assertValidKeyByteLength(bytes.length);
|
|
192
|
-
return bytes;
|
|
193
|
-
}
|
|
194
|
-
/** Returns true when two handles were imported from the same raw operator secret. */
|
|
195
|
-
function wrappingKeysEqual(a, b) {
|
|
196
|
-
const aInternals = getWrappingKeyInternals(a);
|
|
197
|
-
const bInternals = getWrappingKeyInternals(b);
|
|
198
|
-
if (aInternals.rawBytes.length !== bInternals.rawBytes.length) return false;
|
|
199
|
-
for (let i = 0; i < aInternals.rawBytes.length; i++) if (aInternals.rawBytes[i] !== bInternals.rawBytes[i]) return false;
|
|
200
|
-
return true;
|
|
201
|
-
}
|
|
202
|
-
function getWrappingKeyMaterial(key) {
|
|
203
|
-
const keyInternals = getWrappingKeyInternals(key);
|
|
204
|
-
return {
|
|
205
|
-
aesKey: keyInternals.aesKey,
|
|
206
|
-
hmacKey: keyInternals.hmacKey
|
|
207
|
-
};
|
|
208
|
-
}
|
|
209
|
-
function getWrappingKeyInternals(key) {
|
|
210
|
-
const keyInternals = internals.get(key);
|
|
211
|
-
if (keyInternals === void 0) throw new Error("invalid wrapping key");
|
|
212
|
-
return keyInternals;
|
|
213
|
-
}
|
|
214
|
-
async function deriveAesKey(bytes) {
|
|
215
|
-
const base = await crypto.subtle.importKey("raw", bytes, "HKDF", false, ["deriveKey"]);
|
|
216
|
-
return crypto.subtle.deriveKey({
|
|
217
|
-
name: "HKDF",
|
|
218
|
-
hash: "SHA-256",
|
|
219
|
-
salt: new Uint8Array(),
|
|
220
|
-
info: aesInfo
|
|
221
|
-
}, base, {
|
|
222
|
-
name: "AES-CBC",
|
|
223
|
-
length: 256
|
|
224
|
-
}, false, ["encrypt", "decrypt"]);
|
|
225
|
-
}
|
|
226
|
-
async function deriveHmacKey(bytes) {
|
|
227
|
-
const base = await crypto.subtle.importKey("raw", bytes, "HKDF", false, ["deriveKey"]);
|
|
228
|
-
return crypto.subtle.deriveKey({
|
|
229
|
-
name: "HKDF",
|
|
230
|
-
hash: "SHA-256",
|
|
231
|
-
salt: new Uint8Array(),
|
|
232
|
-
info: hmacInfo
|
|
233
|
-
}, base, {
|
|
234
|
-
name: "HMAC",
|
|
235
|
-
hash: "SHA-256",
|
|
236
|
-
length: 256
|
|
237
|
-
}, false, ["sign", "verify"]);
|
|
238
|
-
}
|
|
239
|
-
function assertValidKeyByteLength(byteLength) {
|
|
240
|
-
if (!validKeyByteLengths.has(byteLength)) throw new Error(`invalid wrapping key length: expected 16, 24, or 32 bytes, got ${byteLength}`);
|
|
241
|
-
}
|
|
242
|
-
function assertWrappingKeyFormat(format) {
|
|
243
|
-
if (format !== "hex" && format !== "base64url") throw new Error(`invalid wrapping key format: expected hex or base64url, got '${formatForError(format)}'`);
|
|
244
|
-
}
|
|
245
|
-
function formatForError(value) {
|
|
246
|
-
try {
|
|
247
|
-
return String(value);
|
|
248
|
-
} catch {
|
|
249
|
-
return "[unprintable]";
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
//#endregion
|
|
253
|
-
//#region src/wrapped.ts
|
|
254
|
-
const u32Max = 4294967295;
|
|
255
|
-
const i32Min = -2147483648;
|
|
256
|
-
const i32Max = 2147483647;
|
|
257
|
-
const u64Max = 18446744073709551615n;
|
|
258
|
-
const i64Min = -(1n << 63n);
|
|
259
|
-
const i64Max = (1n << 63n) - 1n;
|
|
260
|
-
function assertSupportedKind(kind) {
|
|
261
|
-
if (kind !== "u32" && kind !== "i32" && kind !== "u64" && kind !== "i64") throw new Error("invalid wrapped key kind: expected u32, i32, u64, or i64");
|
|
262
|
-
}
|
|
263
|
-
function assertNonEmptyKeyring(keys) {
|
|
264
|
-
if (keys.length === 0) throw new Error("wrapped keyring must contain at least one key");
|
|
265
|
-
}
|
|
266
|
-
function assertNonDuplicateKeys(keys) {
|
|
267
|
-
for (let i = 0; i < keys.length; i++) for (let j = i + 1; j < keys.length; j++) if (wrappingKeysEqual(keys[i], keys[j])) throw new Error("duplicate wrapping key in keyring");
|
|
268
|
-
}
|
|
269
|
-
function assertU32LookupKey(lookupKey) {
|
|
270
|
-
if (typeof lookupKey !== "number" || !Number.isInteger(lookupKey) || Object.is(lookupKey, -0) || lookupKey < 0 || lookupKey > u32Max) throw new Error(`invalid u32 lookup key: expected integer in [0, ${u32Max}], got ${lookupKey}`);
|
|
271
|
-
}
|
|
272
|
-
function assertI32LookupKey(lookupKey) {
|
|
273
|
-
if (typeof lookupKey !== "number" || !Number.isInteger(lookupKey) || Object.is(lookupKey, -0) || lookupKey < i32Min || lookupKey > i32Max) throw new Error(`invalid i32 lookup key: expected integer in [${i32Min}, ${i32Max}], got ${lookupKey}`);
|
|
274
|
-
}
|
|
275
|
-
function assertU64LookupKey(lookupKey) {
|
|
276
|
-
if (typeof lookupKey !== "bigint" || lookupKey < 0n || lookupKey > u64Max) throw new Error(`invalid u64 lookup key: expected bigint in [0, ${u64Max}], got ${lookupKey}`);
|
|
277
|
-
}
|
|
278
|
-
function assertI64LookupKey(lookupKey) {
|
|
279
|
-
if (typeof lookupKey !== "bigint" || lookupKey < i64Min || lookupKey > i64Max) throw new Error(`invalid i64 lookup key: expected bigint in [${i64Min}, ${i64Max}], got ${lookupKey}`);
|
|
280
|
-
}
|
|
281
|
-
function assertLookupKey(kind, lookupKey) {
|
|
282
|
-
if (kind === "i32") {
|
|
283
|
-
assertI32LookupKey(lookupKey);
|
|
284
|
-
return;
|
|
285
|
-
}
|
|
286
|
-
if (kind === "u64") {
|
|
287
|
-
assertU64LookupKey(lookupKey);
|
|
288
|
-
return;
|
|
289
|
-
}
|
|
290
|
-
if (kind === "i64") {
|
|
291
|
-
assertI64LookupKey(lookupKey);
|
|
292
|
-
return;
|
|
293
|
-
}
|
|
294
|
-
assertU32LookupKey(lookupKey);
|
|
295
|
-
}
|
|
296
|
-
function createWrappedKeyId(brand, opts) {
|
|
297
|
-
validateBrand(brand);
|
|
298
|
-
registerBrand(brand, opts.allowDuplicateBrand);
|
|
299
|
-
assertSupportedKind(opts.kind);
|
|
300
|
-
assertNonEmptyKeyring(opts.keys);
|
|
301
|
-
const layoutKeys = opts.keys.map(getWrappingKeyMaterial);
|
|
302
|
-
assertNonDuplicateKeys(opts.keys);
|
|
303
|
-
const prefix = `${brand}_`;
|
|
304
|
-
const wire = wireMethods(prefix);
|
|
305
|
-
const layout = createWrappedLayoutOps(prefix, brand, opts.kind, layoutKeys);
|
|
306
|
-
return {
|
|
307
|
-
wrap: async (lookupKey) => {
|
|
308
|
-
assertLookupKey(opts.kind, lookupKey);
|
|
309
|
-
return layout.wrap(lookupKey);
|
|
310
|
-
},
|
|
311
|
-
unwrap: (id) => layout.unwrap(id),
|
|
312
|
-
safeUnwrap: async (input) => {
|
|
313
|
-
const parsed = wire.safeParse(input);
|
|
314
|
-
if (!parsed.ok) return parsed;
|
|
315
|
-
const lookupKey = await layout.tryUnwrap(parsed.id);
|
|
316
|
-
if (lookupKey === null) return {
|
|
317
|
-
ok: false,
|
|
318
|
-
error: "verification_failed"
|
|
319
|
-
};
|
|
320
|
-
return {
|
|
321
|
-
ok: true,
|
|
322
|
-
id: parsed.id,
|
|
323
|
-
lookupKey
|
|
324
|
-
};
|
|
325
|
-
},
|
|
326
|
-
is: wire.is,
|
|
327
|
-
parse: wire.parse,
|
|
328
|
-
safeParse: wire.safeParse,
|
|
329
|
-
toJsonSchema: () => wire.toJsonSchema(brand, layout.exampleWireId()),
|
|
330
|
-
"~standard": wire["~standard"]
|
|
331
|
-
};
|
|
332
|
-
}
|
|
333
|
-
//#endregion
|
|
334
|
-
export { createWrappedKeyId, decodeWrappingKey, encodeWrappingKey, importWrappingKey };
|
|
335
|
-
|
|
336
|
-
//# sourceMappingURL=wrapped.mjs.map
|
|
1
|
+
import { n as isIdsError, t as IdsError } from "./error-Cp5qYZcv.mjs";
|
|
2
|
+
import { i as importWrappingKey, n as decodeWrappingKey, r as encodeWrappingKey, t as createWrappedKeyId } from "./wrapped-0vL72Nje.mjs";
|
|
3
|
+
export { IdsError, createWrappedKeyId, decodeWrappingKey, encodeWrappingKey, importWrappingKey, isIdsError };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@smonn/ids",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Simon Ingeson (https://github.com/smonn)",
|
|
6
6
|
"repository": {
|
|
@@ -17,22 +17,64 @@
|
|
|
17
17
|
"exports": {
|
|
18
18
|
".": "./dist/index.mjs",
|
|
19
19
|
"./opaque": "./dist/opaque.mjs",
|
|
20
|
+
"./reverse": "./dist/reverse.mjs",
|
|
21
|
+
"./signed": "./dist/signed.mjs",
|
|
20
22
|
"./wrapped": "./dist/wrapped.mjs",
|
|
23
|
+
"./drizzle": "./dist/drizzle.mjs",
|
|
24
|
+
"./hono": "./dist/hono.mjs",
|
|
25
|
+
"./kysely": "./dist/kysely.mjs",
|
|
26
|
+
"./prisma": "./dist/prisma.mjs",
|
|
27
|
+
"./express": "./dist/express.mjs",
|
|
28
|
+
"./fastify": "./dist/fastify.mjs",
|
|
21
29
|
"./package.json": "./package.json"
|
|
22
30
|
},
|
|
23
31
|
"devDependencies": {
|
|
24
32
|
"@changesets/cli": "2.31.0",
|
|
33
|
+
"@types/express": "^5.0.6",
|
|
25
34
|
"@types/node": "25.9.3",
|
|
26
35
|
"@vitest/coverage-v8": "4.1.8",
|
|
27
36
|
"dependency-cruiser": "17.4.3",
|
|
37
|
+
"drizzle-orm": "^0.45.2",
|
|
38
|
+
"express": "^5.2.1",
|
|
39
|
+
"fastify": "^5.8.5",
|
|
40
|
+
"hono": "^4.12.26",
|
|
28
41
|
"knip": "6.16.1",
|
|
42
|
+
"kysely": "^0.29.2",
|
|
29
43
|
"mitata": "1.0.34",
|
|
30
|
-
"oxfmt": "0.
|
|
31
|
-
"oxlint": "1.
|
|
44
|
+
"oxfmt": "0.55.0",
|
|
45
|
+
"oxlint": "1.69.0",
|
|
32
46
|
"tsdown": "0.22.2",
|
|
33
47
|
"typescript": "6.0.3",
|
|
34
48
|
"vitest": "4.1.8"
|
|
35
49
|
},
|
|
50
|
+
"peerDependencies": {
|
|
51
|
+
"@prisma/client": ">=5.0.0",
|
|
52
|
+
"drizzle-orm": ">=0.30.0",
|
|
53
|
+
"express": ">=4.0.0",
|
|
54
|
+
"fastify": ">=4.0.0",
|
|
55
|
+
"hono": ">=4.0.0",
|
|
56
|
+
"kysely": ">=0.27.0"
|
|
57
|
+
},
|
|
58
|
+
"peerDependenciesMeta": {
|
|
59
|
+
"drizzle-orm": {
|
|
60
|
+
"optional": true
|
|
61
|
+
},
|
|
62
|
+
"express": {
|
|
63
|
+
"optional": true
|
|
64
|
+
},
|
|
65
|
+
"fastify": {
|
|
66
|
+
"optional": true
|
|
67
|
+
},
|
|
68
|
+
"hono": {
|
|
69
|
+
"optional": true
|
|
70
|
+
},
|
|
71
|
+
"kysely": {
|
|
72
|
+
"optional": true
|
|
73
|
+
},
|
|
74
|
+
"@prisma/client": {
|
|
75
|
+
"optional": true
|
|
76
|
+
}
|
|
77
|
+
},
|
|
36
78
|
"engines": {
|
|
37
79
|
"node": ">=24.0.0"
|
|
38
80
|
},
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"codec-shell-dWpxoFmy.mjs","names":[],"sources":["../src/brand.ts","../src/base32.ts","../src/wire/envelope.ts","../src/wire/invariants.ts","../src/registry.ts","../src/wire/parse.ts","../src/wire/codec-shell.ts"],"sourcesContent":["const brandPattern = /^[a-z]{3}$/;\n\n/** Validates a three-character lowercase brand. Throws on invalid input. */\nexport function validateBrand(brand: string): void {\n if (!brandPattern.test(brand)) {\n throw new Error(\"invalid brand, expected three lowercase a-z characters\");\n }\n}\n","/*\n This is based on Crockford's Base32 spec: https://www.crockford.com/base32.html\n One difference is that it uses lowercase instead of uppercase when encoding.\n\n These functions are internal: codec constructors guarantee that input is a\n 16-byte buffer for encode, or a string of characters drawn from the alphabet\n for decode. Invalid input produces silent garbage rather than a thrown error,\n consistent with the trust-the-type rule in ADR-0003.\n*/\n\nexport const alphabet = \"0123456789abcdefghjkmnpqrstvwxyz\";\n\n// 0–31 → ASCII char code, for write-into-codes-then-fromCharCode encoding.\nconst valueToCharCode = new Uint8Array(32);\nfor (let i = 0; i < 32; i++) valueToCharCode[i] = alphabet.charCodeAt(i);\n\n// charCode → 0–31 value. Canonical lowercase only; upstream resolves case and\n// o/i/l aliases before any string reaches decodeBase32.\nconst INVALID = 0xff;\nconst charCodeToValue = new Uint8Array(256).fill(INVALID);\nfor (let i = 0; i < alphabet.length; i++) charCodeToValue[alphabet.charCodeAt(i)] = i;\n\nexport function encodeBase32(bytes: Uint8Array): string {\n // Build an Array<number> of char codes and pass it to fromCharCode.apply.\n // Faster than `result += char` (avoids cons-string overhead) and than\n // Uint8Array variants (apply has a fast path for plain Arrays).\n // oxlint-disable-next-line no-new-array\n const codes = new Array<number>(Math.floor((bytes.length * 8) / 5) + 1);\n let chi = 0;\n let bits = 0;\n let value = 0;\n\n for (let i = 0; i < bytes.length; i++) {\n value = (value << 8) | bytes[i]!;\n bits += 8;\n while (bits >= 5) {\n bits -= 5;\n codes[chi++] = valueToCharCode[(value >>> bits) & 0x1f]!;\n }\n }\n codes[chi] = valueToCharCode[(value << (5 - bits)) & 0x1f]!;\n return String.fromCharCode.apply(null, codes);\n}\n\nexport function decodeBase32(str: string): Uint8Array {\n const result = new Uint8Array(Math.floor((str.length * 5) / 8));\n let bits = 0;\n let value = 0;\n let index = 0;\n\n for (let i = 0; i < str.length; i++) {\n const v = charCodeToValue[str.charCodeAt(i)]!;\n value = (value << 5) | v;\n bits += 5;\n if (bits >= 8) {\n bits -= 8;\n result[index++] = (value >>> bits) & 0xff;\n }\n }\n return result;\n}\n","import { decodeBase32, encodeBase32 } from \"../base32.js\";\nimport type { Id, Prefix } from \"../types.js\";\n\n/** Encodes a 16-byte payload as lowercase Crockford base32 (26 chars). */\nfunction encodePayload(bytes: Uint8Array): string {\n return encodeBase32(bytes);\n}\n\n/** Decodes a 26-char base32 payload suffix to 16 bytes. Trust-the-type. */\nfunction decodePayload(base32: string): Uint8Array {\n return decodeBase32(base32);\n}\n\n/** Composes a canonical wire ID from a prefix and 16-byte payload. */\nexport function toWireId<Brand extends string>(\n prefix: Prefix<Brand>,\n payload: Uint8Array,\n): Id<Brand> {\n return (prefix + encodePayload(payload)) as Id<Brand>;\n}\n\n/** Decodes the full 16-byte payload from a trusted wire ID. */\nexport function payloadBytesFromId<Brand extends string>(\n prefix: Prefix<Brand>,\n id: Id<Brand>,\n): Uint8Array {\n return decodePayload(id.slice(prefix.length));\n}\n","// Payload is always 16 bytes on the wire (every codec). 16 bytes → 26 Crockford\n// base32 chars. ADR-0002 codifies this as the shared wire-format invariant.\nexport const payloadByteLength: number = 16;\nexport const payloadBase32Length: number = Math.ceil((payloadByteLength * 8) / 5);\n\n// Compact regex character class for the canonical lowercase Crockford alphabet\n// (`0123456789abcdefghjkmnpqrstvwxyz` — excludes i, l, o, u). Used in the JSON\n// Schema `pattern`, which describes the canonical wire form only (ADR-0003).\nexport const base32CharClass: string = \"[0-9a-hjkmnp-tv-z]\";\n","const registeredBrands = new Set<string>();\nconst warnedBrands = new Set<string>();\n\nexport function registerBrand(brand: string, allowDuplicateBrand: boolean | undefined): void {\n if (\n typeof process === \"undefined\" ||\n process.env.NODE_ENV === \"production\" ||\n allowDuplicateBrand\n ) {\n return;\n }\n\n if (registeredBrands.has(brand)) {\n if (!warnedBrands.has(brand)) {\n console.warn(\n `[@smonn/ids] brand \"${brand}\" was registered more than once — this usually indicates a bundling or import bug, or that more than one codec variant is using the same brand. Pass { allowDuplicateBrand: true } to silence.`,\n );\n warnedBrands.add(brand);\n }\n } else {\n registeredBrands.add(brand);\n }\n}\n","import { alphabet } from \"../base32.js\";\nimport type { Id, ParseError, ParseResult, Prefix } from \"../types.js\";\nimport { payloadBase32Length } from \"./invariants.js\";\n\nconst replacePattern = /[ilo]/g;\nconst aliasTestPattern = /[ilo]/;\nconst replacer = (match: string): string => (match === \"o\" ? \"0\" : \"1\");\nconst base32Pattern = new RegExp(`^[${alphabet}]{${payloadBase32Length}}$`);\n\nexport function safeParse<Brand extends string>(\n prefix: Prefix<Brand>,\n value: unknown,\n): ParseResult<Brand> {\n if (typeof value !== \"string\") return { ok: false, error: \"not_string\" };\n const lowercase = value.toLowerCase();\n if (!lowercase.startsWith(prefix)) return { ok: false, error: \"invalid_prefix\" };\n\n const sliced = lowercase.slice(prefix.length);\n const base32 = aliasTestPattern.test(sliced)\n ? sliced.replaceAll(replacePattern, replacer)\n : sliced;\n\n if (!base32Pattern.test(base32)) return { ok: false, error: \"invalid_base32\" };\n\n const id = (prefix + base32) as Id<Brand>;\n return { ok: true, id };\n}\n\nexport function parse<Brand extends string>(prefix: Prefix<Brand>, value: unknown): Id<Brand> {\n const result = safeParse(prefix, value);\n if (result.ok) return result.id;\n throw new Error(`Invalid ID: ${result.error}`);\n}\n\nexport function is<Brand extends string>(\n prefix: Prefix<Brand>,\n value: unknown,\n): value is Id<Brand> {\n if (typeof value !== \"string\") return false;\n if (!value.startsWith(prefix)) return false;\n return base32Pattern.test(value.slice(prefix.length));\n}\n\nfunction errorMessage<Brand extends string>(prefix: Prefix<Brand>, error: ParseError): string {\n switch (error) {\n case \"not_string\":\n return \"expected string\";\n case \"invalid_prefix\":\n return `expected prefix '${prefix}'`;\n case \"invalid_base32\":\n return \"invalid base32 payload\";\n }\n}\n\nexport function standardValidate<Brand extends string>(\n prefix: Prefix<Brand>,\n value: unknown,\n):\n | { readonly value: Id<Brand>; readonly issues?: undefined }\n | { readonly issues: ReadonlyArray<{ readonly message: string }> } {\n const result = safeParse(prefix, value);\n if (result.ok) return { value: result.id };\n return { issues: [{ message: errorMessage(prefix, result.error) }] };\n}\n","import type { Id, JsonSchema, ParseResult, Prefix, StandardSchemaProps } from \"../types.js\";\nimport { base32CharClass, payloadBase32Length } from \"./invariants.js\";\nimport { is, parse, safeParse, standardValidate } from \"./parse.js\";\n\ntype WireMethods<Brand extends string> = {\n is: (value: unknown) => value is Id<Brand>;\n parse: (value: unknown) => Id<Brand>;\n safeParse: (value: unknown) => ParseResult<Brand>;\n toJsonSchema: (brand: Brand, example: string) => JsonSchema;\n \"~standard\": StandardSchemaProps<Brand>;\n};\n\n/** Wire-only methods shared by every codec variant for a fixed prefix. */\nexport function wireMethods<Brand extends string>(prefix: Prefix<Brand>): WireMethods<Brand> {\n const standard: StandardSchemaProps<Brand> = {\n version: 1,\n vendor: \"@smonn/ids\",\n validate: (value: unknown) => standardValidate(prefix, value),\n };\n return {\n is: (value: unknown): value is Id<Brand> => is(prefix, value),\n parse: (value: unknown): Id<Brand> => parse(prefix, value),\n safeParse: (value: unknown): ParseResult<Brand> => safeParse(prefix, value),\n toJsonSchema: (brand: Brand, example: string): JsonSchema => ({\n type: \"string\",\n pattern: `^${prefix}${base32CharClass}{${payloadBase32Length}}$`,\n description: `Branded ID for '${brand}'`,\n example,\n }),\n \"~standard\": standard,\n };\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"opaque-B4ps7Pqk.mjs","names":[],"sources":["../src/layouts/opaque.ts","../src/opaque-key.ts","../src/opaque.ts"],"sourcesContent":["import type { Id, Prefix } from \"../types.js\";\nimport { payloadBytesFromId, toWireId } from \"../wire/envelope.js\";\nimport { payloadBase32Length, payloadByteLength } from \"../wire/invariants.js\";\nimport { readTimestampMs, timestampByteLength, writeTimestamp } from \"../wire/timestamp-bytes.js\";\n\nconst zeroIv = new Uint8Array(payloadByteLength);\nconst pkcsPad = 0x10;\n\nfunction buildPlaintext(ms: number, rng: (target: Uint8Array) => void): Uint8Array {\n const plaintext = new Uint8Array(payloadByteLength);\n writeTimestamp(ms, plaintext);\n rng(plaintext.subarray(timestampByteLength, payloadByteLength));\n return plaintext;\n}\n\nasync function encryptPayload(key: CryptoKey, plaintext: Uint8Array): Promise<Uint8Array> {\n const encrypted = new Uint8Array(\n await crypto.subtle.encrypt(\n { name: \"AES-CBC\", iv: zeroIv },\n key,\n plaintext as Uint8Array<ArrayBuffer>,\n ),\n );\n return encrypted.subarray(0, payloadByteLength);\n}\n\n// AES-CBC strip-and-reconstruct decrypt (ADR-0004). The wire carries only C1\n// (16 bytes); C2 = AES_K(P2 XOR C1) where P2 is the PKCS#7 pad block (0x10×16).\n// Recompute C2 via CBC encrypt of (P2 XOR C1) with IV=0, then decrypt C1‖C2.\nasync function decryptPayload(key: CryptoKey, c1: Uint8Array): Promise<Uint8Array> {\n const c2Input = new Uint8Array(payloadByteLength);\n for (let i = 0; i < payloadByteLength; i++) c2Input[i] = pkcsPad ^ c1[i]!;\n const c2Encrypted = new Uint8Array(\n await crypto.subtle.encrypt(\n { name: \"AES-CBC\", iv: zeroIv },\n key,\n c2Input as Uint8Array<ArrayBuffer>,\n ),\n );\n const ciphertext = new Uint8Array(payloadByteLength * 2);\n ciphertext.set(c1, 0);\n ciphertext.set(c2Encrypted.subarray(0, payloadByteLength), payloadByteLength);\n return new Uint8Array(\n await crypto.subtle.decrypt(\n { name: \"AES-CBC\", iv: zeroIv },\n key,\n ciphertext as Uint8Array<ArrayBuffer>,\n ),\n );\n}\n\nasync function extractTimestampFromId<Brand extends string>(\n prefix: Prefix<Brand>,\n key: CryptoKey,\n id: Id<Brand>,\n): Promise<Date> {\n const plaintext = await decryptPayload(key, payloadBytesFromId(prefix, id));\n return new Date(readTimestampMs(plaintext));\n}\n\n/** Produces a canonical encrypted wire ID. Per-call plaintext/ciphertext buffers —\n * subtle dominates this path; reuse would be safe but not worth pinning to spec detail. */\nasync function generateWireId<Brand extends string>(\n prefix: Prefix<Brand>,\n key: CryptoKey,\n rng: (target: Uint8Array) => void,\n ms: number,\n): Promise<Id<Brand>> {\n const plaintext = buildPlaintext(ms, rng);\n const encrypted = await encryptPayload(key, plaintext);\n return toWireId(prefix, encrypted);\n}\n\n/** Structural placeholder for JSON Schema (encrypt is async). */\nfunction schemaExample<Brand extends string>(prefix: Prefix<Brand>): string {\n return prefix + \"0\".repeat(payloadBase32Length);\n}\n\n/** Layout ops binder for the Opaque Timestamp variant. `extractTimestampFromId` is module-private; the binder exposes `extractTimestamp` for the codec constructor. */\nexport function createOpaqueLayoutOps<Brand extends string>(\n prefix: Prefix<Brand>,\n key: CryptoKey,\n rng: (target: Uint8Array) => void,\n) {\n return {\n generateAt: (ms: number): Promise<Id<Brand>> => generateWireId(prefix, key, rng, ms),\n extractTimestamp: (id: Id<Brand>): Promise<Date> => extractTimestampFromId(prefix, key, id),\n exampleWireId: (): Id<Brand> => schemaExample(prefix) as Id<Brand>,\n };\n}\n","import { decodeBase64Url, decodeHex, encodeBase64Url, encodeHex } from \"./bytes.js\";\n\n/** Wire encoding for opaque AES key material (not Crockford base32). */\nexport type OpaqueKeyFormat = \"hex\" | \"base64url\";\n\nconst validAesKeyByteLengths = new Set([16, 24, 32]);\n\n/**\n * Encodes raw AES key bytes for storage in env vars or secret managers.\n *\n * @param bytes - 16, 24, or 32 raw key bytes (AES-128/192/256).\n * @param format - `hex` (lowercase) or `base64url`.\n */\nexport function encodeOpaqueKey(bytes: Uint8Array, format: OpaqueKeyFormat): string {\n assertOpaqueKeyFormat(format);\n assertValidAesKeyByteLength(bytes.length);\n if (format === \"hex\") return encodeHex(bytes);\n return encodeBase64Url(bytes);\n}\n\n/**\n * Decodes key material emitted by `encodeOpaqueKey` (or `ids keygen`) back to raw bytes.\n *\n * @param encoded - Hex or base64url string.\n * @param format - Must match how the string was encoded.\n */\nexport function decodeOpaqueKey(encoded: string, format: OpaqueKeyFormat): Uint8Array {\n assertOpaqueKeyFormat(format);\n let bytes: Uint8Array;\n if (format === \"hex\") {\n if (encoded.length === 0 || encoded.length % 2 !== 0) {\n throw new Error(\"invalid hex key: length must be a positive even number of characters\");\n }\n if (!/^[0-9a-fA-F]+$/.test(encoded)) {\n throw new Error(\"invalid hex key: expected [0-9a-fA-F] only\");\n }\n bytes = decodeHex(encoded);\n } else {\n try {\n bytes = decodeBase64Url(encoded);\n } catch {\n throw new Error(\"invalid base64url key\");\n }\n }\n assertValidAesKeyByteLength(bytes.length);\n return bytes;\n}\n\nfunction assertValidAesKeyByteLength(byteLength: number): void {\n if (!validAesKeyByteLengths.has(byteLength)) {\n throw new Error(`invalid AES key length: expected 16, 24, or 32 bytes, got ${byteLength}`);\n }\n}\n\nfunction assertOpaqueKeyFormat(format: unknown): asserts format is OpaqueKeyFormat {\n if (format !== \"hex\" && format !== \"base64url\") {\n throw new Error(\n `invalid opaque key format: expected hex or base64url, got '${formatForError(format)}'`,\n );\n }\n}\n\nfunction formatForError(value: unknown): string {\n try {\n return String(value);\n } catch {\n return \"[unprintable]\";\n }\n}\n","import { validateBrand } from \"./brand.js\";\nimport { createOpaqueLayoutOps } from \"./layouts/opaque.js\";\nimport { registerBrand } from \"./registry.js\";\nimport type { Id, JsonSchema, ParseResult, Prefix, StandardSchemaProps } from \"./types.js\";\nimport { wireMethods } from \"./wire/codec-shell.js\";\n\nexport { decodeOpaqueKey, encodeOpaqueKey, type OpaqueKeyFormat } from \"./opaque-key.js\";\n\n/**\n * Configuration options for an Opaque Timestamp codec instance.\n */\nexport type OpaqueTimestampOptions = {\n /** AES-CBC key used for encryption and decryption. */\n key: CryptoKey;\n /** Returns the current timestamp in milliseconds. Defaults to `Date.now`. */\n now?: () => number;\n /** Writes random bytes into `target` for ID generation. Defaults to `crypto.getRandomValues`. */\n rng?: (target: Uint8Array) => void;\n /** If true, silences the duplicate-brand warning in non-production environments. */\n allowDuplicateBrand?: boolean;\n};\n\n/**\n * A brand-scoped codec for generating and validating Opaque Timestamp IDs.\n *\n * Same wire shape as the Timestamp codec (`{brand}_` + 26 base32 chars) but the\n * payload is AES-CBC encrypted. `generate`, `generateAt`, and `extractTimestamp`\n * are async; parsing methods are sync. No `minIdForTime` / `maxIdForTime` —\n * encrypted payloads do not sort by creation time.\n */\nexport type OpaqueTimestampCodec<Brand extends string> = {\n /** Produces a new canonical encrypted ID using the codec's `now` and `rng`. */\n generate(): Promise<Id<Brand>>;\n /** Produces a new canonical encrypted ID with timestamp bytes from `date`. Throws on invalid dates. */\n generateAt(date: Date): Promise<Id<Brand>>;\n /**\n * Strict type guard: `true` only for already-canonical strings for this brand.\n * For untrusted input, use `safeParse()` or `parse()` instead. See ADR-0003.\n */\n is(value: unknown): value is Id<Brand>;\n /**\n * Lenient parse: normalises case and Crockford aliases, returns canonical `Id<Brand>`, or throws.\n */\n parse(value: unknown): Id<Brand>;\n /**\n * Lenient parse without throwing: normalises to canonical form, or returns `{ ok: false, error }`.\n */\n safeParse(value: unknown): ParseResult<Brand>;\n /**\n * Decrypts and decodes the creation `Date` from an `Id<Brand>`. Trusts the type — use `safeParse()` at boundaries first. See ADR-0002.\n */\n extractTimestamp(id: Id<Brand>): Promise<Date>;\n /** JSON Schema for the canonical wire form (`example` is a structural placeholder). */\n toJsonSchema(): JsonSchema;\n /** Standard Schema validate entry point. */\n readonly \"~standard\": StandardSchemaProps<Brand>;\n};\n\nfunction defaultRng(target: Uint8Array): void {\n crypto.getRandomValues(target as Uint8Array<ArrayBuffer>);\n}\n\n/**\n * Imports a raw AES key for use with the Opaque Timestamp codec.\n *\n * @param bytes - Raw key bytes (16, 24, or 32 bytes for AES-128/192/256).\n */\nexport function importOpaqueKey(bytes: Uint8Array): Promise<CryptoKey> {\n return crypto.subtle.importKey(\"raw\", bytes as Uint8Array<ArrayBuffer>, \"AES-CBC\", false, [\n \"encrypt\",\n \"decrypt\",\n ]);\n}\n\n/**\n * Creates an Opaque Timestamp codec for `brand` (three lowercase a–z characters).\n *\n * @param brand - Entity type brand validated once at construction.\n * @param opts - Required `key` plus optional `now`, `rng`, and `allowDuplicateBrand` overrides.\n */\nexport function createOpaqueTimestampId<Brand extends string>(\n brand: Brand,\n opts: OpaqueTimestampOptions,\n): OpaqueTimestampCodec<Brand> {\n validateBrand(brand);\n registerBrand(brand, opts.allowDuplicateBrand);\n\n const key = opts.key;\n const now = opts.now ?? Date.now;\n const rng = opts.rng ?? defaultRng;\n const prefix: Prefix<Brand> = `${brand}_`;\n const wire = wireMethods(prefix);\n const layout = createOpaqueLayoutOps(prefix, key, rng);\n\n return {\n generate: () => layout.generateAt(now()),\n generateAt: (date: Date) => layout.generateAt(date.getTime()),\n is: wire.is,\n parse: wire.parse,\n safeParse: wire.safeParse,\n extractTimestamp: layout.extractTimestamp,\n toJsonSchema: () => wire.toJsonSchema(brand, layout.exampleWireId()),\n \"~standard\": wire[\"~standard\"],\n };\n}\n"],"mappings":"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"}
|
package/dist/wrapped.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"wrapped.mjs","names":[],"sources":["../src/layouts/wrapped.ts","../src/wrapping-key.ts","../src/wrapped.ts"],"sourcesContent":["import type { Id, Prefix } from \"../types.js\";\nimport { payloadBytesFromId, toWireId } from \"../wire/envelope.js\";\nimport { payloadBase32Length, payloadByteLength } from \"../wire/invariants.js\";\n\nconst zeroIv = new Uint8Array(payloadByteLength);\nconst pkcsPad = 0x10;\nconst laneByteLength = 8;\nconst tagByteLength = 8;\n\ntype LayoutWrappingKey = {\n aesKey: CryptoKey;\n hmacKey: CryptoKey;\n};\n\ntype LayoutWrappedKind = \"u32\" | \"i32\" | \"u64\" | \"i64\";\ntype LayoutLookupKey<K extends LayoutWrappedKind> = K extends \"u32\" | \"i32\" ? number : bigint;\n\nfunction writeU32Lane(value: number, lane: Uint8Array): void {\n lane[0] = 0;\n lane[1] = 0;\n lane[2] = 0;\n lane[3] = 0;\n lane[4] = (value >>> 24) & 0xff;\n lane[5] = (value >>> 16) & 0xff;\n lane[6] = (value >>> 8) & 0xff;\n lane[7] = value & 0xff;\n}\n\nfunction readU32Lane(lane: Uint8Array): number | null {\n for (let i = 0; i < 4; i++) {\n if (lane[i] !== 0) return null;\n }\n return ((lane[4]! << 24) | (lane[5]! << 16) | (lane[6]! << 8) | lane[7]!) >>> 0;\n}\n\nfunction writeI32Lane(value: number, lane: Uint8Array): void {\n lane.fill(value < 0 ? 0xff : 0x00, 0, 4);\n new DataView(lane.buffer, lane.byteOffset, lane.byteLength).setInt32(4, value, false);\n}\n\nfunction readI32Lane(lane: Uint8Array): number | null {\n const signExtension = (lane[4]! & 0x80) === 0 ? 0x00 : 0xff;\n for (let i = 0; i < 4; i++) {\n if (lane[i] !== signExtension) return null;\n }\n return new DataView(lane.buffer, lane.byteOffset, lane.byteLength).getInt32(4, false);\n}\n\nfunction writeU64Lane(value: bigint, lane: Uint8Array): void {\n new DataView(lane.buffer, lane.byteOffset, lane.byteLength).setBigUint64(0, value, false);\n}\n\nfunction readU64Lane(lane: Uint8Array): bigint {\n return new DataView(lane.buffer, lane.byteOffset, lane.byteLength).getBigUint64(0, false);\n}\n\nfunction writeI64Lane(value: bigint, lane: Uint8Array): void {\n new DataView(lane.buffer, lane.byteOffset, lane.byteLength).setBigInt64(0, value, false);\n}\n\nfunction readI64Lane(lane: Uint8Array): bigint {\n return new DataView(lane.buffer, lane.byteOffset, lane.byteLength).getBigInt64(0, false);\n}\n\nfunction writeLane<K extends LayoutWrappedKind>(\n kind: K,\n value: LayoutLookupKey<K>,\n lane: Uint8Array,\n): void {\n if (kind === \"i32\") {\n writeI32Lane(value as number, lane);\n return;\n }\n if (kind === \"u64\") {\n writeU64Lane(value as bigint, lane);\n return;\n }\n if (kind === \"i64\") {\n writeI64Lane(value as bigint, lane);\n return;\n }\n writeU32Lane(value as number, lane);\n}\n\nfunction readLane<K extends LayoutWrappedKind>(\n kind: K,\n lane: Uint8Array,\n): LayoutLookupKey<K> | null {\n if (kind === \"u64\") return readU64Lane(lane) as LayoutLookupKey<K>;\n if (kind === \"i64\") return readI64Lane(lane) as LayoutLookupKey<K>;\n const value = kind === \"i32\" ? readI32Lane(lane) : readU32Lane(lane);\n return value as LayoutLookupKey<K> | null;\n}\n\nfunction hmacMessage(brand: string, kind: LayoutWrappedKind, lane: Uint8Array): Uint8Array {\n const prefix = new TextEncoder().encode(`${brand}:${kind}:`);\n const message = new Uint8Array(prefix.length + lane.length);\n message.set(prefix, 0);\n message.set(lane, prefix.length);\n return message;\n}\n\nasync function computeTag(\n key: LayoutWrappingKey,\n brand: string,\n kind: LayoutWrappedKind,\n lane: Uint8Array,\n): Promise<Uint8Array> {\n const signature = new Uint8Array(\n await crypto.subtle.sign(\n \"HMAC\",\n key.hmacKey,\n hmacMessage(brand, kind, lane) as Uint8Array<ArrayBuffer>,\n ),\n );\n return signature.subarray(0, tagByteLength);\n}\n\nfunction tagsEqual(a: Uint8Array, b: Uint8Array): boolean {\n let diff = 0;\n for (let i = 0; i < a.length; i++) diff |= a[i]! ^ b[i]!;\n return diff === 0;\n}\n\nasync function encryptPayload(key: LayoutWrappingKey, plaintext: Uint8Array): Promise<Uint8Array> {\n const encrypted = new Uint8Array(\n await crypto.subtle.encrypt(\n { name: \"AES-CBC\", iv: zeroIv },\n key.aesKey,\n plaintext as Uint8Array<ArrayBuffer>,\n ),\n );\n return encrypted.subarray(0, payloadByteLength);\n}\n\nasync function decryptPayload(key: LayoutWrappingKey, c1: Uint8Array): Promise<Uint8Array> {\n const c2Input = new Uint8Array(payloadByteLength);\n for (let i = 0; i < payloadByteLength; i++) c2Input[i] = pkcsPad ^ c1[i]!;\n const c2Encrypted = new Uint8Array(\n await crypto.subtle.encrypt(\n { name: \"AES-CBC\", iv: zeroIv },\n key.aesKey,\n c2Input as Uint8Array<ArrayBuffer>,\n ),\n );\n const ciphertext = new Uint8Array(payloadByteLength * 2);\n ciphertext.set(c1, 0);\n ciphertext.set(c2Encrypted.subarray(0, payloadByteLength), payloadByteLength);\n return new Uint8Array(\n await crypto.subtle.decrypt(\n { name: \"AES-CBC\", iv: zeroIv },\n key.aesKey,\n ciphertext as Uint8Array<ArrayBuffer>,\n ),\n );\n}\n\nfunction buildPlaintext(lane: Uint8Array, tag: Uint8Array): Uint8Array {\n const plaintext = new Uint8Array(payloadByteLength);\n plaintext.set(lane, 0);\n plaintext.set(tag, laneByteLength);\n return plaintext;\n}\n\nasync function wrapLookupKey<Brand extends string, Kind extends LayoutWrappedKind>(\n prefix: Prefix<Brand>,\n brand: string,\n key: LayoutWrappingKey,\n kind: Kind,\n lookupKey: LayoutLookupKey<Kind>,\n): Promise<Id<Brand>> {\n const lane = new Uint8Array(laneByteLength);\n writeLane(kind, lookupKey, lane);\n const tag = await computeTag(key, brand, kind, lane);\n const encrypted = await encryptPayload(key, buildPlaintext(lane, tag));\n return toWireId(prefix, encrypted);\n}\n\nasync function tryUnwrapLookupKey<Brand extends string, Kind extends LayoutWrappedKind>(\n prefix: Prefix<Brand>,\n brand: string,\n key: LayoutWrappingKey,\n kind: Kind,\n id: Id<Brand>,\n): Promise<LayoutLookupKey<Kind> | null> {\n const plaintext = await decryptPayload(key, payloadBytesFromId(prefix, id));\n const lane = plaintext.subarray(0, laneByteLength);\n const tag = plaintext.subarray(laneByteLength, payloadByteLength);\n const expected = await computeTag(key, brand, kind, lane);\n if (!tagsEqual(tag, expected)) return null;\n return readLane(kind, lane);\n}\n\nfunction schemaExample<Brand extends string>(prefix: Prefix<Brand>): string {\n return prefix + \"0\".repeat(payloadBase32Length);\n}\n\nexport function createWrappedLayoutOps<Brand extends string, Kind extends LayoutWrappedKind>(\n prefix: Prefix<Brand>,\n brand: Brand,\n kind: Kind,\n keys: readonly LayoutWrappingKey[],\n) {\n const wrapKey = keys[0]!;\n return {\n wrap: (lookupKey: LayoutLookupKey<Kind>): Promise<Id<Brand>> =>\n wrapLookupKey(prefix, brand, wrapKey, kind, lookupKey),\n unwrap: async (id: Id<Brand>): Promise<LayoutLookupKey<Kind>> => {\n for (const key of keys) {\n const lookupKey = await tryUnwrapLookupKey(prefix, brand, key, kind, id);\n if (lookupKey !== null) return lookupKey;\n }\n throw new Error(\"verification failed\");\n },\n tryUnwrap: async (id: Id<Brand>): Promise<LayoutLookupKey<Kind> | null> => {\n for (const key of keys) {\n const lookupKey = await tryUnwrapLookupKey(prefix, brand, key, kind, id);\n if (lookupKey !== null) return lookupKey;\n }\n return null;\n },\n exampleWireId: (): Id<Brand> => schemaExample(prefix) as Id<Brand>,\n };\n}\n","import { decodeBase64Url, decodeHex, encodeBase64Url, encodeHex } from \"./bytes.js\";\n\n/** Wire encoding for wrapping operator secret bytes (not Crockford base32). */\nexport type WrappingKeyFormat = \"hex\" | \"base64url\";\n\nconst validKeyByteLengths = new Set([16, 24, 32]);\n\nconst aesInfo = new TextEncoder().encode(\"@smonn/ids/wrapped/aes/v1\");\nconst hmacInfo = new TextEncoder().encode(\"@smonn/ids/wrapped/hmac/v1\");\n\ndeclare const wrappingKeyBrand: unique symbol;\n\n/** Opaque imported handle for one operator wrapping secret (derived AES + HMAC subkeys). */\nexport type WrappingKey = {\n readonly [wrappingKeyBrand]: \"WrappingKey\";\n};\n\ntype WrappingKeyInternals = {\n rawBytes: Uint8Array;\n aesKey: CryptoKey;\n hmacKey: CryptoKey;\n};\n\nexport type WrappingKeyMaterial = {\n aesKey: CryptoKey;\n hmacKey: CryptoKey;\n};\n\nconst internals = new WeakMap<WrappingKey, WrappingKeyInternals>();\n\n/**\n * Imports raw operator secret bytes into a {@link WrappingKey} handle.\n *\n * @param bytes - 16, 24, or 32 raw key bytes (AES-128/192/256).\n */\nexport async function importWrappingKey(bytes: Uint8Array): Promise<WrappingKey> {\n assertValidKeyByteLength(bytes.length);\n const aesKey = await deriveAesKey(bytes);\n const hmacKey = await deriveHmacKey(bytes);\n const key = Object.freeze({}) as WrappingKey;\n internals.set(key, {\n rawBytes: bytes.slice(),\n aesKey,\n hmacKey,\n });\n return key;\n}\n\n/**\n * Encodes raw wrapping operator secret bytes for storage in env vars or secret managers.\n */\nexport function encodeWrappingKey(bytes: Uint8Array, format: WrappingKeyFormat): string {\n assertWrappingKeyFormat(format);\n assertValidKeyByteLength(bytes.length);\n if (format === \"hex\") return encodeHex(bytes);\n return encodeBase64Url(bytes);\n}\n\n/**\n * Decodes key material emitted by {@link encodeWrappingKey} back to raw bytes.\n */\nexport function decodeWrappingKey(encoded: string, format: WrappingKeyFormat): Uint8Array {\n assertWrappingKeyFormat(format);\n let bytes: Uint8Array;\n if (format === \"hex\") {\n if (encoded.length === 0 || encoded.length % 2 !== 0) {\n throw new Error(\"invalid hex key: length must be a positive even number of characters\");\n }\n if (!/^[0-9a-fA-F]+$/.test(encoded)) {\n throw new Error(\"invalid hex key: expected [0-9a-fA-F] only\");\n }\n bytes = decodeHex(encoded);\n } else {\n try {\n bytes = decodeBase64Url(encoded);\n } catch {\n throw new Error(\"invalid base64url key\");\n }\n }\n assertValidKeyByteLength(bytes.length);\n return bytes;\n}\n\n/** Returns true when two handles were imported from the same raw operator secret. */\nexport function wrappingKeysEqual(a: WrappingKey, b: WrappingKey): boolean {\n const aInternals = getWrappingKeyInternals(a);\n const bInternals = getWrappingKeyInternals(b);\n if (aInternals.rawBytes.length !== bInternals.rawBytes.length) return false;\n for (let i = 0; i < aInternals.rawBytes.length; i++) {\n if (aInternals.rawBytes[i] !== bInternals.rawBytes[i]) return false;\n }\n return true;\n}\n\nexport function getWrappingKeyMaterial(key: WrappingKey): WrappingKeyMaterial {\n const keyInternals = getWrappingKeyInternals(key);\n return {\n aesKey: keyInternals.aesKey,\n hmacKey: keyInternals.hmacKey,\n };\n}\n\nfunction getWrappingKeyInternals(key: WrappingKey): WrappingKeyInternals {\n const keyInternals = internals.get(key);\n if (keyInternals === undefined) {\n throw new Error(\"invalid wrapping key\");\n }\n return keyInternals;\n}\n\nasync function deriveAesKey(bytes: Uint8Array): Promise<CryptoKey> {\n const base = await crypto.subtle.importKey(\n \"raw\",\n bytes as Uint8Array<ArrayBuffer>,\n \"HKDF\",\n false,\n [\"deriveKey\"],\n );\n return crypto.subtle.deriveKey(\n { name: \"HKDF\", hash: \"SHA-256\", salt: new Uint8Array(), info: aesInfo },\n base,\n { name: \"AES-CBC\", length: 256 },\n false,\n [\"encrypt\", \"decrypt\"],\n );\n}\n\nasync function deriveHmacKey(bytes: Uint8Array): Promise<CryptoKey> {\n const base = await crypto.subtle.importKey(\n \"raw\",\n bytes as Uint8Array<ArrayBuffer>,\n \"HKDF\",\n false,\n [\"deriveKey\"],\n );\n return crypto.subtle.deriveKey(\n { name: \"HKDF\", hash: \"SHA-256\", salt: new Uint8Array(), info: hmacInfo },\n base,\n { name: \"HMAC\", hash: \"SHA-256\", length: 256 },\n false,\n [\"sign\", \"verify\"],\n );\n}\n\nfunction assertValidKeyByteLength(byteLength: number): void {\n if (!validKeyByteLengths.has(byteLength)) {\n throw new Error(`invalid wrapping key length: expected 16, 24, or 32 bytes, got ${byteLength}`);\n }\n}\n\nfunction assertWrappingKeyFormat(format: unknown): asserts format is WrappingKeyFormat {\n if (format !== \"hex\" && format !== \"base64url\") {\n throw new Error(\n `invalid wrapping key format: expected hex or base64url, got '${formatForError(format)}'`,\n );\n }\n}\n\nfunction formatForError(value: unknown): string {\n try {\n return String(value);\n } catch {\n return \"[unprintable]\";\n }\n}\n","import { validateBrand } from \"./brand.js\";\nimport { createWrappedLayoutOps } from \"./layouts/wrapped.js\";\nimport { registerBrand } from \"./registry.js\";\nimport type {\n Id,\n JsonSchema,\n ParseError,\n ParseResult,\n Prefix,\n StandardSchemaProps,\n} from \"./types.js\";\nimport { wireMethods } from \"./wire/codec-shell.js\";\nimport {\n decodeWrappingKey,\n encodeWrappingKey,\n getWrappingKeyMaterial,\n importWrappingKey,\n type WrappingKey,\n type WrappingKeyFormat,\n wrappingKeysEqual,\n} from \"./wrapping-key.js\";\n\nexport {\n decodeWrappingKey,\n encodeWrappingKey,\n importWrappingKey,\n type WrappingKey,\n type WrappingKeyFormat,\n};\n\nexport type WrappedKind = \"u32\" | \"i32\" | \"u64\" | \"i64\";\n\ntype LookupKeyForKind<K extends WrappedKind> = K extends \"u32\" | \"i32\" ? number : bigint;\n\nexport type UnwrapResult<Brand extends string, Kind extends WrappedKind> =\n | { ok: true; id: Id<Brand>; lookupKey: LookupKeyForKind<Kind> }\n | { ok: false; error: ParseError | \"verification_failed\" };\n\nexport type WrappedKeyCodec<Brand extends string, Kind extends WrappedKind> = {\n wrap(lookupKey: LookupKeyForKind<Kind>): Promise<Id<Brand>>;\n unwrap(id: Id<Brand>): Promise<LookupKeyForKind<Kind>>;\n safeUnwrap(input: unknown): Promise<UnwrapResult<Brand, Kind>>;\n is(value: unknown): value is Id<Brand>;\n parse(value: unknown): Id<Brand>;\n safeParse(value: unknown): ParseResult<Brand>;\n toJsonSchema(): JsonSchema;\n readonly \"~standard\": StandardSchemaProps<Brand>;\n};\n\nexport type WrappedKeyOptions<K extends WrappedKind> = {\n kind: K;\n keys: [WrappingKey, ...WrappingKey[]];\n allowDuplicateBrand?: boolean;\n};\n\nconst u32Max = 0xffff_ffff;\nconst i32Min = -0x8000_0000;\nconst i32Max = 0x7fff_ffff;\nconst u64Max = 0xffff_ffff_ffff_ffffn;\nconst i64Min = -(1n << 63n);\nconst i64Max = (1n << 63n) - 1n;\n\nfunction assertSupportedKind(kind: WrappedKind): asserts kind is WrappedKind {\n if (kind !== \"u32\" && kind !== \"i32\" && kind !== \"u64\" && kind !== \"i64\") {\n throw new Error(\"invalid wrapped key kind: expected u32, i32, u64, or i64\");\n }\n}\n\nfunction assertNonEmptyKeyring(keys: readonly WrappingKey[]): void {\n if (keys.length === 0) {\n throw new Error(\"wrapped keyring must contain at least one key\");\n }\n}\n\nfunction assertNonDuplicateKeys(keys: readonly WrappingKey[]): void {\n for (let i = 0; i < keys.length; i++) {\n for (let j = i + 1; j < keys.length; j++) {\n if (wrappingKeysEqual(keys[i]!, keys[j]!)) {\n throw new Error(\"duplicate wrapping key in keyring\");\n }\n }\n }\n}\n\nfunction assertU32LookupKey(lookupKey: unknown): asserts lookupKey is number {\n if (\n typeof lookupKey !== \"number\" ||\n !Number.isInteger(lookupKey) ||\n Object.is(lookupKey, -0) ||\n lookupKey < 0 ||\n lookupKey > u32Max\n ) {\n throw new Error(`invalid u32 lookup key: expected integer in [0, ${u32Max}], got ${lookupKey}`);\n }\n}\n\nfunction assertI32LookupKey(lookupKey: unknown): asserts lookupKey is number {\n if (\n typeof lookupKey !== \"number\" ||\n !Number.isInteger(lookupKey) ||\n Object.is(lookupKey, -0) ||\n lookupKey < i32Min ||\n lookupKey > i32Max\n ) {\n throw new Error(\n `invalid i32 lookup key: expected integer in [${i32Min}, ${i32Max}], got ${lookupKey}`,\n );\n }\n}\n\nfunction assertU64LookupKey(lookupKey: unknown): asserts lookupKey is bigint {\n if (typeof lookupKey !== \"bigint\" || lookupKey < 0n || lookupKey > u64Max) {\n throw new Error(`invalid u64 lookup key: expected bigint in [0, ${u64Max}], got ${lookupKey}`);\n }\n}\n\nfunction assertI64LookupKey(lookupKey: unknown): asserts lookupKey is bigint {\n if (typeof lookupKey !== \"bigint\" || lookupKey < i64Min || lookupKey > i64Max) {\n throw new Error(\n `invalid i64 lookup key: expected bigint in [${i64Min}, ${i64Max}], got ${lookupKey}`,\n );\n }\n}\n\nfunction assertLookupKey<Kind extends WrappedKind>(\n kind: Kind,\n lookupKey: unknown,\n): asserts lookupKey is LookupKeyForKind<Kind> {\n if (kind === \"i32\") {\n assertI32LookupKey(lookupKey);\n return;\n }\n if (kind === \"u64\") {\n assertU64LookupKey(lookupKey);\n return;\n }\n if (kind === \"i64\") {\n assertI64LookupKey(lookupKey);\n return;\n }\n assertU32LookupKey(lookupKey);\n}\n\nexport function createWrappedKeyId<Brand extends string, Kind extends WrappedKind>(\n brand: Brand,\n opts: WrappedKeyOptions<Kind>,\n): WrappedKeyCodec<Brand, Kind> {\n validateBrand(brand);\n registerBrand(brand, opts.allowDuplicateBrand);\n assertSupportedKind(opts.kind);\n assertNonEmptyKeyring(opts.keys);\n const layoutKeys = opts.keys.map(getWrappingKeyMaterial);\n assertNonDuplicateKeys(opts.keys);\n\n const prefix: Prefix<Brand> = `${brand}_`;\n const wire = wireMethods(prefix);\n const layout = createWrappedLayoutOps(prefix, brand, opts.kind, layoutKeys);\n\n return {\n wrap: async (lookupKey) => {\n assertLookupKey(opts.kind, lookupKey);\n return layout.wrap(lookupKey);\n },\n unwrap: (id) => layout.unwrap(id),\n safeUnwrap: async (input) => {\n const parsed = wire.safeParse(input);\n if (!parsed.ok) return parsed;\n const lookupKey = await layout.tryUnwrap(parsed.id);\n if (lookupKey === null) return { ok: false, error: \"verification_failed\" };\n return { ok: true, id: parsed.id, lookupKey };\n },\n is: wire.is,\n parse: wire.parse,\n safeParse: wire.safeParse,\n toJsonSchema: () => wire.toJsonSchema(brand, layout.exampleWireId()),\n \"~standard\": wire[\"~standard\"],\n };\n}\n"],"mappings":"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"}
|