@swimmingkiim/trust-sdk 0.1.31 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/credentials/vc-handler.service.d.ts +20 -6
- package/dist/credentials/vc-handler.service.d.ts.map +1 -1
- package/dist/credentials/vc-handler.service.js +58 -34
- package/dist/credentials/vc-handler.service.js.map +1 -1
- package/dist/identity/did-manager.d.ts +20 -3
- package/dist/identity/did-manager.d.ts.map +1 -1
- package/dist/identity/did-manager.js +69 -16
- package/dist/identity/did-manager.js.map +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -17
- package/dist/index.js.map +1 -1
- package/dist/resolver.d.ts +13 -0
- package/dist/resolver.d.ts.map +1 -0
- package/dist/resolver.js +21 -0
- package/dist/resolver.js.map +1 -0
- package/package.json +7 -19
- package/src/credentials/vc-handler.service.ts +65 -38
- package/src/identity/did-manager.ts +89 -17
- package/src/index.ts +5 -3
- package/src/resolver.ts +26 -0
- package/test/identity.security.test.ts +44 -54
- package/test/identity.test.ts +59 -47
- package/test/stateless.test.ts +83 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/src/agent.ts +0 -99
|
@@ -1,10 +1,24 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { Resolver } from 'did-resolver';
|
|
2
|
+
import type { EphemeralIdentity } from '../identity/did-manager';
|
|
3
3
|
export declare class VCHandler {
|
|
4
|
-
private
|
|
5
|
-
constructor(
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
private resolver;
|
|
5
|
+
constructor(resolver?: Resolver);
|
|
6
|
+
/**
|
|
7
|
+
* Creates a Verifiable Credential as a JWT string.
|
|
8
|
+
* Stateless: signs in-memory, no DB storage.
|
|
9
|
+
*
|
|
10
|
+
* @param issuerDid - DID of the issuer
|
|
11
|
+
* @param subjectDid - DID of the subject
|
|
12
|
+
* @param claims - Claims to include in the credential
|
|
13
|
+
* @param keyPair - Signing key pair (from IdentityManager.createEphemeralDID())
|
|
14
|
+
* @returns JWT string
|
|
15
|
+
*/
|
|
16
|
+
createCredential(issuerDid: string, subjectDid: string, claims: Record<string, any>, keyPair?: EphemeralIdentity['keyPair']): Promise<string>;
|
|
17
|
+
/**
|
|
18
|
+
* Verifies a Verifiable Credential JWT.
|
|
19
|
+
* Stateless: resolves issuer DID via blockchain/derivation/web,
|
|
20
|
+
* then verifies the JWT signature. No DB required.
|
|
21
|
+
*/
|
|
8
22
|
verifyCredential(vcJwt: string): Promise<boolean>;
|
|
9
23
|
}
|
|
10
24
|
//# sourceMappingURL=vc-handler.service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vc-handler.service.d.ts","sourceRoot":"","sources":["../../src/credentials/vc-handler.service.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"vc-handler.service.d.ts","sourceRoot":"","sources":["../../src/credentials/vc-handler.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAEvC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AAEhE,qBAAa,SAAS;IAClB,OAAO,CAAC,QAAQ,CAAU;gBAEd,QAAQ,CAAC,EAAE,QAAQ;IAI/B;;;;;;;;;OASG;IACG,gBAAgB,CAClB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC3B,OAAO,CAAC,EAAE,iBAAiB,CAAC,SAAS,CAAC,GACvC,OAAO,CAAC,MAAM,CAAC;IA6BlB;;;;OAIG;IACG,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAwB1D"}
|
|
@@ -1,50 +1,74 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.VCHandler = void 0;
|
|
4
|
-
const
|
|
4
|
+
const did_jwt_vc_1 = require("did-jwt-vc");
|
|
5
|
+
const did_jwt_1 = require("did-jwt");
|
|
6
|
+
const resolver_1 = require("../resolver");
|
|
5
7
|
class VCHandler {
|
|
6
|
-
|
|
7
|
-
constructor(
|
|
8
|
-
this.
|
|
8
|
+
resolver;
|
|
9
|
+
constructor(resolver) {
|
|
10
|
+
this.resolver = resolver ?? (0, resolver_1.createResolver)();
|
|
9
11
|
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Creates a Verifiable Credential as a JWT string.
|
|
14
|
+
* Stateless: signs in-memory, no DB storage.
|
|
15
|
+
*
|
|
16
|
+
* @param issuerDid - DID of the issuer
|
|
17
|
+
* @param subjectDid - DID of the subject
|
|
18
|
+
* @param claims - Claims to include in the credential
|
|
19
|
+
* @param keyPair - Signing key pair (from IdentityManager.createEphemeralDID())
|
|
20
|
+
* @returns JWT string
|
|
21
|
+
*/
|
|
22
|
+
async createCredential(issuerDid, subjectDid, claims, keyPair) {
|
|
23
|
+
if (!keyPair) {
|
|
24
|
+
throw new Error('keyPair is required for credential issuance. Use IdentityManager.createEphemeralDID() to generate one.');
|
|
25
|
+
}
|
|
26
|
+
const signer = (0, did_jwt_1.EdDSASigner)(keyPair.secretKey);
|
|
27
|
+
const vcPayload = {
|
|
28
|
+
sub: subjectDid,
|
|
29
|
+
nbf: Math.floor(Date.now() / 1000),
|
|
30
|
+
vc: {
|
|
31
|
+
'@context': ['https://www.w3.org/2018/credentials/v1'],
|
|
32
|
+
type: ['VerifiableCredential'],
|
|
20
33
|
credentialSubject: {
|
|
21
34
|
id: subjectDid,
|
|
22
|
-
...claims
|
|
23
|
-
}
|
|
35
|
+
...claims,
|
|
36
|
+
},
|
|
24
37
|
},
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
38
|
+
};
|
|
39
|
+
const issuer = {
|
|
40
|
+
did: issuerDid,
|
|
41
|
+
signer,
|
|
42
|
+
alg: 'EdDSA',
|
|
43
|
+
};
|
|
44
|
+
return await (0, did_jwt_vc_1.createVerifiableCredentialJwt)(vcPayload, issuer);
|
|
29
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* Verifies a Verifiable Credential JWT.
|
|
48
|
+
* Stateless: resolves issuer DID via blockchain/derivation/web,
|
|
49
|
+
* then verifies the JWT signature. No DB required.
|
|
50
|
+
*/
|
|
30
51
|
async verifyCredential(vcJwt) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
if (!result.verified) {
|
|
36
|
-
console.error('Credential verification failed:', result.error);
|
|
37
|
-
return false;
|
|
38
|
-
}
|
|
39
|
-
// Explicit expiration check
|
|
40
|
-
if (result.verifiableCredential && result.verifiableCredential.expirationDate) {
|
|
41
|
-
const expirationDate = new Date(result.verifiableCredential.expirationDate);
|
|
42
|
-
if (expirationDate < new Date()) {
|
|
43
|
-
console.error(`Credential expired on ${expirationDate.toISOString()}`);
|
|
52
|
+
try {
|
|
53
|
+
const result = await (0, did_jwt_vc_1.verifyCredential)(vcJwt, this.resolver);
|
|
54
|
+
if (!result.verified) {
|
|
55
|
+
console.error('Credential verification failed:', result);
|
|
44
56
|
return false;
|
|
45
57
|
}
|
|
58
|
+
// Explicit expiration check
|
|
59
|
+
if (result.verifiableCredential?.expirationDate) {
|
|
60
|
+
const expirationDate = new Date(result.verifiableCredential.expirationDate);
|
|
61
|
+
if (expirationDate < new Date()) {
|
|
62
|
+
console.error(`Credential expired on ${expirationDate.toISOString()}`);
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
console.error('VC verification error:', error);
|
|
70
|
+
return false;
|
|
46
71
|
}
|
|
47
|
-
return result.verified;
|
|
48
72
|
}
|
|
49
73
|
}
|
|
50
74
|
exports.VCHandler = VCHandler;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vc-handler.service.js","sourceRoot":"","sources":["../../src/credentials/vc-handler.service.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"vc-handler.service.js","sourceRoot":"","sources":["../../src/credentials/vc-handler.service.ts"],"names":[],"mappings":";;;AAAA,2CAAwF;AACxF,qCAAqC;AAErC,0CAA4C;AAG5C,MAAa,SAAS;IACV,QAAQ,CAAU;IAE1B,YAAY,QAAmB;QAC3B,IAAI,CAAC,QAAQ,GAAG,QAAQ,IAAI,IAAA,yBAAc,GAAE,CAAA;IAChD,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,gBAAgB,CAClB,SAAiB,EACjB,UAAkB,EAClB,MAA2B,EAC3B,OAAsC;QAEtC,IAAI,CAAC,OAAO,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,wGAAwG,CAAC,CAAA;QAC7H,CAAC;QAED,MAAM,MAAM,GAAG,IAAA,qBAAW,EAAC,OAAO,CAAC,SAAS,CAAC,CAAA;QAE7C,MAAM,SAAS,GAAG;YACd,GAAG,EAAE,UAAU;YACf,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;YAClC,EAAE,EAAE;gBACA,UAAU,EAAE,CAAC,wCAAwC,CAAC;gBACtD,IAAI,EAAE,CAAC,sBAAsB,CAAC;gBAC9B,iBAAiB,EAAE;oBACf,EAAE,EAAE,UAAU;oBACd,GAAG,MAAM;iBACZ;aACJ;SACJ,CAAA;QAED,MAAM,MAAM,GAAG;YACX,GAAG,EAAE,SAAS;YACd,MAAM;YACN,GAAG,EAAE,OAAgB;SACxB,CAAA;QAED,OAAO,MAAM,IAAA,0CAA6B,EAAC,SAAS,EAAE,MAAM,CAAC,CAAA;IACjE,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,gBAAgB,CAAC,KAAa;QAChC,IAAI,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,IAAA,6BAAQ,EAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAA;YAEnD,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;gBACnB,OAAO,CAAC,KAAK,CAAC,iCAAiC,EAAE,MAAM,CAAC,CAAA;gBACxD,OAAO,KAAK,CAAA;YAChB,CAAC;YAED,4BAA4B;YAC5B,IAAI,MAAM,CAAC,oBAAoB,EAAE,cAAc,EAAE,CAAC;gBAC9C,MAAM,cAAc,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC,cAAc,CAAC,CAAA;gBAC3E,IAAI,cAAc,GAAG,IAAI,IAAI,EAAE,EAAE,CAAC;oBAC9B,OAAO,CAAC,KAAK,CAAC,yBAAyB,cAAc,CAAC,WAAW,EAAE,EAAE,CAAC,CAAA;oBACtE,OAAO,KAAK,CAAA;gBAChB,CAAC;YACL,CAAC;YAED,OAAO,IAAI,CAAA;QACf,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,wBAAwB,EAAE,KAAK,CAAC,CAAA;YAC9C,OAAO,KAAK,CAAA;QAChB,CAAC;IACL,CAAC;CACJ;AAhFD,8BAgFC"}
|
|
@@ -1,6 +1,23 @@
|
|
|
1
|
+
import { Resolver } from 'did-resolver';
|
|
2
|
+
export interface EphemeralIdentity {
|
|
3
|
+
did: string;
|
|
4
|
+
keyPair: {
|
|
5
|
+
publicKey: Uint8Array;
|
|
6
|
+
secretKey: Uint8Array;
|
|
7
|
+
};
|
|
8
|
+
}
|
|
1
9
|
export declare class IdentityManager {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
10
|
+
private resolver;
|
|
11
|
+
constructor(resolver?: Resolver);
|
|
12
|
+
/**
|
|
13
|
+
* Creates an ephemeral (in-memory) did:key identity.
|
|
14
|
+
* Uses Node.js built-in crypto — no external dependencies, no database.
|
|
15
|
+
*/
|
|
16
|
+
createEphemeralDID(): Promise<EphemeralIdentity>;
|
|
17
|
+
/**
|
|
18
|
+
* Resolves a DID to its DID Document.
|
|
19
|
+
* Stateless: uses blockchain (did:ethr) or derivation (did:key).
|
|
20
|
+
*/
|
|
21
|
+
resolveDID(did: string): Promise<any>;
|
|
5
22
|
}
|
|
6
23
|
//# sourceMappingURL=did-manager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"did-manager.d.ts","sourceRoot":"","sources":["../../src/identity/did-manager.ts"],"names":[],"mappings":"AAEA,qBAAa,eAAe;
|
|
1
|
+
{"version":3,"file":"did-manager.d.ts","sourceRoot":"","sources":["../../src/identity/did-manager.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAEvC,MAAM,WAAW,iBAAiB;IAC9B,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,EAAE;QACL,SAAS,EAAE,UAAU,CAAA;QACrB,SAAS,EAAE,UAAU,CAAA;KACxB,CAAA;CACJ;AAgDD,qBAAa,eAAe;IACxB,OAAO,CAAC,QAAQ,CAAU;gBAEd,QAAQ,CAAC,EAAE,QAAQ;IAI/B;;;OAGG;IACG,kBAAkB,IAAI,OAAO,CAAC,iBAAiB,CAAC;IAoBtD;;;OAGG;IACG,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;CAG9C"}
|
|
@@ -1,26 +1,79 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.IdentityManager = void 0;
|
|
4
|
-
const
|
|
7
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
8
|
+
const resolver_1 = require("../resolver");
|
|
9
|
+
// Ed25519 multicodec prefix (0xed01)
|
|
10
|
+
const ED25519_MULTICODEC_PREFIX = new Uint8Array([0xed, 0x01]);
|
|
11
|
+
// Base58btc alphabet (Bitcoin alphabet)
|
|
12
|
+
const BASE58_ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
|
|
13
|
+
/**
|
|
14
|
+
* Encodes a Uint8Array to base58btc string.
|
|
15
|
+
* Pure implementation with no external dependencies.
|
|
16
|
+
*/
|
|
17
|
+
function base58btcEncode(bytes) {
|
|
18
|
+
// Count leading zeros
|
|
19
|
+
let leadingZeros = 0;
|
|
20
|
+
for (let i = 0; i < bytes.length && bytes[i] === 0; i++) {
|
|
21
|
+
leadingZeros++;
|
|
22
|
+
}
|
|
23
|
+
// Convert to BigInt for base conversion
|
|
24
|
+
let num = BigInt('0x' + Buffer.from(bytes).toString('hex'));
|
|
25
|
+
const chars = [];
|
|
26
|
+
while (num > 0n) {
|
|
27
|
+
const remainder = Number(num % 58n);
|
|
28
|
+
chars.unshift(BASE58_ALPHABET[remainder]);
|
|
29
|
+
num = num / 58n;
|
|
30
|
+
}
|
|
31
|
+
// Add '1' for each leading zero byte
|
|
32
|
+
for (let i = 0; i < leadingZeros; i++) {
|
|
33
|
+
chars.unshift('1');
|
|
34
|
+
}
|
|
35
|
+
return chars.join('');
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Encodes an Ed25519 public key as a did:key identifier.
|
|
39
|
+
* Format: did:key:z + base58btc(multicodec_prefix + public_key)
|
|
40
|
+
*/
|
|
41
|
+
function publicKeyToDidKey(publicKey) {
|
|
42
|
+
const multicodecKey = new Uint8Array(ED25519_MULTICODEC_PREFIX.length + publicKey.length);
|
|
43
|
+
multicodecKey.set(ED25519_MULTICODEC_PREFIX);
|
|
44
|
+
multicodecKey.set(publicKey, ED25519_MULTICODEC_PREFIX.length);
|
|
45
|
+
return `did:key:z${base58btcEncode(multicodecKey)}`;
|
|
46
|
+
}
|
|
5
47
|
class IdentityManager {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
provider: 'did:key'
|
|
10
|
-
});
|
|
11
|
-
return identifier;
|
|
48
|
+
resolver;
|
|
49
|
+
constructor(resolver) {
|
|
50
|
+
this.resolver = resolver ?? (0, resolver_1.createResolver)();
|
|
12
51
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
});
|
|
19
|
-
|
|
52
|
+
/**
|
|
53
|
+
* Creates an ephemeral (in-memory) did:key identity.
|
|
54
|
+
* Uses Node.js built-in crypto — no external dependencies, no database.
|
|
55
|
+
*/
|
|
56
|
+
async createEphemeralDID() {
|
|
57
|
+
const { publicKey, privateKey } = crypto_1.default.generateKeyPairSync('ed25519');
|
|
58
|
+
// Export raw key bytes from DER format
|
|
59
|
+
const pubDer = publicKey.export({ type: 'spki', format: 'der' });
|
|
60
|
+
const privDer = privateKey.export({ type: 'pkcs8', format: 'der' });
|
|
61
|
+
// Ed25519 SPKI DER: 12-byte header + 32-byte key
|
|
62
|
+
const rawPublicKey = new Uint8Array(pubDer.subarray(pubDer.length - 32));
|
|
63
|
+
// Ed25519 PKCS8 DER: 16-byte header + 32-byte key
|
|
64
|
+
const rawSecretKey = new Uint8Array(privDer.subarray(privDer.length - 32));
|
|
65
|
+
const did = publicKeyToDidKey(rawPublicKey);
|
|
66
|
+
return {
|
|
67
|
+
did,
|
|
68
|
+
keyPair: { publicKey: rawPublicKey, secretKey: rawSecretKey },
|
|
69
|
+
};
|
|
20
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* Resolves a DID to its DID Document.
|
|
73
|
+
* Stateless: uses blockchain (did:ethr) or derivation (did:key).
|
|
74
|
+
*/
|
|
21
75
|
async resolveDID(did) {
|
|
22
|
-
|
|
23
|
-
return await agent.resolveDid({ didUrl: did });
|
|
76
|
+
return await this.resolver.resolve(did);
|
|
24
77
|
}
|
|
25
78
|
}
|
|
26
79
|
exports.IdentityManager = IdentityManager;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"did-manager.js","sourceRoot":"","sources":["../../src/identity/did-manager.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"did-manager.js","sourceRoot":"","sources":["../../src/identity/did-manager.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export
|
|
1
|
+
export { IdentityManager } from './identity/did-manager';
|
|
2
|
+
export type { EphemeralIdentity } from './identity/did-manager';
|
|
3
|
+
export { VCHandler } from './credentials/vc-handler.service';
|
|
4
|
+
export { createResolver } from './resolver';
|
|
5
|
+
export type { ResolverOptions } from './resolver';
|
|
4
6
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACxD,YAAY,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAA;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAC3C,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,20 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
3
|
+
exports.createResolver = exports.VCHandler = exports.IdentityManager = void 0;
|
|
4
|
+
var did_manager_1 = require("./identity/did-manager");
|
|
5
|
+
Object.defineProperty(exports, "IdentityManager", { enumerable: true, get: function () { return did_manager_1.IdentityManager; } });
|
|
6
|
+
var vc_handler_service_1 = require("./credentials/vc-handler.service");
|
|
7
|
+
Object.defineProperty(exports, "VCHandler", { enumerable: true, get: function () { return vc_handler_service_1.VCHandler; } });
|
|
8
|
+
var resolver_1 = require("./resolver");
|
|
9
|
+
Object.defineProperty(exports, "createResolver", { enumerable: true, get: function () { return resolver_1.createResolver; } });
|
|
20
10
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,sDAAwD;AAA/C,8GAAA,eAAe,OAAA;AAExB,uEAA4D;AAAnD,+GAAA,SAAS,OAAA;AAClB,uCAA2C;AAAlC,0GAAA,cAAc,OAAA"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Resolver } from 'did-resolver';
|
|
2
|
+
export interface ResolverOptions {
|
|
3
|
+
/** Ethereum network name for did:ethr (default: 'base') */
|
|
4
|
+
ethNetwork?: string;
|
|
5
|
+
/** RPC URL for did:ethr resolution */
|
|
6
|
+
rpcUrl?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Creates a stateless DID Resolver.
|
|
10
|
+
* No database, no state — only blockchain/key-based resolution.
|
|
11
|
+
*/
|
|
12
|
+
export declare function createResolver(options?: ResolverOptions): Resolver;
|
|
13
|
+
//# sourceMappingURL=resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../src/resolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAIvC,MAAM,WAAW,eAAe;IAC5B,2DAA2D;IAC3D,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,sCAAsC;IACtC,MAAM,CAAC,EAAE,MAAM,CAAA;CAClB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,QAAQ,CAUlE"}
|
package/dist/resolver.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createResolver = createResolver;
|
|
4
|
+
const did_resolver_1 = require("did-resolver");
|
|
5
|
+
const key_did_resolver_1 = require("key-did-resolver");
|
|
6
|
+
const ethr_did_resolver_1 = require("ethr-did-resolver");
|
|
7
|
+
/**
|
|
8
|
+
* Creates a stateless DID Resolver.
|
|
9
|
+
* No database, no state — only blockchain/key-based resolution.
|
|
10
|
+
*/
|
|
11
|
+
function createResolver(options) {
|
|
12
|
+
const ethNetwork = options?.ethNetwork || 'base';
|
|
13
|
+
const rpcUrl = options?.rpcUrl || 'https://mainnet.base.org';
|
|
14
|
+
return new did_resolver_1.Resolver({
|
|
15
|
+
...(0, key_did_resolver_1.getResolver)(),
|
|
16
|
+
...(0, ethr_did_resolver_1.getResolver)({
|
|
17
|
+
networks: [{ name: ethNetwork, rpcUrl }],
|
|
18
|
+
}),
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.js","sourceRoot":"","sources":["../src/resolver.ts"],"names":[],"mappings":";;AAeA,wCAUC;AAzBD,+CAAuC;AACvC,uDAAgE;AAChE,yDAAkE;AASlE;;;GAGG;AACH,SAAgB,cAAc,CAAC,OAAyB;IACpD,MAAM,UAAU,GAAG,OAAO,EAAE,UAAU,IAAI,MAAM,CAAA;IAChD,MAAM,MAAM,GAAG,OAAO,EAAE,MAAM,IAAI,0BAA0B,CAAA;IAE5D,OAAO,IAAI,uBAAQ,CAAC;QAChB,GAAG,IAAA,8BAAc,GAAE;QACnB,GAAG,IAAA,+BAAe,EAAC;YACf,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;SAC3C,CAAC;KACL,CAAC,CAAA;AACN,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@swimmingkiim/trust-sdk",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/swimmingkiim/a2a-project.git"
|
|
@@ -15,31 +15,19 @@
|
|
|
15
15
|
}
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"@veramo/data-store": "^6.0.2",
|
|
21
|
-
"@veramo/did-manager": "^6.0.2",
|
|
22
|
-
"@veramo/did-provider-ethr": "^6.0.2",
|
|
23
|
-
"@veramo/did-provider-key": "^6.0.2",
|
|
24
|
-
"@veramo/did-resolver": "^6.0.2",
|
|
25
|
-
"@veramo/key-manager": "^6.0.2",
|
|
26
|
-
"@veramo/kms-local": "^6.0.2",
|
|
27
|
-
"did-jwt-vc": "^3.2.0",
|
|
18
|
+
"did-jwt": "^8.0.9",
|
|
19
|
+
"did-jwt-vc": "^4.0.8",
|
|
28
20
|
"did-resolver": "^4.1.0",
|
|
29
|
-
"ethers": "^6.11.1",
|
|
30
21
|
"ethr-did-resolver": "^11.0.5",
|
|
31
|
-
"key-did-resolver": "^4.0.0"
|
|
32
|
-
"reflect-metadata": "^0.2.2",
|
|
33
|
-
"sqlite3": "^5.1.7",
|
|
34
|
-
"ts-node": "^10.9.2",
|
|
35
|
-
"typeorm": "^0.3.28"
|
|
22
|
+
"key-did-resolver": "^4.0.0"
|
|
36
23
|
},
|
|
37
24
|
"devDependencies": {
|
|
38
25
|
"tsx": "^4.21.0",
|
|
39
|
-
"typescript": "^5.3.3"
|
|
26
|
+
"typescript": "^5.3.3",
|
|
27
|
+
"vitest": "^4.0.18"
|
|
40
28
|
},
|
|
41
29
|
"scripts": {
|
|
42
30
|
"build": "tsc",
|
|
43
|
-
"test": "
|
|
31
|
+
"test": "vitest run"
|
|
44
32
|
}
|
|
45
33
|
}
|
|
@@ -1,60 +1,87 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { createVerifiableCredentialJwt, verifyCredential as verifyVC } from 'did-jwt-vc'
|
|
2
|
+
import { EdDSASigner } from 'did-jwt'
|
|
3
|
+
import { Resolver } from 'did-resolver'
|
|
4
|
+
import { createResolver } from '../resolver'
|
|
5
|
+
import type { EphemeralIdentity } from '../identity/did-manager'
|
|
3
6
|
|
|
4
7
|
export class VCHandler {
|
|
5
|
-
private
|
|
8
|
+
private resolver: Resolver
|
|
6
9
|
|
|
7
|
-
constructor(
|
|
8
|
-
this.
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
private async getAgent(): Promise<Agent> {
|
|
12
|
-
if (this.agent) return this.agent
|
|
13
|
-
return await initAgent()
|
|
10
|
+
constructor(resolver?: Resolver) {
|
|
11
|
+
this.resolver = resolver ?? createResolver()
|
|
14
12
|
}
|
|
15
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Creates a Verifiable Credential as a JWT string.
|
|
16
|
+
* Stateless: signs in-memory, no DB storage.
|
|
17
|
+
*
|
|
18
|
+
* @param issuerDid - DID of the issuer
|
|
19
|
+
* @param subjectDid - DID of the subject
|
|
20
|
+
* @param claims - Claims to include in the credential
|
|
21
|
+
* @param keyPair - Signing key pair (from IdentityManager.createEphemeralDID())
|
|
22
|
+
* @returns JWT string
|
|
23
|
+
*/
|
|
16
24
|
async createCredential(
|
|
17
25
|
issuerDid: string,
|
|
18
26
|
subjectDid: string,
|
|
19
|
-
claims: Record<string, any
|
|
20
|
-
|
|
21
|
-
|
|
27
|
+
claims: Record<string, any>,
|
|
28
|
+
keyPair?: EphemeralIdentity['keyPair']
|
|
29
|
+
): Promise<string> {
|
|
30
|
+
if (!keyPair) {
|
|
31
|
+
throw new Error('keyPair is required for credential issuance. Use IdentityManager.createEphemeralDID() to generate one.')
|
|
32
|
+
}
|
|
22
33
|
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
34
|
+
const signer = EdDSASigner(keyPair.secretKey)
|
|
35
|
+
|
|
36
|
+
const vcPayload = {
|
|
37
|
+
sub: subjectDid,
|
|
38
|
+
nbf: Math.floor(Date.now() / 1000),
|
|
39
|
+
vc: {
|
|
40
|
+
'@context': ['https://www.w3.org/2018/credentials/v1'],
|
|
41
|
+
type: ['VerifiableCredential'],
|
|
26
42
|
credentialSubject: {
|
|
27
43
|
id: subjectDid,
|
|
28
|
-
...claims
|
|
29
|
-
}
|
|
44
|
+
...claims,
|
|
45
|
+
},
|
|
30
46
|
},
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const issuer = {
|
|
50
|
+
did: issuerDid,
|
|
51
|
+
signer,
|
|
52
|
+
alg: 'EdDSA' as const,
|
|
53
|
+
}
|
|
34
54
|
|
|
35
|
-
return
|
|
55
|
+
return await createVerifiableCredentialJwt(vcPayload, issuer)
|
|
36
56
|
}
|
|
37
57
|
|
|
58
|
+
/**
|
|
59
|
+
* Verifies a Verifiable Credential JWT.
|
|
60
|
+
* Stateless: resolves issuer DID via blockchain/derivation/web,
|
|
61
|
+
* then verifies the JWT signature. No DB required.
|
|
62
|
+
*/
|
|
38
63
|
async verifyCredential(vcJwt: string): Promise<boolean> {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
credential: vcJwt
|
|
42
|
-
})
|
|
64
|
+
try {
|
|
65
|
+
const result = await verifyVC(vcJwt, this.resolver)
|
|
43
66
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
return false
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Explicit expiration check
|
|
50
|
-
if (result.verifiableCredential && result.verifiableCredential.expirationDate) {
|
|
51
|
-
const expirationDate = new Date(result.verifiableCredential.expirationDate)
|
|
52
|
-
if (expirationDate < new Date()) {
|
|
53
|
-
console.error(`Credential expired on ${expirationDate.toISOString()}`)
|
|
67
|
+
if (!result.verified) {
|
|
68
|
+
console.error('Credential verification failed:', result)
|
|
54
69
|
return false
|
|
55
70
|
}
|
|
56
|
-
}
|
|
57
71
|
|
|
58
|
-
|
|
72
|
+
// Explicit expiration check
|
|
73
|
+
if (result.verifiableCredential?.expirationDate) {
|
|
74
|
+
const expirationDate = new Date(result.verifiableCredential.expirationDate)
|
|
75
|
+
if (expirationDate < new Date()) {
|
|
76
|
+
console.error(`Credential expired on ${expirationDate.toISOString()}`)
|
|
77
|
+
return false
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return true
|
|
82
|
+
} catch (error) {
|
|
83
|
+
console.error('VC verification error:', error)
|
|
84
|
+
return false
|
|
85
|
+
}
|
|
59
86
|
}
|
|
60
87
|
}
|