@ternent/seal-cli 0.1.7 → 0.2.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # @ternent/seal-cli
2
2
 
3
- Seal signs files and manifests. It verifies artifacts offline. It emits portable proof JSON that `apps/proof` can verify in the browser without duplicate crypto logic.
3
+ Seal signs files and manifests. It verifies artifacts offline. It emits portable proof JSON that `apps/seal` can verify in the browser without duplicate crypto logic.
4
4
 
5
5
  ## Install
6
6
 
@@ -10,21 +10,20 @@ pnpm add -D @ternent/seal-cli
10
10
 
11
11
  ## Environment
12
12
 
13
- `@ternent/seal-cli` reads signer material from environment variables:
13
+ `@ternent/seal-cli` reads signer material from a v2 identity JSON payload:
14
14
 
15
15
  ```bash
16
- export SEAL_PRIVATE_KEY="$(cat private-key.pem)"
17
- export SEAL_PUBLIC_KEY="$(cat public-key.pem)"
16
+ export SEAL_IDENTITY="$(cat identity.json)"
17
+ # or
18
+ export SEAL_IDENTITY_FILE="./identity.json"
18
19
  ```
19
20
 
20
- `SEAL_PUBLIC_KEY` is optional. If it is present, Seal verifies that it matches `SEAL_PRIVATE_KEY`.
21
-
22
21
  ## Commands
23
22
 
24
23
  ```bash
25
- seal manifest create --input apps/proof/dist --out apps/proof/dist/dist-manifest.json
26
- seal sign --input apps/proof/dist/dist-manifest.json --out apps/proof/dist/proof.json
27
- seal verify --proof apps/proof/dist/proof.json --input apps/proof/dist/dist-manifest.json --json
24
+ seal manifest create --input apps/seal/dist --out apps/seal/dist/dist-manifest.json
25
+ seal sign --input apps/seal/dist/dist-manifest.json --out apps/seal/dist/proof.json
26
+ seal verify --proof apps/seal/dist/proof.json --input apps/seal/dist/dist-manifest.json --json
28
27
  seal public-key --json
29
28
  ```
30
29
 
@@ -36,8 +35,7 @@ Use the published GitHub Action:
36
35
  - name: Generate Seal artifacts
37
36
  uses: samternent/seal-action@v1
38
37
  env:
39
- SEAL_PRIVATE_KEY: ${{ secrets.SEAL_PRIVATE_KEY }}
40
- SEAL_PUBLIC_KEY: ${{ secrets.SEAL_PUBLIC_KEY }}
38
+ SEAL_IDENTITY: ${{ secrets.SEAL_IDENTITY }}
41
39
  with:
42
40
  assets-directory: dist
43
41
  package-name: @ternent/seal-cli
@@ -88,9 +86,9 @@ Proof:
88
86
 
89
87
  ```json
90
88
  {
91
- "version": "1",
89
+ "version": "2",
92
90
  "type": "seal-proof",
93
- "algorithm": "ECDSA-P256-SHA256",
91
+ "algorithm": "Ed25519",
94
92
  "createdAt": "2026-03-13T00:00:00.000Z",
95
93
  "subject": {
96
94
  "kind": "manifest",
@@ -98,7 +96,7 @@ Proof:
98
96
  "hash": "sha256:..."
99
97
  },
100
98
  "signer": {
101
- "publicKey": "BASE64-SPKI",
99
+ "publicKey": "BASE64URL-RAW-ED25519-PUBLIC-KEY",
102
100
  "keyId": "..."
103
101
  },
104
102
  "signature": "..."
@@ -109,21 +107,23 @@ Public key:
109
107
 
110
108
  ```json
111
109
  {
112
- "algorithm": "ECDSA-P256-SHA256",
113
- "publicKey": "BASE64-SPKI",
110
+ "version": "2",
111
+ "type": "seal-public-key",
112
+ "algorithm": "Ed25519",
113
+ "publicKey": "BASE64URL-RAW-ED25519-PUBLIC-KEY",
114
114
  "keyId": "..."
115
115
  }
