-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathverify.ts
More file actions
73 lines (66 loc) · 2.46 KB
/
Copy pathverify.ts
File metadata and controls
73 lines (66 loc) · 2.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#!/usr/bin/env npx tsx
/**
* KYA-OS Proof Verification Example
*
* Verifies a DetachedProof JSON from stdin or a file argument: resolves the
* signer's DID, checks the JWS signature, nonce-replay, and timestamp skew.
* (To additionally detect content substitution — e.g. a swapped consent URL —
* verify with the received request/response; see anti-mitm-demo.ts.)
*
* Usage:
* echo '{"jws":"...","meta":{...}}' | npx tsx examples/verify-proof/verify.ts
* npx tsx examples/verify-proof/verify.ts proof.json
*/
import { readFileSync } from 'node:fs';
import {
ProofVerifier,
NodeCryptoProvider,
MemoryNonceCacheProvider,
SystemClockProvider,
RuntimeFetchProvider,
type DetachedProof,
} from '@kya-os/mcp';
async function main() {
let input: string;
if (process.argv[2]) {
input = readFileSync(process.argv[2], 'utf-8');
} else if (!process.stdin.isTTY) {
const chunks: Buffer[] = [];
for await (const chunk of process.stdin) {
chunks.push(chunk as Buffer);
}
input = Buffer.concat(chunks).toString('utf-8');
} else {
console.error('Usage: npx tsx verify.ts <proof.json> (or pipe the proof JSON on stdin)');
process.exit(1);
}
const proof = JSON.parse(input) as DetachedProof;
console.log('Proof DID: ', proof.meta?.did);
console.log('Key ID: ', proof.meta?.kid);
console.log('Session: ', proof.meta?.sessionId);
console.log('Outcome: ', proof.meta?.outcome ?? 'allowed (success)');
console.log('Timestamp: ', new Date((proof.meta?.ts ?? 0) * 1000).toISOString());
const verifier = new ProofVerifier({
cryptoProvider: new NodeCryptoProvider(),
clockProvider: new SystemClockProvider(),
nonceCacheProvider: new MemoryNonceCacheProvider(),
fetchProvider: new RuntimeFetchProvider(),
timestampSkewSeconds: 300, // generous for offline verification
});
// Resolve the signer's public key from its DID (did:key resolved offline).
const jwk = await verifier.fetchPublicKeyFromDID(proof.meta.did);
if (!jwk) {
console.log('\nVerification result: INVALID (could not resolve signer DID)');
process.exit(1);
}
const result = await verifier.verifyProof(proof, jwk);
console.log('\nVerification result:', result.valid ? 'VALID' : 'INVALID');
if (!result.valid) {
console.log('Reason:', result.errorCode, '-', result.reason);
process.exit(1);
}
}
main().catch((err) => {
console.error('Error:', err instanceof Error ? err.message : String(err));
process.exit(1);
});