@vess-id/ai-identity 0.0.1 → 0.0.2
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 +33 -12
- package/dist/index.d.mts +3004 -0
- package/dist/index.d.ts +3004 -0
- package/dist/index.js +266 -54
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +261 -54
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -2
package/dist/index.js
CHANGED
|
@@ -57,15 +57,20 @@ __export(index_exports, {
|
|
|
57
57
|
checkPermissionWithVP: () => checkPermissionWithVP,
|
|
58
58
|
configure: () => configure,
|
|
59
59
|
createAjv: () => createAjv,
|
|
60
|
+
createDidJwk: () => createDidJwk,
|
|
60
61
|
defaultConstraintEvaluator: () => defaultConstraintEvaluator,
|
|
61
62
|
evaluateConstraints: () => evaluateConstraints,
|
|
63
|
+
extractPublicKey: () => extractPublicKey,
|
|
64
|
+
extractPublicKeyFromDid: () => extractPublicKeyFromDid,
|
|
62
65
|
generateKeyPair: () => generateKeyPair,
|
|
63
66
|
generateNonce: () => generateNonce,
|
|
64
67
|
getClient: () => getClient,
|
|
68
|
+
getKeyIdFromDid: () => getKeyIdFromDid,
|
|
65
69
|
getRequiredRelations: () => getRequiredRelations,
|
|
66
70
|
getRequiredScopes: () => getRequiredScopes,
|
|
67
71
|
indexActions: () => indexActions,
|
|
68
72
|
indexCapabilities: () => indexCapabilities,
|
|
73
|
+
isValidDidJwk: () => isValidDidJwk,
|
|
69
74
|
loadActionRegistryFromFile: () => loadActionRegistryFromFile,
|
|
70
75
|
loadActionRegistryFromObject: () => loadActionRegistryFromObject,
|
|
71
76
|
planDelegationForVC: () => planDelegationForVC,
|
|
@@ -427,7 +432,51 @@ async function getVerifier(publicKey) {
|
|
|
427
432
|
};
|
|
428
433
|
}
|
|
429
434
|
|
|
435
|
+
// src/did/did-utils.ts
|
|
436
|
+
function createDidJwk(publicKey) {
|
|
437
|
+
const publicJwk = {
|
|
438
|
+
kty: publicKey.kty,
|
|
439
|
+
crv: publicKey.crv,
|
|
440
|
+
x: publicKey.x,
|
|
441
|
+
y: publicKey.y,
|
|
442
|
+
use: publicKey.use,
|
|
443
|
+
alg: publicKey.alg
|
|
444
|
+
};
|
|
445
|
+
const cleanedJwk = Object.fromEntries(
|
|
446
|
+
Object.entries(publicJwk).filter(([_, v]) => v !== void 0)
|
|
447
|
+
);
|
|
448
|
+
const encoded = Buffer.from(JSON.stringify(cleanedJwk)).toString("base64url");
|
|
449
|
+
return `did:jwk:${encoded}`;
|
|
450
|
+
}
|
|
451
|
+
function extractPublicKey(privateKey) {
|
|
452
|
+
const { d, key_ops, ...publicKey } = privateKey;
|
|
453
|
+
return publicKey;
|
|
454
|
+
}
|
|
455
|
+
function extractPublicKeyFromDid(did) {
|
|
456
|
+
if (!did.startsWith("did:jwk:")) {
|
|
457
|
+
throw new Error("Only did:jwk format is supported");
|
|
458
|
+
}
|
|
459
|
+
const encoded = did.replace("did:jwk:", "");
|
|
460
|
+
return JSON.parse(Buffer.from(encoded, "base64url").toString());
|
|
461
|
+
}
|
|
462
|
+
function isValidDidJwk(did) {
|
|
463
|
+
if (!did.startsWith("did:jwk:")) {
|
|
464
|
+
return false;
|
|
465
|
+
}
|
|
466
|
+
try {
|
|
467
|
+
const encoded = did.replace("did:jwk:", "");
|
|
468
|
+
const decoded = JSON.parse(Buffer.from(encoded, "base64url").toString());
|
|
469
|
+
return typeof decoded === "object" && decoded.kty !== void 0;
|
|
470
|
+
} catch {
|
|
471
|
+
return false;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
function getKeyIdFromDid(did) {
|
|
475
|
+
return `${did}#0`;
|
|
476
|
+
}
|
|
477
|
+
|
|
430
478
|
// src/utils/sdjwt-client.ts
|
|
479
|
+
var import_node_crypto2 = require("crypto");
|
|
431
480
|
var SDJwtClient = class {
|
|
432
481
|
static instances = /* @__PURE__ */ new Map();
|
|
433
482
|
static keyManager;
|
|
@@ -632,6 +681,212 @@ var SDJwtClient = class {
|
|
|
632
681
|
verifierCount: this.verifierCache.size
|
|
633
682
|
};
|
|
634
683
|
}
|
|
684
|
+
/**
|
|
685
|
+
* Create a verifier function from an external public key
|
|
686
|
+
* This is used for verifying SD-JWTs when you don't have the private key
|
|
687
|
+
* (e.g., API side verifying credentials issued by MCP)
|
|
688
|
+
*/
|
|
689
|
+
static async getVerifierFromPublicKey(publicKey) {
|
|
690
|
+
const key = await import_node_crypto2.subtle.importKey(
|
|
691
|
+
"jwk",
|
|
692
|
+
publicKey,
|
|
693
|
+
{
|
|
694
|
+
name: "ECDSA",
|
|
695
|
+
namedCurve: "P-256"
|
|
696
|
+
},
|
|
697
|
+
true,
|
|
698
|
+
["verify"]
|
|
699
|
+
);
|
|
700
|
+
return async (data, signatureBase64url) => {
|
|
701
|
+
const encoder = new TextEncoder();
|
|
702
|
+
const signature = Uint8Array.from(
|
|
703
|
+
atob(signatureBase64url.replace(/-/g, "+").replace(/_/g, "/")),
|
|
704
|
+
(c) => c.charCodeAt(0)
|
|
705
|
+
);
|
|
706
|
+
const isValid = await import_node_crypto2.subtle.verify(
|
|
707
|
+
{
|
|
708
|
+
name: "ECDSA",
|
|
709
|
+
hash: { name: "SHA-256" }
|
|
710
|
+
},
|
|
711
|
+
key,
|
|
712
|
+
signature,
|
|
713
|
+
encoder.encode(data)
|
|
714
|
+
);
|
|
715
|
+
return isValid;
|
|
716
|
+
};
|
|
717
|
+
}
|
|
718
|
+
/**
|
|
719
|
+
* Get SDJwtVcInstance for verification with an external public key
|
|
720
|
+
* Used when verifying credentials without having the issuer's private key
|
|
721
|
+
*/
|
|
722
|
+
static async getVerificationInstance(publicKey) {
|
|
723
|
+
const cacheKey = `verify:${JSON.stringify(publicKey)}`;
|
|
724
|
+
if (!this.instances.has(cacheKey)) {
|
|
725
|
+
const dummySigner = async () => "dummy";
|
|
726
|
+
const verifier = await this.getVerifierFromPublicKey(publicKey);
|
|
727
|
+
const instance = new import_sd_jwt_vc.SDJwtVcInstance({
|
|
728
|
+
signer: dummySigner,
|
|
729
|
+
verifier,
|
|
730
|
+
signAlg: import_crypto_nodejs.ES256.alg,
|
|
731
|
+
hasher: import_crypto_nodejs.digest,
|
|
732
|
+
hashAlg: "sha-256",
|
|
733
|
+
saltGenerator: import_crypto_nodejs.generateSalt
|
|
734
|
+
});
|
|
735
|
+
this.instances.set(cacheKey, instance);
|
|
736
|
+
}
|
|
737
|
+
return this.instances.get(cacheKey);
|
|
738
|
+
}
|
|
739
|
+
/**
|
|
740
|
+
* Get SDJwtVcInstance for decoding without verification
|
|
741
|
+
*/
|
|
742
|
+
static async getDecodingInstance() {
|
|
743
|
+
const cacheKey = "decode:dummy";
|
|
744
|
+
if (!this.instances.has(cacheKey)) {
|
|
745
|
+
const dummySigner = async () => "dummy";
|
|
746
|
+
const dummyVerifier = async () => false;
|
|
747
|
+
const instance = new import_sd_jwt_vc.SDJwtVcInstance({
|
|
748
|
+
signer: dummySigner,
|
|
749
|
+
verifier: dummyVerifier,
|
|
750
|
+
signAlg: import_crypto_nodejs.ES256.alg,
|
|
751
|
+
hasher: import_crypto_nodejs.digest,
|
|
752
|
+
hashAlg: "sha-256",
|
|
753
|
+
saltGenerator: import_crypto_nodejs.generateSalt
|
|
754
|
+
});
|
|
755
|
+
this.instances.set(cacheKey, instance);
|
|
756
|
+
}
|
|
757
|
+
return this.instances.get(cacheKey);
|
|
758
|
+
}
|
|
759
|
+
/**
|
|
760
|
+
* Verify an SD-JWT with an external public key
|
|
761
|
+
* Use this when you have the issuer's public key but not their private key
|
|
762
|
+
*
|
|
763
|
+
* @param credential - The SD-JWT credential string
|
|
764
|
+
* @param publicKey - The issuer's public key (JWK format)
|
|
765
|
+
* @returns Verification result with valid flag and payload
|
|
766
|
+
*
|
|
767
|
+
* @example
|
|
768
|
+
* ```typescript
|
|
769
|
+
* const publicKey = extractPublicKeyFromDid(issuerDid)
|
|
770
|
+
* const result = await SDJwtClient.verifyWithExternalKey(credential, publicKey)
|
|
771
|
+
* if (result.valid) {
|
|
772
|
+
* console.log('Verified claims:', result.payload.claims)
|
|
773
|
+
* }
|
|
774
|
+
* ```
|
|
775
|
+
*/
|
|
776
|
+
static async verifyWithExternalKey(credential, publicKey) {
|
|
777
|
+
try {
|
|
778
|
+
const sdJwtInstance = await this.getVerificationInstance(publicKey);
|
|
779
|
+
const verificationResult = await sdJwtInstance.verify(credential, {});
|
|
780
|
+
if (!verificationResult) {
|
|
781
|
+
return { valid: false, error: "Verification failed" };
|
|
782
|
+
}
|
|
783
|
+
const claims = await sdJwtInstance.getClaims(credential);
|
|
784
|
+
return {
|
|
785
|
+
valid: true,
|
|
786
|
+
payload: verificationResult.payload,
|
|
787
|
+
claims
|
|
788
|
+
};
|
|
789
|
+
} catch (error) {
|
|
790
|
+
return {
|
|
791
|
+
valid: false,
|
|
792
|
+
error: error.message
|
|
793
|
+
};
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
/**
|
|
797
|
+
* Verify an SD-JWT by extracting the issuer's public key from the DID
|
|
798
|
+
* Automatically resolves did:jwk DIDs
|
|
799
|
+
*
|
|
800
|
+
* @param credential - The SD-JWT credential string
|
|
801
|
+
* @returns Verification result with valid flag and payload
|
|
802
|
+
*
|
|
803
|
+
* @example
|
|
804
|
+
* ```typescript
|
|
805
|
+
* const result = await SDJwtClient.verifyWithIssuerDid(credential)
|
|
806
|
+
* if (result.valid) {
|
|
807
|
+
* console.log('Issuer:', result.payload.iss)
|
|
808
|
+
* }
|
|
809
|
+
* ```
|
|
810
|
+
*/
|
|
811
|
+
static async verifyWithIssuerDid(credential) {
|
|
812
|
+
try {
|
|
813
|
+
const decoded = await this.decodeWithoutVerification(credential);
|
|
814
|
+
if (!decoded.payload) {
|
|
815
|
+
return { valid: false, error: "Failed to decode credential" };
|
|
816
|
+
}
|
|
817
|
+
const issuerDid = decoded.payload.iss || decoded.payload.issuer;
|
|
818
|
+
if (!issuerDid || typeof issuerDid !== "string") {
|
|
819
|
+
return { valid: false, error: "Issuer DID not found in credential" };
|
|
820
|
+
}
|
|
821
|
+
const publicKey = extractPublicKeyFromDid(issuerDid);
|
|
822
|
+
const result = await this.verifyWithExternalKey(credential, publicKey);
|
|
823
|
+
return {
|
|
824
|
+
...result,
|
|
825
|
+
issuerDid
|
|
826
|
+
};
|
|
827
|
+
} catch (error) {
|
|
828
|
+
return {
|
|
829
|
+
valid: false,
|
|
830
|
+
error: error.message
|
|
831
|
+
};
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
/**
|
|
835
|
+
* Decode an SD-JWT without verification
|
|
836
|
+
* Use this when you need to inspect the credential before verification
|
|
837
|
+
* or when you don't have the issuer's public key
|
|
838
|
+
*
|
|
839
|
+
* WARNING: The returned payload has not been verified!
|
|
840
|
+
* Only use this for inspection purposes, not for authorization decisions.
|
|
841
|
+
*
|
|
842
|
+
* @param credential - The SD-JWT credential string
|
|
843
|
+
* @returns Decoded JWT payload, header, and disclosures
|
|
844
|
+
*
|
|
845
|
+
* @example
|
|
846
|
+
* ```typescript
|
|
847
|
+
* const decoded = await SDJwtClient.decodeWithoutVerification(credential)
|
|
848
|
+
* console.log('Issuer (unverified):', decoded.payload?.iss)
|
|
849
|
+
* console.log('Disclosures:', decoded.disclosures?.length)
|
|
850
|
+
* ```
|
|
851
|
+
*/
|
|
852
|
+
static async decodeWithoutVerification(credential) {
|
|
853
|
+
try {
|
|
854
|
+
const sdJwtInstance = await this.getDecodingInstance();
|
|
855
|
+
const decoded = await sdJwtInstance.decode(credential);
|
|
856
|
+
if (!decoded || !decoded.jwt) {
|
|
857
|
+
return { error: "Failed to decode SD-JWT" };
|
|
858
|
+
}
|
|
859
|
+
const claims = await decoded.getClaims(import_crypto_nodejs.digest);
|
|
860
|
+
return {
|
|
861
|
+
payload: decoded.jwt.payload,
|
|
862
|
+
header: decoded.jwt.header,
|
|
863
|
+
disclosures: decoded.disclosures,
|
|
864
|
+
claims
|
|
865
|
+
};
|
|
866
|
+
} catch (error) {
|
|
867
|
+
return { error: error.message };
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
/**
|
|
871
|
+
* Extract issuer DID from an SD-JWT without verification
|
|
872
|
+
* Useful for determining the issuer before verification
|
|
873
|
+
*
|
|
874
|
+
* @param credential - The SD-JWT credential string
|
|
875
|
+
* @returns The issuer DID or null if not found
|
|
876
|
+
*/
|
|
877
|
+
static extractIssuerDid(credential) {
|
|
878
|
+
try {
|
|
879
|
+
const parts = credential.split("~");
|
|
880
|
+
if (parts.length === 0) return null;
|
|
881
|
+
const jwt = parts[0];
|
|
882
|
+
const jwtParts = jwt.split(".");
|
|
883
|
+
if (jwtParts.length !== 3) return null;
|
|
884
|
+
const payload = JSON.parse(Buffer.from(jwtParts[1], "base64url").toString());
|
|
885
|
+
return payload.iss || payload.issuer || null;
|
|
886
|
+
} catch {
|
|
887
|
+
return null;
|
|
888
|
+
}
|
|
889
|
+
}
|
|
635
890
|
};
|
|
636
891
|
|
|
637
892
|
// src/agent/agent-did-manager.ts
|
|
@@ -647,7 +902,7 @@ var AgentDIDManager = class {
|
|
|
647
902
|
*/
|
|
648
903
|
async generateAgentDID(agentId) {
|
|
649
904
|
const keyPair = await SDJwtClient.generateKeyPair();
|
|
650
|
-
const did =
|
|
905
|
+
const did = createDidJwk(keyPair.publicKey);
|
|
651
906
|
await this.keyManager.storeKey(did, keyPair.privateKey);
|
|
652
907
|
this.agentDIDMap.set(agentId, did);
|
|
653
908
|
await this.saveAgentDIDMapping(agentId, did);
|
|
@@ -689,7 +944,7 @@ var AgentDIDManager = class {
|
|
|
689
944
|
}
|
|
690
945
|
return {
|
|
691
946
|
privateKey,
|
|
692
|
-
publicKey:
|
|
947
|
+
publicKey: extractPublicKey(privateKey)
|
|
693
948
|
};
|
|
694
949
|
}
|
|
695
950
|
/**
|
|
@@ -731,31 +986,6 @@ var AgentDIDManager = class {
|
|
|
731
986
|
return [];
|
|
732
987
|
}
|
|
733
988
|
}
|
|
734
|
-
/**
|
|
735
|
-
* Create did:jwk from public key
|
|
736
|
-
*/
|
|
737
|
-
createDidJwk(publicKey) {
|
|
738
|
-
const publicJwk = {
|
|
739
|
-
kty: publicKey.kty,
|
|
740
|
-
crv: publicKey.crv,
|
|
741
|
-
x: publicKey.x,
|
|
742
|
-
y: publicKey.y,
|
|
743
|
-
use: publicKey.use,
|
|
744
|
-
alg: publicKey.alg
|
|
745
|
-
};
|
|
746
|
-
const encoded = Buffer.from(JSON.stringify(publicJwk)).toString("base64url");
|
|
747
|
-
return `did:jwk:${encoded}`;
|
|
748
|
-
}
|
|
749
|
-
/**
|
|
750
|
-
* Extract public key from private key
|
|
751
|
-
*/
|
|
752
|
-
extractPublicKey(privateKey) {
|
|
753
|
-
const { d, key_ops, ...publicKey } = privateKey;
|
|
754
|
-
return {
|
|
755
|
-
...publicKey
|
|
756
|
-
// Remove key_ops for public key
|
|
757
|
-
};
|
|
758
|
-
}
|
|
759
989
|
/**
|
|
760
990
|
* Save agent ID -> DID mapping to persistent storage
|
|
761
991
|
*/
|
|
@@ -972,7 +1202,7 @@ var UserIdentityManager = class {
|
|
|
972
1202
|
*/
|
|
973
1203
|
async createUserDID() {
|
|
974
1204
|
const keyPair = await SDJwtClient.generateKeyPair();
|
|
975
|
-
const did =
|
|
1205
|
+
const did = createDidJwk(keyPair.publicKey);
|
|
976
1206
|
await this.keyManager.storeKey(did, keyPair.privateKey);
|
|
977
1207
|
await this.saveUserDID(did);
|
|
978
1208
|
this.currentUserDID = did;
|
|
@@ -989,7 +1219,7 @@ var UserIdentityManager = class {
|
|
|
989
1219
|
}
|
|
990
1220
|
return {
|
|
991
1221
|
privateKey,
|
|
992
|
-
publicKey:
|
|
1222
|
+
publicKey: extractPublicKey(privateKey)
|
|
993
1223
|
};
|
|
994
1224
|
}
|
|
995
1225
|
/**
|
|
@@ -1030,34 +1260,11 @@ var UserIdentityManager = class {
|
|
|
1030
1260
|
await this.clearUserDID();
|
|
1031
1261
|
return await this.createUserDID();
|
|
1032
1262
|
}
|
|
1033
|
-
/**
|
|
1034
|
-
* Create did:jwk from public key
|
|
1035
|
-
*/
|
|
1036
|
-
createDidJwk(publicKey) {
|
|
1037
|
-
const publicJwk = {
|
|
1038
|
-
kty: publicKey.kty,
|
|
1039
|
-
crv: publicKey.crv,
|
|
1040
|
-
x: publicKey.x,
|
|
1041
|
-
y: publicKey.y,
|
|
1042
|
-
use: publicKey.use,
|
|
1043
|
-
alg: publicKey.alg
|
|
1044
|
-
};
|
|
1045
|
-
const encoded = Buffer.from(JSON.stringify(publicJwk)).toString("base64url");
|
|
1046
|
-
return `did:jwk:${encoded}`;
|
|
1047
|
-
}
|
|
1048
|
-
/**
|
|
1049
|
-
* Extract public key from private key
|
|
1050
|
-
*/
|
|
1051
|
-
extractPublicKey(privateKey) {
|
|
1052
|
-
const { d, key_ops, ...publicKey } = privateKey;
|
|
1053
|
-
return publicKey;
|
|
1054
|
-
}
|
|
1055
1263
|
/**
|
|
1056
1264
|
* Resolve did:jwk locally
|
|
1057
1265
|
*/
|
|
1058
1266
|
resolveDidJwkLocally(did) {
|
|
1059
|
-
const
|
|
1060
|
-
const publicJwk = JSON.parse(Buffer.from(encoded, "base64url").toString());
|
|
1267
|
+
const publicJwk = extractPublicKeyFromDid(did);
|
|
1061
1268
|
return this.createDidDocument(did, publicJwk);
|
|
1062
1269
|
}
|
|
1063
1270
|
/**
|
|
@@ -3028,7 +3235,7 @@ var MetricsManager = class {
|
|
|
3028
3235
|
/**
|
|
3029
3236
|
* End tracking an operation
|
|
3030
3237
|
*/
|
|
3031
|
-
endOperation(
|
|
3238
|
+
endOperation(_operationId, success, error) {
|
|
3032
3239
|
const endTime = performance.now();
|
|
3033
3240
|
const operation = this.operations[this.operations.length - 1];
|
|
3034
3241
|
if (operation) {
|
|
@@ -4551,15 +4758,20 @@ var version = "0.0.1";
|
|
|
4551
4758
|
checkPermissionWithVP,
|
|
4552
4759
|
configure,
|
|
4553
4760
|
createAjv,
|
|
4761
|
+
createDidJwk,
|
|
4554
4762
|
defaultConstraintEvaluator,
|
|
4555
4763
|
evaluateConstraints,
|
|
4764
|
+
extractPublicKey,
|
|
4765
|
+
extractPublicKeyFromDid,
|
|
4556
4766
|
generateKeyPair,
|
|
4557
4767
|
generateNonce,
|
|
4558
4768
|
getClient,
|
|
4769
|
+
getKeyIdFromDid,
|
|
4559
4770
|
getRequiredRelations,
|
|
4560
4771
|
getRequiredScopes,
|
|
4561
4772
|
indexActions,
|
|
4562
4773
|
indexCapabilities,
|
|
4774
|
+
isValidDidJwk,
|
|
4563
4775
|
loadActionRegistryFromFile,
|
|
4564
4776
|
loadActionRegistryFromObject,
|
|
4565
4777
|
planDelegationForVC,
|