116
116
  ```
117
117
 
118
118
  ## Frontend Contract
119
119
 
120
- `apps/proof` verifies published artifacts by fetching:
120
+ `apps/seal` verifies published artifacts by fetching:
121
121
 
122
122
  - `/dist-manifest.json`
123
123
  - `/proof.json`
124
124
  - `/public-key.json` (optional)
125
125
 
126
- Browser verification reuses `@ternent/seal-cli/proof`, `@ternent/seal-cli/crypto`, `ternent-identity`, and `ternent-utils`.
126
+ Browser verification reuses `@ternent/seal-cli/proof`, `@ternent/seal-cli/crypto`, `@ternent/identity`, and `ternent-utils`.
127
127
 
128
128
  Validation rules:
129
129
 
@@ -0,0 +1,245 @@
1
+ const IDENTITY_FORMAT = "ternent-identity";
2
+ const IDENTITY_VERSION = "2";
3
+ const IDENTITY_ALGORITHM = "Ed25519";
4
+ const ED25519_CONTEXT = "ternent-seal/v2";
5
+ const ED25519_PKCS8_PREFIX = hexToBytes("302e020100300506032b657004220420");
6
+ const ED25519_SPKI_PREFIX = hexToBytes("302a300506032b6570032100");
7
+ hexToBytes("302e020100300506032b656e04220420");
8
+ function getWebCrypto() {
9
+ if (typeof globalThis.crypto !== "undefined") {
10
+ return globalThis.crypto;
11
+ }
12
+ throw new Error("Web Crypto is not available in this runtime.");
13
+ }
14
+ function base64Encode(bytes) {
15
+ const buffer = globalThis.Buffer;
16
+ if (buffer) {
17
+ return buffer.from(bytes).toString("base64");
18
+ }
19
+ let binary = "";
20
+ for (const byte of bytes) {
21
+ binary += String.fromCharCode(byte);
22
+ }
23
+ if (typeof btoa !== "undefined") {
24
+ return btoa(binary);
25
+ }
26
+ throw new Error("Base64 encoding is not available in this runtime.");
27
+ }
28
+ function base64Decode(value) {
29
+ const normalized = value.replace(/-/g, "+").replace(/_/g, "/");
30
+ const buffer = globalThis.Buffer;
31
+ if (buffer) {
32
+ return new Uint8Array(buffer.from(normalized, "base64"));
33
+ }
34
+ if (typeof atob !== "undefined") {
35
+ const binary = atob(normalized);
36
+ const bytes = new Uint8Array(binary.length);
37
+ for (let index = 0; index < binary.length; index += 1) {
38
+ bytes[index] = binary.charCodeAt(index);
39
+ }
40
+ return bytes;
41
+ }
42
+ throw new Error("Base64 decoding is not available in this runtime.");
43
+ }
44
+ function isRecord(value) {
45
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
46
+ }
47
+ function hexToBytes(value) {
48
+ const bytes = new Uint8Array(value.length / 2);
49
+ for (let index = 0; index < value.length; index += 2) {
50
+ bytes[index / 2] = Number.parseInt(value.slice(index, index + 2), 16);
51
+ }
52
+ return bytes;
53
+ }
54
+ function concatBytes(...parts) {
55
+ const length = parts.reduce((sum, part) => sum + part.length, 0);
56
+ const output = new Uint8Array(length);
57
+ let offset = 0;
58
+ for (const part of parts) {
59
+ output.set(part, offset);
60
+ offset += part.length;
61
+ }
62
+ return output;
63
+ }
64
+ function ensureBytes(value, label) {
65
+ const bytes = value instanceof Uint8Array ? value : new Uint8Array(value);
66
+ if (bytes.length === 0) {
67
+ throw new Error(`${label} must not be empty.`);
68
+ }
69
+ return bytes;
70
+ }
71
+ function bytesToHex(bytes) {
72
+ return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join(
73
+ ""
74
+ );
75
+ }
76
+ function normalizeBase64Url(value) {
77
+ return String(value || "").trim().replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
78
+ }
79
+ function base64UrlEncode(bytes) {
80
+ return base64Encode(bytes).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
81
+ }
82
+ function base64UrlDecode(value) {
83
+ const normalized = normalizeBase64Url(value);
84
+ if (!normalized) {
85
+ throw new Error("Base64url value is required.");
86
+ }
87
+ const pad = normalized.length % 4 === 0 ? "" : "=".repeat(4 - normalized.length % 4);
88
+ return base64Decode(`${normalized}${pad}`);
89
+ }
90
+ function utf8Bytes(value) {
91
+ return new TextEncoder().encode(value);
92
+ }
93
+ function combineContext(payload, context = ED25519_CONTEXT) {
94
+ return concatBytes(utf8Bytes(context), new Uint8Array([0]), payload);
95
+ }
96
+ async function sha256(bytes) {
97
+ const hash = await getWebCrypto().subtle.digest("SHA-256", bytes);
98
+ return new Uint8Array(hash);
99
+ }
100
+ async function importEd25519PrivateKey(seedBytes) {
101
+ return getWebCrypto().subtle.importKey(
102
+ "pkcs8",
103
+ concatBytes(ED25519_PKCS8_PREFIX, seedBytes),
104
+ { name: "Ed25519" },
105
+ true,
106
+ ["sign"]
107
+ );
108
+ }
109
+ async function importEd25519PublicKey(publicKeyBytes) {
110
+ return getWebCrypto().subtle.importKey(
111
+ "spki",
112
+ concatBytes(ED25519_SPKI_PREFIX, publicKeyBytes),
113
+ { name: "Ed25519" },
114
+ true,
115
+ ["verify"]
116
+ );
117
+ }
118
+ function isSerializedIdentity(value) {
119
+ return isRecord(value) && value.format === IDENTITY_FORMAT && value.version === IDENTITY_VERSION && value.algorithm === IDENTITY_ALGORITHM && typeof value.createdAt === "string" && typeof value.seed === "string" && typeof value.publicKey === "string" && typeof value.keyId === "string";
120
+ }
121
+ function toCanonicalIdentity(identity) {
122
+ return {
123
+ format: identity.format,
124
+ version: identity.version,
125
+ algorithm: identity.algorithm,
126
+ createdAt: identity.createdAt,
127
+ seed: identity.seed,
128
+ publicKey: identity.publicKey,
129
+ keyId: identity.keyId
130
+ };
131
+ }
132
+ function resolveSeedBytes(input) {
133
+ if (input instanceof Uint8Array || input instanceof ArrayBuffer) {
134
+ const bytes = ensureBytes(input, "Seed");
135
+ if (bytes.length !== 32) {
136
+ throw new Error("Seed must be 32 bytes.");
137
+ }
138
+ return bytes;
139
+ }
140
+ if (typeof input === "string") {
141
+ const bytes = base64UrlDecode(input);
142
+ if (bytes.length !== 32) {
143
+ throw new Error("Seed must be 32 bytes.");
144
+ }
145
+ return bytes;
146
+ }
147
+ if (isSerializedIdentity(input)) {
148
+ return resolveSeedBytes(input.seed);
149
+ }
150
+ throw new Error("A valid identity or 32-byte seed is required.");
151
+ }
152
+ function resolvePublicKeyBytes(input) {
153
+ if (input instanceof Uint8Array || input instanceof ArrayBuffer) {
154
+ const bytes = ensureBytes(input, "Public key");
155
+ if (bytes.length !== 32) {
156
+ throw new Error("Public key must be 32 bytes.");
157
+ }
158
+ return bytes;
159
+ }
160
+ if (typeof input === "string") {
161
+ const bytes = base64UrlDecode(input);
162
+ if (bytes.length !== 32) {
163
+ throw new Error("Public key must be 32 bytes.");
164
+ }
165
+ return bytes;
166
+ }
167
+ if (isSerializedIdentity(input)) {
168
+ return resolvePublicKeyBytes(input.publicKey);
169
+ }
170
+ if (isRecord(input) && "publicKey" in input) {
171
+ return resolvePublicKeyBytes(
172
+ input.publicKey
173
+ );
174
+ }
175
+ throw new Error("A valid 32-byte public key is required.");
176
+ }
177
+ async function deriveKeyId(publicKey) {
178
+ return bytesToHex(await sha256(resolvePublicKeyBytes(publicKey)));
179
+ }
180
+ function parseIdentity(input) {
181
+ const parsed = typeof input === "string" ? JSON.parse(input) : input;
182
+ if (!isSerializedIdentity(parsed)) {
183
+ throw new Error("Identity payload must be a ternent-identity v2 object.");
184
+ }
185
+ return toCanonicalIdentity(parsed);
186
+ }
187
+ function serializeIdentity(identity, pretty = true) {
188
+ return `${JSON.stringify(parseIdentity(identity), null, pretty ? 2 : 0)}
189
+ `;
190
+ }
191
+ async function signBytes(identityOrSeed, payload, options = {}) {
192
+ const privateKey = await importEd25519PrivateKey(resolveSeedBytes(identityOrSeed));
193
+ const signature = await getWebCrypto().subtle.sign(
194
+ "Ed25519",
195
+ privateKey,
196
+ combineContext(ensureBytes(payload, "Payload"), options.context)
197
+ );
198
+ return base64UrlEncode(new Uint8Array(signature));
199
+ }
200
+ async function verifyBytes(publicKey, payload, signature, options = {}) {
201
+ const verifyKey = await importEd25519PublicKey(resolvePublicKeyBytes(publicKey));
202
+ return getWebCrypto().subtle.verify(
203
+ "Ed25519",
204
+ verifyKey,
205
+ base64UrlDecode(signature),
206
+ combineContext(ensureBytes(payload, "Payload"), options.context)
207
+ );
208
+ }
209
+ async function signUtf8(identityOrSeed, value, options = {}) {
210
+ return signBytes(identityOrSeed, utf8Bytes(value), options);
211
+ }
212
+ async function verifyUtf8(publicKey, value, signature, options = {}) {
213
+ return verifyBytes(publicKey, utf8Bytes(value), signature, options);
214
+ }
215
+ const SEAL_SIGNATURE_CONTEXT = "ternent-seal/v2";
216
+ function exportIdentityJson(identity) {
217
+ return serializeIdentity(identity);
218
+ }
219
+ async function resolveSealSigner(input) {
220
+ const identity = parseIdentity(input.identity);
221
+ const keyId = await deriveKeyId(identity.publicKey);
222
+ if (keyId !== identity.keyId) {
223
+ throw new Error("Identity keyId does not match the signer public key.");
224
+ }
225
+ return {
226
+ identity,
227
+ publicKey: identity.publicKey,
228
+ keyId
229
+ };
230
+ }
231
+ async function signSealUtf8(identity, value) {
232
+ return signUtf8(identity, value, {
233
+ context: SEAL_SIGNATURE_CONTEXT
234
+ });
235
+ }
236
+ async function verifySealUtf8(signature, value, publicKey) {
237
+ return verifyUtf8(publicKey, value, signature, {
238
+ context: SEAL_SIGNATURE_CONTEXT
239
+ });
240
+ }
241
+ async function verifyPublicKeyKeyId(publicKey, keyId) {
242
+ return await deriveKeyId(publicKey) === keyId;
243
+ }
244
+ export { SEAL_SIGNATURE_CONTEXT as S, verifySealUtf8 as a, exportIdentityJson as e, parseIdentity as p, resolveSealSigner as r, signSealUtf8 as s, verifyPublicKeyKeyId as v };
245
+ //# sourceMappingURL=crypto-8a814dd3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto-8a814dd3.js","sources":["../../../identity-v2/src/index.ts","../../src/crypto.ts"],"sourcesContent":["const IDENTITY_FORMAT = \"ternent-identity\" as const;\nconst IDENTITY_VERSION = \"2\" as const;\nconst IDENTITY_ALGORITHM = \"Ed25519\" as const;\nconst ED25519_CONTEXT = \"ternent-seal/v2\";\n\nconst ED25519_PKCS8_PREFIX = hexToBytes(\"302e020100300506032b657004220420\");\nconst ED25519_SPKI_PREFIX = hexToBytes(\"302a300506032b6570032100\");\nconst X25519_PKCS8_PREFIX = hexToBytes(\"302e020100300506032b656e04220420\");\n\nconst CURVE25519_P = (1n << 255n) - 19n;\nconst BECH32_GENERATORS = [\n 0x3b6a57b2,\n 0x26508e6d,\n 0x1ea119fa,\n 0x3d4233dd,\n 0x2a1462b3,\n];\n\nfunction getWebCrypto(): Crypto {\n if (typeof globalThis.crypto !== \"undefined\") {\n return globalThis.crypto;\n }\n throw new Error(\"Web Crypto is not available in this runtime.\");\n}\n\nfunction base64Encode(bytes: Uint8Array): string {\n const buffer = (globalThis as typeof globalThis & {\n Buffer?: {\n from(input: Uint8Array): { toString(encoding: \"base64\"): string };\n from(input: string, encoding: \"base64\"): Uint8Array;\n };\n }).Buffer;\n\n if (buffer) {\n return buffer.from(bytes).toString(\"base64\");\n }\n\n let binary = \"\";\n for (const byte of bytes) {\n binary += String.fromCharCode(byte);\n }\n if (typeof btoa !== \"undefined\") {\n return btoa(binary);\n }\n throw new Error(\"Base64 encoding is not available in this runtime.\");\n}\n\nfunction base64Decode(value: string): Uint8Array {\n const normalized = value.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const buffer = (globalThis as typeof globalThis & {\n Buffer?: {\n from(input: Uint8Array): { toString(encoding: \"base64\"): string };\n from(input: string, encoding: \"base64\"): Uint8Array;\n };\n }).Buffer;\n\n if (buffer) {\n return new Uint8Array(buffer.from(normalized, \"base64\"));\n }\n\n if (typeof atob !== \"undefined\") {\n const binary = atob(normalized);\n const bytes = new Uint8Array(binary.length);\n for (let index = 0; index < binary.length; index += 1) {\n bytes[index] = binary.charCodeAt(index);\n }\n return bytes;\n }\n\n throw new Error(\"Base64 decoding is not available in this runtime.\");\n}\n\nexport type SerializedIdentity = {\n format: typeof IDENTITY_FORMAT;\n version: typeof IDENTITY_VERSION;\n algorithm: typeof IDENTITY_ALGORITHM;\n createdAt: string;\n seed: string;\n publicKey: string;\n keyId: string;\n};\n\ntype SeedLike = SerializedIdentity | Uint8Array | ArrayBuffer | string;\ntype PublicKeyLike =\n | SerializedIdentity\n | Uint8Array\n | ArrayBuffer\n | string\n | { publicKey: string | Uint8Array | ArrayBuffer }\n | { seed: string | Uint8Array | ArrayBuffer };\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction hexToBytes(value: string): Uint8Array {\n const bytes = new Uint8Array(value.length / 2);\n for (let index = 0; index < value.length; index += 2) {\n bytes[index / 2] = Number.parseInt(value.slice(index, index + 2), 16);\n }\n return bytes;\n}\n\nfunction concatBytes(...parts: Uint8Array[]): Uint8Array {\n const length = parts.reduce((sum, part) => sum + part.length, 0);\n const output = new Uint8Array(length);\n let offset = 0;\n for (const part of parts) {\n output.set(part, offset);\n offset += part.length;\n }\n return output;\n}\n\nfunction ensureBytes(\n value: Uint8Array | ArrayBuffer,\n label: string\n): Uint8Array {\n const bytes = value instanceof Uint8Array ? value : new Uint8Array(value);\n if (bytes.length === 0) {\n throw new Error(`${label} must not be empty.`);\n }\n return bytes;\n}\n\nfunction bytesToHex(bytes: Uint8Array): string {\n return Array.from(bytes, (byte) => byte.toString(16).padStart(2, \"0\")).join(\n \"\"\n );\n}\n\nfunction normalizeBase64Url(value: string): string {\n return String(value || \"\")\n .trim()\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/=+$/g, \"\");\n}\n\nfunction base64UrlEncode(bytes: Uint8Array): string {\n return base64Encode(bytes)\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/=+$/g, \"\");\n}\n\nfunction base64UrlDecode(value: string): Uint8Array {\n const normalized = normalizeBase64Url(value);\n if (!normalized) {\n throw new Error(\"Base64url value is required.\");\n }\n const pad =\n normalized.length % 4 === 0 ? \"\" : \"=\".repeat(4 - (normalized.length % 4));\n return base64Decode(`${normalized}${pad}`);\n}\n\nfunction utf8Bytes(value: string): Uint8Array {\n return new TextEncoder().encode(value);\n}\n\nfunction combineContext(\n payload: Uint8Array,\n context = ED25519_CONTEXT\n): Uint8Array {\n return concatBytes(utf8Bytes(context), new Uint8Array([0]), payload);\n}\n\nasync function sha256(bytes: Uint8Array): Promise<Uint8Array> {\n const hash = await getWebCrypto().subtle.digest(\"SHA-256\", bytes);\n return new Uint8Array(hash);\n}\n\nasync function sha512(bytes: Uint8Array): Promise<Uint8Array> {\n const hash = await getWebCrypto().subtle.digest(\"SHA-512\", bytes);\n return new Uint8Array(hash);\n}\n\nfunction toLittleEndianBigInt(bytes: Uint8Array): bigint {\n let result = 0n;\n for (let index = bytes.length - 1; index >= 0; index -= 1) {\n result = (result << 8n) + BigInt(bytes[index]);\n }\n return result;\n}\n\nfunction fromLittleEndianBigInt(value: bigint, length: number): Uint8Array {\n let remaining = value;\n const bytes = new Uint8Array(length);\n for (let index = 0; index < length; index += 1) {\n bytes[index] = Number(remaining & 0xffn);\n remaining >>= 8n;\n }\n return bytes;\n}\n\nfunction mod(value: bigint, modulus: bigint): bigint {\n const result = value % modulus;\n return result >= 0n ? result : result + modulus;\n}\n\nfunction modPow(base: bigint, exponent: bigint, modulus: bigint): bigint {\n let result = 1n;\n let factor = mod(base, modulus);\n let power = exponent;\n while (power > 0n) {\n if (power & 1n) {\n result = mod(result * factor, modulus);\n }\n factor = mod(factor * factor, modulus);\n power >>= 1n;\n }\n return result;\n}\n\nfunction modInverse(value: bigint, modulus: bigint): bigint {\n if (value === 0n) {\n throw new Error(\"Cannot invert zero in the field.\");\n }\n return modPow(value, modulus - 2n, modulus);\n}\n\nasync function importEd25519PrivateKey(seedBytes: Uint8Array): Promise<CryptoKey> {\n return getWebCrypto().subtle.importKey(\n \"pkcs8\",\n concatBytes(ED25519_PKCS8_PREFIX, seedBytes),\n { name: \"Ed25519\" },\n true,\n [\"sign\"]\n );\n}\n\nasync function importEd25519PublicKey(publicKeyBytes: Uint8Array): Promise<CryptoKey> {\n return getWebCrypto().subtle.importKey(\n \"spki\",\n concatBytes(ED25519_SPKI_PREFIX, publicKeyBytes),\n { name: \"Ed25519\" },\n true,\n [\"verify\"]\n );\n}\n\nasync function exportEd25519PublicKeyFromSeed(\n seedBytes: Uint8Array\n): Promise<Uint8Array> {\n const privateKey = await importEd25519PrivateKey(seedBytes);\n const jwk = (await getWebCrypto().subtle.exportKey(\n \"jwk\",\n privateKey\n )) as JsonWebKey;\n if (!jwk.x) {\n throw new Error(\"Unable to derive Ed25519 public key.\");\n }\n return base64UrlDecode(jwk.x);\n}\n\nasync function exportX25519PublicKeyFromScalar(\n scalarBytes: Uint8Array\n): Promise<Uint8Array> {\n const privateKey = await getWebCrypto().subtle.importKey(\n \"pkcs8\",\n concatBytes(X25519_PKCS8_PREFIX, scalarBytes),\n { name: \"X25519\" },\n true,\n [\"deriveBits\"]\n );\n const jwk = (await getWebCrypto().subtle.exportKey(\n \"jwk\",\n privateKey\n )) as JsonWebKey;\n if (!jwk.x) {\n throw new Error(\"Unable to derive X25519 public key.\");\n }\n return base64UrlDecode(jwk.x);\n}\n\nfunction isSerializedIdentity(value: unknown): value is SerializedIdentity {\n return (\n isRecord(value) &&\n value.format === IDENTITY_FORMAT &&\n value.version === IDENTITY_VERSION &&\n value.algorithm === IDENTITY_ALGORITHM &&\n typeof value.createdAt === \"string\" &&\n typeof value.seed === \"string\" &&\n typeof value.publicKey === \"string\" &&\n typeof value.keyId === \"string\"\n );\n}\n\nfunction toCanonicalIdentity(identity: SerializedIdentity): SerializedIdentity {\n return {\n format: identity.format,\n version: identity.version,\n algorithm: identity.algorithm,\n createdAt: identity.createdAt,\n seed: identity.seed,\n publicKey: identity.publicKey,\n keyId: identity.keyId,\n };\n}\n\nfunction resolveSeedBytes(input: SeedLike): Uint8Array {\n if (input instanceof Uint8Array || input instanceof ArrayBuffer) {\n const bytes = ensureBytes(input, \"Seed\");\n if (bytes.length !== 32) {\n throw new Error(\"Seed must be 32 bytes.\");\n }\n return bytes;\n }\n if (typeof input === \"string\") {\n const bytes = base64UrlDecode(input);\n if (bytes.length !== 32) {\n throw new Error(\"Seed must be 32 bytes.\");\n }\n return bytes;\n }\n if (isSerializedIdentity(input)) {\n return resolveSeedBytes(input.seed);\n }\n throw new Error(\"A valid identity or 32-byte seed is required.\");\n}\n\nfunction resolvePublicKeyBytes(input: PublicKeyLike): Uint8Array {\n if (input instanceof Uint8Array || input instanceof ArrayBuffer) {\n const bytes = ensureBytes(input, \"Public key\");\n if (bytes.length !== 32) {\n throw new Error(\"Public key must be 32 bytes.\");\n }\n return bytes;\n }\n if (typeof input === \"string\") {\n const bytes = base64UrlDecode(input);\n if (bytes.length !== 32) {\n throw new Error(\"Public key must be 32 bytes.\");\n }\n return bytes;\n }\n if (isSerializedIdentity(input)) {\n return resolvePublicKeyBytes(input.publicKey);\n }\n if (isRecord(input) && \"publicKey\" in input) {\n return resolvePublicKeyBytes(\n input.publicKey as string | Uint8Array | ArrayBuffer\n );\n }\n throw new Error(\"A valid 32-byte public key is required.\");\n}\n\nasync function resolveX25519PrivateKeyBytes(input: SeedLike): Promise<Uint8Array> {\n const seedBytes = resolveSeedBytes(input);\n const hashed = await sha512(seedBytes);\n const scalar = hashed.slice(0, 32);\n scalar[0] &= 248;\n scalar[31] &= 127;\n scalar[31] |= 64;\n return scalar;\n}\n\nfunction convertEd25519PublicKeyToX25519PublicKeyBytes(\n publicKeyBytes: Uint8Array\n): Uint8Array {\n const yBytes = publicKeyBytes.slice();\n yBytes[31] &= 0x7f;\n const y = toLittleEndianBigInt(yBytes);\n const numerator = mod(1n + y, CURVE25519_P);\n const denominator = mod(1n - y, CURVE25519_P);\n const u = mod(\n numerator * modInverse(denominator, CURVE25519_P),\n CURVE25519_P\n );\n return fromLittleEndianBigInt(u, 32);\n}\n\nasync function resolveX25519PublicKeyBytes(\n input: PublicKeyLike\n): Promise<Uint8Array> {\n if (isRecord(input) && \"seed\" in input) {\n return exportX25519PublicKeyFromScalar(\n await resolveX25519PrivateKeyBytes(\n input.seed as string | Uint8Array | ArrayBuffer\n )\n );\n }\n if (isSerializedIdentity(input)) {\n return exportX25519PublicKeyFromScalar(\n await resolveX25519PrivateKeyBytes(input)\n );\n }\n if (\n typeof input === \"string\" ||\n input instanceof Uint8Array ||\n input instanceof ArrayBuffer\n ) {\n return convertEd25519PublicKeyToX25519PublicKeyBytes(\n resolvePublicKeyBytes(input)\n );\n }\n if (isRecord(input) && \"publicKey\" in input) {\n return convertEd25519PublicKeyToX25519PublicKeyBytes(\n resolvePublicKeyBytes(\n input.publicKey as string | Uint8Array | ArrayBuffer\n )\n );\n }\n throw new Error(\"A valid identity seed or Ed25519 public key is required.\");\n}\n\nfunction bech32Polymod(values: number[]): number {\n let checksum = 1;\n for (const value of values) {\n const top = checksum >>> 25;\n checksum = ((checksum & 0x1ffffff) << 5) ^ value;\n for (let bit = 0; bit < 5; bit += 1) {\n if ((top >>> bit) & 1) {\n checksum ^= BECH32_GENERATORS[bit];\n }\n }\n }\n return checksum;\n}\n\nfunction bech32HrpExpand(hrp: string): number[] {\n const output: number[] = [];\n for (let index = 0; index < hrp.length; index += 1) {\n output.push(hrp.charCodeAt(index) >> 5);\n }\n output.push(0);\n for (let index = 0; index < hrp.length; index += 1) {\n output.push(hrp.charCodeAt(index) & 31);\n }\n return output;\n}\n\nfunction convertBits(data: Uint8Array, fromBits: number, toBits: number): number[] {\n let value = 0;\n let bits = 0;\n const maxValue = (1 << toBits) - 1;\n const output: number[] = [];\n for (const byte of data) {\n value = (value << fromBits) | byte;\n bits += fromBits;\n while (bits >= toBits) {\n bits -= toBits;\n output.push((value >> bits) & maxValue);\n }\n }\n if (bits > 0) {\n output.push((value << (toBits - bits)) & maxValue);\n }\n return output;\n}\n\nfunction bech32CreateChecksum(hrp: string, data: number[]): number[] {\n const values = [...bech32HrpExpand(hrp), ...data, 0, 0, 0, 0, 0, 0];\n const polymod = bech32Polymod(values) ^ 1;\n const checksum: number[] = [];\n for (let index = 0; index < 6; index += 1) {\n checksum.push((polymod >> (5 * (5 - index))) & 31);\n }\n return checksum;\n}\n\nfunction bech32Encode(hrp: string, data: Uint8Array): string {\n const charset = \"qpzry9x8gf2tvdw0s3jn54khce6mua7l\";\n const words = convertBits(data, 8, 5);\n const combined = [...words, ...bech32CreateChecksum(hrp, words)];\n return `${hrp}1${combined.map((value) => charset[value]).join(\"\")}`;\n}\n\nexport function getDefaultSignatureContext(): string {\n return ED25519_CONTEXT;\n}\n\nexport async function createIdentity(\n createdAt = new Date().toISOString()\n): Promise<SerializedIdentity> {\n const seedBytes = getWebCrypto().getRandomValues(new Uint8Array(32));\n const publicKeyBytes = await exportEd25519PublicKeyFromSeed(seedBytes);\n return {\n format: IDENTITY_FORMAT,\n version: IDENTITY_VERSION,\n algorithm: IDENTITY_ALGORITHM,\n createdAt,\n seed: base64UrlEncode(seedBytes),\n publicKey: base64UrlEncode(publicKeyBytes),\n keyId: await deriveKeyId(publicKeyBytes),\n };\n}\n\nexport async function derivePublicKey(\n seed: string | Uint8Array | ArrayBuffer\n): Promise<string> {\n return base64UrlEncode(\n await exportEd25519PublicKeyFromSeed(resolveSeedBytes(seed))\n );\n}\n\nexport async function deriveKeyId(\n publicKey: string | Uint8Array | ArrayBuffer\n): Promise<string> {\n return bytesToHex(await sha256(resolvePublicKeyBytes(publicKey)));\n}\n\nexport function parseIdentity(input: string | SerializedIdentity): SerializedIdentity {\n const parsed = typeof input === \"string\" ? JSON.parse(input) : input;\n if (!isSerializedIdentity(parsed)) {\n throw new Error(\"Identity payload must be a ternent-identity v2 object.\");\n }\n return toCanonicalIdentity(parsed);\n}\n\nexport function serializeIdentity(\n identity: SerializedIdentity,\n pretty = true\n): string {\n return `${JSON.stringify(parseIdentity(identity), null, pretty ? 2 : 0)}\\n`;\n}\n\nexport async function validateIdentity(\n identity: SerializedIdentity\n): Promise<SerializedIdentity> {\n const parsed = parseIdentity(identity);\n const derivedPublicKey = await derivePublicKey(parsed.seed);\n if (derivedPublicKey !== normalizeBase64Url(parsed.publicKey)) {\n throw new Error(\"Identity publicKey does not match the stored seed.\");\n }\n const derivedKeyId = await deriveKeyId(parsed.publicKey);\n if (derivedKeyId !== parsed.keyId) {\n throw new Error(\"Identity keyId does not match the public key.\");\n }\n return parsed;\n}\n\nexport async function signBytes(\n identityOrSeed: SeedLike,\n payload: Uint8Array | ArrayBuffer,\n options: { context?: string } = {}\n): Promise<string> {\n const privateKey = await importEd25519PrivateKey(resolveSeedBytes(identityOrSeed));\n const signature = await getWebCrypto().subtle.sign(\n \"Ed25519\",\n privateKey,\n combineContext(ensureBytes(payload, \"Payload\"), options.context)\n );\n return base64UrlEncode(new Uint8Array(signature));\n}\n\nexport async function verifyBytes(\n publicKey: string | Uint8Array | ArrayBuffer,\n payload: Uint8Array | ArrayBuffer,\n signature: string,\n options: { context?: string } = {}\n): Promise<boolean> {\n const verifyKey = await importEd25519PublicKey(resolvePublicKeyBytes(publicKey));\n return getWebCrypto().subtle.verify(\n \"Ed25519\",\n verifyKey,\n base64UrlDecode(signature),\n combineContext(ensureBytes(payload, \"Payload\"), options.context)\n );\n}\n\nexport async function signUtf8(\n identityOrSeed: SeedLike,\n value: string,\n options: { context?: string } = {}\n): Promise<string> {\n return signBytes(identityOrSeed, utf8Bytes(value), options);\n}\n\nexport async function verifyUtf8(\n publicKey: string | Uint8Array | ArrayBuffer,\n value: string,\n signature: string,\n options: { context?: string } = {}\n): Promise<boolean> {\n return verifyBytes(publicKey, utf8Bytes(value), signature, options);\n}\n\nexport async function deriveX25519PrivateKey(input: SeedLike): Promise<string> {\n return base64UrlEncode(await resolveX25519PrivateKeyBytes(input));\n}\n\nexport async function deriveX25519PublicKey(input: PublicKeyLike): Promise<string> {\n return base64UrlEncode(await resolveX25519PublicKeyBytes(input));\n}\n\nexport async function convertEd25519PublicKeyToX25519PublicKey(\n publicKey: string | Uint8Array | ArrayBuffer\n): Promise<string> {\n return base64UrlEncode(\n convertEd25519PublicKeyToX25519PublicKeyBytes(resolvePublicKeyBytes(publicKey))\n );\n}\n\nexport async function deriveAgeRecipient(input: PublicKeyLike): Promise<string> {\n return bech32Encode(\"age\", await resolveX25519PublicKeyBytes(input));\n}\n\nexport async function deriveAgeSecretKey(input: SeedLike): Promise<string> {\n return bech32Encode(\n \"age-secret-key-\",\n await resolveX25519PrivateKeyBytes(input)\n ).toUpperCase();\n}\n","import {\n deriveKeyId,\n parseIdentity,\n serializeIdentity,\n signUtf8,\n verifyUtf8,\n type SerializedIdentity,\n} from \"@ternent/identity\";\n\nexport type SealSignerInput = {\n identity: SerializedIdentity;\n};\n\nexport type ResolvedSealSigner = {\n identity: SerializedIdentity;\n publicKey: string;\n keyId: string;\n};\n\nexport const SEAL_SIGNATURE_CONTEXT = \"ternent-seal/v2\";\n\nexport function exportIdentityJson(identity: SerializedIdentity): string {\n return serializeIdentity(identity);\n}\n\nexport async function resolveSealSigner(\n input: SealSignerInput\n): Promise<ResolvedSealSigner> {\n const identity = parseIdentity(input.identity);\n const keyId = await deriveKeyId(identity.publicKey);\n if (keyId !== identity.keyId) {\n throw new Error(\"Identity keyId does not match the signer public key.\");\n }\n\n return {\n identity,\n publicKey: identity.publicKey,\n keyId,\n };\n}\n\nexport async function signSealUtf8(\n identity: SerializedIdentity,\n value: string\n): Promise<string> {\n return signUtf8(identity, value, {\n context: SEAL_SIGNATURE_CONTEXT,\n });\n}\n\nexport async function verifySealUtf8(\n signature: string,\n value: string,\n publicKey: string\n): Promise<boolean> {\n return verifyUtf8(publicKey, value, signature, {\n context: SEAL_SIGNATURE_CONTEXT,\n });\n}\n\nexport async function verifyPublicKeyKeyId(\n publicKey: string,\n keyId: string\n): Promise<boolean> {\n return (await deriveKeyId(publicKey)) === keyId;\n}\n"],"names":[],"mappings":"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"}
@@ -1,8 +1,3 @@
1
- function formatIdentityKey(key) {
2
- return `-----BEGIN PUBLIC KEY-----
3
- ${key}
4
- -----END PUBLIC KEY-----`;
5
- }
6
1
  function getHashArray(hash) {
7
2
  return Array.from(new Uint8Array(hash));
8
3
  }
