anon-identity
Version:
Decentralized identity framework with DIDs, Verifiable Credentials, and privacy-preserving selective disclosure
249 lines • 10.9 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.UserWallet = void 0;
const jose_1 = require("jose");
const crypto_1 = require("../core/crypto");
const did_1 = require("../core/did");
const storage_1 = require("../core/storage");
const selective_disclosure_1 = require("../zkp/selective-disclosure");
const storage_2 = require("../storage");
const agent_identity_1 = require("../agent/agent-identity");
const delegation_manager_1 = require("../agent/delegation-manager");
const agent_revocation_service_1 = require("../agent/agent-revocation-service");
class UserWallet {
constructor(keyPair, storageProvider) {
this.keyPair = keyPair;
const didObject = did_1.DIDService.createDIDKey(keyPair.publicKey);
this.did = didObject.id;
this.storageProvider = storageProvider || storage_2.StorageFactory.getDefaultProvider();
this.agentManager = new agent_identity_1.AgentIdentityManager();
this.delegationManager = new delegation_manager_1.DelegationManager();
this.agentRevocationService = new agent_revocation_service_1.AgentRevocationService(keyPair, this.did, this.storageProvider);
}
static async create(storageProvider) {
const keyPair = await crypto_1.CryptoService.generateKeyPair();
const wallet = new UserWallet(keyPair, storageProvider);
// Store DID document
const publicKeyMultibase = wallet.did.substring('did:key:'.length); // Extract multibase from DID
const didDocument = {
'@context': ['https://www.w3.org/ns/did/v1'],
id: wallet.did,
verificationMethod: [{
id: `${wallet.did}#key-1`,
type: 'Ed25519VerificationKey2020',
controller: wallet.did,
publicKeyMultibase: publicKeyMultibase
}],
authentication: [`${wallet.did}#key-1`],
assertionMethod: [`${wallet.did}#key-1`],
created: new Date().toISOString()
};
await wallet.storageProvider.storeDID(wallet.did, didDocument);
return wallet;
}
static async restore(passphrase, identifier = 'default', storageProvider) {
const keyPair = await storage_1.SecureStorage.retrieveKeyPair(passphrase, identifier);
if (!keyPair)
return null;
const wallet = new UserWallet(keyPair, storageProvider);
return wallet;
}
async save(passphrase, identifier = 'default') {
// Store key pair using SecureStorage (which uses the storage provider internally)
await storage_1.SecureStorage.storeKeyPair(this.keyPair, passphrase, identifier);
}
async storeCredential(credential) {
await this.storageProvider.storeCredential(credential);
}
async getCredential(credentialId) {
return await this.storageProvider.getCredential(credentialId);
}
async getAllCredentials() {
return await this.storageProvider.listCredentials(this.did);
}
async getCredentialsByType(type) {
const allCredentials = await this.getAllCredentials();
return allCredentials.filter(vc => vc.type.includes(type));
}
async createVerifiablePresentation(credentialIds) {
// Collect selected credentials
const selectedCredentials = [];
for (const credId of credentialIds) {
const credential = await this.storageProvider.getCredential(credId);
if (!credential) {
throw new Error(`Credential not found: ${credId}`);
}
selectedCredentials.push(credential);
}
if (selectedCredentials.length === 0) {
throw new Error('No credentials selected for presentation');
}
// Create the presentation without proof
const presentation = {
"@context": ["https://www.w3.org/2018/credentials/v1"],
type: ["VerifiablePresentation"],
verifiableCredential: selectedCredentials
};
// Sign the presentation
const signedPresentation = await this.signPresentation(presentation);
return signedPresentation;
}
async createSelectiveDisclosurePresentation(disclosureRequests) {
const disclosedCredentials = [];
for (const request of disclosureRequests) {
const credential = await this.storageProvider.getCredential(request.credentialId);
if (!credential) {
throw new Error(`Credential not found: ${request.credentialId}`);
}
// If no specific attributes requested, include the full credential
if (!request.attributesToDisclose || request.attributesToDisclose.length === 0) {
disclosedCredentials.push(credential);
}
else {
// Create selectively disclosed credential
const disclosedCredential = await selective_disclosure_1.SelectiveDisclosure.createSelectivelyDisclosedCredential(credential, request.attributesToDisclose, this.keyPair.privateKey, this.did);
disclosedCredentials.push(disclosedCredential);
}
}
if (disclosedCredentials.length === 0) {
throw new Error('No credentials selected for presentation');
}
// Create the presentation with selectively disclosed credentials
const presentation = {
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://w3id.org/security/suites/ed25519-2020/v1"
],
type: ["VerifiablePresentation", "SelectiveDisclosurePresentation"],
verifiableCredential: disclosedCredentials
};
// Sign the presentation
const signedPresentation = await this.signPresentation(presentation);
return signedPresentation;
}
async signPresentation(presentation) {
// Create a copy without the proof field for signing
const presentationToSign = { ...presentation };
delete presentationToSign.proof;
// Convert private key to JWK format for jose
const privateKeyJwk = {
kty: 'OKP',
crv: 'Ed25519',
x: Buffer.from(this.keyPair.publicKey).toString('base64url'),
d: Buffer.from(this.keyPair.privateKey).toString('base64url')
};
const privateKey = await (0, jose_1.importJWK)(privateKeyJwk, 'EdDSA');
// Create JWT
const jwt = await new jose_1.SignJWT(presentationToSign)
.setProtectedHeader({
alg: 'EdDSA',
typ: 'JWT',
kid: `${this.did}#key-1`
})
.setIssuedAt()
.setIssuer(this.did)
.sign(privateKey);
// Add proof to presentation
const signedPresentation = {
...presentation,
proof: {
type: 'Ed25519Signature2020',
created: new Date().toISOString(),
proofPurpose: 'authentication',
verificationMethod: `${this.did}#key-1`,
jws: jwt
}
};
return signedPresentation;
}
getDID() {
return this.did;
}
getPublicKey() {
return this.keyPair.publicKey;
}
setStorageProvider(provider) {
this.storageProvider = provider;
}
// Agent management methods
async createAgent(config) {
const agent = await this.agentManager.createAgent(this.did, config);
// Store agent information in storage provider
await this.storageProvider.storeCredential({
'@context': ['https://www.w3.org/2018/credentials/v1'],
id: `${this.did}/agents/${agent.did}`,
type: ['VerifiableCredential', 'AgentRegistration'],
issuer: this.did,
issuanceDate: new Date().toISOString(),
credentialSubject: {
id: agent.did,
type: 'Agent',
name: agent.name,
description: agent.description,
parentDID: this.did,
createdAt: agent.createdAt.toISOString()
}
});
return agent;
}
async grantAgentAccess(agentDID, grant) {
const agent = this.agentManager.getAgent(agentDID);
if (!agent || agent.parentDID !== this.did) {
throw new Error('Agent not found or not owned by this wallet');
}
// Create delegation credential
const delegationCredential = await this.delegationManager.createDelegationCredential(this.did, this.keyPair, agentDID, agent.name, grant);
// Store grant and credential
this.agentManager.addAccessGrant(agentDID, grant);
this.agentManager.addDelegationCredential(agentDID, delegationCredential);
// Store in persistent storage
await this.storageProvider.storeCredential(delegationCredential);
return delegationCredential;
}
listAgents() {
return this.agentManager.listAgents(this.did);
}
getAgentAccess(agentDID) {
const agent = this.agentManager.getAgent(agentDID);
if (!agent || agent.parentDID !== this.did) {
throw new Error('Agent not found or not owned by this wallet');
}
return this.agentManager.getAccessGrants(agentDID);
}
async revokeAgentAccess(agentDID, serviceDID) {
const agent = this.agentManager.getAgent(agentDID);
if (!agent || agent.parentDID !== this.did) {
throw new Error('Agent not found or not owned by this wallet');
}
if (serviceDID) {
// Revoke specific service access
this.agentManager.revokeServiceAccess(agentDID, serviceDID);
// Add to revocation list
await this.agentRevocationService.revokeAgentServiceAccess(agentDID, this.did, serviceDID, 'Access revoked by user');
}
else {
// Revoke all access for the agent
const grants = this.agentManager.getAccessGrants(agentDID);
for (const grant of grants) {
this.agentManager.revokeServiceAccess(agentDID, grant.serviceDID);
}
// Add agent to revocation list
await this.agentRevocationService.revokeAgent(agentDID, this.did, 'Agent access completely revoked by user');
}
}
async revokeAgent(agentDID) {
const agent = this.agentManager.getAgent(agentDID);
if (!agent || agent.parentDID !== this.did) {
throw new Error('Agent not found or not owned by this wallet');
}
// Revoke all access
await this.revokeAgentAccess(agentDID);
// Delete the agent
this.agentManager.deleteAgent(agentDID);
}
getAgentManager() {
return this.agentManager;
}
}
exports.UserWallet = UserWallet;
//# sourceMappingURL=user-wallet.js.map