burnledger 0.1.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 +166 -0
- package/dist/cjs/client.d.ts +84 -0
- package/dist/cjs/client.d.ts.map +1 -0
- package/dist/cjs/client.js +275 -0
- package/dist/cjs/client.js.map +1 -0
- package/dist/cjs/crypto-browser.d.ts +7 -0
- package/dist/cjs/crypto-browser.d.ts.map +1 -0
- package/dist/cjs/crypto-browser.js +37 -0
- package/dist/cjs/crypto-browser.js.map +1 -0
- package/dist/cjs/crypto-node.d.ts +4 -0
- package/dist/cjs/crypto-node.d.ts.map +1 -0
- package/dist/cjs/crypto-node.js +30 -0
- package/dist/cjs/crypto-node.js.map +1 -0
- package/dist/cjs/crypto.d.ts +6 -0
- package/dist/cjs/crypto.d.ts.map +1 -0
- package/dist/cjs/crypto.js +4 -0
- package/dist/cjs/crypto.js.map +1 -0
- package/dist/cjs/errors.d.ts +76 -0
- package/dist/cjs/errors.d.ts.map +1 -0
- package/dist/cjs/errors.js +119 -0
- package/dist/cjs/errors.js.map +1 -0
- package/dist/cjs/http.d.ts +35 -0
- package/dist/cjs/http.d.ts.map +1 -0
- package/dist/cjs/http.js +136 -0
- package/dist/cjs/http.js.map +1 -0
- package/dist/cjs/index.browser.d.ts +31 -0
- package/dist/cjs/index.browser.d.ts.map +1 -0
- package/dist/cjs/index.browser.js +54 -0
- package/dist/cjs/index.browser.js.map +1 -0
- package/dist/cjs/index.d.ts +26 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +50 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/models.d.ts +119 -0
- package/dist/cjs/models.d.ts.map +1 -0
- package/dist/cjs/models.js +144 -0
- package/dist/cjs/models.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/pagination.d.ts +21 -0
- package/dist/cjs/pagination.d.ts.map +1 -0
- package/dist/cjs/pagination.js +50 -0
- package/dist/cjs/pagination.js.map +1 -0
- package/dist/cjs/verify.d.ts +47 -0
- package/dist/cjs/verify.d.ts.map +1 -0
- package/dist/cjs/verify.js +471 -0
- package/dist/cjs/verify.js.map +1 -0
- package/dist/cjs/webhooks.d.ts +17 -0
- package/dist/cjs/webhooks.d.ts.map +1 -0
- package/dist/cjs/webhooks.js +39 -0
- package/dist/cjs/webhooks.js.map +1 -0
- package/dist/esm/client.d.ts +84 -0
- package/dist/esm/client.d.ts.map +1 -0
- package/dist/esm/client.js +238 -0
- package/dist/esm/client.js.map +1 -0
- package/dist/esm/crypto-browser.d.ts +7 -0
- package/dist/esm/crypto-browser.d.ts.map +1 -0
- package/dist/esm/crypto-browser.js +34 -0
- package/dist/esm/crypto-browser.js.map +1 -0
- package/dist/esm/crypto-node.d.ts +4 -0
- package/dist/esm/crypto-node.d.ts.map +1 -0
- package/dist/esm/crypto-node.js +27 -0
- package/dist/esm/crypto-node.js.map +1 -0
- package/dist/esm/crypto.d.ts +6 -0
- package/dist/esm/crypto.d.ts.map +1 -0
- package/dist/esm/crypto.js +3 -0
- package/dist/esm/crypto.js.map +1 -0
- package/dist/esm/errors.d.ts +76 -0
- package/dist/esm/errors.d.ts.map +1 -0
- package/dist/esm/errors.js +105 -0
- package/dist/esm/errors.js.map +1 -0
- package/dist/esm/http.d.ts +35 -0
- package/dist/esm/http.d.ts.map +1 -0
- package/dist/esm/http.js +132 -0
- package/dist/esm/http.js.map +1 -0
- package/dist/esm/index.browser.d.ts +31 -0
- package/dist/esm/index.browser.d.ts.map +1 -0
- package/dist/esm/index.browser.js +31 -0
- package/dist/esm/index.browser.js.map +1 -0
- package/dist/esm/index.d.ts +26 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +26 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/models.d.ts +119 -0
- package/dist/esm/models.d.ts.map +1 -0
- package/dist/esm/models.js +132 -0
- package/dist/esm/models.js.map +1 -0
- package/dist/esm/pagination.d.ts +21 -0
- package/dist/esm/pagination.d.ts.map +1 -0
- package/dist/esm/pagination.js +46 -0
- package/dist/esm/pagination.js.map +1 -0
- package/dist/esm/verify.d.ts +47 -0
- package/dist/esm/verify.d.ts.map +1 -0
- package/dist/esm/verify.js +462 -0
- package/dist/esm/verify.js.map +1 -0
- package/dist/esm/webhooks.d.ts +17 -0
- package/dist/esm/webhooks.d.ts.map +1 -0
- package/dist/esm/webhooks.js +36 -0
- package/dist/esm/webhooks.js.map +1 -0
- package/package.json +62 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/** Offline certificate and transparency verification.
|
|
2
|
+
*
|
|
3
|
+
* Ports the Go signing payload builders (core/payload.go) and Merkle tree
|
|
4
|
+
* verification (core/merkle.go) to TypeScript. All crypto is delegated to
|
|
5
|
+
* a CryptoOps provider (Node or browser).
|
|
6
|
+
*
|
|
7
|
+
* Critical encoding details:
|
|
8
|
+
* - Go's json.Marshal encodes []byte as base64, [N]byte as number arrays.
|
|
9
|
+
* - The payload builders normalize both formats to lowercase hex strings.
|
|
10
|
+
* - Timestamps in payloads use second-precision UTC: "YYYY-MM-DDTHH:MM:SSZ".
|
|
11
|
+
* - RFC 8785 canonical JSON: sorted keys recursively, no whitespace.
|
|
12
|
+
* - Transparency leaf = SHA-256(0x00 || issuanceBytes(cert)), NOT the
|
|
13
|
+
* certificate signing payload. issuanceBytes reconstructs json.Marshal
|
|
14
|
+
* output at issuance time (transparency_status=PENDING, no transparency).
|
|
15
|
+
*/
|
|
16
|
+
import type { CryptoOps } from "./crypto.js";
|
|
17
|
+
import type { TransparencyResult, VerificationResult } from "./models.js";
|
|
18
|
+
export declare function hexToBytes(hex: string): Uint8Array;
|
|
19
|
+
export declare function bytesToHex(bytes: Uint8Array): string;
|
|
20
|
+
export interface PublicKeyInfo {
|
|
21
|
+
readonly keyBytes: Uint8Array;
|
|
22
|
+
readonly keyId: string;
|
|
23
|
+
readonly revoked: boolean;
|
|
24
|
+
}
|
|
25
|
+
export declare function publicKeyFromHex(crypto: CryptoOps, hexKey: string, opts?: {
|
|
26
|
+
revoked?: boolean;
|
|
27
|
+
}): Promise<PublicKeyInfo>;
|
|
28
|
+
type Cert = Record<string, unknown>;
|
|
29
|
+
/** Verify all signatures on a deletion certificate offline. */
|
|
30
|
+
export declare function verifyCertificate(crypto: CryptoOps, certificate: Cert, publicKeys: Map<string, PublicKeyInfo>): Promise<VerificationResult>;
|
|
31
|
+
/** Verify the transparency proof embedded in a certificate. */
|
|
32
|
+
export declare function verifyTransparency(crypto: CryptoOps, certificate: Cert, publicKeys: Map<string, PublicKeyInfo>): Promise<TransparencyResult>;
|
|
33
|
+
/** Reconstruct the certificate JSON as it existed at issuance time.
|
|
34
|
+
*
|
|
35
|
+
* At issuance: transparency_status = "PENDING", transparency = nil (omitted).
|
|
36
|
+
* Go uses json.Marshal(cert) which preserves struct field order. JSON.parse
|
|
37
|
+
* preserves key insertion order from the Go JSON, so JSON.stringify reproduces
|
|
38
|
+
* the same bytes.
|
|
39
|
+
*/
|
|
40
|
+
export declare function issuanceBytes(certificate: Cert): Uint8Array;
|
|
41
|
+
/** Verify a Merkle consistency proof (RFC 6962 Section 2.1.4).
|
|
42
|
+
*
|
|
43
|
+
* Port of Go's VerifyConsistency / Python's _verify_consistency.
|
|
44
|
+
*/
|
|
45
|
+
export declare function verifyConsistency(crypto: CryptoOps, oldSize: number, newSize: number, oldRoot: Uint8Array, newRoot: Uint8Array, proof: Uint8Array[]): Promise<boolean>;
|
|
46
|
+
export {};
|
|
47
|
+
//# sourceMappingURL=verify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/verify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,OAAO,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAQ1E,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CASlD;AAYD,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAQpD;AAoCD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAED,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAC3B,OAAO,CAAC,aAAa,CAAC,CAKxB;AAMD,KAAK,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEpC,+DAA+D;AAC/D,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,IAAI,EACjB,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,GACrC,OAAO,CAAC,kBAAkB,CAAC,CAsC7B;AAED,+DAA+D;AAC/D,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,IAAI,EACjB,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,GACrC,OAAO,CAAC,kBAAkB,CAAC,CAwC7B;AAMD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,IAAI,GAAG,UAAU,CAK3D;AAkSD;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,UAAU,EACnB,OAAO,EAAE,UAAU,EACnB,KAAK,EAAE,UAAU,EAAE,GAClB,OAAO,CAAC,OAAO,CAAC,CAgDlB"}
|
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
/** Offline certificate and transparency verification.
|
|
2
|
+
*
|
|
3
|
+
* Ports the Go signing payload builders (core/payload.go) and Merkle tree
|
|
4
|
+
* verification (core/merkle.go) to TypeScript. All crypto is delegated to
|
|
5
|
+
* a CryptoOps provider (Node or browser).
|
|
6
|
+
*
|
|
7
|
+
* Critical encoding details:
|
|
8
|
+
* - Go's json.Marshal encodes []byte as base64, [N]byte as number arrays.
|
|
9
|
+
* - The payload builders normalize both formats to lowercase hex strings.
|
|
10
|
+
* - Timestamps in payloads use second-precision UTC: "YYYY-MM-DDTHH:MM:SSZ".
|
|
11
|
+
* - RFC 8785 canonical JSON: sorted keys recursively, no whitespace.
|
|
12
|
+
* - Transparency leaf = SHA-256(0x00 || issuanceBytes(cert)), NOT the
|
|
13
|
+
* certificate signing payload. issuanceBytes reconstructs json.Marshal
|
|
14
|
+
* output at issuance time (transparency_status=PENDING, no transparency).
|
|
15
|
+
*/
|
|
16
|
+
import { VerificationError } from "./errors.js";
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
// Pure byte helpers (no Buffer, no node:crypto)
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
const HEX_CHARS = "0123456789abcdef";
|
|
21
|
+
export function hexToBytes(hex) {
|
|
22
|
+
const len = hex.length >>> 1;
|
|
23
|
+
const out = new Uint8Array(len);
|
|
24
|
+
for (let i = 0; i < len; i++) {
|
|
25
|
+
const hi = hex.charCodeAt(i * 2);
|
|
26
|
+
const lo = hex.charCodeAt(i * 2 + 1);
|
|
27
|
+
out[i] = (unhex(hi) << 4) | unhex(lo);
|
|
28
|
+
}
|
|
29
|
+
return out;
|
|
30
|
+
}
|
|
31
|
+
function unhex(c) {
|
|
32
|
+
// 0-9
|
|
33
|
+
if (c >= 48 && c <= 57)
|
|
34
|
+
return c - 48;
|
|
35
|
+
// a-f
|
|
36
|
+
if (c >= 97 && c <= 102)
|
|
37
|
+
return c - 87;
|
|
38
|
+
// A-F
|
|
39
|
+
if (c >= 65 && c <= 70)
|
|
40
|
+
return c - 55;
|
|
41
|
+
return 0;
|
|
42
|
+
}
|
|
43
|
+
export function bytesToHex(bytes) {
|
|
44
|
+
let out = "";
|
|
45
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
46
|
+
const b = bytes[i];
|
|
47
|
+
out += HEX_CHARS[b >>> 4];
|
|
48
|
+
out += HEX_CHARS[b & 0x0f];
|
|
49
|
+
}
|
|
50
|
+
return out;
|
|
51
|
+
}
|
|
52
|
+
function concatBytes(a, b) {
|
|
53
|
+
const out = new Uint8Array(a.length + b.length);
|
|
54
|
+
out.set(a, 0);
|
|
55
|
+
out.set(b, a.length);
|
|
56
|
+
return out;
|
|
57
|
+
}
|
|
58
|
+
function bytesEqual(a, b) {
|
|
59
|
+
if (a.length !== b.length)
|
|
60
|
+
return false;
|
|
61
|
+
for (let i = 0; i < a.length; i++) {
|
|
62
|
+
if (a[i] !== b[i])
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
function base64ToBytes(b64) {
|
|
68
|
+
// Use atob for universal browser+node compatibility.
|
|
69
|
+
// Node 18+ has atob globally; browsers always have it.
|
|
70
|
+
const bin = atob(b64);
|
|
71
|
+
const out = new Uint8Array(bin.length);
|
|
72
|
+
for (let i = 0; i < bin.length; i++) {
|
|
73
|
+
out[i] = bin.charCodeAt(i);
|
|
74
|
+
}
|
|
75
|
+
return out;
|
|
76
|
+
}
|
|
77
|
+
function textToBytes(s) {
|
|
78
|
+
return new TextEncoder().encode(s);
|
|
79
|
+
}
|
|
80
|
+
export async function publicKeyFromHex(crypto, hexKey, opts) {
|
|
81
|
+
const raw = hexToBytes(hexKey);
|
|
82
|
+
const hash = await crypto.sha256(raw);
|
|
83
|
+
const keyId = "dp_k_" + bytesToHex(hash);
|
|
84
|
+
return { keyBytes: raw, keyId, revoked: opts?.revoked ?? false };
|
|
85
|
+
}
|
|
86
|
+
/** Verify all signatures on a deletion certificate offline. */
|
|
87
|
+
export async function verifyCertificate(crypto, certificate, publicKeys) {
|
|
88
|
+
const issuer = certificate.issuer;
|
|
89
|
+
const keyId = issuer.key_id;
|
|
90
|
+
const pki = publicKeys.get(keyId);
|
|
91
|
+
if (pki === undefined)
|
|
92
|
+
throw new VerificationError(`unknown issuer key: ${keyId}`);
|
|
93
|
+
if (pki.revoked)
|
|
94
|
+
throw new VerificationError(`issuer key is revoked: ${keyId}`);
|
|
95
|
+
// 1. Attestation signature
|
|
96
|
+
const att = certificate.attestation;
|
|
97
|
+
const attPayload = buildAttestationPayload(certificate.subject, att);
|
|
98
|
+
const attSig = decodeSignature(att.attestation_signature);
|
|
99
|
+
if (!(await crypto.ed25519Verify(pki.keyBytes, attPayload, attSig))) {
|
|
100
|
+
throw new VerificationError("attestation signature is invalid");
|
|
101
|
+
}
|
|
102
|
+
// 2. Verification signature
|
|
103
|
+
const ver = certificate.verification;
|
|
104
|
+
const verPayload = buildVerificationPayload(certificate.attestation_id, ver);
|
|
105
|
+
const verSig = decodeSignature(ver.verification_signature);
|
|
106
|
+
if (!(await crypto.ed25519Verify(pki.keyBytes, verPayload, verSig))) {
|
|
107
|
+
throw new VerificationError("verification signature is invalid");
|
|
108
|
+
}
|
|
109
|
+
// 3. Certificate signature
|
|
110
|
+
const certPayload = buildCertificatePayload(certificate);
|
|
111
|
+
const certSig = decodeSignature(certificate.certificate_signature);
|
|
112
|
+
if (!(await crypto.ed25519Verify(pki.keyBytes, certPayload, certSig))) {
|
|
113
|
+
throw new VerificationError("certificate signature is invalid");
|
|
114
|
+
}
|
|
115
|
+
return "VALID";
|
|
116
|
+
}
|
|
117
|
+
/** Verify the transparency proof embedded in a certificate. */
|
|
118
|
+
export async function verifyTransparency(crypto, certificate, publicKeys) {
|
|
119
|
+
const transparency = certificate.transparency;
|
|
120
|
+
if (transparency == null) {
|
|
121
|
+
return "NOT_AVAILABLE";
|
|
122
|
+
}
|
|
123
|
+
const sth = transparency.signed_tree_head;
|
|
124
|
+
const issuer = certificate.issuer;
|
|
125
|
+
const keyId = issuer.key_id;
|
|
126
|
+
const pki = publicKeys.get(keyId);
|
|
127
|
+
if (pki === undefined)
|
|
128
|
+
throw new VerificationError(`unknown issuer key: ${keyId}`);
|
|
129
|
+
if (pki.revoked)
|
|
130
|
+
throw new VerificationError(`issuer key is revoked: ${keyId}`);
|
|
131
|
+
// 1. Tree head signature
|
|
132
|
+
const headPayload = buildTreeHeadPayload(sth);
|
|
133
|
+
const headSig = decodeSignature(sth.signature);
|
|
134
|
+
if (!(await crypto.ed25519Verify(pki.keyBytes, headPayload, headSig))) {
|
|
135
|
+
throw new VerificationError("tree head signature is invalid");
|
|
136
|
+
}
|
|
137
|
+
// 2. Merkle inclusion proof — leaf is hash of issuance-time certificate JSON,
|
|
138
|
+
// NOT the canonical signing payload. Matches Go's core.IssuanceBytes(cert).
|
|
139
|
+
const issuanceData = issuanceBytes(certificate);
|
|
140
|
+
const leaf = await hashLeaf(crypto, issuanceData);
|
|
141
|
+
const proofHashes = (transparency.inclusion_proof ?? []).map((h) => decodeBytes(h));
|
|
142
|
+
const root = decodeBytes(sth.root_hash);
|
|
143
|
+
const index = transparency.entry_index;
|
|
144
|
+
const treeSize = sth.tree_size;
|
|
145
|
+
if (!(await verifyInclusion(crypto, leaf, index, treeSize, proofHashes, root))) {
|
|
146
|
+
throw new VerificationError("merkle inclusion proof is invalid");
|
|
147
|
+
}
|
|
148
|
+
return "INCLUDED";
|
|
149
|
+
}
|
|
150
|
+
// ---------------------------------------------------------------------------
|
|
151
|
+
// Issuance bytes — matches Go's core.IssuanceBytes(cert)
|
|
152
|
+
// ---------------------------------------------------------------------------
|
|
153
|
+
/** Reconstruct the certificate JSON as it existed at issuance time.
|
|
154
|
+
*
|
|
155
|
+
* At issuance: transparency_status = "PENDING", transparency = nil (omitted).
|
|
156
|
+
* Go uses json.Marshal(cert) which preserves struct field order. JSON.parse
|
|
157
|
+
* preserves key insertion order from the Go JSON, so JSON.stringify reproduces
|
|
158
|
+
* the same bytes.
|
|
159
|
+
*/
|
|
160
|
+
export function issuanceBytes(certificate) {
|
|
161
|
+
const clone = JSON.parse(JSON.stringify(certificate));
|
|
162
|
+
clone.transparency_status = "PENDING";
|
|
163
|
+
delete clone.transparency;
|
|
164
|
+
return textToBytes(JSON.stringify(clone));
|
|
165
|
+
}
|
|
166
|
+
// ---------------------------------------------------------------------------
|
|
167
|
+
// RFC 8785 Canonical JSON
|
|
168
|
+
// ---------------------------------------------------------------------------
|
|
169
|
+
function canonicalJson(obj) {
|
|
170
|
+
return textToBytes(canonicalStringify(obj));
|
|
171
|
+
}
|
|
172
|
+
function canonicalStringify(val) {
|
|
173
|
+
if (val === null || val === undefined)
|
|
174
|
+
return "null";
|
|
175
|
+
if (typeof val === "boolean")
|
|
176
|
+
return val ? "true" : "false";
|
|
177
|
+
if (typeof val === "number")
|
|
178
|
+
return JSON.stringify(val);
|
|
179
|
+
if (typeof val === "string")
|
|
180
|
+
return JSON.stringify(val);
|
|
181
|
+
if (Array.isArray(val)) {
|
|
182
|
+
return "[" + val.map(canonicalStringify).join(",") + "]";
|
|
183
|
+
}
|
|
184
|
+
if (typeof val === "object") {
|
|
185
|
+
const obj = val;
|
|
186
|
+
const keys = Object.keys(obj).sort();
|
|
187
|
+
const pairs = keys.map((k) => JSON.stringify(k) + ":" + canonicalStringify(obj[k]));
|
|
188
|
+
return "{" + pairs.join(",") + "}";
|
|
189
|
+
}
|
|
190
|
+
return JSON.stringify(val);
|
|
191
|
+
}
|
|
192
|
+
// ---------------------------------------------------------------------------
|
|
193
|
+
// Byte encoding helpers
|
|
194
|
+
// ---------------------------------------------------------------------------
|
|
195
|
+
/** Convert a byte field to lowercase hex. Handles:
|
|
196
|
+
* - hex string (from hand-crafted test data)
|
|
197
|
+
* - base64 string (from Go's json.Marshal of []byte slices)
|
|
198
|
+
* - number[] (from Go's json.Marshal of [N]byte fixed arrays)
|
|
199
|
+
*/
|
|
200
|
+
function toHex(value) {
|
|
201
|
+
if (Array.isArray(value)) {
|
|
202
|
+
return bytesToHex(new Uint8Array(value));
|
|
203
|
+
}
|
|
204
|
+
const str = value;
|
|
205
|
+
if (/^[0-9a-fA-F]+$/.test(str) && str.length % 2 === 0) {
|
|
206
|
+
return str.toLowerCase();
|
|
207
|
+
}
|
|
208
|
+
return bytesToHex(base64ToBytes(str));
|
|
209
|
+
}
|
|
210
|
+
/** Decode a signature field to raw bytes. Same format handling as toHex. */
|
|
211
|
+
function decodeSignature(value) {
|
|
212
|
+
if (Array.isArray(value)) {
|
|
213
|
+
return new Uint8Array(value);
|
|
214
|
+
}
|
|
215
|
+
const str = value;
|
|
216
|
+
if (/^[0-9a-fA-F]+$/.test(str)) {
|
|
217
|
+
const raw = hexToBytes(str);
|
|
218
|
+
if (raw.length === 64)
|
|
219
|
+
return raw;
|
|
220
|
+
}
|
|
221
|
+
return base64ToBytes(str);
|
|
222
|
+
}
|
|
223
|
+
/** Decode a hash/bytes field to raw bytes. Same format handling as toHex. */
|
|
224
|
+
function decodeBytes(value) {
|
|
225
|
+
if (Array.isArray(value)) {
|
|
226
|
+
return new Uint8Array(value);
|
|
227
|
+
}
|
|
228
|
+
const str = value;
|
|
229
|
+
if (/^[0-9a-fA-F]+$/.test(str) && str.length % 2 === 0) {
|
|
230
|
+
return hexToBytes(str);
|
|
231
|
+
}
|
|
232
|
+
return base64ToBytes(str);
|
|
233
|
+
}
|
|
234
|
+
function formatTimestamp(ts) {
|
|
235
|
+
// Strip fractional seconds, normalize to YYYY-MM-DDTHH:MM:SSZ
|
|
236
|
+
let s = ts;
|
|
237
|
+
const dotIdx = s.indexOf(".");
|
|
238
|
+
if (dotIdx !== -1) {
|
|
239
|
+
// Find the end of fractional seconds (Z, +, or end)
|
|
240
|
+
let endIdx = s.length;
|
|
241
|
+
for (let i = dotIdx + 1; i < s.length; i++) {
|
|
242
|
+
if (s[i] === "Z" || s[i] === "+" || s[i] === "-") {
|
|
243
|
+
endIdx = i;
|
|
244
|
+
break;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
s = s.slice(0, dotIdx) + s.slice(endIdx);
|
|
248
|
+
}
|
|
249
|
+
if (s.endsWith("Z"))
|
|
250
|
+
return s;
|
|
251
|
+
// Strip timezone offset
|
|
252
|
+
const plusIdx = s.indexOf("+");
|
|
253
|
+
if (plusIdx !== -1) {
|
|
254
|
+
s = s.slice(0, plusIdx);
|
|
255
|
+
}
|
|
256
|
+
return s + "Z";
|
|
257
|
+
}
|
|
258
|
+
// ---------------------------------------------------------------------------
|
|
259
|
+
// Payload builders — exact ports of core/payload.go
|
|
260
|
+
// ---------------------------------------------------------------------------
|
|
261
|
+
function buildAttestationPayload(subject, att) {
|
|
262
|
+
const attestedAt = formatTimestamp(att.attested_at);
|
|
263
|
+
const systems = att.systems.map((s) => ({
|
|
264
|
+
canonical_version: s.canonical_version ?? null,
|
|
265
|
+
connector_type: s.connector_type,
|
|
266
|
+
hash_scope: s.hash_scope,
|
|
267
|
+
merkle_root: s.merkle_root
|
|
268
|
+
? toHex(s.merkle_root)
|
|
269
|
+
: null,
|
|
270
|
+
observed_at: attestedAt,
|
|
271
|
+
record_count: s.record_count,
|
|
272
|
+
system_id: s.system_name,
|
|
273
|
+
}));
|
|
274
|
+
const payload = {
|
|
275
|
+
attested_at: attestedAt,
|
|
276
|
+
proof_mode: att.proof_mode,
|
|
277
|
+
subject_hash: toHex(subject.identifier_hash),
|
|
278
|
+
systems,
|
|
279
|
+
};
|
|
280
|
+
return canonicalJson(payload);
|
|
281
|
+
}
|
|
282
|
+
function buildVerificationPayload(attestationId, ver) {
|
|
283
|
+
const verifiedAt = formatTimestamp(ver.verified_at);
|
|
284
|
+
const systems = ver.systems.map((s) => ({
|
|
285
|
+
observed_at: verifiedAt,
|
|
286
|
+
record_count: s.record_count,
|
|
287
|
+
system_id: s.system_name,
|
|
288
|
+
}));
|
|
289
|
+
const payload = {
|
|
290
|
+
attestation_id: attestationId,
|
|
291
|
+
systems,
|
|
292
|
+
verified_at: verifiedAt,
|
|
293
|
+
};
|
|
294
|
+
return canonicalJson(payload);
|
|
295
|
+
}
|
|
296
|
+
function buildCertificatePayload(cert) {
|
|
297
|
+
const att = cert.attestation;
|
|
298
|
+
const ver = cert.verification;
|
|
299
|
+
const issuer = cert.issuer;
|
|
300
|
+
const subject = cert.subject;
|
|
301
|
+
// Attestation systems — uses "system_name" field name
|
|
302
|
+
const attSystems = att.systems.map((s) => ({
|
|
303
|
+
canonical_version: s.canonical_version ?? null,
|
|
304
|
+
connector_type: s.connector_type,
|
|
305
|
+
hash_scope: s.hash_scope,
|
|
306
|
+
merkle_root: s.merkle_root
|
|
307
|
+
? toHex(s.merkle_root)
|
|
308
|
+
: null,
|
|
309
|
+
record_count: s.record_count,
|
|
310
|
+
system_name: s.system_name,
|
|
311
|
+
}));
|
|
312
|
+
const attObj = {
|
|
313
|
+
attestation_signature: toHex(att.attestation_signature),
|
|
314
|
+
attested_at: formatTimestamp(att.attested_at),
|
|
315
|
+
proof_mode: att.proof_mode,
|
|
316
|
+
systems: attSystems,
|
|
317
|
+
};
|
|
318
|
+
// Verification systems
|
|
319
|
+
const verSystems = ver.systems.map((s) => ({
|
|
320
|
+
connector_type: s.connector_type,
|
|
321
|
+
record_count: s.record_count,
|
|
322
|
+
system_name: s.system_name,
|
|
323
|
+
}));
|
|
324
|
+
const verObj = {
|
|
325
|
+
systems: verSystems,
|
|
326
|
+
verification_signature: toHex(ver.verification_signature),
|
|
327
|
+
verified_at: formatTimestamp(ver.verified_at),
|
|
328
|
+
};
|
|
329
|
+
const issuerObj = {
|
|
330
|
+
key_id: issuer.key_id,
|
|
331
|
+
name: issuer.name,
|
|
332
|
+
public_key: toHex(issuer.public_key),
|
|
333
|
+
};
|
|
334
|
+
const subjectObj = {
|
|
335
|
+
identifier_hash: toHex(subject.identifier_hash),
|
|
336
|
+
identifier_type_hint: subject.identifier_type_hint,
|
|
337
|
+
};
|
|
338
|
+
// Revocation
|
|
339
|
+
let revocation = null;
|
|
340
|
+
const rev = cert.revocation;
|
|
341
|
+
if (rev != null) {
|
|
342
|
+
revocation = {
|
|
343
|
+
reason: rev.reason,
|
|
344
|
+
replacement_certificate_id: rev.replacement_certificate_id ?? null,
|
|
345
|
+
revoked_at: formatTimestamp(rev.revoked_at),
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
const payload = {
|
|
349
|
+
attestation: attObj,
|
|
350
|
+
attestation_id: cert.attestation_id,
|
|
351
|
+
certificate_format_version: cert.certificate_format_version,
|
|
352
|
+
certificate_id: cert.certificate_id,
|
|
353
|
+
issued_at: formatTimestamp(cert.issued_at),
|
|
354
|
+
issuer: issuerObj,
|
|
355
|
+
revocation,
|
|
356
|
+
status: cert.status,
|
|
357
|
+
subject: subjectObj,
|
|
358
|
+
verification: verObj,
|
|
359
|
+
};
|
|
360
|
+
return canonicalJson(payload);
|
|
361
|
+
}
|
|
362
|
+
function buildTreeHeadPayload(head) {
|
|
363
|
+
const payload = {
|
|
364
|
+
root_hash: toHex(head.root_hash),
|
|
365
|
+
timestamp: formatTimestamp(head.timestamp),
|
|
366
|
+
tree_size: head.tree_size,
|
|
367
|
+
};
|
|
368
|
+
return canonicalJson(payload);
|
|
369
|
+
}
|
|
370
|
+
// ---------------------------------------------------------------------------
|
|
371
|
+
// Merkle tree (RFC 6962) — ports of core/merkle.go
|
|
372
|
+
// ---------------------------------------------------------------------------
|
|
373
|
+
async function hashLeaf(crypto, data) {
|
|
374
|
+
return crypto.sha256(concatBytes(new Uint8Array([0x00]), data));
|
|
375
|
+
}
|
|
376
|
+
async function hashNode(crypto, left, right) {
|
|
377
|
+
const prefix = new Uint8Array([0x01]);
|
|
378
|
+
return crypto.sha256(concatBytes(prefix, concatBytes(left, right)));
|
|
379
|
+
}
|
|
380
|
+
function splitPoint(n) {
|
|
381
|
+
let k = 1;
|
|
382
|
+
while (k * 2 < n) {
|
|
383
|
+
k *= 2;
|
|
384
|
+
}
|
|
385
|
+
return k;
|
|
386
|
+
}
|
|
387
|
+
async function verifyInclusion(crypto, leaf, index, size, proof, root) {
|
|
388
|
+
if (size === 0 || index >= size)
|
|
389
|
+
return false;
|
|
390
|
+
if (size === 1)
|
|
391
|
+
return proof.length === 0 && bytesEqual(leaf, root);
|
|
392
|
+
const [computed, consumed] = await chainInclusion(crypto, leaf, index, size, proof);
|
|
393
|
+
return consumed === proof.length && bytesEqual(computed, root);
|
|
394
|
+
}
|
|
395
|
+
async function chainInclusion(crypto, leaf, index, n, proof) {
|
|
396
|
+
if (n === 1)
|
|
397
|
+
return [leaf, 0];
|
|
398
|
+
const k = splitPoint(n);
|
|
399
|
+
if (index < k) {
|
|
400
|
+
const [inner, used] = await chainInclusion(crypto, leaf, index, k, proof);
|
|
401
|
+
if (used >= proof.length)
|
|
402
|
+
return [inner, used + 1];
|
|
403
|
+
return [await hashNode(crypto, inner, proof[used]), used + 1];
|
|
404
|
+
}
|
|
405
|
+
const [inner, used] = await chainInclusion(crypto, leaf, index - k, n - k, proof);
|
|
406
|
+
if (used >= proof.length)
|
|
407
|
+
return [inner, used + 1];
|
|
408
|
+
return [await hashNode(crypto, proof[used], inner), used + 1];
|
|
409
|
+
}
|
|
410
|
+
function isPow2(n) {
|
|
411
|
+
return n > 0 && (n & (n - 1)) === 0;
|
|
412
|
+
}
|
|
413
|
+
/** Verify a Merkle consistency proof (RFC 6962 Section 2.1.4).
|
|
414
|
+
*
|
|
415
|
+
* Port of Go's VerifyConsistency / Python's _verify_consistency.
|
|
416
|
+
*/
|
|
417
|
+
export async function verifyConsistency(crypto, oldSize, newSize, oldRoot, newRoot, proof) {
|
|
418
|
+
if (oldSize === 0 || newSize === 0 || oldSize > newSize)
|
|
419
|
+
return false;
|
|
420
|
+
if (oldSize === newSize) {
|
|
421
|
+
return proof.length === 0 && bytesEqual(oldRoot, newRoot);
|
|
422
|
+
}
|
|
423
|
+
let pIdx = 0;
|
|
424
|
+
let fr;
|
|
425
|
+
let sr;
|
|
426
|
+
if (isPow2(oldSize)) {
|
|
427
|
+
fr = oldRoot;
|
|
428
|
+
sr = oldRoot;
|
|
429
|
+
}
|
|
430
|
+
else {
|
|
431
|
+
if (pIdx >= proof.length)
|
|
432
|
+
return false;
|
|
433
|
+
fr = proof[pIdx];
|
|
434
|
+
sr = proof[pIdx];
|
|
435
|
+
pIdx++;
|
|
436
|
+
}
|
|
437
|
+
let fn = oldSize - 1;
|
|
438
|
+
let sn = newSize - 1;
|
|
439
|
+
while ((fn & 1) === 1) {
|
|
440
|
+
fn >>= 1;
|
|
441
|
+
sn >>= 1;
|
|
442
|
+
}
|
|
443
|
+
while (pIdx < proof.length) {
|
|
444
|
+
const c = proof[pIdx];
|
|
445
|
+
pIdx++;
|
|
446
|
+
if ((fn & 1) === 1 || fn === sn) {
|
|
447
|
+
fr = await hashNode(crypto, c, fr);
|
|
448
|
+
sr = await hashNode(crypto, c, sr);
|
|
449
|
+
while (fn !== 0 && (fn & 1) === 0) {
|
|
450
|
+
fn >>= 1;
|
|
451
|
+
sn >>= 1;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
else {
|
|
455
|
+
sr = await hashNode(crypto, sr, c);
|
|
456
|
+
}
|
|
457
|
+
fn >>= 1;
|
|
458
|
+
sn >>= 1;
|
|
459
|
+
}
|
|
460
|
+
return sn === 0 && bytesEqual(fr, oldRoot) && bytesEqual(sr, newRoot);
|
|
461
|
+
}
|
|
462
|
+
//# sourceMappingURL=verify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/verify.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** Webhook signature verification for incoming BurnLedger events.
|
|
2
|
+
*
|
|
3
|
+
* The server signs webhook payloads with HMAC-SHA256 using the webhook secret.
|
|
4
|
+
* The signature is sent in the X-BurnLedger-Signature header as a hex string.
|
|
5
|
+
*
|
|
6
|
+
* Node-only — webhooks are received server-side.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Verify that a webhook payload was signed by the expected secret.
|
|
10
|
+
*
|
|
11
|
+
* @param secret The webhook secret (raw UTF-8, as returned by the API)
|
|
12
|
+
* @param body The raw request body bytes
|
|
13
|
+
* @param signature The hex-encoded HMAC-SHA256 signature from the X-BurnLedger-Signature header
|
|
14
|
+
* @returns true if the signature is valid
|
|
15
|
+
*/
|
|
16
|
+
export declare function verifyWebhookSignature(secret: string, body: Uint8Array | string, signature: string): boolean;
|
|
17
|
+
//# sourceMappingURL=webhooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhooks.d.ts","sourceRoot":"","sources":["../../src/webhooks.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,UAAU,GAAG,MAAM,EACzB,SAAS,EAAE,MAAM,GAChB,OAAO,CAkBT"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/** Webhook signature verification for incoming BurnLedger events.
|
|
2
|
+
*
|
|
3
|
+
* The server signs webhook payloads with HMAC-SHA256 using the webhook secret.
|
|
4
|
+
* The signature is sent in the X-BurnLedger-Signature header as a hex string.
|
|
5
|
+
*
|
|
6
|
+
* Node-only — webhooks are received server-side.
|
|
7
|
+
*/
|
|
8
|
+
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
9
|
+
/**
|
|
10
|
+
* Verify that a webhook payload was signed by the expected secret.
|
|
11
|
+
*
|
|
12
|
+
* @param secret The webhook secret (raw UTF-8, as returned by the API)
|
|
13
|
+
* @param body The raw request body bytes
|
|
14
|
+
* @param signature The hex-encoded HMAC-SHA256 signature from the X-BurnLedger-Signature header
|
|
15
|
+
* @returns true if the signature is valid
|
|
16
|
+
*/
|
|
17
|
+
export function verifyWebhookSignature(secret, body, signature) {
|
|
18
|
+
if (secret.length === 0)
|
|
19
|
+
return false;
|
|
20
|
+
if (signature.length === 0)
|
|
21
|
+
return false;
|
|
22
|
+
const expected = createHmac("sha256", secret)
|
|
23
|
+
.update(typeof body === "string" ? Buffer.from(body, "utf-8") : body)
|
|
24
|
+
.digest();
|
|
25
|
+
let received;
|
|
26
|
+
try {
|
|
27
|
+
received = Buffer.from(signature, "hex");
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
if (received.length !== expected.length)
|
|
33
|
+
return false;
|
|
34
|
+
return timingSafeEqual(expected, received);
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=webhooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhooks.js","sourceRoot":"","sources":["../../src/webhooks.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE1D;;;;;;;GAOG;AACH,MAAM,UAAU,sBAAsB,CACpC,MAAc,EACd,IAAyB,EACzB,SAAiB;IAEjB,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACtC,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAEzC,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC;SAC1C,MAAM,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;SACpE,MAAM,EAAE,CAAC;IAEZ,IAAI,QAAgB,CAAC;IACrB,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,QAAQ,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAEtD,OAAO,eAAe,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;AAC7C,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "burnledger",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "TypeScript SDK for the BurnLedger API — cryptographic deletion certificates",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/cjs/index.js",
|
|
7
|
+
"module": "./dist/esm/index.js",
|
|
8
|
+
"types": "./dist/esm/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": {
|
|
12
|
+
"types": "./dist/esm/index.d.ts",
|
|
13
|
+
"default": "./dist/esm/index.js"
|
|
14
|
+
},
|
|
15
|
+
"require": {
|
|
16
|
+
"types": "./dist/cjs/index.d.ts",
|
|
17
|
+
"default": "./dist/cjs/index.js"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"./browser": {
|
|
21
|
+
"import": {
|
|
22
|
+
"types": "./dist/esm/index.browser.d.ts",
|
|
23
|
+
"default": "./dist/esm/index.browser.js"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"dist"
|
|
29
|
+
],
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=18.0.0"
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build": "tsc -p tsconfig.esm.json && tsc -p tsconfig.cjs.json && echo '{\"type\":\"commonjs\"}' > dist/cjs/package.json",
|
|
35
|
+
"check": "tsc -p tsconfig.esm.json --noEmit",
|
|
36
|
+
"test": "vitest run",
|
|
37
|
+
"test:watch": "vitest",
|
|
38
|
+
"prepublishOnly": "npm run check && npm test && npm run build"
|
|
39
|
+
},
|
|
40
|
+
"keywords": [
|
|
41
|
+
"burnledger",
|
|
42
|
+
"deletion",
|
|
43
|
+
"certificate",
|
|
44
|
+
"compliance",
|
|
45
|
+
"gdpr",
|
|
46
|
+
"privacy",
|
|
47
|
+
"attestation",
|
|
48
|
+
"verification"
|
|
49
|
+
],
|
|
50
|
+
"license": "MIT",
|
|
51
|
+
"repository": {
|
|
52
|
+
"type": "git",
|
|
53
|
+
"url": "https://github.com/fdfretes/burnledger.git",
|
|
54
|
+
"directory": "sdk/typescript"
|
|
55
|
+
},
|
|
56
|
+
"homepage": "https://github.com/fdfretes/burnledger/tree/main/sdk/typescript",
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"@types/node": "^25.3.0",
|
|
59
|
+
"typescript": "^5.7.0",
|
|
60
|
+
"vitest": "^3.0.0"
|
|
61
|
+
}
|
|
62
|
+
}
|