@@ -52,5 +47,5 @@ async function hashBytes(input) {
52
47
  const hashBuffer = await crypto.subtle.digest("SHA-256", bytes);
53
48
  return getHashHex(getHashArray(hashBuffer));
54
49
  }
55
- export { canonicalStringify as c, formatIdentityKey as f, hashBytes as h };
56
- //# sourceMappingURL=utils.es-586f669f.js.map
50
+ export { canonicalStringify as c, hashBytes as h };
51
+ //# sourceMappingURL=utils.es-7e2ade90.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.es-586f669f.js","sources":["../../../utils/dist/utils.es.js"],"sourcesContent":["function getBufferCtor() {\n const maybeBuffer = globalThis.Buffer;\n return maybeBuffer != null ? maybeBuffer : null;\n}\nfunction addNewLines(str) {\n let finalString = \"\";\n while (str.length > 0) {\n finalString += str.substring(0, 64) + \"\\n\";\n str = str.substring(64);\n }\n return finalString;\n}\nfunction removeLines(str) {\n return str.replaceAll(\"\\n\", \"\");\n}\nfunction stripIdentityKey(key) {\n return key.replace(\"-----BEGIN PUBLIC KEY-----\\n\", \"\").replace(\"\\n-----END PUBLIC KEY-----\", \"\");\n}\nfunction formatIdentityKey(key) {\n return `-----BEGIN PUBLIC KEY-----\n${key}\n-----END PUBLIC KEY-----`;\n}\nfunction stripEncryptionFile(file) {\n return file.replace(\"-----BEGIN AGE ENCRYPTED FILE-----\\n\", \"\").replace(\"\\n-----END AGE ENCRYPTED FILE-----\\n\", \"\");\n}\nfunction formatEncryptionFile(file) {\n return `-----BEGIN AGE ENCRYPTED FILE-----\n${file}\n-----END AGE ENCRYPTED FILE-----\n`;\n}\nfunction generateId() {\n const uint32 = crypto.getRandomValues(new Uint32Array(1))[0];\n return uint32.toString(16);\n}\nfunction arrayBufferToBase64(arrayBuffer) {\n const byteArray = new Uint8Array(arrayBuffer);\n const bufferCtor = getBufferCtor();\n if (bufferCtor) {\n return bufferCtor.from(byteArray).toString(\"base64\");\n }\n let byteString = \"\";\n for (let i = 0; i < byteArray.byteLength; i++) {\n byteString += String.fromCharCode(byteArray[i]);\n }\n return btoa(byteString);\n}\nfunction base64ToArrayBuffer(b64) {\n const bufferCtor = getBufferCtor();\n if (bufferCtor) {\n const bytes = Uint8Array.from(\n bufferCtor.from(b64, \"base64\").toString(\"binary\"),\n (char) => char.charCodeAt(0)\n );\n return bytes.buffer.slice(\n bytes.byteOffset,\n bytes.byteOffset + bytes.byteLength\n );\n }\n const byteString = atob(b64);\n const byteArray = new Uint8Array(byteString.length);\n for (let i = 0; i < byteString.length; i++) {\n byteArray[i] = byteString.charCodeAt(i);\n }\n return byteArray.buffer;\n}\nfunction b64encode(buf) {\n return arrayBufferToBase64(buf);\n}\nfunction b64decode(str) {\n return base64ToArrayBuffer(str);\n}\nfunction encode(data) {\n const payload = typeof data === \"string\" ? data : JSON.stringify(data);\n return new TextEncoder().encode(payload);\n}\nfunction decode(data) {\n return new TextDecoder(\"utf-8\").decode(new Uint8Array(data));\n}\nfunction getHashBuffer(data) {\n return crypto.subtle.digest(\"SHA-256\", encode(data));\n}\nfunction getHashArray(hash) {\n return Array.from(new Uint8Array(hash));\n}\nfunction getHashHex(hash) {\n return hash.map((buf) => buf.toString(16).padStart(2, \"0\")).join(\"\");\n}\nfunction canonicalize(value, seen) {\n if (value === void 0) {\n throw new TypeError(\"Cannot hash undefined\");\n }\n const valueType = typeof value;\n if (valueType === \"function\" || valueType === \"symbol\") {\n throw new TypeError(`Cannot hash ${valueType} values`);\n }\n if (value === null || valueType === \"string\" || valueType === \"number\" || valueType === \"boolean\") {\n return value;\n }\n if (valueType === \"bigint\") {\n throw new TypeError(\"Cannot hash bigint values\");\n }\n if (typeof value.toJSON === \"function\") {\n return canonicalize(value.toJSON(), seen);\n }\n if (Array.isArray(value)) {\n return value.map((item) => canonicalize(item, seen));\n }\n if (typeof value === \"object\") {\n if (seen.has(value)) {\n throw new TypeError(\"Cannot hash circular references\");\n }\n seen.add(value);\n const entries = Object.keys(value).sort();\n const result = {};\n for (const key of entries) {\n result[key] = canonicalize(value[key], seen);\n }\n seen.delete(value);\n return result;\n }\n throw new TypeError(`Cannot hash unsupported value type: ${valueType}`);\n}\nfunction canonicalStringify(data) {\n return JSON.stringify(canonicalize(data, /* @__PURE__ */ new WeakSet()));\n}\nasync function hashData(data) {\n const hash_buffer = await getHashBuffer(canonicalStringify(data));\n const hash_array = getHashArray(hash_buffer);\n return getHashHex(hash_array);\n}\nasync function hashBytes(input) {\n const bytes = input instanceof Uint8Array ? input : new Uint8Array(input);\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", bytes);\n return getHashHex(getHashArray(hashBuffer));\n}\nfunction generateColorStops(primaryColor, secondaryColor, steps) {\n const colors = [];\n for (let i = 0; i <= steps; i++) {\n const ratio = i / steps;\n const color = lerpColor(primaryColor, secondaryColor, ratio);\n colors.push(color);\n }\n return colors;\n}\nfunction lerpColor(color1, color2, ratio) {\n const r1 = parseInt(color1.substring(1, 3), 16);\n const g1 = parseInt(color1.substring(3, 5), 16);\n const b1 = parseInt(color1.substring(5, 7), 16);\n const r2 = parseInt(color2.substring(1, 3), 16);\n const g2 = parseInt(color2.substring(3, 5), 16);\n const b2 = parseInt(color2.substring(5, 7), 16);\n const r = Math.round(r1 + (r2 - r1) * ratio);\n const g = Math.round(g1 + (g2 - g1) * ratio);\n const b = Math.round(b1 + (b2 - b1) * ratio);\n return `#${(1 << 24 | r << 16 | g << 8 | b).toString(16).slice(1).toUpperCase()}`;\n}\nexport { addNewLines, arrayBufferToBase64, b64decode, b64encode, base64ToArrayBuffer, canonicalStringify, decode, encode, formatEncryptionFile, formatIdentityKey, generateColorStops, generateId, getHashArray, getHashBuffer, getHashHex, hashBytes, hashData, removeLines, stripEncryptionFile, stripIdentityKey };\n"],"names":[],"mappings":"AAkBA,SAAS,kBAAkB,KAAK;AAC9B,SAAO;AAAA,EACP;AAAA;AAEF;AA6DA,SAAS,aAAa,MAAM;AAC1B,SAAO,MAAM,KAAK,IAAI,WAAW,IAAI,CAAC;AACxC;AACA,SAAS,WAAW,MAAM;AACxB,SAAO,KAAK,IAAI,CAAC,QAAQ,IAAI,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAAE,KAAK,EAAE;AACrE;AACA,SAAS,aAAa,OAAO,MAAM;AACjC,MAAI,UAAU,QAAQ;AACpB,UAAM,IAAI,UAAU,uBAAuB;AAAA,EAC5C;AACD,QAAM,YAAY,OAAO;AACzB,MAAI,cAAc,cAAc,cAAc,UAAU;AACtD,UAAM,IAAI,UAAU,eAAe,kBAAkB;AAAA,EACtD;AACD,MAAI,UAAU,QAAQ,cAAc,YAAY,cAAc,YAAY,cAAc,WAAW;AACjG,WAAO;AAAA,EACR;AACD,MAAI,cAAc,UAAU;AAC1B,UAAM,IAAI,UAAU,2BAA2B;AAAA,EAChD;AACD,MAAI,OAAO,MAAM,WAAW,YAAY;AACtC,WAAO,aAAa,MAAM,OAAQ,GAAE,IAAI;AAAA,EACzC;AACD,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,WAAO,MAAM,IAAI,CAAC,SAAS,aAAa,MAAM,IAAI,CAAC;AAAA,EACpD;AACD,MAAI,OAAO,UAAU,UAAU;AAC7B,QAAI,KAAK,IAAI,KAAK,GAAG;AACnB,YAAM,IAAI,UAAU,iCAAiC;AAAA,IACtD;AACD,SAAK,IAAI,KAAK;AACd,UAAM,UAAU,OAAO,KAAK,KAAK,EAAE,KAAI;AACvC,UAAM,SAAS,CAAA;AACf,eAAW,OAAO,SAAS;AACzB,aAAO,OAAO,aAAa,MAAM,MAAM,IAAI;AAAA,IAC5C;AACD,SAAK,OAAO,KAAK;AACjB,WAAO;AAAA,EACR;AACD,QAAM,IAAI,UAAU,uCAAuC,WAAW;AACxE;AACA,SAAS,mBAAmB,MAAM;AAChC,SAAO,KAAK,UAAU,aAAa,MAAsB,oBAAI,QAAS,CAAA,CAAC;AACzE;AAMA,eAAe,UAAU,OAAO;AAC9B,QAAM,QAAQ,iBAAiB,aAAa,QAAQ,IAAI,WAAW,KAAK;AACxE,QAAM,aAAa,MAAM,OAAO,OAAO,OAAO,WAAW,KAAK;AAC9D,SAAO,WAAW,aAAa,UAAU,CAAC;AAC5C;;"}
1
+ {"version":3,"file":"utils.es-7e2ade90.js","sources":["../../../utils/dist/utils.es.js"],"sourcesContent":["function getBufferCtor() {\n const maybeBuffer = globalThis.Buffer;\n return maybeBuffer != null ? maybeBuffer : null;\n}\nfunction addNewLines(str) {\n let finalString = \"\";\n while (str.length > 0) {\n finalString += str.substring(0, 64) + \"\\n\";\n str = str.substring(64);\n }\n return finalString;\n}\nfunction removeLines(str) {\n return str.replaceAll(\"\\n\", \"\");\n}\nfunction stripIdentityKey(key) {\n return key.replace(\"-----BEGIN PUBLIC KEY-----\\n\", \"\").replace(\"\\n-----END PUBLIC KEY-----\", \"\");\n}\nfunction formatIdentityKey(key) {\n return `-----BEGIN PUBLIC KEY-----\n${key}\n-----END PUBLIC KEY-----`;\n}\nfunction stripEncryptionFile(file) {\n return file.replace(\"-----BEGIN AGE ENCRYPTED FILE-----\\n\", \"\").replace(\"\\n-----END AGE ENCRYPTED FILE-----\\n\", \"\");\n}\nfunction formatEncryptionFile(file) {\n return `-----BEGIN AGE ENCRYPTED FILE-----\n${file}\n-----END AGE ENCRYPTED FILE-----\n`;\n}\nfunction generateId() {\n const uint32 = crypto.getRandomValues(new Uint32Array(1))[0];\n return uint32.toString(16);\n}\nfunction arrayBufferToBase64(arrayBuffer) {\n const byteArray = new Uint8Array(arrayBuffer);\n const bufferCtor = getBufferCtor();\n if (bufferCtor) {\n return bufferCtor.from(byteArray).toString(\"base64\");\n }\n let byteString = \"\";\n for (let i = 0; i < byteArray.byteLength; i++) {\n byteString += String.fromCharCode(byteArray[i]);\n }\n return btoa(byteString);\n}\nfunction base64ToArrayBuffer(b64) {\n const bufferCtor = getBufferCtor();\n if (bufferCtor) {\n const bytes = Uint8Array.from(\n bufferCtor.from(b64, \"base64\").toString(\"binary\"),\n (char) => char.charCodeAt(0)\n );\n return bytes.buffer.slice(\n bytes.byteOffset,\n bytes.byteOffset + bytes.byteLength\n );\n }\n const byteString = atob(b64);\n const byteArray = new Uint8Array(byteString.length);\n for (let i = 0; i < byteString.length; i++) {\n byteArray[i] = byteString.charCodeAt(i);\n }\n return byteArray.buffer;\n}\nfunction b64encode(buf) {\n return arrayBufferToBase64(buf);\n}\nfunction b64decode(str) {\n return base64ToArrayBuffer(str);\n}\nfunction encode(data) {\n const payload = typeof data === \"string\" ? data : JSON.stringify(data);\n return new TextEncoder().encode(payload);\n}\nfunction decode(data) {\n return new TextDecoder(\"utf-8\").decode(new Uint8Array(data));\n}\nfunction getHashBuffer(data) {\n return crypto.subtle.digest(\"SHA-256\", encode(data));\n}\nfunction getHashArray(hash) {\n return Array.from(new Uint8Array(hash));\n}\nfunction getHashHex(hash) {\n return hash.map((buf) => buf.toString(16).padStart(2, \"0\")).join(\"\");\n}\nfunction canonicalize(value, seen) {\n if (value === void 0) {\n throw new TypeError(\"Cannot hash undefined\");\n }\n const valueType = typeof value;\n if (valueType === \"function\" || valueType === \"symbol\") {\n throw new TypeError(`Cannot hash ${valueType} values`);\n }\n if (value === null || valueType === \"string\" || valueType === \"number\" || valueType === \"boolean\") {\n return value;\n }\n if (valueType === \"bigint\") {\n throw new TypeError(\"Cannot hash bigint values\");\n }\n if (typeof value.toJSON === \"function\") {\n return canonicalize(value.toJSON(), seen);\n }\n if (Array.isArray(value)) {\n return value.map((item) => canonicalize(item, seen));\n }\n if (typeof value === \"object\") {\n if (seen.has(value)) {\n throw new TypeError(\"Cannot hash circular references\");\n }\n seen.add(value);\n const entries = Object.keys(value).sort();\n const result = {};\n for (const key of entries) {\n result[key] = canonicalize(value[key], seen);\n }\n seen.delete(value);\n return result;\n }\n throw new TypeError(`Cannot hash unsupported value type: ${valueType}`);\n}\nfunction canonicalStringify(data) {\n return JSON.stringify(canonicalize(data, /* @__PURE__ */ new WeakSet()));\n}\nasync function hashData(data) {\n const hash_buffer = await getHashBuffer(canonicalStringify(data));\n const hash_array = getHashArray(hash_buffer);\n return getHashHex(hash_array);\n}\nasync function hashBytes(input) {\n const bytes = input instanceof Uint8Array ? input : new Uint8Array(input);\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", bytes);\n return getHashHex(getHashArray(hashBuffer));\n}\nfunction generateColorStops(primaryColor, secondaryColor, steps) {\n const colors = [];\n for (let i = 0; i <= steps; i++) {\n const ratio = i / steps;\n const color = lerpColor(primaryColor, secondaryColor, ratio);\n colors.push(color);\n }\n return colors;\n}\nfunction lerpColor(color1, color2, ratio) {\n const r1 = parseInt(color1.substring(1, 3), 16);\n const g1 = parseInt(color1.substring(3, 5), 16);\n const b1 = parseInt(color1.substring(5, 7), 16);\n const r2 = parseInt(color2.substring(1, 3), 16);\n const g2 = parseInt(color2.substring(3, 5), 16);\n const b2 = parseInt(color2.substring(5, 7), 16);\n const r = Math.round(r1 + (r2 - r1) * ratio);\n const g = Math.round(g1 + (g2 - g1) * ratio);\n const b = Math.round(b1 + (b2 - b1) * ratio);\n return `#${(1 << 24 | r << 16 | g << 8 | b).toString(16).slice(1).toUpperCase()}`;\n}\nexport { addNewLines, arrayBufferToBase64, b64decode, b64encode, base64ToArrayBuffer, canonicalStringify, decode, encode, formatEncryptionFile, formatIdentityKey, generateColorStops, generateId, getHashArray, getHashBuffer, getHashHex, hashBytes, hashData, removeLines, stripEncryptionFile, stripIdentityKey };\n"],"names":[],"mappings":"AAmFA,SAAS,aAAa,MAAM;AAC1B,SAAO,MAAM,KAAK,IAAI,WAAW,IAAI,CAAC;AACxC;AACA,SAAS,WAAW,MAAM;AACxB,SAAO,KAAK,IAAI,CAAC,QAAQ,IAAI,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAAE,KAAK,EAAE;AACrE;AACA,SAAS,aAAa,OAAO,MAAM;AACjC,MAAI,UAAU,QAAQ;AACpB,UAAM,IAAI,UAAU,uBAAuB;AAAA,EAC5C;AACD,QAAM,YAAY,OAAO;AACzB,MAAI,cAAc,cAAc,cAAc,UAAU;AACtD,UAAM,IAAI,UAAU,eAAe,kBAAkB;AAAA,EACtD;AACD,MAAI,UAAU,QAAQ,cAAc,YAAY,cAAc,YAAY,cAAc,WAAW;AACjG,WAAO;AAAA,EACR;AACD,MAAI,cAAc,UAAU;AAC1B,UAAM,IAAI,UAAU,2BAA2B;AAAA,EAChD;AACD,MAAI,OAAO,MAAM,WAAW,YAAY;AACtC,WAAO,aAAa,MAAM,OAAQ,GAAE,IAAI;AAAA,EACzC;AACD,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,WAAO,MAAM,IAAI,CAAC,SAAS,aAAa,MAAM,IAAI,CAAC;AAAA,EACpD;AACD,MAAI,OAAO,UAAU,UAAU;AAC7B,QAAI,KAAK,IAAI,KAAK,GAAG;AACnB,YAAM,IAAI,UAAU,iCAAiC;AAAA,IACtD;AACD,SAAK,IAAI,KAAK;AACd,UAAM,UAAU,OAAO,KAAK,KAAK,EAAE,KAAI;AACvC,UAAM,SAAS,CAAA;AACf,eAAW,OAAO,SAAS;AACzB,aAAO,OAAO,aAAa,MAAM,MAAM,IAAI;AAAA,IAC5C;AACD,SAAK,OAAO,KAAK;AACjB,WAAO;AAAA,EACR;AACD,QAAM,IAAI,UAAU,uCAAuC,WAAW;AACxE;AACA,SAAS,mBAAmB,MAAM;AAChC,SAAO,KAAK,UAAU,aAAa,MAAsB,oBAAI,QAAS,CAAA,CAAC;AACzE;AAMA,eAAe,UAAU,OAAO;AAC9B,QAAM,QAAQ,iBAAiB,aAAa,QAAQ,IAAI,WAAW,KAAK;AACxE,QAAM,aAAa,MAAM,OAAO,OAAO,OAAO,WAAW,KAAK;AAC9D,SAAO,WAAW,aAAa,UAAU,CAAC;AAC5C;;"}
package/dist/cli.js CHANGED
@@ -3,9 +3,9 @@ import { resolve, basename, join, relative, dirname } from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
4
  import { createSealHash, createSealProof, createSealPublicKeyArtifact, parseSealProofJson, verifySealProofAgainstBytes } from "./proof.js";
