@cardanowall/poe-standard 0.2.0 → 0.3.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/dist/error-codes.cjs +6 -0
- package/dist/error-codes.cjs.map +1 -1
- package/dist/error-codes.d.cts +2 -2
- package/dist/error-codes.d.ts +2 -2
- package/dist/error-codes.js +6 -0
- package/dist/error-codes.js.map +1 -1
- package/dist/index.cjs +130 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +130 -16
- package/dist/index.js.map +1 -1
- package/dist/validator.cjs +127 -16
- package/dist/validator.cjs.map +1 -1
- package/dist/validator.js +127 -16
- package/dist/validator.js.map +1 -1
- package/package.json +2 -2
package/dist/validator.cjs
CHANGED
|
@@ -2185,6 +2185,60 @@ function decodeCoseSign1(bytes) {
|
|
|
2185
2185
|
};
|
|
2186
2186
|
}
|
|
2187
2187
|
|
|
2188
|
+
// ../crypto-core/dist/sealed-poe.js
|
|
2189
|
+
var CARDANO_POE_SLOTS_TRANSCRIPT_PREFIX = new TextEncoder().encode(
|
|
2190
|
+
"cardano-poe-slots-transcript-v1"
|
|
2191
|
+
);
|
|
2192
|
+
var CARDANO_POE_HKDF_INFO_PAYLOAD = new TextEncoder().encode(
|
|
2193
|
+
"cardano-poe-payload-v1"
|
|
2194
|
+
);
|
|
2195
|
+
var CARDANO_POE_HKDF_INFO_PAYLOAD_PASSPHRASE = new TextEncoder().encode(
|
|
2196
|
+
"cardano-poe-payload-passphrase-v1"
|
|
2197
|
+
);
|
|
2198
|
+
var CARDANO_POE_XWING_KEK_SALT_PREFIX = new TextEncoder().encode(
|
|
2199
|
+
"cardano-poe-xwing-kek-salt-v1"
|
|
2200
|
+
);
|
|
2201
|
+
if (CARDANO_POE_SLOTS_TRANSCRIPT_PREFIX.length !== 31) {
|
|
2202
|
+
throw new Error(
|
|
2203
|
+
"CARDANO_POE_SLOTS_TRANSCRIPT_PREFIX byte-length invariant violated (expected 31)"
|
|
2204
|
+
);
|
|
2205
|
+
}
|
|
2206
|
+
if (CARDANO_POE_HKDF_INFO_PAYLOAD.length !== 22) {
|
|
2207
|
+
throw new Error("CARDANO_POE_HKDF_INFO_PAYLOAD byte-length invariant violated (expected 22)");
|
|
2208
|
+
}
|
|
2209
|
+
if (CARDANO_POE_HKDF_INFO_PAYLOAD_PASSPHRASE.length !== 33) {
|
|
2210
|
+
throw new Error(
|
|
2211
|
+
"CARDANO_POE_HKDF_INFO_PAYLOAD_PASSPHRASE byte-length invariant violated (expected 33)"
|
|
2212
|
+
);
|
|
2213
|
+
}
|
|
2214
|
+
if (CARDANO_POE_XWING_KEK_SALT_PREFIX.length !== 29) {
|
|
2215
|
+
throw new Error("CARDANO_POE_XWING_KEK_SALT_PREFIX byte-length invariant violated (expected 29)");
|
|
2216
|
+
}
|
|
2217
|
+
var MAX_SLOTS = 1024;
|
|
2218
|
+
var MAX_DECODED_ENVELOPE_BYTES = 65536;
|
|
2219
|
+
var CARDANO_POE_HKDF_INFO_KEK = new TextEncoder().encode("cardano-poe-kek-v1");
|
|
2220
|
+
var CARDANO_POE_HKDF_INFO_KEK_MLKEM768X25519 = new TextEncoder().encode(
|
|
2221
|
+
"cardano-poe-kek-mlkem768x25519-v1"
|
|
2222
|
+
);
|
|
2223
|
+
var CARDANO_POE_HKDF_INFO_SLOTS_MAC = new TextEncoder().encode(
|
|
2224
|
+
"cardano-poe-slots-mac-v1"
|
|
2225
|
+
);
|
|
2226
|
+
var ZERO_NONCE_12 = new Uint8Array(12);
|
|
2227
|
+
if (CARDANO_POE_HKDF_INFO_KEK.length !== 18) {
|
|
2228
|
+
throw new Error("CARDANO_POE_HKDF_INFO_KEK byte-length invariant violated (expected 18)");
|
|
2229
|
+
}
|
|
2230
|
+
if (CARDANO_POE_HKDF_INFO_KEK_MLKEM768X25519.length !== 33) {
|
|
2231
|
+
throw new Error(
|
|
2232
|
+
"CARDANO_POE_HKDF_INFO_KEK_MLKEM768X25519 byte-length invariant violated (expected 33)"
|
|
2233
|
+
);
|
|
2234
|
+
}
|
|
2235
|
+
if (CARDANO_POE_HKDF_INFO_SLOTS_MAC.length !== 24) {
|
|
2236
|
+
throw new Error("CARDANO_POE_HKDF_INFO_SLOTS_MAC byte-length invariant violated (expected 24)");
|
|
2237
|
+
}
|
|
2238
|
+
if (ZERO_NONCE_12.length !== 12) {
|
|
2239
|
+
throw new Error("ZERO_NONCE_12 byte-length invariant violated (expected 12)");
|
|
2240
|
+
}
|
|
2241
|
+
|
|
2188
2242
|
// src/chunked.ts
|
|
2189
2243
|
var UTF8_ENCODER = new TextEncoder();
|
|
2190
2244
|
function bytesChunkArrayConcat(chunks) {
|
|
@@ -2230,6 +2284,9 @@ var SEVERITY = Object.freeze({
|
|
|
2230
2284
|
UNSUPPORTED_ENVELOPE_SCHEME: "error",
|
|
2231
2285
|
ENC_SLOTS_EMPTY: "error",
|
|
2232
2286
|
ENC_SLOT_INVALID_SHAPE: "error",
|
|
2287
|
+
ENC_SLOTS_DUPLICATE_KEM_MATERIAL: "error",
|
|
2288
|
+
ENC_SLOTS_TOO_MANY: "error",
|
|
2289
|
+
ENC_ENVELOPE_TOO_LARGE: "error",
|
|
2233
2290
|
UNSUPPORTED_KEM_ALG: "error",
|
|
2234
2291
|
ENC_KEM_REQUIRED: "error",
|
|
2235
2292
|
KEM_EPK_LENGTH_MISMATCH: "error",
|
|
@@ -2409,6 +2466,8 @@ var KEM_FIELD_LENGTH_CODE = {
|
|
|
2409
2466
|
epk: "KEM_EPK_LENGTH_MISMATCH",
|
|
2410
2467
|
kem_ct: "KEM_CT_LENGTH_MISMATCH"
|
|
2411
2468
|
};
|
|
2469
|
+
var NONCE_LENGTH = 24;
|
|
2470
|
+
var SLOTS_MAC_LENGTH = 32;
|
|
2412
2471
|
var PASSPHRASE_KDF_ALGS = /* @__PURE__ */ new Set(["argon2id"]);
|
|
2413
2472
|
var KNOWN_SIG_ALG_IDS = /* @__PURE__ */ new Set([-8, -19]);
|
|
2414
2473
|
function validatePoeRecord(bytes) {
|
|
@@ -2725,24 +2784,62 @@ function checkItemEnc(item, idx, errors) {
|
|
|
2725
2784
|
);
|
|
2726
2785
|
}
|
|
2727
2786
|
if (hasSlots) {
|
|
2728
|
-
|
|
2787
|
+
const slotCount = enc.slots.length;
|
|
2788
|
+
if (slotCount < 1) {
|
|
2729
2789
|
errors.push(
|
|
2730
|
-
issue("ENC_SLOTS_EMPTY", [...basePath, "slots"], `slots length ${
|
|
2790
|
+
issue("ENC_SLOTS_EMPTY", [...basePath, "slots"], `slots length ${slotCount} < 1`)
|
|
2731
2791
|
);
|
|
2732
|
-
}
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
);
|
|
2745
|
-
|
|
2792
|
+
} else if (slotCount > MAX_SLOTS) {
|
|
2793
|
+
errors.push(
|
|
2794
|
+
issue(
|
|
2795
|
+
"ENC_SLOTS_TOO_MANY",
|
|
2796
|
+
[...basePath, "slots"],
|
|
2797
|
+
`slots length ${slotCount} exceeds MAX_SLOTS=${MAX_SLOTS}`
|
|
2798
|
+
)
|
|
2799
|
+
);
|
|
2800
|
+
} else {
|
|
2801
|
+
const descriptor = enc.kem !== void 0 ? KEM_SLOT_DESCRIPTORS[enc.kem] : void 0;
|
|
2802
|
+
if (descriptor !== void 0) {
|
|
2803
|
+
const rawSlotKeys = rawSlotKeySets(item.enc);
|
|
2804
|
+
const seenKemMaterial = /* @__PURE__ */ new Set();
|
|
2805
|
+
enc.slots.forEach((slot, si) => {
|
|
2806
|
+
const slotPath = [...basePath, "slots", si];
|
|
2807
|
+
checkSlotShape(
|
|
2808
|
+
slot,
|
|
2809
|
+
rawSlotKeys[si] ?? /* @__PURE__ */ new Set(),
|
|
2810
|
+
descriptor,
|
|
2811
|
+
enc.kem,
|
|
2812
|
+
slotPath,
|
|
2813
|
+
errors
|
|
2814
|
+
);
|
|
2815
|
+
const material = slotKemMaterial(slot, descriptor);
|
|
2816
|
+
if (material !== void 0) {
|
|
2817
|
+
const key = bytesToHex2(material);
|
|
2818
|
+
if (seenKemMaterial.has(key)) {
|
|
2819
|
+
errors.push(
|
|
2820
|
+
issue(
|
|
2821
|
+
"ENC_SLOTS_DUPLICATE_KEM_MATERIAL",
|
|
2822
|
+
[...slotPath, descriptor.field],
|
|
2823
|
+
`slot ${si} ${descriptor.field} duplicates an earlier slot \u2014 per-slot KEK uniqueness is violated`
|
|
2824
|
+
)
|
|
2825
|
+
);
|
|
2826
|
+
} else {
|
|
2827
|
+
seenKemMaterial.add(key);
|
|
2828
|
+
}
|
|
2829
|
+
}
|
|
2830
|
+
});
|
|
2831
|
+
const perSlotBytes = descriptor.fieldLength + descriptor.wrapLength;
|
|
2832
|
+
const decodedEnvelopeBytes = NONCE_LENGTH + SLOTS_MAC_LENGTH + slotCount * perSlotBytes;
|
|
2833
|
+
if (decodedEnvelopeBytes > MAX_DECODED_ENVELOPE_BYTES) {
|
|
2834
|
+
errors.push(
|
|
2835
|
+
issue(
|
|
2836
|
+
"ENC_ENVELOPE_TOO_LARGE",
|
|
2837
|
+
[...basePath, "slots"],
|
|
2838
|
+
`decoded envelope size ${decodedEnvelopeBytes} exceeds MAX_DECODED_ENVELOPE_BYTES=${MAX_DECODED_ENVELOPE_BYTES}`
|
|
2839
|
+
)
|
|
2840
|
+
);
|
|
2841
|
+
}
|
|
2842
|
+
}
|
|
2746
2843
|
}
|
|
2747
2844
|
}
|
|
2748
2845
|
if (hasPassphrase) {
|
|
@@ -2899,6 +2996,20 @@ function checkSlotShape(slot, rawKeys, descriptor, kem, slotPath, errors) {
|
|
|
2899
2996
|
);
|
|
2900
2997
|
}
|
|
2901
2998
|
}
|
|
2999
|
+
function slotKemMaterial(slot, descriptor) {
|
|
3000
|
+
if (descriptor.field === "epk") {
|
|
3001
|
+
return slot.epk;
|
|
3002
|
+
}
|
|
3003
|
+
if (slot.kem_ct === void 0) return void 0;
|
|
3004
|
+
return bytesChunkArrayConcat(slot.kem_ct);
|
|
3005
|
+
}
|
|
3006
|
+
function bytesToHex2(bytes) {
|
|
3007
|
+
let hex = "";
|
|
3008
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
3009
|
+
hex += bytes[i].toString(16).padStart(2, "0");
|
|
3010
|
+
}
|
|
3011
|
+
return hex;
|
|
3012
|
+
}
|
|
2902
3013
|
function rawSlotKeySets(rawEnc) {
|
|
2903
3014
|
const slots = mapLikeGet(rawEnc, "slots");
|
|
2904
3015
|
if (!Array.isArray(slots)) return [];
|