anon-identity
Version:
Decentralized identity framework with DIDs, Verifiable Credentials, and privacy-preserving selective disclosure
371 lines • 14.1 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.IPFSStorageProvider = void 0;
const uuid_1 = require("uuid");
class IPFSStorageProvider {
constructor(config) {
this.ipfsClient = null;
this.localIndex = new Map(); // Maps IDs to IPFS CIDs
this.localKeyStore = new Map(); // Keys are always stored locally
if (!config.ipfs) {
throw new Error('IPFS configuration is required');
}
// Initialize IPFS client lazily to avoid import issues
this.initializeIPFSClient(config.ipfs);
}
async initializeIPFSClient(ipfsConfig) {
try {
// Dynamic import to avoid ESM issues
const { create } = await Promise.resolve().then(() => __importStar(require('kubo-rpc-client')));
this.ipfsClient = create({
host: ipfsConfig.host,
port: ipfsConfig.port,
protocol: ipfsConfig.protocol,
});
}
catch (error) {
console.error('Failed to initialize Kubo RPC client:', error);
throw new Error('Kubo RPC client initialization failed');
}
}
// Helper methods for IPFS operations
async storeToIPFS(data) {
if (!this.ipfsClient) {
throw new Error('IPFS client not initialized');
}
const jsonData = JSON.stringify(data);
const result = await this.ipfsClient.add(jsonData);
return result.cid.toString(); // Returns the IPFS CID
}
async retrieveFromIPFS(cid) {
try {
if (!this.ipfsClient) {
throw new Error('IPFS client not initialized');
}
const chunks = [];
for await (const chunk of this.ipfsClient.cat(cid)) {
chunks.push(chunk);
}
const data = Buffer.concat(chunks).toString('utf8');
return JSON.parse(data);
}
catch (error) {
console.error('Error retrieving from IPFS:', error);
return null;
}
}
// DID Operations
async storeDID(did, document) {
const storedData = {
type: 'did',
data: document,
metadata: {
created: new Date().toISOString(),
updated: new Date().toISOString(),
version: '1.0',
},
};
const cid = await this.storeToIPFS(storedData);
this.localIndex.set(`did:${did}`, cid);
}
async resolveDID(did) {
const cid = this.localIndex.get(`did:${did}`);
if (!cid)
return null;
const storedData = await this.retrieveFromIPFS(cid);
return storedData?.data || null;
}
async listDIDs(owner) {
// Filter DIDs from local index
const dids = [];
for (const [key, _] of this.localIndex) {
if (key.startsWith('did:')) {
const did = key.substring(4);
if (!owner) {
dids.push(did);
}
else {
// Need to retrieve and check ownership
const document = await this.resolveDID(did);
if (document?.verificationMethod?.some(vm => vm.controller === owner)) {
dids.push(did);
}
}
}
}
return dids;
}
// Credential Operations
async storeCredential(credential) {
const storedData = {
type: 'credential',
data: credential,
metadata: {
created: new Date().toISOString(),
updated: new Date().toISOString(),
version: '1.0',
},
};
const cid = await this.storeToIPFS(storedData);
this.localIndex.set(`credential:${credential.id}`, cid);
// Also index by holder
const holder = credential.credentialSubject.id;
const holderKey = `holder:${holder}:credentials`;
const holderCreds = this.localIndex.get(holderKey) || '';
const credIds = holderCreds ? holderCreds.split(',') : [];
if (!credIds.includes(credential.id)) {
credIds.push(credential.id);
this.localIndex.set(holderKey, credIds.join(','));
}
}
async getCredential(id) {
const cid = this.localIndex.get(`credential:${id}`);
if (!cid)
return null;
const storedData = await this.retrieveFromIPFS(cid);
return storedData?.data || null;
}
async listCredentials(holder) {
const holderKey = `holder:${holder}:credentials`;
const credIds = this.localIndex.get(holderKey)?.split(',') || [];
const credentials = [];
for (const credId of credIds) {
if (credId) {
const credential = await this.getCredential(credId);
if (credential) {
credentials.push(credential);
}
}
}
return credentials;
}
async deleteCredential(id) {
const credential = await this.getCredential(id);
if (credential) {
// Remove from holder index
const holder = credential.credentialSubject.id;
const holderKey = `holder:${holder}:credentials`;
const credIds = this.localIndex.get(holderKey)?.split(',') || [];
const updatedIds = credIds.filter(cid => cid !== id);
if (updatedIds.length > 0) {
this.localIndex.set(holderKey, updatedIds.join(','));
}
else {
this.localIndex.delete(holderKey);
}
// Remove credential index
this.localIndex.delete(`credential:${id}`);
}
}
// Revocation Operations
async publishRevocation(issuerDID, revocationList) {
const storedData = {
type: 'revocation',
data: revocationList,
metadata: {
created: new Date().toISOString(),
updated: new Date().toISOString(),
version: '1.0',
},
};
const cid = await this.storeToIPFS(storedData);
this.localIndex.set(`revocation:${issuerDID}`, cid);
}
async checkRevocation(issuerDID, credentialId) {
const revocationList = await this.getRevocationList(issuerDID);
if (!revocationList)
return false;
return revocationList.revokedCredentialIds.includes(credentialId);
}
async getRevocationList(issuerDID) {
const cid = this.localIndex.get(`revocation:${issuerDID}`);
if (!cid)
return null;
const storedData = await this.retrieveFromIPFS(cid);
return storedData?.data || null;
}
// Key Management (always local)
async storeKeyPair(identifier, encryptedKeyPair) {
this.localKeyStore.set(identifier, encryptedKeyPair);
}
async retrieveKeyPair(identifier) {
return this.localKeyStore.get(identifier) || null;
}
async deleteKeyPair(identifier) {
this.localKeyStore.delete(identifier);
}
// Schema Operations
async registerSchema(schema) {
const schemaId = schema.id || `schema:${(0, uuid_1.v4)()}`;
const schemaWithId = { ...schema, id: schemaId };
const storedData = {
type: 'schema',
data: schemaWithId,
metadata: {
created: new Date().toISOString(),
updated: new Date().toISOString(),
version: '1.0',
},
};
const cid = await this.storeToIPFS(storedData);
this.localIndex.set(`schema:${schemaId}`, cid);
// Index by issuer
const issuerKey = `issuer:${schema.issuerDID}:schemas`;
const issuerSchemas = this.localIndex.get(issuerKey) || '';
const schemaIds = issuerSchemas ? issuerSchemas.split(',') : [];
if (!schemaIds.includes(schemaId)) {
schemaIds.push(schemaId);
this.localIndex.set(issuerKey, schemaIds.join(','));
}
return schemaId;
}
async getSchema(schemaId) {
const cid = this.localIndex.get(`schema:${schemaId}`);
if (!cid)
return null;
const storedData = await this.retrieveFromIPFS(cid);
return storedData?.data || null;
}
async listSchemas(issuerDID) {
if (!issuerDID) {
// List all schemas
const schemas = [];
for (const [key, cid] of this.localIndex) {
if (key.startsWith('schema:')) {
const storedData = await this.retrieveFromIPFS(cid);
if (storedData?.data) {
schemas.push(storedData.data);
}
}
}
return schemas;
}
// List schemas by issuer
const issuerKey = `issuer:${issuerDID}:schemas`;
const schemaIds = this.localIndex.get(issuerKey)?.split(',') || [];
const schemas = [];
for (const schemaId of schemaIds) {
if (schemaId) {
const schema = await this.getSchema(schemaId);
if (schema) {
schemas.push(schema);
}
}
}
return schemas;
}
// General operations
async clear() {
// Note: This doesn't remove data from IPFS (which is immutable)
// It only clears the local index
this.localIndex.clear();
this.localKeyStore.clear();
}
// IPFS-specific methods
async pin(cid) {
if (!this.ipfsClient) {
throw new Error('IPFS client not initialized');
}
await this.ipfsClient.pin.add(cid);
}
async unpin(cid) {
if (!this.ipfsClient) {
throw new Error('IPFS client not initialized');
}
await this.ipfsClient.pin.rm(cid);
}
async getStorageStats() {
if (!this.ipfsClient) {
throw new Error('IPFS client not initialized');
}
const nodeInfo = await this.ipfsClient.id();
return {
totalItems: this.localIndex.size,
indexSize: JSON.stringify([...this.localIndex.entries()]).length,
ipfsNodeInfo: nodeInfo,
};
}
// Phone Number Operations (not implemented for IPFS)
async storePhoneNumber(userDID, phoneNumber) {
throw new Error('Phone number storage not implemented for IPFS provider');
}
async getPhoneNumber(userDID, phoneId) {
throw new Error('Phone number storage not implemented for IPFS provider');
}
async listPhoneNumbers(userDID) {
throw new Error('Phone number storage not implemented for IPFS provider');
}
async updatePhoneNumber(userDID, phoneId, phoneNumber) {
throw new Error('Phone number storage not implemented for IPFS provider');
}
async deletePhoneNumber(userDID, phoneId) {
throw new Error('Phone number storage not implemented for IPFS provider');
}
// Address Operations (not implemented for IPFS)
async storeAddress(userDID, address) {
throw new Error('Address storage not implemented for IPFS provider');
}
async getAddress(userDID, addressId) {
throw new Error('Address storage not implemented for IPFS provider');
}
async listAddresses(userDID) {
throw new Error('Address storage not implemented for IPFS provider');
}
async updateAddress(userDID, addressId, address) {
throw new Error('Address storage not implemented for IPFS provider');
}
async deleteAddress(userDID, addressId) {
throw new Error('Address storage not implemented for IPFS provider');
}
// Email Address Operations (not implemented for IPFS)
async storeEmailAddress(userDID, emailAddress) {
throw new Error('Email address storage not implemented for IPFS provider');
}
async getEmailAddress(userDID, emailId) {
throw new Error('Email address storage not implemented for IPFS provider');
}
async listEmailAddresses(userDID) {
throw new Error('Email address storage not implemented for IPFS provider');
}
async updateEmailAddress(userDID, emailId, emailAddress) {
throw new Error('Email address storage not implemented for IPFS provider');
}
async deleteEmailAddress(userDID, emailId) {
throw new Error('Email address storage not implemented for IPFS provider');
}
}
exports.IPFSStorageProvider = IPFSStorageProvider;
//# sourceMappingURL=ipfs-storage-provider.js.map