5
5
  import { SEAL_MANIFEST_VERSION, SEAL_MANIFEST_TYPE, stringifySealManifest, parseSealManifestJson } from "./manifest.js";
6
+ import { p as parseIdentity } from "./chunks/crypto-8a814dd3.js";
6
7
  import { EXIT_SUCCESS, EXIT_HASH_MISMATCH, EXIT_SIGNATURE_INVALID, SealCliError, EXIT_FAILURE, EXIT_INVALID_PROOF, EXIT_KEY_CONFIG, getExitCode } from "./errors.js";
7
- import "./chunks/utils.es-586f669f.js";
8
- import "./crypto.js";
8
+ import "./chunks/utils.es-7e2ade90.js";
9
9
  function normalizeRelativePath(value) {
10
10
  return value.split("\\").join("/");
11
11
  }
@@ -59,8 +59,7 @@ async function createProofArtifact(params) {
59
59
  const parsedManifest = parseSealManifestJson(raw);
60
60
  const proof = await createSealProof({
61
61
  signer: {
62
- privateKeyPem: params.privateKeyPem,
63
- publicKeyPem: params.publicKeyPem
62
+ identity: params.identity
64
63
  },
65
64
  subject: {
66
65
  kind: parsedManifest.ok ? "manifest" : "file",
@@ -75,10 +74,7 @@ async function createProofArtifact(params) {
75
74
  };
76
75
  }
77
76
  async function createPublicKeyArtifact(params) {
78
- return createSealPublicKeyArtifact({
79
- privateKeyPem: params.privateKeyPem,
80
- publicKeyPem: params.publicKeyPem
81
- });
77
+ return createSealPublicKeyArtifact(params);
82
78
  }
83
79
  async function verifyProofArtifact(params) {
84
80
  const rawProof = await readFile(params.proofPath, "utf8");
@@ -93,6 +89,19 @@ async function verifyProofArtifact(params) {
93
89
  result
94
90
  };
95
91
  }
92
+ async function resolveSealIdentityFromEnv(env) {
93
+ const identityJson = String(env.SEAL_IDENTITY || "").trim();
94
+ if (identityJson) {
95
+ return parseIdentity(identityJson);
96
+ }
97
+ const identityFile = String(env.SEAL_IDENTITY_FILE || "").trim();
98
+ if (identityFile) {
99
+ return parseIdentity(await readFile(identityFile, "utf8"));
100
+ }
101
+ throw new Error(
102
+ "Missing SEAL_IDENTITY or SEAL_IDENTITY_FILE environment variable."
103
+ );
104
+ }
96
105
  function parseArgs(argv) {
97
106
  const result = { _: [], flags: {} };
98
107
  for (let index = 0; index < argv.length; index += 1) {
@@ -144,10 +153,6 @@ function requireFlag(flags, key) {
144
153
  }
145
154
  return value;
146
155
  }
147
- function getEnvVar(env, name) {
148
- const value = env[name];
149
- return value && value.trim().length > 0 ? value : void 0;
150
- }
151
156
  async function writeOutputFile(filePath, content) {
152
157
  const resolvedPath = resolve(filePath);
153
158
  await mkdir(dirname(resolvedPath), { recursive: true });
@@ -184,19 +189,6 @@ function outputError(writer, json, error) {
184
189
  }
185
190
  return exitCode;
186
191
  }
187
- function readSigningEnv(env) {
188
- const privateKeyPem = getEnvVar(env, "SEAL_PRIVATE_KEY");
189
- if (!privateKeyPem) {
190
- throw new SealCliError(
191
- "Missing SEAL_PRIVATE_KEY environment variable.",
192
- EXIT_KEY_CONFIG
193
- );
194
- }
195
- return {
196
- privateKeyPem,
197
- publicKeyPem: getEnvVar(env, "SEAL_PUBLIC_KEY")
198
- };
199
- }
200
192
  async function runCli(argv, params = {}) {
201
193
  const parsed = parseArgs(argv);
202
194
  const env = params.env ?? process.env;
@@ -220,10 +212,10 @@ async function runCli(argv, params = {}) {
220
212
  return EXIT_SUCCESS;
221
213
  }
222
214
  if (command === "sign") {
223
- const signingEnv = readSigningEnv(env);
215
+ const identity = await resolveSealIdentityFromEnv(env);
224
216
  const artifact = await createProofArtifact({
225
217
  inputPath: requireFlag(parsed.flags, "input"),
226
- ...signingEnv
218
+ identity
227
219
  });
228
220
  const outPath = getFlag(parsed.flags, "out");
229
221
  if (outPath) {
@@ -260,7 +252,9 @@ async function runCli(argv, params = {}) {
260
252
  return EXIT_SUCCESS;
261
253
  }
262
254
  if (command === "public-key") {
263
- const artifact = await createPublicKeyArtifact(readSigningEnv(env));
255
+ const artifact = await createPublicKeyArtifact({
256
+ identity: await resolveSealIdentityFromEnv(env)
257
+ });
264
258
  outputResult(writer, true, quiet, artifact);
265
259
  return EXIT_SUCCESS;
266
260
  }
@@ -276,7 +270,7 @@ async function runCli(argv, params = {}) {
276
270
  new SealCliError(error.message, EXIT_INVALID_PROOF)
277
271
  );
278
272
  }
279
- if (error instanceof Error && (error.message.includes("public key") || error.message.includes("SEAL_PRIVATE_KEY") || error.message.includes("private key"))) {
273
+ if (error instanceof Error && (error.message.includes("public key") || error.message.includes("SEAL_IDENTITY") || error.message.includes("identity"))) {
280
274
  return outputError(
281
275
  writer,
282
276
  json,
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sources":["../src/commands/manifest.ts","../src/commands/sign.ts","../src/commands/publicKey.ts","../src/commands/verify.ts","../src/cli.ts"],"sourcesContent":["import { readdir, readFile, stat } from \"node:fs/promises\";\nimport { basename, join, relative, resolve } from \"node:path\";\nimport { createSealHash } from \"../proof\";\nimport {\n SEAL_MANIFEST_TYPE,\n SEAL_MANIFEST_VERSION,\n stringifySealManifest,\n type SealManifestV1,\n} from \"../manifest\";\n\nfunction normalizeRelativePath(value: string): string {\n return value.split(\"\\\\\").join(\"/\");\n}\n\nasync function collectFiles(\n rootPath: string,\n currentPath: string,\n files: Record<string, SealManifestV1[\"files\"][string]>\n): Promise<void> {\n const entries = await readdir(currentPath, { withFileTypes: true });\n const sorted = entries\n .filter((entry) => entry.name !== \".DS_Store\")\n .sort((a, b) => a.name.localeCompare(b.name));\n\n for (const entry of sorted) {\n const entryPath = join(currentPath, entry.name);\n if (entry.isDirectory()) {\n await collectFiles(rootPath, entryPath, files);\n continue;\n }\n if (!entry.isFile()) {\n continue;\n }\n const bytes = await readFile(entryPath);\n const relativePath = normalizeRelativePath(relative(rootPath, entryPath));\n files[relativePath] = await createSealHash(bytes);\n }\n}\n\nexport async function createManifestArtifact(inputPath: string): Promise<{\n manifest: SealManifestV1;\n content: string;\n}> {\n const resolvedInput = resolve(inputPath);\n const inputStat = await stat(resolvedInput);\n const root = basename(resolvedInput);\n const files: SealManifestV1[\"files\"] = {};\n\n if (inputStat.isDirectory()) {\n await collectFiles(resolvedInput, resolvedInput, files);\n } else if (inputStat.isFile()) {\n const bytes = await readFile(resolvedInput);\n files[root] = await createSealHash(bytes);\n } else {\n throw new Error(\"Manifest input must be a file or directory.\");\n }\n\n const manifest: SealManifestV1 = {\n version: SEAL_MANIFEST_VERSION,\n type: SEAL_MANIFEST_TYPE,\n root,\n files: Object.fromEntries(\n Object.entries(files).sort(([left], [right]) => left.localeCompare(right))\n ),\n };\n\n return {\n manifest,\n content: `${stringifySealManifest(manifest)}\\n`,\n };\n}\n","import { basename } from \"node:path\";\nimport { readFile } from \"node:fs/promises\";\nimport { parseSealManifestJson } from \"../manifest\";\nimport { createSealProof, createSealHash, type SealProofV1 } from \"../proof\";\n\nexport async function createProofArtifact(params: {\n inputPath: string;\n privateKeyPem: string;\n publicKeyPem?: string;\n}): Promise<{\n proof: SealProofV1;\n content: string;\n}> {\n const bytes = await readFile(params.inputPath);\n const raw = new TextDecoder().decode(bytes);\n const parsedManifest = parseSealManifestJson(raw);\n const proof = await createSealProof({\n signer: {\n privateKeyPem: params.privateKeyPem,\n publicKeyPem: params.publicKeyPem,\n },\n subject: {\n kind: parsedManifest.ok ? \"manifest\" : \"file\",\n path: basename(params.inputPath),\n hash: await createSealHash(bytes),\n },\n });\n\n return {\n proof,\n content: `${JSON.stringify(proof, null, 2)}\\n`,\n };\n}\n","import { createSealPublicKeyArtifact } from \"../proof\";\n\nexport async function createPublicKeyArtifact(params: {\n privateKeyPem: string;\n publicKeyPem?: string;\n}) {\n return createSealPublicKeyArtifact({\n privateKeyPem: params.privateKeyPem,\n publicKeyPem: params.publicKeyPem,\n });\n}\n","import { readFile } from \"node:fs/promises\";\nimport {\n parseSealProofJson,\n verifySealProofAgainstBytes,\n type SealProofV1,\n} from \"../proof\";\n\nexport type VerifyArtifactResult = {\n valid: boolean;\n hashMatch: boolean;\n signatureValid: boolean;\n keyId: string;\n algorithm: \"ECDSA-P256-SHA256\";\n subjectHash: `sha256:${string}`;\n};\n\nexport async function verifyProofArtifact(params: {\n proofPath: string;\n inputPath: string;\n}): Promise<{\n proof: SealProofV1;\n result: VerifyArtifactResult;\n}> {\n const rawProof = await readFile(params.proofPath, \"utf8\");\n const parsed = parseSealProofJson(rawProof);\n if (!parsed.ok || !parsed.proof) {\n throw new Error(parsed.errors.join(\" \"));\n }\n\n const subjectBytes = await readFile(params.inputPath);\n const result = await verifySealProofAgainstBytes(parsed.proof, subjectBytes);\n return {\n proof: parsed.proof,\n result,\n };\n}\n","import { mkdir, writeFile } from \"node:fs/promises\";\nimport { dirname, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { createManifestArtifact } from \"./commands/manifest\";\nimport { createProofArtifact } from \"./commands/sign\";\nimport { createPublicKeyArtifact } from \"./commands/publicKey\";\nimport { verifyProofArtifact } from \"./commands/verify\";\nimport {\n EXIT_FAILURE,\n EXIT_HASH_MISMATCH,\n EXIT_INVALID_PROOF,\n EXIT_KEY_CONFIG,\n EXIT_SIGNATURE_INVALID,\n EXIT_SUCCESS,\n SealCliError,\n getExitCode,\n} from \"./errors\";\n\ntype ProcessEnvLike = Record<string, string | undefined>;\n\ndeclare const process: {\n argv: string[];\n env: ProcessEnvLike;\n stdout: { write: (value: string) => void };\n stderr: { write: (value: string) => void };\n exitCode?: number;\n};\n\ntype ParsedArgs = {\n _: string[];\n flags: Record<string, string | boolean | string[]>;\n};\n\ntype OutputWriter = {\n stdout: (value: string) => void;\n stderr: (value: string) => void;\n};\n\nfunction parseArgs(argv: string[]): ParsedArgs {\n const result: ParsedArgs = { _: [], flags: {} };\n for (let index = 0; index < argv.length; index += 1) {\n const arg = argv[index];\n if (!arg.startsWith(\"--\")) {\n result._.push(arg);\n continue;\n }\n\n const [rawKey, inlineValue] = arg.slice(2).split(\"=\");\n const key = rawKey.trim();\n const next = argv[index + 1];\n const hasNextValue = inlineValue === undefined && next && !next.startsWith(\"--\");\n const value = inlineValue ?? (hasNextValue ? next : undefined);\n\n if (hasNextValue) {\n index += 1;\n }\n\n if (value === undefined) {\n result.flags[key] = true;\n continue;\n }\n\n const existing = result.flags[key];\n if (existing === undefined) {\n result.flags[key] = value;\n continue;\n }\n\n if (Array.isArray(existing)) {\n existing.push(value);\n result.flags[key] = existing;\n continue;\n }\n\n result.flags[key] = [String(existing), value];\n }\n\n return result;\n}\n\nfunction getFlag(flags: ParsedArgs[\"flags\"], key: string): string | undefined {\n const value = flags[key];\n if (Array.isArray(value)) {\n return value[value.length - 1];\n }\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction hasFlag(flags: ParsedArgs[\"flags\"], key: string): boolean {\n return flags[key] === true;\n}\n\nfunction requireFlag(flags: ParsedArgs[\"flags\"], key: string): string {\n const value = getFlag(flags, key);\n if (!value) {\n throw new SealCliError(`Missing --${key}`, EXIT_FAILURE);\n }\n return value;\n}\n\nfunction getEnvVar(env: ProcessEnvLike, name: string): string | undefined {\n const value = env[name];\n return value && value.trim().length > 0 ? value : undefined;\n}\n\nasync function writeOutputFile(filePath: string, content: string): Promise<void> {\n const resolvedPath = resolve(filePath);\n await mkdir(dirname(resolvedPath), { recursive: true });\n await writeFile(resolvedPath, content, \"utf8\");\n}\n\nfunction outputResult(\n writer: OutputWriter,\n json: boolean,\n quiet: boolean,\n value: unknown\n): void {\n if (quiet) {\n return;\n }\n\n if (typeof value === \"string\") {\n writer.stdout(`${value}\\n`);\n return;\n }\n\n if (json) {\n writer.stdout(`${JSON.stringify(value, null, 2)}\\n`);\n return;\n }\n\n writer.stdout(`${JSON.stringify(value, null, 2)}\\n`);\n}\n\nfunction outputError(\n writer: OutputWriter,\n json: boolean,\n error: unknown\n): number {\n const exitCode = getExitCode(error);\n const message = error instanceof Error ? error.message : String(error);\n if (json) {\n writer.stderr(\n `${JSON.stringify({ error: message, exitCode }, null, 2)}\\n`\n );\n } else {\n writer.stderr(`${message}\\n`);\n }\n return exitCode;\n}\n\nfunction readSigningEnv(env: ProcessEnvLike): {\n privateKeyPem: string;\n publicKeyPem?: string;\n} {\n const privateKeyPem = getEnvVar(env, \"SEAL_PRIVATE_KEY\");\n if (!privateKeyPem) {\n throw new SealCliError(\n \"Missing SEAL_PRIVATE_KEY environment variable.\",\n EXIT_KEY_CONFIG\n );\n }\n\n return {\n privateKeyPem,\n publicKeyPem: getEnvVar(env, \"SEAL_PUBLIC_KEY\"),\n };\n}\n\nexport async function runCli(\n argv: string[],\n params: {\n env?: ProcessEnvLike;\n writer?: OutputWriter;\n } = {}\n): Promise<number> {\n const parsed = parseArgs(argv);\n const env = params.env ?? process.env;\n const writer: OutputWriter = params.writer ?? {\n stdout: (value) => process.stdout.write(value),\n stderr: (value) => process.stderr.write(value),\n };\n const json = hasFlag(parsed.flags, \"json\");\n const quiet = hasFlag(parsed.flags, \"quiet\");\n\n try {\n const [command, subcommand] = parsed._;\n\n if (command === \"manifest\" && subcommand === \"create\") {\n const artifact = await createManifestArtifact(requireFlag(parsed.flags, \"input\"));\n const outPath = getFlag(parsed.flags, \"out\");\n if (outPath) {\n await writeOutputFile(outPath, artifact.content);\n outputResult(writer, json, quiet, json ? artifact.manifest : outPath);\n } else {\n outputResult(writer, true, quiet, artifact.manifest);\n }\n return EXIT_SUCCESS;\n }\n\n if (command === \"sign\") {\n const signingEnv = readSigningEnv(env);\n const artifact = await createProofArtifact({\n inputPath: requireFlag(parsed.flags, \"input\"),\n ...signingEnv,\n });\n const outPath = getFlag(parsed.flags, \"out\");\n if (outPath) {\n await writeOutputFile(outPath, artifact.content);\n outputResult(writer, json, quiet, json ? artifact.proof : outPath);\n } else {\n outputResult(writer, true, quiet, artifact.proof);\n }\n return EXIT_SUCCESS;\n }\n\n if (command === \"verify\") {\n const proofPath = requireFlag(parsed.flags, \"proof\");\n const inputPath = requireFlag(parsed.flags, \"input\");\n const { result } = await verifyProofArtifact({ proofPath, inputPath });\n outputResult(\n writer,\n json,\n quiet,\n json\n ? result\n : [\n `valid=${result.valid}`,\n `hashMatch=${result.hashMatch}`,\n `signatureValid=${result.signatureValid}`,\n `keyId=${result.keyId}`,\n `algorithm=${result.algorithm}`,\n `subjectHash=${result.subjectHash}`,\n ].join(\"\\n\")\n );\n\n if (!result.hashMatch) {\n return EXIT_HASH_MISMATCH;\n }\n if (!result.signatureValid) {\n return EXIT_SIGNATURE_INVALID;\n }\n return EXIT_SUCCESS;\n }\n\n if (command === \"public-key\") {\n const artifact = await createPublicKeyArtifact(readSigningEnv(env));\n outputResult(writer, true, quiet, artifact);\n return EXIT_SUCCESS;\n }\n\n throw new SealCliError(\n \"Usage: seal manifest create --input <path> [--out <path>] [--json] [--quiet]\\n\" +\n \" seal sign --input <path> [--out <path>] [--json] [--quiet]\\n\" +\n \" seal verify --proof <proof.json> --input <path> [--json] [--quiet]\\n\" +\n \" seal public-key [--json] [--quiet]\",\n EXIT_FAILURE\n );\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"Proof\")) {\n return outputError(\n writer,\n json,\n new SealCliError(error.message, EXIT_INVALID_PROOF)\n );\n }\n if (\n error instanceof Error &&\n (error.message.includes(\"public key\") ||\n error.message.includes(\"SEAL_PRIVATE_KEY\") ||\n error.message.includes(\"private key\"))\n ) {\n return outputError(\n writer,\n json,\n new SealCliError(error.message, EXIT_KEY_CONFIG)\n );\n }\n return outputError(writer, json, error);\n }\n}\n\nconst isDirectRun =\n typeof process !== \"undefined\" &&\n process.argv[1] &&\n fileURLToPath(import.meta.url) === resolve(process.argv[1]);\n\nif (isDirectRun) {\n runCli(process.argv.slice(2)).then((exitCode) => {\n process.exitCode = exitCode;\n });\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sources":["../src/commands/manifest.ts","../src/commands/sign.ts","../src/commands/publicKey.ts","../src/commands/verify.ts","../src/node.ts","../src/cli.ts"],"sourcesContent":["import { readdir, readFile, stat } from \"node:fs/promises\";\nimport { basename, join, relative, resolve } from \"node:path\";\nimport { createSealHash } from \"../proof\";\nimport {\n SEAL_MANIFEST_TYPE,\n SEAL_MANIFEST_VERSION,\n stringifySealManifest,\n type SealManifestV1,\n} from \"../manifest\";\n\nfunction normalizeRelativePath(value: string): string {\n return value.split(\"\\\\\").join(\"/\");\n}\n\nasync function collectFiles(\n rootPath: string,\n currentPath: string,\n files: Record<string, SealManifestV1[\"files\"][string]>\n): Promise<void> {\n const entries = await readdir(currentPath, { withFileTypes: true });\n const sorted = entries\n .filter((entry) => entry.name !== \".DS_Store\")\n .sort((a, b) => a.name.localeCompare(b.name));\n\n for (const entry of sorted) {\n const entryPath = join(currentPath, entry.name);\n if (entry.isDirectory()) {\n await collectFiles(rootPath, entryPath, files);\n continue;\n }\n if (!entry.isFile()) {\n continue;\n }\n const bytes = await readFile(entryPath);\n const relativePath = normalizeRelativePath(relative(rootPath, entryPath));\n files[relativePath] = await createSealHash(bytes);\n }\n}\n\nexport async function createManifestArtifact(inputPath: string): Promise<{\n manifest: SealManifestV1;\n content: string;\n}> {\n const resolvedInput = resolve(inputPath);\n const inputStat = await stat(resolvedInput);\n const root = basename(resolvedInput);\n const files: SealManifestV1[\"files\"] = {};\n\n if (inputStat.isDirectory()) {\n await collectFiles(resolvedInput, resolvedInput, files);\n } else if (inputStat.isFile()) {\n const bytes = await readFile(resolvedInput);\n files[root] = await createSealHash(bytes);\n } else {\n throw new Error(\"Manifest input must be a file or directory.\");\n }\n\n const manifest: SealManifestV1 = {\n version: SEAL_MANIFEST_VERSION,\n type: SEAL_MANIFEST_TYPE,\n root,\n files: Object.fromEntries(\n Object.entries(files).sort(([left], [right]) => left.localeCompare(right))\n ),\n };\n\n return {\n manifest,\n content: `${stringifySealManifest(manifest)}\\n`,\n };\n}\n","import { basename } from \"node:path\";\nimport { readFile } from \"node:fs/promises\";\nimport { parseSealManifestJson } from \"../manifest\";\nimport { createSealProof, createSealHash, type SealProofV1 } from \"../proof\";\n\nexport async function createProofArtifact(params: {\n inputPath: string;\n identity: import(\"@ternent/identity\").SerializedIdentity;\n}): Promise<{\n proof: SealProofV1;\n content: string;\n}> {\n const bytes = await readFile(params.inputPath);\n const raw = new TextDecoder().decode(bytes);\n const parsedManifest = parseSealManifestJson(raw);\n const proof = await createSealProof({\n signer: {\n identity: params.identity,\n },\n subject: {\n kind: parsedManifest.ok ? \"manifest\" : \"file\",\n path: basename(params.inputPath),\n hash: await createSealHash(bytes),\n },\n });\n\n return {\n proof,\n content: `${JSON.stringify(proof, null, 2)}\\n`,\n };\n}\n","import { createSealPublicKeyArtifact } from \"../proof\";\n\nexport async function createPublicKeyArtifact(params: {\n identity: import(\"@ternent/identity\").SerializedIdentity;\n}) {\n return createSealPublicKeyArtifact(params);\n}\n","import { readFile } from \"node:fs/promises\";\nimport {\n parseSealProofJson,\n verifySealProofAgainstBytes,\n type SealProofV1,\n} from \"../proof\";\n\nexport type VerifyArtifactResult = {\n valid: boolean;\n hashMatch: boolean;\n signatureValid: boolean;\n keyId: string;\n algorithm: \"Ed25519\";\n subjectHash: `sha256:${string}`;\n};\n\nexport async function verifyProofArtifact(params: {\n proofPath: string;\n inputPath: string;\n}): Promise<{\n proof: SealProofV1;\n result: VerifyArtifactResult;\n}> {\n const rawProof = await readFile(params.proofPath, \"utf8\");\n const parsed = parseSealProofJson(rawProof);\n if (!parsed.ok || !parsed.proof) {\n throw new Error(parsed.errors.join(\" \"));\n }\n\n const subjectBytes = await readFile(params.inputPath);\n const result = await verifySealProofAgainstBytes(parsed.proof, subjectBytes);\n return {\n proof: parsed.proof,\n result,\n };\n}\n","import { readFile } from \"node:fs/promises\";\nimport { parseIdentity, type SerializedIdentity } from \"@ternent/identity\";\n\nexport async function resolveSealIdentityFromEnv(\n env: Record<string, string | undefined>\n): Promise<SerializedIdentity> {\n const identityJson = String(env.SEAL_IDENTITY || \"\").trim();\n if (identityJson) {\n return parseIdentity(identityJson);\n }\n\n const identityFile = String(env.SEAL_IDENTITY_FILE || \"\").trim();\n if (identityFile) {\n return parseIdentity(await readFile(identityFile, \"utf8\"));\n }\n\n throw new Error(\n \"Missing SEAL_IDENTITY or SEAL_IDENTITY_FILE environment variable.\"\n );\n}\n","import { mkdir, writeFile } from \"node:fs/promises\";\nimport { dirname, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { createManifestArtifact } from \"./commands/manifest\";\nimport { createProofArtifact } from \"./commands/sign\";\nimport { createPublicKeyArtifact } from \"./commands/publicKey\";\nimport { verifyProofArtifact } from \"./commands/verify\";\nimport { resolveSealIdentityFromEnv } from \"./node\";\nimport {\n EXIT_FAILURE,\n EXIT_HASH_MISMATCH,\n EXIT_INVALID_PROOF,\n EXIT_KEY_CONFIG,\n EXIT_SIGNATURE_INVALID,\n EXIT_SUCCESS,\n SealCliError,\n getExitCode,\n} from \"./errors\";\n\ntype ProcessEnvLike = Record<string, string | undefined>;\n\ndeclare const process: {\n argv: string[];\n env: ProcessEnvLike;\n stdout: { write: (value: string) => void };\n stderr: { write: (value: string) => void };\n exitCode?: number;\n};\n\ntype ParsedArgs = {\n _: string[];\n flags: Record<string, string | boolean | string[]>;\n};\n\ntype OutputWriter = {\n stdout: (value: string) => void;\n stderr: (value: string) => void;\n};\n\nfunction parseArgs(argv: string[]): ParsedArgs {\n const result: ParsedArgs = { _: [], flags: {} };\n for (let index = 0; index < argv.length; index += 1) {\n const arg = argv[index];\n if (!arg.startsWith(\"--\")) {\n result._.push(arg);\n continue;\n }\n\n const [rawKey, inlineValue] = arg.slice(2).split(\"=\");\n const key = rawKey.trim();\n const next = argv[index + 1];\n const hasNextValue = inlineValue === undefined && next && !next.startsWith(\"--\");\n const value = inlineValue ?? (hasNextValue ? next : undefined);\n\n if (hasNextValue) {\n index += 1;\n }\n\n if (value === undefined) {\n result.flags[key] = true;\n continue;\n }\n\n const existing = result.flags[key];\n if (existing === undefined) {\n result.flags[key] = value;\n continue;\n }\n\n if (Array.isArray(existing)) {\n existing.push(value);\n result.flags[key] = existing;\n continue;\n }\n\n result.flags[key] = [String(existing), value];\n }\n\n return result;\n}\n\nfunction getFlag(flags: ParsedArgs[\"flags\"], key: string): string | undefined {\n const value = flags[key];\n if (Array.isArray(value)) {\n return value[value.length - 1];\n }\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction hasFlag(flags: ParsedArgs[\"flags\"], key: string): boolean {\n return flags[key] === true;\n}\n\nfunction requireFlag(flags: ParsedArgs[\"flags\"], key: string): string {\n const value = getFlag(flags, key);\n if (!value) {\n throw new SealCliError(`Missing --${key}`, EXIT_FAILURE);\n }\n return value;\n}\n\nasync function writeOutputFile(filePath: string, content: string): Promise<void> {\n const resolvedPath = resolve(filePath);\n await mkdir(dirname(resolvedPath), { recursive: true });\n await writeFile(resolvedPath, content, \"utf8\");\n}\n\nfunction outputResult(\n writer: OutputWriter,\n json: boolean,\n quiet: boolean,\n value: unknown\n): void {\n if (quiet) {\n return;\n }\n\n if (typeof value === \"string\") {\n writer.stdout(`${value}\\n`);\n return;\n }\n\n if (json) {\n writer.stdout(`${JSON.stringify(value, null, 2)}\\n`);\n return;\n }\n\n writer.stdout(`${JSON.stringify(value, null, 2)}\\n`);\n}\n\nfunction outputError(\n writer: OutputWriter,\n json: boolean,\n error: unknown\n): number {\n const exitCode = getExitCode(error);\n const message = error instanceof Error ? error.message : String(error);\n if (json) {\n writer.stderr(\n `${JSON.stringify({ error: message, exitCode }, null, 2)}\\n`\n );\n } else {\n writer.stderr(`${message}\\n`);\n }\n return exitCode;\n}\n\nexport async function runCli(\n argv: string[],\n params: {\n env?: ProcessEnvLike;\n writer?: OutputWriter;\n } = {}\n): Promise<number> {\n const parsed = parseArgs(argv);\n const env = params.env ?? process.env;\n const writer: OutputWriter = params.writer ?? {\n stdout: (value) => process.stdout.write(value),\n stderr: (value) => process.stderr.write(value),\n };\n const json = hasFlag(parsed.flags, \"json\");\n const quiet = hasFlag(parsed.flags, \"quiet\");\n\n try {\n const [command, subcommand] = parsed._;\n\n if (command === \"manifest\" && subcommand === \"create\") {\n const artifact = await createManifestArtifact(requireFlag(parsed.flags, \"input\"));\n const outPath = getFlag(parsed.flags, \"out\");\n if (outPath) {\n await writeOutputFile(outPath, artifact.content);\n outputResult(writer, json, quiet, json ? artifact.manifest : outPath);\n } else {\n outputResult(writer, true, quiet, artifact.manifest);\n }\n return EXIT_SUCCESS;\n }\n\n if (command === \"sign\") {\n const identity = await resolveSealIdentityFromEnv(env);\n const artifact = await createProofArtifact({\n inputPath: requireFlag(parsed.flags, \"input\"),\n identity,\n });\n const outPath = getFlag(parsed.flags, \"out\");\n if (outPath) {\n await writeOutputFile(outPath, artifact.content);\n outputResult(writer, json, quiet, json ? artifact.proof : outPath);\n } else {\n outputResult(writer, true, quiet, artifact.proof);\n }\n return EXIT_SUCCESS;\n }\n\n if (command === \"verify\") {\n const proofPath = requireFlag(parsed.flags, \"proof\");\n const inputPath = requireFlag(parsed.flags, \"input\");\n const { result } = await verifyProofArtifact({ proofPath, inputPath });\n outputResult(\n writer,\n json,\n quiet,\n json\n ? result\n : [\n `valid=${result.valid}`,\n `hashMatch=${result.hashMatch}`,\n `signatureValid=${result.signatureValid}`,\n `keyId=${result.keyId}`,\n `algorithm=${result.algorithm}`,\n `subjectHash=${result.subjectHash}`,\n ].join(\"\\n\")\n );\n\n if (!result.hashMatch) {\n return EXIT_HASH_MISMATCH;\n }\n if (!result.signatureValid) {\n return EXIT_SIGNATURE_INVALID;\n }\n return EXIT_SUCCESS;\n }\n\n if (command === \"public-key\") {\n const artifact = await createPublicKeyArtifact({\n identity: await resolveSealIdentityFromEnv(env),\n });\n outputResult(writer, true, quiet, artifact);\n return EXIT_SUCCESS;\n }\n\n throw new SealCliError(\n \"Usage: seal manifest create --input <path> [--out <path>] [--json] [--quiet]\\n\" +\n \" seal sign --input <path> [--out <path>] [--json] [--quiet]\\n\" +\n \" seal verify --proof <proof.json> --input <path> [--json] [--quiet]\\n\" +\n \" seal public-key [--json] [--quiet]\",\n EXIT_FAILURE\n );\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"Proof\")) {\n return outputError(\n writer,\n json,\n new SealCliError(error.message, EXIT_INVALID_PROOF)\n );\n }\n if (\n error instanceof Error &&\n (error.message.includes(\"public key\") ||\n error.message.includes(\"SEAL_IDENTITY\") ||\n error.message.includes(\"identity\"))\n ) {\n return outputError(\n writer,\n json,\n new SealCliError(error.message, EXIT_KEY_CONFIG)\n );\n }\n return outputError(writer, json, error);\n }\n}\n\nconst isDirectRun =\n typeof process !== \"undefined\" &&\n process.argv[1] &&\n fileURLToPath(import.meta.url) === resolve(process.argv[1]);\n\nif (isDirectRun) {\n runCli(process.argv.slice(2)).then((exitCode) => {\n process.exitCode = exitCode;\n });\n}\n"],"names":[],"mappings":"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"}
package/dist/crypto.js CHANGED
@@ -1,249 +1,2 @@
1
- import { f as formatIdentityKey } from "./chunks/utils.es-586f669f.js";
2
- function getBufferCtor() {
3
- const maybeBuffer = globalThis.Buffer;
4
- return maybeBuffer != null ? maybeBuffer : null;
5
- }
6
- function addNewLines(str) {
7
- let finalString = "";
8
- while (str.length > 0) {
9
- finalString += str.substring(0, 64) + "\n";
10
- str = str.substring(64);
11
- }
12
- return finalString;
13
- }
14
- function removeLines(str) {
15
- return str.replaceAll("\n", "");
16
- }
17
- function arrayBufferToBase64(arrayBuffer) {
18
- const byteArray = new Uint8Array(arrayBuffer);
19
- const bufferCtor = getBufferCtor();
20
- if (bufferCtor) {
21
- return bufferCtor.from(byteArray).toString("base64");
22
- }
23
- let byteString = "";
24
- for (let i = 0; i < byteArray.byteLength; i++) {
25
- byteString += String.fromCharCode(byteArray[i]);
26
- }
27
- return btoa(byteString);
28
- }
29
- function base64ToArrayBuffer(b64) {
30
- const bufferCtor = getBufferCtor();
31
- if (bufferCtor) {
32
- const bytes = Uint8Array.from(
33
- bufferCtor.from(b64, "base64").toString("binary"),
34
- (char) => char.charCodeAt(0)
35
- );
36
- return bytes.buffer.slice(
37
- bytes.byteOffset,
38
- bytes.byteOffset + bytes.byteLength
39
- );
40
- }
41
- const byteString = atob(b64);
42
- const byteArray = new Uint8Array(byteString.length);
43
- for (let i = 0; i < byteString.length; i++) {
44
- byteArray[i] = byteString.charCodeAt(i);
45
- }
46
- return byteArray.buffer;
47
- }
48
- function b64encode(buf) {
49
- return arrayBufferToBase64(buf);
50
- }
51
- function b64decode(str) {
52
- return base64ToArrayBuffer(str);
53
- }
54
- function encode(data) {
55
- const payload = typeof data === "string" ? data : JSON.stringify(data);
56
- return new TextEncoder().encode(payload);
57
- }
58
- function getHashBuffer(data) {
59
- return crypto.subtle.digest("SHA-256", encode(data));
60
- }
61
- function getHashArray(hash) {
62
- return Array.from(new Uint8Array(hash));
63
- }
64
- function getHashHex(hash) {
65
- return hash.map((buf) => buf.toString(16).padStart(2, "0")).join("");
66
- }
67
- function canonicalize(value, seen) {
68
- if (value === void 0) {
69
- throw new TypeError("Cannot hash undefined");
70
- }
71
- const valueType = typeof value;
72
- if (valueType === "function" || valueType === "symbol") {
73
- throw new TypeError(`Cannot hash ${valueType} values`);
74
- }
75
- if (value === null || valueType === "string" || valueType === "number" || valueType === "boolean") {
76
- return value;
77
- }
78
- if (valueType === "bigint") {
79
- throw new TypeError("Cannot hash bigint values");
80
- }
81
- if (typeof value.toJSON === "function") {
82
- return canonicalize(value.toJSON(), seen);
83
- }
84
- if (Array.isArray(value)) {
85
- return value.map((item) => canonicalize(item, seen));
86
- }
87
- if (typeof value === "object") {
88
- if (seen.has(value)) {
89
- throw new TypeError("Cannot hash circular references");
90
- }
91
- seen.add(value);
92
- const entries = Object.keys(value).sort();
93
- const result = {};
94
- for (const key of entries) {
95
- result[key] = canonicalize(value[key], seen);
96
- }
97
- seen.delete(value);
98
- return result;
99
- }
100
- throw new TypeError(`Cannot hash unsupported value type: ${valueType}`);
101
- }
102
- function canonicalStringify(data) {
103
- return JSON.stringify(canonicalize(data, /* @__PURE__ */ new WeakSet()));
104
- }
105
- async function hashData(data) {
106
- const hash_buffer = await getHashBuffer(canonicalStringify(data));
107
- const hash_array = getHashArray(hash_buffer);
108
- return getHashHex(hash_array);
109
- }
110
- async function importPrivateKeyFromPem(key) {
111
- const b64key = key.replace("-----BEGIN PRIVATE KEY-----", "").replace("-----END PRIVATE KEY-----", "");
112
- return crypto.subtle.importKey(
113
- "pkcs8",
114
- base64ToArrayBuffer(removeLines(b64key)),
115
- { name: "ECDSA", namedCurve: "P-256" },
116
- true,
117
- ["sign"]
118
- );
119
- }
120
- async function exportPrivateKey(privateKey) {
121
- return crypto.subtle.exportKey("jwk", privateKey);
122
- }
123
- function importPublicKey(points) {
124
- return crypto.subtle.importKey(
125
- "jwk",
126
- {
127
- crv: "P-256",
128
- ext: true,
129
- kty: "EC",
130
- ...points
131
- },
132
- {
133
- name: "ECDSA",
134
- namedCurve: "P-256"
135
- },
136
- true,
137
- ["verify"]
138
- );
139
- }
140
- async function importPublicKeyFromPem(key) {
141
- const b64key = key.replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLIC KEY-----", "");
142
- return crypto.subtle.importKey(
143
- "spki",
144
- base64ToArrayBuffer(removeLines(b64key)),
145
- { name: "ECDSA", namedCurve: "P-256" },
146
- true,
147
- ["verify"]
148
- );
149
- }
150
- async function exportPublicKey(key) {
151
- const exported = await crypto.subtle.exportKey("spki", key);
152
- return b64encode(exported);
153
- }
154
- async function exportPublicKeyAsPem(key) {
155
- const exportedPublicKey = await crypto.subtle.exportKey("spki", key);
156
- return `-----BEGIN PUBLIC KEY-----
157
- ${addNewLines(arrayBufferToBase64(exportedPublicKey))}-----END PUBLIC KEY-----`;
158
- }
159
- async function derivePublicFromPrivatePEM(privateKeyPEM) {
160
- const key = await importPrivateKeyFromPem(privateKeyPEM);
161
- const priv = await exportPrivateKey(key);
162
- const pub = await importPublicKey({ x: priv.x, y: priv.y });
163
- return exportPublicKeyAsPem(pub);
164
- }
165
- async function signBytes(signingKey, data) {
166
- const bytes = data instanceof Uint8Array ? data : new Uint8Array(data);
167
- const signatureBuffer = await crypto.subtle.sign(
168
- {
169
- name: "ECDSA",
170
- hash: {
171
- name: "SHA-256"
172
- }
173
- },
174
- signingKey,
175
- bytes
176
- );
177
- return b64encode(signatureBuffer);
178
- }
179
- async function verifyBytes(signature, data, publicKey) {
180
- const bytes = data instanceof Uint8Array ? data : new Uint8Array(data);
181
- return crypto.subtle.verify(
182
- {
183
- name: "ECDSA",
184
- hash: { name: "SHA-256" }
185
- },
186
- publicKey,
187
- b64decode(signature),
188
- bytes
189
- );
190
- }
191
- function normalizePublicKeyBody(publicKeyBase64) {
192
- return addNewLines(publicKeyBase64).trimEnd();
193
- }
194
- async function deriveKeyIdFromPublicKeyBase64(publicKeyBase64) {
195
- return hashData(normalizePublicKeyBody(publicKeyBase64));
196
- }
197
- async function deriveKeyIdFromPublicKey(publicKey) {
198
- const publicKeyBase64 = await exportPublicKey(publicKey);
199
- return deriveKeyIdFromPublicKeyBase64(publicKeyBase64);
200
- }
201
- function utf8Bytes(value) {
202
- return new TextEncoder().encode(value);
203
- }
204
- async function importPublicKeyFromBase64(publicKeyBase64) {
205
- return importPublicKeyFromPem(formatIdentityKey(publicKeyBase64));
206
- }
207
- async function exportPublicKeyBase64(key) {
208
- return exportPublicKey(key);
209
- }
210
- async function derivePublicKeyBase64FromPrivateKeyPem(privateKeyPem) {
211
- const publicKeyPem = await derivePublicFromPrivatePEM(privateKeyPem);
212
- const publicKey = await importPublicKeyFromPem(publicKeyPem);
213
- return exportPublicKeyBase64(publicKey);
214
- }
215
- async function resolveSealSigner(input) {
216
- const privateKey = await importPrivateKeyFromPem(input.privateKeyPem);
217
- const publicKeyPem = input.publicKeyPem ? input.publicKeyPem : await derivePublicFromPrivatePEM(input.privateKeyPem);
218
- const publicKey = await importPublicKeyFromPem(publicKeyPem);
219
- const publicKeyBase64 = await exportPublicKeyBase64(publicKey);
220
- const derivedPublicKeyBase64 = await derivePublicKeyBase64FromPrivateKeyPem(
221
- input.privateKeyPem
222
- );
223
- if (publicKeyBase64 !== derivedPublicKeyBase64) {
224
- throw new Error("Provided public key does not match the private key.");
225
- }
226
- const derivedKeyId = await deriveKeyIdFromPublicKey(publicKey);
227
- if (input.keyId && input.keyId !== derivedKeyId) {
228
- throw new Error("Provided keyId does not match the signer public key.");
229
- }
230
- const keyId = input.keyId ?? derivedKeyId;
231
- return {
232
- privateKey,
233
- publicKey,
234
- publicKeyPem,
235
- publicKeyBase64,
236
- keyId
237
- };
238
- }
239
- async function signUtf8(signingKey, value) {
240
- return signBytes(signingKey, utf8Bytes(value));
241
- }
242
- async function verifyUtf8(signature, value, publicKey) {
243
- return verifyBytes(signature, utf8Bytes(value), publicKey);
244
- }
245
- async function verifyPublicKeyKeyId(publicKeyBase64, keyId) {
246
- return await deriveKeyIdFromPublicKeyBase64(publicKeyBase64) === keyId;
247
- }
248
- export { derivePublicKeyBase64FromPrivateKeyPem, exportPublicKeyBase64, importPublicKeyFromBase64, resolveSealSigner, signUtf8, verifyPublicKeyKeyId, verifyUtf8 };
1
+ export { S as SEAL_SIGNATURE_CONTEXT, e as exportIdentityJson, r as resolveSealSigner, s as signSealUtf8, v as verifyPublicKeyKeyId, a as verifySealUtf8 } from "./chunks/crypto-8a814dd3.js";
249
2
  //# sourceMappingURL=crypto.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"crypto.js","sources":["../../identity/dist/identity.es.js","../src/crypto.ts"],"sourcesContent":["async function createIdentity() {\n return crypto.subtle.generateKey(\n { name: \"ECDSA\", namedCurve: \"P-256\" },\n true,\n [\"sign\", \"verify\"]\n );\n}\nfunction getBufferCtor() {\n const maybeBuffer = globalThis.Buffer;\n return maybeBuffer != null ? maybeBuffer : null;\n}\nfunction addNewLines(str) {\n let finalString = \"\";\n while (str.length > 0) {\n finalString += str.substring(0, 64) + \"\\n\";\n str = str.substring(64);\n }\n return finalString;\n}\nfunction removeLines(str) {\n return str.replaceAll(\"\\n\", \"\");\n}\nfunction stripIdentityKey(key) {\n return key.replace(\"-----BEGIN PUBLIC KEY-----\\n\", \"\").replace(\"\\n-----END PUBLIC KEY-----\", \"\");\n}\nfunction arrayBufferToBase64(arrayBuffer) {\n const byteArray = new Uint8Array(arrayBuffer);\n const bufferCtor = getBufferCtor();\n if (bufferCtor) {\n return bufferCtor.from(byteArray).toString(\"base64\");\n }\n let byteString = \"\";\n for (let i = 0; i < byteArray.byteLength; i++) {\n byteString += String.fromCharCode(byteArray[i]);\n }\n return btoa(byteString);\n}\nfunction base64ToArrayBuffer(b64) {\n const bufferCtor = getBufferCtor();\n if (bufferCtor) {\n const bytes = Uint8Array.from(\n bufferCtor.from(b64, \"base64\").toString(\"binary\"),\n (char) => char.charCodeAt(0)\n );\n return bytes.buffer.slice(\n bytes.byteOffset,\n bytes.byteOffset + bytes.byteLength\n );\n }\n const byteString = atob(b64);\n const byteArray = new Uint8Array(byteString.length);\n for (let i = 0; i < byteString.length; i++) {\n byteArray[i] = byteString.charCodeAt(i);\n }\n return byteArray.buffer;\n}\nfunction b64encode(buf) {\n return arrayBufferToBase64(buf);\n}\nfunction b64decode(str) {\n return base64ToArrayBuffer(str);\n}\nfunction encode(data) {\n const payload = typeof data === \"string\" ? data : JSON.stringify(data);\n return new TextEncoder().encode(payload);\n}\nfunction getHashBuffer(data) {\n return crypto.subtle.digest(\"SHA-256\", encode(data));\n}\nfunction getHashArray(hash) {\n return Array.from(new Uint8Array(hash));\n}\nfunction getHashHex(hash) {\n return hash.map((buf) => buf.toString(16).padStart(2, \"0\")).join(\"\");\n}\nfunction canonicalize(value, seen) {\n if (value === void 0) {\n throw new TypeError(\"Cannot hash undefined\");\n }\n const valueType = typeof value;\n if (valueType === \"function\" || valueType === \"symbol\") {\n throw new TypeError(`Cannot hash ${valueType} values`);\n }\n if (value === null || valueType === \"string\" || valueType === \"number\" || valueType === \"boolean\") {\n return value;\n }\n if (valueType === \"bigint\") {\n throw new TypeError(\"Cannot hash bigint values\");\n }\n if (typeof value.toJSON === \"function\") {\n return canonicalize(value.toJSON(), seen);\n }\n if (Array.isArray(value)) {\n return value.map((item) => canonicalize(item, seen));\n }\n if (typeof value === \"object\") {\n if (seen.has(value)) {\n throw new TypeError(\"Cannot hash circular references\");\n }\n seen.add(value);\n const entries = Object.keys(value).sort();\n const result = {};\n for (const key of entries) {\n result[key] = canonicalize(value[key], seen);\n }\n seen.delete(value);\n return result;\n }\n throw new TypeError(`Cannot hash unsupported value type: ${valueType}`);\n}\nfunction canonicalStringify(data) {\n return JSON.stringify(canonicalize(data, /* @__PURE__ */ new WeakSet()));\n}\nasync function hashData(data) {\n const hash_buffer = await getHashBuffer(canonicalStringify(data));\n const hash_array = getHashArray(hash_buffer);\n return getHashHex(hash_array);\n}\nfunction importPrivateKey(points, secret) {\n return crypto.subtle.importKey(\n \"jwk\",\n {\n crv: \"P-256\",\n ext: true,\n kty: \"EC\",\n ...points,\n d: secret\n },\n {\n name: \"ECDSA\",\n namedCurve: \"P-256\"\n },\n true,\n [\"sign\"]\n );\n}\nasync function importPrivateKeyFromPem(key) {\n const b64key = key.replace(\"-----BEGIN PRIVATE KEY-----\", \"\").replace(\"-----END PRIVATE KEY-----\", \"\");\n return crypto.subtle.importKey(\n \"pkcs8\",\n base64ToArrayBuffer(removeLines(b64key)),\n { name: \"ECDSA\", namedCurve: \"P-256\" },\n true,\n [\"sign\"]\n );\n}\nasync function exportPrivateKey(privateKey) {\n return crypto.subtle.exportKey(\"jwk\", privateKey);\n}\nasync function exportPrivateKeyAsPem(privateKey) {\n const exportedPrivateKey = await crypto.subtle.exportKey(\"pkcs8\", privateKey);\n return `-----BEGIN PRIVATE KEY-----\n${addNewLines(\n arrayBufferToBase64(exportedPrivateKey)\n )}-----END PRIVATE KEY-----`;\n}\nfunction importPublicKey(points) {\n return crypto.subtle.importKey(\n \"jwk\",\n {\n crv: \"P-256\",\n ext: true,\n kty: \"EC\",\n ...points\n },\n {\n name: \"ECDSA\",\n namedCurve: \"P-256\"\n },\n true,\n [\"verify\"]\n );\n}\nasync function importPublicKeyFromPem(key) {\n const b64key = key.replace(\"-----BEGIN PUBLIC KEY-----\", \"\").replace(\"-----END PUBLIC KEY-----\", \"\");\n return crypto.subtle.importKey(\n \"spki\",\n base64ToArrayBuffer(removeLines(b64key)),\n { name: \"ECDSA\", namedCurve: \"P-256\" },\n true,\n [\"verify\"]\n );\n}\nasync function exportPublicKey(key) {\n const exported = await crypto.subtle.exportKey(\"spki\", key);\n return b64encode(exported);\n}\nasync function exportPublicKeyAsPem(key) {\n const exportedPublicKey = await crypto.subtle.exportKey(\"spki\", key);\n return `-----BEGIN PUBLIC KEY-----\n${addNewLines(arrayBufferToBase64(exportedPublicKey))}-----END PUBLIC KEY-----`;\n}\nasync function derivePublicFromPrivatePEM(privateKeyPEM) {\n const key = await importPrivateKeyFromPem(privateKeyPEM);\n const priv = await exportPrivateKey(key);\n const pub = await importPublicKey({ x: priv.x, y: priv.y });\n return exportPublicKeyAsPem(pub);\n}\nasync function signBytes(signingKey, data) {\n const bytes = data instanceof Uint8Array ? data : new Uint8Array(data);\n const signatureBuffer = await crypto.subtle.sign(\n {\n name: \"ECDSA\",\n hash: {\n name: \"SHA-256\"\n }\n },\n signingKey,\n bytes\n );\n return b64encode(signatureBuffer);\n}\nasync function sign(signingKey, data) {\n const payload = typeof data === \"string\" ? data : JSON.stringify(data);\n const dataBuffer = new TextEncoder().encode(payload);\n return signBytes(signingKey, dataBuffer);\n}\nasync function verifyBytes(signature, data, publicKey) {\n const bytes = data instanceof Uint8Array ? data : new Uint8Array(data);\n return crypto.subtle.verify(\n {\n name: \"ECDSA\",\n hash: { name: \"SHA-256\" }\n },\n publicKey,\n b64decode(signature),\n bytes\n );\n}\nasync function verify(signature, data, publicKey) {\n const dataBuffer = new TextEncoder().encode(data);\n return verifyBytes(signature, dataBuffer, publicKey);\n}\nasync function verifyJson(signature, data, publicKey) {\n return verify(signature, JSON.stringify(data), publicKey);\n}\nfunction normalizePublicKeyBody(publicKeyBase64) {\n return addNewLines(publicKeyBase64).trimEnd();\n}\nasync function deriveKeyIdFromPublicKeyBase64(publicKeyBase64) {\n return hashData(normalizePublicKeyBody(publicKeyBase64));\n}\nasync function deriveKeyIdFromPublicKeyPem(publicKeyPem) {\n return hashData(stripIdentityKey(publicKeyPem));\n}\nasync function deriveKeyIdFromPublicKey(publicKey) {\n const publicKeyBase64 = await exportPublicKey(publicKey);\n return deriveKeyIdFromPublicKeyBase64(publicKeyBase64);\n}\nexport { createIdentity, deriveKeyIdFromPublicKey, deriveKeyIdFromPublicKeyBase64, deriveKeyIdFromPublicKeyPem, derivePublicFromPrivatePEM, exportPrivateKey, exportPrivateKeyAsPem, exportPublicKey, exportPublicKeyAsPem, importPrivateKey, importPrivateKeyFromPem, importPublicKey, importPublicKeyFromPem, sign, signBytes, verify, verifyBytes, verifyJson };\n","import {\n deriveKeyIdFromPublicKey,\n deriveKeyIdFromPublicKeyBase64,\n derivePublicFromPrivatePEM,\n exportPublicKey,\n importPrivateKeyFromPem,\n importPublicKeyFromPem,\n signBytes,\n verifyBytes,\n} from \"ternent-identity\";\nimport { formatIdentityKey } from \"ternent-utils\";\n\nexport type SealSignerInput = {\n privateKeyPem: string;\n publicKeyPem?: string;\n keyId?: string;\n};\n\nexport type ResolvedSealSigner = {\n privateKey: CryptoKey;\n publicKey: CryptoKey;\n publicKeyPem: string;\n publicKeyBase64: string;\n keyId: string;\n};\n\nfunction utf8Bytes(value: string): Uint8Array {\n return new TextEncoder().encode(value);\n}\n\nexport async function importPublicKeyFromBase64(\n publicKeyBase64: string\n): Promise<CryptoKey> {\n return importPublicKeyFromPem(formatIdentityKey(publicKeyBase64));\n}\n\nexport async function exportPublicKeyBase64(key: CryptoKey): Promise<string> {\n return exportPublicKey(key);\n}\n\nexport async function derivePublicKeyBase64FromPrivateKeyPem(\n privateKeyPem: string\n): Promise<string> {\n const publicKeyPem = await derivePublicFromPrivatePEM(privateKeyPem);\n const publicKey = await importPublicKeyFromPem(publicKeyPem);\n return exportPublicKeyBase64(publicKey);\n}\n\nexport async function resolveSealSigner(\n input: SealSignerInput\n): Promise<ResolvedSealSigner> {\n const privateKey = await importPrivateKeyFromPem(input.privateKeyPem);\n const publicKeyPem = input.publicKeyPem\n ? input.publicKeyPem\n : await derivePublicFromPrivatePEM(input.privateKeyPem);\n const publicKey = await importPublicKeyFromPem(publicKeyPem);\n const publicKeyBase64 = await exportPublicKeyBase64(publicKey);\n const derivedPublicKeyBase64 = await derivePublicKeyBase64FromPrivateKeyPem(\n input.privateKeyPem\n );\n\n if (publicKeyBase64 !== derivedPublicKeyBase64) {\n throw new Error(\"Provided public key does not match the private key.\");\n }\n\n const derivedKeyId = await deriveKeyIdFromPublicKey(publicKey);\n if (input.keyId && input.keyId !== derivedKeyId) {\n throw new Error(\"Provided keyId does not match the signer public key.\");\n }\n const keyId = input.keyId ?? derivedKeyId;\n\n return {\n privateKey,\n publicKey,\n publicKeyPem,\n publicKeyBase64,\n keyId,\n };\n}\n\nexport async function signUtf8(\n signingKey: CryptoKey,\n value: string\n): Promise<string> {\n return signBytes(signingKey, utf8Bytes(value));\n}\n\nexport async function verifyUtf8(\n signature: string,\n value: string,\n publicKey: CryptoKey\n): Promise<boolean> {\n return verifyBytes(signature, utf8Bytes(value), publicKey);\n}\n\nexport async function verifyPublicKeyKeyId(\n publicKeyBase64: string,\n keyId: string\n): Promise<boolean> {\n return (await deriveKeyIdFromPublicKeyBase64(publicKeyBase64)) === keyId;\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"crypto.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
- export { SEAL_PROOF_TYPE, SEAL_PROOF_VERSION, SEAL_SIGNATURE_ALGORITHM, createSealHash, createSealProof, createSealPublicKeyArtifact, getSealProofSignableFields, getSealProofSigningPayload, parseSealProofJson, parseSealPublicKeyJson, validateSealProofShape, validateSealPublicKeyShape, verifySealProofAgainstBytes, verifySealProofSignature } from "./proof.js";
1
+ export { SEAL_PROOF_TYPE, SEAL_PROOF_VERSION, SEAL_PUBLIC_KEY_TYPE, SEAL_SIGNATURE_ALGORITHM, createSealHash, createSealProof, createSealPublicKeyArtifact, getSealProofSignableFields, getSealProofSigningPayload, parseSealProofJson, parseSealPublicKeyJson, validateSealProofShape, validateSealPublicKeyShape, verifySealProofAgainstBytes, verifySealProofSignature } from "./proof.js";
2
2
  export { SEAL_MANIFEST_TYPE, SEAL_MANIFEST_VERSION, parseSealManifestJson, stringifySealManifest, validateSealManifestShape } from "./manifest.js";
3
- export { derivePublicKeyBase64FromPrivateKeyPem, exportPublicKeyBase64, importPublicKeyFromBase64, resolveSealSigner, signUtf8, verifyPublicKeyKeyId, verifyUtf8 } from "./crypto.js";
3
+ export { S as SEAL_SIGNATURE_CONTEXT, e as exportIdentityJson, r as resolveSealSigner, s as signSealUtf8, v as verifyPublicKeyKeyId, a as verifySealUtf8 } from "./chunks/crypto-8a814dd3.js";
4
4
  export { EXIT_FAILURE, EXIT_HASH_MISMATCH, EXIT_INVALID_PROOF, EXIT_KEY_CONFIG, EXIT_SIGNATURE_INVALID, EXIT_SUCCESS, SealCliError, getExitCode } from "./errors.js";
5
- import "./chunks/utils.es-586f669f.js";
5
+ import "./chunks/utils.es-7e2ade90.js";
6
6
  //# sourceMappingURL=index.js.map
package/dist/manifest.js CHANGED
@@ -1,4 +1,4 @@
1
- import { c as canonicalStringify } from "./chunks/utils.es-586f669f.js";
1
+ import { c as canonicalStringify } from "./chunks/utils.es-7e2ade90.js";
2
2
  const SEAL_MANIFEST_VERSION = "1";
3
3
  const SEAL_MANIFEST_TYPE = "seal-manifest";
4
4
  function isRecord(value) {
package/dist/proof.js CHANGED
@@ -1,8 +1,9 @@
1
- import { c as canonicalStringify, h as hashBytes } from "./chunks/utils.es-586f669f.js";
2
- import { resolveSealSigner, signUtf8, verifyPublicKeyKeyId, importPublicKeyFromBase64, verifyUtf8 } from "./crypto.js";
3
- const SEAL_PROOF_VERSION = "1";
1
+ import { c as canonicalStringify, h as hashBytes } from "./chunks/utils.es-7e2ade90.js";
2
+ import { r as resolveSealSigner, s as signSealUtf8, v as verifyPublicKeyKeyId, a as verifySealUtf8 } from "./chunks/crypto-8a814dd3.js";
3
+ const SEAL_PROOF_VERSION = "2";
4
4
  const SEAL_PROOF_TYPE = "seal-proof";
5
- const SEAL_SIGNATURE_ALGORITHM = "ECDSA-P256-SHA256";
5
+ const SEAL_PUBLIC_KEY_TYPE = "seal-public-key";
6
+ const SEAL_SIGNATURE_ALGORITHM = "Ed25519";
6
7
  function isRecord(value) {
7
8
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
8
9
  }
@@ -41,12 +42,12 @@ async function createSealProof(input) {
41
42
  createdAt: input.createdAt ?? new Date().toISOString(),
42
43
  subject: input.subject,
43
44
  signer: {
44
- publicKey: signer.publicKeyBase64,
45
+ publicKey: signer.publicKey,
45
46
  keyId: signer.keyId
46
47
  }
47
48
  };
48
- const signature = await signUtf8(
49
- signer.privateKey,
49
+ const signature = await signSealUtf8(
50
+ signer.identity,
50
51
  getSealProofSigningPayload(fields)
51
52
  );
52
53
  return {
@@ -57,8 +58,10 @@ async function createSealProof(input) {
57
58
  async function createSealPublicKeyArtifact(signer) {
58
59
  const resolved = await resolveSealSigner(signer);
59
60
  return {
61
+ version: SEAL_PROOF_VERSION,
62
+ type: SEAL_PUBLIC_KEY_TYPE,
60
63
  algorithm: SEAL_SIGNATURE_ALGORITHM,
61
- publicKey: resolved.publicKeyBase64,
64
+ publicKey: resolved.publicKey,
62
65
  keyId: resolved.keyId
63
66
  };
64
67
  }
@@ -91,7 +94,7 @@ function validateSealProofShape(value) {
91
94
  errors.push("Proof createdAt must be an ISO timestamp.");
92
95
  }
93
96
  if (typeof value.signature !== "string" || value.signature.length === 0) {
94
- errors.push("Proof signature must be a non-empty base64 string.");
97
+ errors.push("Proof signature must be a non-empty base64url string.");
95
98
  }
96
99
  if (!isRecord(value.subject)) {
97
100
  errors.push("Proof subject must be an object.");
@@ -118,7 +121,7 @@ function validateSealProofShape(value) {
118
121
  errors.push("Proof subject hash must be a sha256 hash.");
119
122
  }
120
123
  if (typeof value.signer.publicKey !== "string" || value.signer.publicKey.length === 0) {
121
- errors.push("Proof signer publicKey must be a non-empty base64 string.");
124
+ errors.push("Proof signer publicKey must be a non-empty base64url string.");
122
125
  }
123
126
  if (typeof value.signer.keyId !== "string" || value.signer.keyId.length === 0) {
124
127
  errors.push("Proof signer keyId must be a non-empty string.");
@@ -152,14 +155,20 @@ function validateSealPublicKeyShape(value) {
152
155
  };
153
156
  }
154
157
  const errors = [];
155
- if (!hasOnlyKeys(value, ["algorithm", "publicKey", "keyId"])) {
158
+ if (!hasOnlyKeys(value, ["version", "type", "algorithm", "publicKey", "keyId"])) {
156
159
  errors.push("Public key artifact contains unsupported fields.");
157
160
  }
161
+ if (value.version !== SEAL_PROOF_VERSION) {
162
+ errors.push(`Public key artifact version must be ${SEAL_PROOF_VERSION}.`);
163
+ }
164
+ if (value.type !== SEAL_PUBLIC_KEY_TYPE) {
165
+ errors.push(`Public key artifact type must be ${SEAL_PUBLIC_KEY_TYPE}.`);
166
+ }
158
167
  if (value.algorithm !== SEAL_SIGNATURE_ALGORITHM) {
159
168
  errors.push(`Public key artifact algorithm must be ${SEAL_SIGNATURE_ALGORITHM}.`);
160
169
  }
161
170
  if (typeof value.publicKey !== "string" || value.publicKey.length === 0) {
162
- errors.push("Public key artifact publicKey must be a non-empty base64 string.");
171
+ errors.push("Public key artifact publicKey must be a non-empty base64url string.");
163
172
  }
164
173
  if (typeof value.keyId !== "string" || value.keyId.length === 0) {
165
174
  errors.push("Public key artifact keyId must be a non-empty string.");
@@ -196,11 +205,10 @@ async function verifySealProofSignature(proof) {
196
205
  };
197
206
  }
198
207
  try {
199
- const publicKey = await importPublicKeyFromBase64(proof.signer.publicKey);
200
- const valid = await verifyUtf8(
208
+ const valid = await verifySealUtf8(
201
209
  proof.signature,
202
210
  getSealProofSigningPayload(proof),
203
- publicKey
211
+ proof.signer.publicKey
204
212
  );
205
213
  if (!valid) {
206
214
  return { ok: false, errors: ["Invalid signature."] };
@@ -228,5 +236,5 @@ async function verifySealProofAgainstBytes(proof, bytes) {
228
236
  subjectHash
229
237
  };
230
238
  }
231
- export { SEAL_PROOF_TYPE, SEAL_PROOF_VERSION, SEAL_SIGNATURE_ALGORITHM, createSealHash, createSealProof, createSealPublicKeyArtifact, getSealProofSignableFields, getSealProofSigningPayload, parseSealProofJson, parseSealPublicKeyJson, validateSealProofShape, validateSealPublicKeyShape, verifySealProofAgainstBytes, verifySealProofSignature };
239
+ export { SEAL_PROOF_TYPE, SEAL_PROOF_VERSION, SEAL_PUBLIC_KEY_TYPE, SEAL_SIGNATURE_ALGORITHM, createSealHash, createSealProof, createSealPublicKeyArtifact, getSealProofSignableFields, getSealProofSigningPayload, parseSealProofJson, parseSealPublicKeyJson, validateSealProofShape, validateSealPublicKeyShape, verifySealProofAgainstBytes, verifySealProofSignature };
232
240
  //# sourceMappingURL=proof.js.map
package/dist/proof.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"proof.js","sources":["../src/proof.ts"],"sourcesContent":["import { canonicalStringify, hashBytes } from \"ternent-utils\";\nimport {\n importPublicKeyFromBase64,\n resolveSealSigner,\n signUtf8,\n verifyPublicKeyKeyId,\n verifyUtf8,\n type SealSignerInput,\n} from \"./crypto\";\n\nexport const SEAL_PROOF_VERSION = \"1\" as const;\nexport const SEAL_PROOF_TYPE = \"seal-proof\" as const;\nexport const SEAL_SIGNATURE_ALGORITHM = \"ECDSA-P256-SHA256\" as const;\n\nexport type SealSubjectKind = \"file\" | \"manifest\";\n\nexport type SealProofV1 = {\n version: typeof SEAL_PROOF_VERSION;\n type: typeof SEAL_PROOF_TYPE;\n algorithm: typeof SEAL_SIGNATURE_ALGORITHM;\n createdAt: string;\n subject: {\n kind: SealSubjectKind;\n path: string;\n hash: `sha256:${string}`;\n };\n signer: {\n publicKey: string;\n keyId: string;\n };\n signature: string;\n};\n\nexport type SealPublicKeyArtifact = {\n algorithm: typeof SEAL_SIGNATURE_ALGORITHM;\n publicKey: string;\n keyId: string;\n};\n\ntype SealProofSignableFields = Omit<SealProofV1, \"signature\">;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction hasOnlyKeys(\n value: Record<string, unknown>,\n allowed: string[]\n): boolean {\n return Object.keys(value).every((key) => allowed.includes(key));\n}\n\nfunction isSealHash(value: unknown): value is `sha256:${string}` {\n return typeof value === \"string\" && /^sha256:[0-9a-f]{64}$/.test(value);\n}\n\nfunction isIsoDate(value: string): boolean {\n return !Number.isNaN(Date.parse(value));\n}\n\nexport function getSealProofSignableFields(\n proof: SealProofV1 | SealProofSignableFields\n): SealProofSignableFields {\n return {\n version: proof.version,\n type: proof.type,\n algorithm: proof.algorithm,\n createdAt: proof.createdAt,\n subject: proof.subject,\n signer: proof.signer,\n };\n}\n\nexport function getSealProofSigningPayload(\n proof: SealProofV1 | SealProofSignableFields\n): string {\n return canonicalStringify(getSealProofSignableFields(proof));\n}\n\nexport async function createSealHash(\n bytes: Uint8Array | ArrayBuffer\n): Promise<`sha256:${string}`> {\n const hash = await hashBytes(bytes);\n return `sha256:${hash}`;\n}\n\nexport async function createSealProof(input: {\n createdAt?: string;\n signer: SealSignerInput;\n subject: SealProofV1[\"subject\"];\n}): Promise<SealProofV1> {\n const signer = await resolveSealSigner(input.signer);\n const fields: SealProofSignableFields = {\n version: SEAL_PROOF_VERSION,\n type: SEAL_PROOF_TYPE,\n algorithm: SEAL_SIGNATURE_ALGORITHM,\n createdAt: input.createdAt ?? new Date().toISOString(),\n subject: input.subject,\n signer: {\n publicKey: signer.publicKeyBase64,\n keyId: signer.keyId,\n },\n };\n\n const signature = await signUtf8(\n signer.privateKey,\n getSealProofSigningPayload(fields)\n );\n\n return {\n ...fields,\n signature,\n };\n}\n\nexport async function createSealPublicKeyArtifact(\n signer: SealSignerInput\n): Promise<SealPublicKeyArtifact> {\n const resolved = await resolveSealSigner(signer);\n return {\n algorithm: SEAL_SIGNATURE_ALGORITHM,\n publicKey: resolved.publicKeyBase64,\n keyId: resolved.keyId,\n };\n}\n\nexport function validateSealProofShape(value: unknown): {\n ok: boolean;\n errors: string[];\n proof: SealProofV1 | null;\n} {\n if (!isRecord(value)) {\n return { ok: false, errors: [\"Proof must be a JSON object.\"], proof: null };\n }\n\n const errors: string[] = [];\n\n if (\n !hasOnlyKeys(value, [\n \"version\",\n \"type\",\n \"algorithm\",\n \"createdAt\",\n \"subject\",\n \"signer\",\n \"signature\",\n ])\n ) {\n errors.push(\"Proof contains unsupported fields.\");\n }\n\n if (value.version !== SEAL_PROOF_VERSION) {\n errors.push(`Proof version must be ${SEAL_PROOF_VERSION}.`);\n }\n if (value.type !== SEAL_PROOF_TYPE) {\n errors.push(`Proof type must be ${SEAL_PROOF_TYPE}.`);\n }\n if (value.algorithm !== SEAL_SIGNATURE_ALGORITHM) {\n errors.push(`Proof algorithm must be ${SEAL_SIGNATURE_ALGORITHM}.`);\n }\n if (typeof value.createdAt !== \"string\" || !isIsoDate(value.createdAt)) {\n errors.push(\"Proof createdAt must be an ISO timestamp.\");\n }\n if (typeof value.signature !== \"string\" || value.signature.length === 0) {\n errors.push(\"Proof signature must be a non-empty base64 string.\");\n }\n if (!isRecord(value.subject)) {\n errors.push(\"Proof subject must be an object.\");\n }\n if (!isRecord(value.signer)) {\n errors.push(\"Proof signer must be an object.\");\n }\n\n if (errors.length > 0 || !isRecord(value.subject) || !isRecord(value.signer)) {\n return { ok: false, errors, proof: null };\n }\n\n if (!hasOnlyKeys(value.subject, [\"kind\", \"path\", \"hash\"])) {\n errors.push(\"Proof subject contains unsupported fields.\");\n }\n if (!hasOnlyKeys(value.signer, [\"publicKey\", \"keyId\"])) {\n errors.push(\"Proof signer contains unsupported fields.\");\n }\n\n if (value.subject.kind !== \"file\" && value.subject.kind !== \"manifest\") {\n errors.push(\"Proof subject kind must be file or manifest.\");\n }\n if (typeof value.subject.path !== \"string\" || value.subject.path.length === 0) {\n errors.push(\"Proof subject path must be a non-empty string.\");\n }\n if (!isSealHash(value.subject.hash)) {\n errors.push(\"Proof subject hash must be a sha256 hash.\");\n }\n if (\n typeof value.signer.publicKey !== \"string\" ||\n value.signer.publicKey.length === 0\n ) {\n errors.push(\"Proof signer publicKey must be a non-empty base64 string.\");\n }\n if (typeof value.signer.keyId !== \"string\" || value.signer.keyId.length === 0) {\n errors.push(\"Proof signer keyId must be a non-empty string.\");\n }\n\n if (errors.length > 0) {\n return { ok: false, errors, proof: null };\n }\n\n return {\n ok: true,\n errors: [],\n proof: value as SealProofV1,\n };\n}\n\nexport function parseSealProofJson(raw: string): {\n ok: boolean;\n errors: string[];\n proof: SealProofV1 | null;\n} {\n try {\n return validateSealProofShape(JSON.parse(raw));\n } catch {\n return {\n ok: false,\n errors: [\"Proof JSON is not valid JSON.\"],\n proof: null,\n };\n }\n}\n\nexport function validateSealPublicKeyShape(value: unknown): {\n ok: boolean;\n errors: string[];\n artifact: SealPublicKeyArtifact | null;\n} {\n if (!isRecord(value)) {\n return {\n ok: false,\n errors: [\"Public key artifact must be a JSON object.\"],\n artifact: null,\n };\n }\n\n const errors: string[] = [];\n\n if (!hasOnlyKeys(value, [\"algorithm\", \"publicKey\", \"keyId\"])) {\n errors.push(\"Public key artifact contains unsupported fields.\");\n }\n if (value.algorithm !== SEAL_SIGNATURE_ALGORITHM) {\n errors.push(`Public key artifact algorithm must be ${SEAL_SIGNATURE_ALGORITHM}.`);\n }\n if (typeof value.publicKey !== \"string\" || value.publicKey.length === 0) {\n errors.push(\"Public key artifact publicKey must be a non-empty base64 string.\");\n }\n if (typeof value.keyId !== \"string\" || value.keyId.length === 0) {\n errors.push(\"Public key artifact keyId must be a non-empty string.\");\n }\n\n if (errors.length > 0) {\n return { ok: false, errors, artifact: null };\n }\n\n return {\n ok: true,\n errors: [],\n artifact: value as SealPublicKeyArtifact,\n };\n}\n\nexport function parseSealPublicKeyJson(raw: string): {\n ok: boolean;\n errors: string[];\n artifact: SealPublicKeyArtifact | null;\n} {\n try {\n return validateSealPublicKeyShape(JSON.parse(raw));\n } catch {\n return {\n ok: false,\n errors: [\"Public key JSON is not valid JSON.\"],\n artifact: null,\n };\n }\n}\n\nexport async function verifySealProofSignature(proof: SealProofV1): Promise<{\n ok: boolean;\n errors: string[];\n}> {\n const validation = validateSealProofShape(proof);\n if (!validation.ok || !validation.proof) {\n return { ok: false, errors: validation.errors };\n }\n\n if (!(await verifyPublicKeyKeyId(proof.signer.publicKey, proof.signer.keyId))) {\n return {\n ok: false,\n errors: [\"Proof signer keyId does not match signer public key.\"],\n };\n }\n\n try {\n const publicKey = await importPublicKeyFromBase64(proof.signer.publicKey);\n const valid = await verifyUtf8(\n proof.signature,\n getSealProofSigningPayload(proof),\n publicKey\n );\n if (!valid) {\n return { ok: false, errors: [\"Invalid signature.\"] };\n }\n return { ok: true, errors: [] };\n } catch (caught) {\n const message = caught instanceof Error ? caught.message : String(caught);\n return {\n ok: false,\n errors: [`Failed to verify signature: ${message}`],\n };\n }\n}\n\nexport async function verifySealProofAgainstBytes(\n proof: SealProofV1,\n bytes: Uint8Array | ArrayBuffer\n): Promise<{\n valid: boolean;\n hashMatch: boolean;\n signatureValid: boolean;\n keyId: string;\n algorithm: typeof SEAL_SIGNATURE_ALGORITHM;\n subjectHash: `sha256:${string}`;\n}> {\n const subjectHash = await createSealHash(bytes);\n const signatureCheck = await verifySealProofSignature(proof);\n const hashMatch = subjectHash === proof.subject.hash;\n const signatureValid = signatureCheck.ok;\n\n return {\n valid: hashMatch && signatureValid,\n hashMatch,\n signatureValid,\n keyId: proof.signer.keyId,\n algorithm: proof.algorithm,\n subjectHash,\n };\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"proof.js","sources":["../src/proof.ts"],"sourcesContent":["import { canonicalStringify, hashBytes } from \"ternent-utils\";\nimport {\n resolveSealSigner,\n signSealUtf8,\n verifyPublicKeyKeyId,\n verifySealUtf8,\n type SealSignerInput,\n} from \"./crypto\";\n\nexport const SEAL_PROOF_VERSION = \"2\" as const;\nexport const SEAL_PROOF_TYPE = \"seal-proof\" as const;\nexport const SEAL_PUBLIC_KEY_TYPE = \"seal-public-key\" as const;\nexport const SEAL_SIGNATURE_ALGORITHM = \"Ed25519\" as const;\n\nexport type SealSubjectKind = \"file\" | \"manifest\";\n\nexport type SealProofV1 = {\n version: typeof SEAL_PROOF_VERSION;\n type: typeof SEAL_PROOF_TYPE;\n algorithm: typeof SEAL_SIGNATURE_ALGORITHM;\n createdAt: string;\n subject: {\n kind: SealSubjectKind;\n path: string;\n hash: `sha256:${string}`;\n };\n signer: {\n publicKey: string;\n keyId: string;\n };\n signature: string;\n};\n\nexport type SealPublicKeyArtifact = {\n version: typeof SEAL_PROOF_VERSION;\n type: typeof SEAL_PUBLIC_KEY_TYPE;\n algorithm: typeof SEAL_SIGNATURE_ALGORITHM;\n publicKey: string;\n keyId: string;\n};\n\ntype SealProofSignableFields = Omit<SealProofV1, \"signature\">;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction hasOnlyKeys(\n value: Record<string, unknown>,\n allowed: string[]\n): boolean {\n return Object.keys(value).every((key) => allowed.includes(key));\n}\n\nfunction isSealHash(value: unknown): value is `sha256:${string}` {\n return typeof value === \"string\" && /^sha256:[0-9a-f]{64}$/.test(value);\n}\n\nfunction isIsoDate(value: string): boolean {\n return !Number.isNaN(Date.parse(value));\n}\n\nexport function getSealProofSignableFields(\n proof: SealProofV1 | SealProofSignableFields\n): SealProofSignableFields {\n return {\n version: proof.version,\n type: proof.type,\n algorithm: proof.algorithm,\n createdAt: proof.createdAt,\n subject: proof.subject,\n signer: proof.signer,\n };\n}\n\nexport function getSealProofSigningPayload(\n proof: SealProofV1 | SealProofSignableFields\n): string {\n return canonicalStringify(getSealProofSignableFields(proof));\n}\n\nexport async function createSealHash(\n bytes: Uint8Array | ArrayBuffer\n): Promise<`sha256:${string}`> {\n const hash = await hashBytes(bytes);\n return `sha256:${hash}`;\n}\n\nexport async function createSealProof(input: {\n createdAt?: string;\n signer: SealSignerInput;\n subject: SealProofV1[\"subject\"];\n}): Promise<SealProofV1> {\n const signer = await resolveSealSigner(input.signer);\n const fields: SealProofSignableFields = {\n version: SEAL_PROOF_VERSION,\n type: SEAL_PROOF_TYPE,\n algorithm: SEAL_SIGNATURE_ALGORITHM,\n createdAt: input.createdAt ?? new Date().toISOString(),\n subject: input.subject,\n signer: {\n publicKey: signer.publicKey,\n keyId: signer.keyId,\n },\n };\n\n const signature = await signSealUtf8(\n signer.identity,\n getSealProofSigningPayload(fields)\n );\n\n return {\n ...fields,\n signature,\n };\n}\n\nexport async function createSealPublicKeyArtifact(\n signer: SealSignerInput\n): Promise<SealPublicKeyArtifact> {\n const resolved = await resolveSealSigner(signer);\n return {\n version: SEAL_PROOF_VERSION,\n type: SEAL_PUBLIC_KEY_TYPE,\n algorithm: SEAL_SIGNATURE_ALGORITHM,\n publicKey: resolved.publicKey,\n keyId: resolved.keyId,\n };\n}\n\nexport function validateSealProofShape(value: unknown): {\n ok: boolean;\n errors: string[];\n proof: SealProofV1 | null;\n} {\n if (!isRecord(value)) {\n return { ok: false, errors: [\"Proof must be a JSON object.\"], proof: null };\n }\n\n const errors: string[] = [];\n\n if (\n !hasOnlyKeys(value, [\n \"version\",\n \"type\",\n \"algorithm\",\n \"createdAt\",\n \"subject\",\n \"signer\",\n \"signature\",\n ])\n ) {\n errors.push(\"Proof contains unsupported fields.\");\n }\n\n if (value.version !== SEAL_PROOF_VERSION) {\n errors.push(`Proof version must be ${SEAL_PROOF_VERSION}.`);\n }\n if (value.type !== SEAL_PROOF_TYPE) {\n errors.push(`Proof type must be ${SEAL_PROOF_TYPE}.`);\n }\n if (value.algorithm !== SEAL_SIGNATURE_ALGORITHM) {\n errors.push(`Proof algorithm must be ${SEAL_SIGNATURE_ALGORITHM}.`);\n }\n if (typeof value.createdAt !== \"string\" || !isIsoDate(value.createdAt)) {\n errors.push(\"Proof createdAt must be an ISO timestamp.\");\n }\n if (typeof value.signature !== \"string\" || value.signature.length === 0) {\n errors.push(\"Proof signature must be a non-empty base64url string.\");\n }\n if (!isRecord(value.subject)) {\n errors.push(\"Proof subject must be an object.\");\n }\n if (!isRecord(value.signer)) {\n errors.push(\"Proof signer must be an object.\");\n }\n\n if (errors.length > 0 || !isRecord(value.subject) || !isRecord(value.signer)) {\n return { ok: false, errors, proof: null };\n }\n\n if (!hasOnlyKeys(value.subject, [\"kind\", \"path\", \"hash\"])) {\n errors.push(\"Proof subject contains unsupported fields.\");\n }\n if (!hasOnlyKeys(value.signer, [\"publicKey\", \"keyId\"])) {\n errors.push(\"Proof signer contains unsupported fields.\");\n }\n if (value.subject.kind !== \"file\" && value.subject.kind !== \"manifest\") {\n errors.push(\"Proof subject kind must be file or manifest.\");\n }\n if (typeof value.subject.path !== \"string\" || value.subject.path.length === 0) {\n errors.push(\"Proof subject path must be a non-empty string.\");\n }\n if (!isSealHash(value.subject.hash)) {\n errors.push(\"Proof subject hash must be a sha256 hash.\");\n }\n if (\n typeof value.signer.publicKey !== \"string\" ||\n value.signer.publicKey.length === 0\n ) {\n errors.push(\"Proof signer publicKey must be a non-empty base64url string.\");\n }\n if (typeof value.signer.keyId !== \"string\" || value.signer.keyId.length === 0) {\n errors.push(\"Proof signer keyId must be a non-empty string.\");\n }\n\n if (errors.length > 0) {\n return { ok: false, errors, proof: null };\n }\n\n return {\n ok: true,\n errors: [],\n proof: value as SealProofV1,\n };\n}\n\nexport function parseSealProofJson(raw: string): {\n ok: boolean;\n errors: string[];\n proof: SealProofV1 | null;\n} {\n try {\n return validateSealProofShape(JSON.parse(raw));\n } catch {\n return {\n ok: false,\n errors: [\"Proof JSON is not valid JSON.\"],\n proof: null,\n };\n }\n}\n\nexport function validateSealPublicKeyShape(value: unknown): {\n ok: boolean;\n errors: string[];\n artifact: SealPublicKeyArtifact | null;\n} {\n if (!isRecord(value)) {\n return {\n ok: false,\n errors: [\"Public key artifact must be a JSON object.\"],\n artifact: null,\n };\n }\n\n const errors: string[] = [];\n\n if (!hasOnlyKeys(value, [\"version\", \"type\", \"algorithm\", \"publicKey\", \"keyId\"])) {\n errors.push(\"Public key artifact contains unsupported fields.\");\n }\n if (value.version !== SEAL_PROOF_VERSION) {\n errors.push(`Public key artifact version must be ${SEAL_PROOF_VERSION}.`);\n }\n if (value.type !== SEAL_PUBLIC_KEY_TYPE) {\n errors.push(`Public key artifact type must be ${SEAL_PUBLIC_KEY_TYPE}.`);\n }\n if (value.algorithm !== SEAL_SIGNATURE_ALGORITHM) {\n errors.push(`Public key artifact algorithm must be ${SEAL_SIGNATURE_ALGORITHM}.`);\n }\n if (typeof value.publicKey !== \"string\" || value.publicKey.length === 0) {\n errors.push(\"Public key artifact publicKey must be a non-empty base64url string.\");\n }\n if (typeof value.keyId !== \"string\" || value.keyId.length === 0) {\n errors.push(\"Public key artifact keyId must be a non-empty string.\");\n }\n\n if (errors.length > 0) {\n return { ok: false, errors, artifact: null };\n }\n\n return {\n ok: true,\n errors: [],\n artifact: value as SealPublicKeyArtifact,\n };\n}\n\nexport function parseSealPublicKeyJson(raw: string): {\n ok: boolean;\n errors: string[];\n artifact: SealPublicKeyArtifact | null;\n} {\n try {\n return validateSealPublicKeyShape(JSON.parse(raw));\n } catch {\n return {\n ok: false,\n errors: [\"Public key JSON is not valid JSON.\"],\n artifact: null,\n };\n }\n}\n\nexport async function verifySealProofSignature(proof: SealProofV1): Promise<{\n ok: boolean;\n errors: string[];\n}> {\n const validation = validateSealProofShape(proof);\n if (!validation.ok || !validation.proof) {\n return { ok: false, errors: validation.errors };\n }\n\n if (!(await verifyPublicKeyKeyId(proof.signer.publicKey, proof.signer.keyId))) {\n return {\n ok: false,\n errors: [\"Proof signer keyId does not match signer public key.\"],\n };\n }\n\n try {\n const valid = await verifySealUtf8(\n proof.signature,\n getSealProofSigningPayload(proof),\n proof.signer.publicKey\n );\n if (!valid) {\n return { ok: false, errors: [\"Invalid signature.\"] };\n }\n return { ok: true, errors: [] };\n } catch (caught) {\n const message = caught instanceof Error ? caught.message : String(caught);\n return {\n ok: false,\n errors: [`Failed to verify signature: ${message}`],\n };\n }\n}\n\nexport async function verifySealProofAgainstBytes(\n proof: SealProofV1,\n bytes: Uint8Array | ArrayBuffer\n): Promise<{\n valid: boolean;\n hashMatch: boolean;\n signatureValid: boolean;\n keyId: string;\n algorithm: typeof SEAL_SIGNATURE_ALGORITHM;\n subjectHash: `sha256:${string}`;\n}> {\n const subjectHash = await createSealHash(bytes);\n const signatureCheck = await verifySealProofSignature(proof);\n const hashMatch = subjectHash === proof.subject.hash;\n const signatureValid = signatureCheck.ok;\n\n return {\n valid: hashMatch && signatureValid,\n hashMatch,\n signatureValid,\n keyId: proof.signer.keyId,\n algorithm: proof.algorithm,\n subjectHash,\n };\n}\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ternent/seal-cli",
3
- "version": "0.1.7",
3
+ "version": "0.2.0",
4
4
  "description": "Deterministic artifact signing for Seal",
5
5
  "license": "ISC",
6
6
  "type": "module",
@@ -44,7 +44,7 @@
44
44
  "devDependencies": {
45
45
  "vite": "^2.9.18",
46
46
  "vitest": "^1.6.0",
47
- "ternent-identity": "0.0.13",
47
+ "@ternent/identity": "0.2.0",
48
48
  "ternent-utils": "1.1.1"
49
49
  },
50
50
  "scripts": {