@keytrace/claims 0.0.5

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 ADDED
@@ -0,0 +1,105 @@
1
+ # @keytrace/claims
2
+
3
+ Get Keytrace identity claims, and also verify their signatures. Works in both browser and Node.js.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @keytrace/claims
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```typescript
14
+ import { getClaimsForHandle, getClaimsForDid } from '@keytrace/claims';
15
+
16
+ // Verify all claims for a handle
17
+ const result = await getClaimsForHandle('alice.bsky.social');
18
+
19
+ console.log(`${result.summary.verified}/${result.summary.total} claims verified`);
20
+
21
+ for (const claim of result.claims) {
22
+ if (claim.verified) {
23
+ console.log(`✓ ${claim.type}: ${claim.identity.subject}`);
24
+ } else {
25
+ console.log(`✗ ${claim.type}: ${claim.error}`);
26
+ }
27
+ }
28
+
29
+ // Or verify by DID directly
30
+ const result2 = await getClaimsForDid('did:plc:abc123');
31
+ ```
32
+
33
+ ## API
34
+
35
+ ### `getClaimsForHandle(handle, options?)`
36
+
37
+ Verify all keytrace claims for an ATProto handle.
38
+
39
+ ```typescript
40
+ const result = await getClaimsForHandle('alice.bsky.social');
41
+ ```
42
+
43
+ ### `getClaimsForDid(did, options?)`
44
+
45
+ Verify all keytrace claims for a DID.
46
+
47
+ ```typescript
48
+ const result = await getClaimsForDid('did:plc:abc123');
49
+ ```
50
+
51
+ ### Options
52
+
53
+ ```typescript
54
+ interface VerifyOptions {
55
+ fetch?: typeof fetch; // Custom fetch function
56
+ timeout?: number; // Request timeout in ms (default: 10000)
57
+ plcDirectoryUrl?: string; // PLC directory URL (default: https://plc.directory)
58
+ publicApiUrl?: string; // Public API URL (default: https://public.api.bsky.app)
59
+ }
60
+ ```
61
+
62
+ ### Return Type
63
+
64
+ ```typescript
65
+ interface VerificationResult {
66
+ did: string;
67
+ handle?: string;
68
+ claims: ClaimVerificationResult[];
69
+ summary: {
70
+ total: number;
71
+ verified: number;
72
+ failed: number;
73
+ };
74
+ }
75
+
76
+ interface ClaimVerificationResult {
77
+ uri: string; // AT URI of the claim
78
+ rkey: string; // Record key
79
+ type: string; // Claim type (github, dns, etc.)
80
+ claimUri: string; // The claimed identity URI
81
+ verified: boolean; // Whether signature is valid
82
+ steps: VerificationStep[]; // Verification steps performed
83
+ error?: string; // Error message if failed
84
+ identity: ClaimIdentity; // Identity info from the claim
85
+ claim: ClaimRecord; // Full claim record
86
+ }
87
+ ```
88
+
89
+ ## How It Works
90
+
91
+ 1. Resolves the handle to a DID (if needed)
92
+ 2. Fetches the user's PDS endpoint from their DID document
93
+ 3. Lists all `dev.keytrace.claim` records from their repo
94
+ 4. For each claim:
95
+ - Fetches the signing key from the `sig.src` AT URI
96
+ - Reconstructs the signed claim data
97
+ - Verifies the ES256 signature using Web Crypto API
98
+
99
+ ## Platform Support
100
+
101
+ - Node.js 18+
102
+ - Modern browsers (Chrome, Firefox, Safari, Edge)
103
+ - Deno, Cloudflare Workers, and other runtimes with Web Crypto API
104
+
105
+ Zero runtime dependencies - uses standard `fetch` and `crypto.subtle` APIs.
@@ -0,0 +1,22 @@
1
+ import type { ClaimRecord, VerifyOptions } from "./types.js";
2
+ /**
3
+ * Resolve a handle to a DID using the public ATProto API.
4
+ */
5
+ export declare function resolveHandle(handle: string, options?: VerifyOptions): Promise<string>;
6
+ /**
7
+ * Resolve the PDS endpoint from a DID document.
8
+ */
9
+ export declare function resolvePds(did: string, options?: VerifyOptions): Promise<string>;
10
+ /**
11
+ * List all keytrace claim records from a user's repo.
12
+ */
13
+ export declare function listClaimRecords(pdsUrl: string, did: string, options?: VerifyOptions): Promise<Array<{
14
+ uri: string;
15
+ rkey: string;
16
+ value: ClaimRecord;
17
+ }>>;
18
+ /**
19
+ * Fetch a single record by AT URI.
20
+ */
21
+ export declare function getRecordByUri<T>(atUri: string, options?: VerifyOptions): Promise<T>;
22
+ //# sourceMappingURL=atproto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"atproto.d.ts","sourceRoot":"","sources":["../src/atproto.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAa,aAAa,EAAE,MAAM,YAAY,CAAC;AA6CxE;;GAEG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAgB5F;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CA0BtF;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,WAAW,CAAA;CAAE,CAAC,CAAC,CA0C9J;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,CAAC,CAAC,CAqB1F"}
@@ -0,0 +1,134 @@
1
+ import { PUBLIC_API_URL, PLC_DIRECTORY_URL, COLLECTION_NSID, DEFAULT_TIMEOUT } from "./constants.js";
2
+ /**
3
+ * Fetch with timeout support
4
+ */
5
+ async function fetchWithTimeout(url, options) {
6
+ const fetchFn = options?.fetch ?? globalThis.fetch;
7
+ const timeout = options?.timeout ?? DEFAULT_TIMEOUT;
8
+ const controller = new AbortController();
9
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
10
+ try {
11
+ const response = await fetchFn(url, { signal: controller.signal });
12
+ return response;
13
+ }
14
+ finally {
15
+ clearTimeout(timeoutId);
16
+ }
17
+ }
18
+ /**
19
+ * Resolve a handle to a DID using the public ATProto API.
20
+ */
21
+ export async function resolveHandle(handle, options) {
22
+ // If it's already a DID, return it
23
+ if (handle.startsWith("did:")) {
24
+ return handle;
25
+ }
26
+ const baseUrl = options?.publicApiUrl ?? PUBLIC_API_URL;
27
+ const url = `${baseUrl}/xrpc/com.atproto.identity.resolveHandle?handle=${encodeURIComponent(handle)}`;
28
+ const response = await fetchWithTimeout(url, options);
29
+ if (!response.ok) {
30
+ throw new Error(`Failed to resolve handle: ${response.status} ${response.statusText}`);
31
+ }
32
+ const data = (await response.json());
33
+ return data.did;
34
+ }
35
+ /**
36
+ * Resolve the PDS endpoint from a DID document.
37
+ */
38
+ export async function resolvePds(did, options) {
39
+ const plcUrl = options?.plcDirectoryUrl ?? PLC_DIRECTORY_URL;
40
+ try {
41
+ let url;
42
+ if (did.startsWith("did:plc:")) {
43
+ url = `${plcUrl}/${did}`;
44
+ }
45
+ else if (did.startsWith("did:web:")) {
46
+ const host = did.replace("did:web:", "").replaceAll(":", "/");
47
+ url = `https://${host}/.well-known/did.json`;
48
+ }
49
+ else {
50
+ return PUBLIC_API_URL;
51
+ }
52
+ const response = await fetchWithTimeout(url, options);
53
+ if (!response.ok) {
54
+ return PUBLIC_API_URL;
55
+ }
56
+ const doc = (await response.json());
57
+ const pdsService = doc.service?.find((s) => s.id === "#atproto_pds" || s.type === "AtprotoPersonalDataServer");
58
+ return pdsService?.serviceEndpoint ?? PUBLIC_API_URL;
59
+ }
60
+ catch {
61
+ return PUBLIC_API_URL;
62
+ }
63
+ }
64
+ /**
65
+ * List all keytrace claim records from a user's repo.
66
+ */
67
+ export async function listClaimRecords(pdsUrl, did, options) {
68
+ const claims = [];
69
+ try {
70
+ let cursor;
71
+ do {
72
+ const url = new URL(`${pdsUrl}/xrpc/com.atproto.repo.listRecords`);
73
+ url.searchParams.set("repo", did);
74
+ url.searchParams.set("collection", COLLECTION_NSID);
75
+ url.searchParams.set("limit", "100");
76
+ if (cursor)
77
+ url.searchParams.set("cursor", cursor);
78
+ const response = await fetchWithTimeout(url.toString(), options);
79
+ if (!response.ok) {
80
+ // No records or repo not found
81
+ if (response.status === 400 || response.status === 404) {
82
+ break;
83
+ }
84
+ throw new Error(`Failed to list records: ${response.status}`);
85
+ }
86
+ const data = (await response.json());
87
+ for (const record of data.records) {
88
+ const rkey = parseAtUriRkey(record.uri);
89
+ claims.push({
90
+ uri: record.uri,
91
+ rkey,
92
+ value: record.value,
93
+ });
94
+ }
95
+ cursor = data.cursor;
96
+ } while (cursor);
97
+ }
98
+ catch (err) {
99
+ // Silently handle errors - return whatever we got
100
+ if (claims.length === 0) {
101
+ throw err;
102
+ }
103
+ }
104
+ return claims;
105
+ }
106
+ /**
107
+ * Fetch a single record by AT URI.
108
+ */
109
+ export async function getRecordByUri(atUri, options) {
110
+ const match = atUri.match(/^at:\/\/([^/]+)\/([^/]+)\/(.+)$/);
111
+ if (!match) {
112
+ throw new Error(`Invalid AT URI: ${atUri}`);
113
+ }
114
+ const [, repo, collection, rkey] = match;
115
+ const pdsUrl = await resolvePds(repo, options);
116
+ const url = new URL(`${pdsUrl}/xrpc/com.atproto.repo.getRecord`);
117
+ url.searchParams.set("repo", repo);
118
+ url.searchParams.set("collection", collection);
119
+ url.searchParams.set("rkey", rkey);
120
+ const response = await fetchWithTimeout(url.toString(), options);
121
+ if (!response.ok) {
122
+ throw new Error(`Failed to fetch record: ${response.status}`);
123
+ }
124
+ const data = (await response.json());
125
+ return data.value;
126
+ }
127
+ /**
128
+ * Parse the rkey from an AT URI.
129
+ */
130
+ function parseAtUriRkey(atUri) {
131
+ const match = atUri.match(/^at:\/\/[^/]+\/[^/]+\/(.+)$/);
132
+ return match?.[1] ?? "";
133
+ }
134
+ //# sourceMappingURL=atproto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"atproto.js","sourceRoot":"","sources":["../src/atproto.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export declare const PUBLIC_API_URL = "https://public.api.bsky.app";
2
+ export declare const PLC_DIRECTORY_URL = "https://plc.directory";
3
+ export declare const COLLECTION_NSID = "dev.keytrace.claim";
4
+ export declare const KEY_COLLECTION_NSID = "dev.keytrace.key";
5
+ export declare const DEFAULT_TIMEOUT = 10000;
6
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc,gCAAgC,CAAC;AAC5D,eAAO,MAAM,iBAAiB,0BAA0B,CAAC;AACzD,eAAO,MAAM,eAAe,uBAAuB,CAAC;AACpD,eAAO,MAAM,mBAAmB,qBAAqB,CAAC;AACtD,eAAO,MAAM,eAAe,QAAQ,CAAC"}
@@ -0,0 +1,6 @@
1
+ export const PUBLIC_API_URL = "https://public.api.bsky.app";
2
+ export const PLC_DIRECTORY_URL = "https://plc.directory";
3
+ export const COLLECTION_NSID = "dev.keytrace.claim";
4
+ export const KEY_COLLECTION_NSID = "dev.keytrace.key";
5
+ export const DEFAULT_TIMEOUT = 10000;
6
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,cAAc,GAAG,6BAA6B,CAAC;AAC5D,MAAM,CAAC,MAAM,iBAAiB,GAAG,uBAAuB,CAAC;AACzD,MAAM,CAAC,MAAM,eAAe,GAAG,oBAAoB,CAAC;AACpD,MAAM,CAAC,MAAM,mBAAmB,GAAG,kBAAkB,CAAC;AACtD,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Base64url decode a string to UTF-8 text.
3
+ */
4
+ export declare function base64urlDecode(str: string): string;
5
+ /**
6
+ * Base64url decode a string to raw bytes.
7
+ */
8
+ export declare function base64urlDecodeToBytes(str: string): Uint8Array;
9
+ //# sourceMappingURL=base64url.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base64url.d.ts","sourceRoot":"","sources":["../../src/crypto/base64url.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAGnD;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAiB9D"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Base64url decode a string to UTF-8 text.
3
+ */
4
+ export function base64urlDecode(str) {
5
+ const bytes = base64urlDecodeToBytes(str);
6
+ return new TextDecoder().decode(bytes);
7
+ }
8
+ /**
9
+ * Base64url decode a string to raw bytes.
10
+ */
11
+ export function base64urlDecodeToBytes(str) {
12
+ // Add padding if needed
13
+ let padded = str;
14
+ const remainder = str.length % 4;
15
+ if (remainder === 2)
16
+ padded += "==";
17
+ else if (remainder === 3)
18
+ padded += "=";
19
+ // Convert URL-safe characters back to standard base64
20
+ const base64 = padded.replace(/-/g, "+").replace(/_/g, "/");
21
+ // Decode - works in both browser and Node.js
22
+ const binary = atob(base64);
23
+ const bytes = new Uint8Array(binary.length);
24
+ for (let i = 0; i < binary.length; i++) {
25
+ bytes[i] = binary.charCodeAt(i);
26
+ }
27
+ return bytes;
28
+ }
29
+ //# sourceMappingURL=base64url.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base64url.js","sourceRoot":"","sources":["../../src/crypto/base64url.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,GAAW;IACzC,MAAM,KAAK,GAAG,sBAAsB,CAAC,GAAG,CAAC,CAAC;IAC1C,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACzC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,sBAAsB,CAAC,GAAW;IAChD,wBAAwB;IACxB,IAAI,MAAM,GAAG,GAAG,CAAC;IACjB,MAAM,SAAS,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;IACjC,IAAI,SAAS,KAAK,CAAC;QAAE,MAAM,IAAI,IAAI,CAAC;SAC/B,IAAI,SAAS,KAAK,CAAC;QAAE,MAAM,IAAI,GAAG,CAAC;IAExC,sDAAsD;IACtD,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAE5D,6CAA6C;IAC7C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5B,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Canonicalize a value according to RFC 8785 (JSON Canonicalization Scheme).
3
+ * https://datatracker.ietf.org/doc/html/rfc8785
4
+ *
5
+ * This ensures deterministic JSON output for cryptographic signing by:
6
+ * - Sorting object keys by UTF-16 code units
7
+ * - Serializing numbers per ES2020 Number.toString() (no -0, no NaN/Infinity)
8
+ * - No optional whitespace
9
+ * - Proper string escaping per RFC 8259
10
+ */
11
+ export declare function canonicalize(data: unknown): string;
12
+ //# sourceMappingURL=canonicalize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonicalize.d.ts","sourceRoot":"","sources":["../../src/crypto/canonicalize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAElD"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Canonicalize a value according to RFC 8785 (JSON Canonicalization Scheme).
3
+ * https://datatracker.ietf.org/doc/html/rfc8785
4
+ *
5
+ * This ensures deterministic JSON output for cryptographic signing by:
6
+ * - Sorting object keys by UTF-16 code units
7
+ * - Serializing numbers per ES2020 Number.toString() (no -0, no NaN/Infinity)
8
+ * - No optional whitespace
9
+ * - Proper string escaping per RFC 8259
10
+ */
11
+ export function canonicalize(data) {
12
+ return serialize(data);
13
+ }
14
+ function serialize(value) {
15
+ if (value === null) {
16
+ return "null";
17
+ }
18
+ switch (typeof value) {
19
+ case "boolean":
20
+ return value ? "true" : "false";
21
+ case "number":
22
+ if (!Number.isFinite(value)) {
23
+ throw new Error("RFC 8785: Cannot serialize Infinity or NaN");
24
+ }
25
+ // RFC 8785 Section 3.2.2.3: -0 must be serialized as 0
26
+ if (Object.is(value, -0)) {
27
+ return "0";
28
+ }
29
+ // Use ES Number.toString() which produces RFC 8785 compliant output
30
+ return String(value);
31
+ case "string":
32
+ // JSON.stringify handles RFC 8259 string escaping
33
+ return JSON.stringify(value);
34
+ case "object":
35
+ if (Array.isArray(value)) {
36
+ return "[" + value.map(serialize).join(",") + "]";
37
+ }
38
+ return serializeObject(value);
39
+ default:
40
+ throw new Error(`RFC 8785: Cannot serialize value of type ${typeof value}`);
41
+ }
42
+ }
43
+ /**
44
+ * Serialize an object with keys sorted by UTF-16 code units per RFC 8785 Section 3.2.3.
45
+ */
46
+ function serializeObject(obj) {
47
+ // RFC 8785: Sort keys by comparing UTF-16 code units
48
+ const keys = Object.keys(obj).sort((a, b) => {
49
+ const len = Math.min(a.length, b.length);
50
+ for (let i = 0; i < len; i++) {
51
+ const diff = a.charCodeAt(i) - b.charCodeAt(i);
52
+ if (diff !== 0)
53
+ return diff;
54
+ }
55
+ return a.length - b.length;
56
+ });
57
+ const pairs = [];
58
+ for (const key of keys) {
59
+ const val = obj[key];
60
+ // Skip undefined values (not valid in JSON)
61
+ if (val !== undefined) {
62
+ pairs.push(JSON.stringify(key) + ":" + serialize(val));
63
+ }
64
+ }
65
+ return "{" + pairs.join(",") + "}";
66
+ }
67
+ //# sourceMappingURL=canonicalize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonicalize.js","sourceRoot":"","sources":["../../src/crypto/canonicalize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,UAAU,YAAY,CAAC,IAAa;IACxC,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC;AACzB,CAAC;AAED,SAAS,SAAS,CAAC,KAAc;IAC/B,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,QAAQ,OAAO,KAAK,EAAE,CAAC;QACrB,KAAK,SAAS;YACZ,OAAO,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;QAElC,KAAK,QAAQ;YACX,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC5B,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;YAChE,CAAC;YACD,uDAAuD;YACvD,IAAI,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACzB,OAAO,GAAG,CAAC;YACb,CAAC;YACD,oEAAoE;YACpE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;QAEvB,KAAK,QAAQ;YACX,kDAAkD;YAClD,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAE/B,KAAK,QAAQ;YACX,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBACzB,OAAO,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;YACpD,CAAC;YACD,OAAO,eAAe,CAAC,KAAgC,CAAC,CAAC;QAE3D;YACE,MAAM,IAAI,KAAK,CAAC,4CAA4C,OAAO,KAAK,EAAE,CAAC,CAAC;IAChF,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,eAAe,CAAC,GAA4B;IACnD,qDAAqD;IACrD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QAC1C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;QACzC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7B,MAAM,IAAI,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YAC/C,IAAI,IAAI,KAAK,CAAC;gBAAE,OAAO,IAAI,CAAC;QAC9B,CAAC;QACD,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7B,CAAC,CAAC,CAAC;IAEH,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QACrB,4CAA4C;QAC5C,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACtB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;IAED,OAAO,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;AACrC,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { ES256PublicJwk, SignedClaimData } from "../types.js";
2
+ /**
3
+ * Verify a JWS ES256 signature using Web Crypto API.
4
+ *
5
+ * @param claimData The claim data that was signed
6
+ * @param jws The JWS compact serialization (header.payload.signature)
7
+ * @param publicJwk The P-256 public key as JWK
8
+ * @returns true if signature is valid, false otherwise
9
+ */
10
+ export declare function verifyES256Signature(claimData: SignedClaimData, jws: string, publicJwk: ES256PublicJwk): Promise<boolean>;
11
+ //# sourceMappingURL=signature.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signature.d.ts","sourceRoot":"","sources":["../../src/crypto/signature.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAInE;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CAAC,SAAS,EAAE,eAAe,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,CAuB/H"}
@@ -0,0 +1,31 @@
1
+ import { canonicalize } from "./canonicalize.js";
2
+ import { base64urlDecode, base64urlDecodeToBytes } from "./base64url.js";
3
+ /**
4
+ * Verify a JWS ES256 signature using Web Crypto API.
5
+ *
6
+ * @param claimData The claim data that was signed
7
+ * @param jws The JWS compact serialization (header.payload.signature)
8
+ * @param publicJwk The P-256 public key as JWK
9
+ * @returns true if signature is valid, false otherwise
10
+ */
11
+ export async function verifyES256Signature(claimData, jws, publicJwk) {
12
+ const parts = jws.split(".");
13
+ if (parts.length !== 3)
14
+ return false;
15
+ const [headerB64, payloadB64, signatureB64] = parts;
16
+ // Verify payload matches expected canonical form
17
+ const expectedPayload = canonicalize(claimData);
18
+ const actualPayload = base64urlDecode(payloadB64);
19
+ if (actualPayload !== expectedPayload)
20
+ return false;
21
+ // Import JWK as CryptoKey
22
+ const key = await crypto.subtle.importKey("jwk", { ...publicJwk, alg: "ES256", use: "sig" }, { name: "ECDSA", namedCurve: "P-256" }, false, ["verify"]);
23
+ // Web Crypto expects raw signature bytes (R||S format) - which is what JWS ES256 uses
24
+ const signatureBytes = base64urlDecodeToBytes(signatureB64);
25
+ const signingInput = new TextEncoder().encode(`${headerB64}.${payloadB64}`);
26
+ // Create a fresh ArrayBuffer to satisfy TypeScript's strict BufferSource type
27
+ const signatureBuffer = new ArrayBuffer(signatureBytes.length);
28
+ new Uint8Array(signatureBuffer).set(signatureBytes);
29
+ return crypto.subtle.verify({ name: "ECDSA", hash: "SHA-256" }, key, signatureBuffer, signingInput);
30
+ }
31
+ //# sourceMappingURL=signature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signature.js","sourceRoot":"","sources":["../../src/crypto/signature.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAEzE;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,SAA0B,EAAE,GAAW,EAAE,SAAyB;IAC3G,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAErC,MAAM,CAAC,SAAS,EAAE,UAAU,EAAE,YAAY,CAAC,GAAG,KAAK,CAAC;IAEpD,iDAAiD;IACjD,MAAM,eAAe,GAAG,YAAY,CAAC,SAA+C,CAAC,CAAC;IACtF,MAAM,aAAa,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;IAClD,IAAI,aAAa,KAAK,eAAe;QAAE,OAAO,KAAK,CAAC;IAEpD,0BAA0B;IAC1B,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,EAAE,GAAG,SAAS,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IAExJ,sFAAsF;IACtF,MAAM,cAAc,GAAG,sBAAsB,CAAC,YAAY,CAAC,CAAC;IAC5D,MAAM,YAAY,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,GAAG,SAAS,IAAI,UAAU,EAAE,CAAC,CAAC;IAE5E,8EAA8E;IAC9E,MAAM,eAAe,GAAG,IAAI,WAAW,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;IAC/D,IAAI,UAAU,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAEpD,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,GAAG,EAAE,eAAe,EAAE,YAAY,CAAC,CAAC;AACtG,CAAC"}
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Identity metadata from a claim record
3
+ */
4
+ export interface ClaimIdentity {
5
+ subject: string;
6
+ avatarUrl?: string;
7
+ profileUrl?: string;
8
+ displayName?: string;
9
+ }
10
+ /**
11
+ * Signature data from a claim record
12
+ */
13
+ export interface ClaimSignature {
14
+ /** Key identifier (YYYY-MM-DD) */
15
+ kid: string;
16
+ /** AT URI to the signing key record */
17
+ src: string;
18
+ /** Timestamp when signed */
19
+ signedAt: string;
20
+ /** JWS compact serialization */
21
+ attestation: string;
22
+ }
23
+ /**
24
+ * Raw claim record from ATProto
25
+ */
26
+ export interface ClaimRecord {
27
+ $type: "dev.keytrace.claim";
28
+ type: string;
29
+ claimUri: string;
30
+ identity: ClaimIdentity;
31
+ sig: ClaimSignature;
32
+ comment?: string;
33
+ createdAt: string;
34
+ prerelease?: boolean;
35
+ }
36
+ /**
37
+ * Public key record from keytrace service
38
+ */
39
+ export interface KeyRecord {
40
+ $type: "dev.keytrace.key";
41
+ publicJwk: string;
42
+ validFrom: string;
43
+ validUntil: string;
44
+ }
45
+ /**
46
+ * Parsed JWK for P-256 public key
47
+ */
48
+ export interface ES256PublicJwk {
49
+ kty: "EC";
50
+ crv: "P-256";
51
+ x: string;
52
+ y: string;
53
+ }
54
+ /**
55
+ * Claim data that is signed (canonical form)
56
+ */
57
+ export interface SignedClaimData {
58
+ did: string;
59
+ subject: string;
60
+ type: string;
61
+ verifiedAt: string;
62
+ }
63
+ /**
64
+ * Verification step detail for debugging/auditing
65
+ */
66
+ export interface VerificationStep {
67
+ step: string;
68
+ success: boolean;
69
+ detail?: string;
70
+ error?: string;
71
+ }
72
+ /**
73
+ * Result of verifying a single claim
74
+ */
75
+ export interface ClaimVerificationResult {
76
+ /** AT URI of the claim record */
77
+ uri: string;
78
+ /** Record key */
79
+ rkey: string;
80
+ /** Claim type (github, dns, etc.) */
81
+ type: string;
82
+ /** The claim URI being verified */
83
+ claimUri: string;
84
+ /** Whether signature verification passed */
85
+ verified: boolean;
86
+ /** Verification steps performed */
87
+ steps: VerificationStep[];
88
+ /** Error message if verification failed */
89
+ error?: string;
90
+ /** Identity data (available regardless of verification status) */
91
+ identity: ClaimIdentity;
92
+ /** Full claim record */
93
+ claim: ClaimRecord;
94
+ }
95
+ /**
96
+ * Result of verifying all claims for a DID
97
+ */
98
+ export interface VerificationResult {
99
+ /** The DID that was verified */
100
+ did: string;
101
+ /** Resolved handle (if available) */
102
+ handle?: string;
103
+ /** Array of claim verification results */
104
+ claims: ClaimVerificationResult[];
105
+ /** Summary statistics */
106
+ summary: {
107
+ total: number;
108
+ verified: number;
109
+ failed: number;
110
+ };
111
+ }
112
+ /**
113
+ * Options for verification
114
+ */
115
+ export interface VerifyOptions {
116
+ /** Custom fetch function (defaults to globalThis.fetch) */
117
+ fetch?: typeof fetch;
118
+ /** Request timeout in ms (default: 10000) */
119
+ timeout?: number;
120
+ /** PLC directory URL (default: https://plc.directory) */
121
+ plcDirectoryUrl?: string;
122
+ /** Public ATProto API URL for handle resolution (default: https://public.api.bsky.app) */
123
+ publicApiUrl?: string;
124
+ }
125
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,19 @@
1
+ import type { VerificationResult, VerifyOptions } from "./types.js";
2
+ export type { ClaimIdentity, ClaimRecord, ClaimSignature, ClaimVerificationResult, ES256PublicJwk, KeyRecord, SignedClaimData, VerificationResult, VerificationStep, VerifyOptions, } from "./types.js";
3
+ /**
4
+ * Verify all keytrace claims for a handle.
5
+ *
6
+ * @param handle The ATProto handle (e.g., "alice.bsky.social") or DID
7
+ * @param options Optional configuration
8
+ * @returns Verification results for all claims
9
+ */
10
+ export declare function getClaimsForHandle(handle: string, options?: VerifyOptions): Promise<VerificationResult>;
11
+ /**
12
+ * Verify all keytrace claims for a DID.
13
+ *
14
+ * @param did The ATProto DID (e.g., "did:plc:abc123")
15
+ * @param options Optional configuration
16
+ * @returns Verification results for all claims
17
+ */
18
+ export declare function getClaimsForDid(did: string, options?: VerifyOptions): Promise<VerificationResult>;
19
+ //# sourceMappingURL=verify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../src/verify.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAoF,kBAAkB,EAAoB,aAAa,EAAE,MAAM,YAAY,CAAC;AAKxK,YAAY,EACV,aAAa,EACb,WAAW,EACX,cAAc,EACd,uBAAuB,EACvB,cAAc,EACd,SAAS,EACT,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,GACd,MAAM,YAAY,CAAC;AAEpB;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAQ7G;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAkCvG"}