UNPKG

anon-identity

Version:

Decentralized identity framework with DIDs, Verifiable Credentials, and privacy-preserving selective disclosure

176 lines 6.35 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ProofManager = void 0; /** * Manages multiple proofs on credentials and presentations */ class ProofManager { /** * Add a proof to a document (credential or presentation) * @param document The document to add proof to * @param newProof The proof to add * @returns The document with the new proof added */ static addProof(document, newProof) { const documentCopy = { ...document }; if (!documentCopy.proof) { // No existing proof, add as single proof documentCopy.proof = newProof; } else if (Array.isArray(documentCopy.proof)) { // Already an array, add to it documentCopy.proof = [...documentCopy.proof, newProof]; } else { // Single proof exists, convert to array documentCopy.proof = [documentCopy.proof, newProof]; } return documentCopy; } /** * Get all proofs from a document * @param document The document to get proofs from * @returns Array of proofs (empty if none) */ static getProofs(document) { if (!document.proof) { return []; } return Array.isArray(document.proof) ? document.proof : [document.proof]; } /** * Find proofs by purpose * @param document The document to search * @param purpose The proof purpose to find * @returns Array of matching proofs */ static findProofsByPurpose(document, purpose) { const proofs = this.getProofs(document); return proofs.filter(p => p.proofPurpose === purpose); } /** * Find proofs by type * @param document The document to search * @param type The proof type to find * @returns Array of matching proofs */ static findProofsByType(document, type) { const proofs = this.getProofs(document); return proofs.filter(p => p.type === type); } /** * Find proofs by verification method * @param document The document to search * @param verificationMethod The verification method to find * @returns Array of matching proofs */ static findProofsByVerificationMethod(document, verificationMethod) { const proofs = this.getProofs(document); return proofs.filter(p => p.verificationMethod === verificationMethod); } /** * Validate proof chain (each proof must be created before the next) * @param proofs Array of proofs to validate * @returns Validation result */ static validateProofChain(proofs) { if (proofs.length < 2) { return { valid: true }; } const errors = []; const sortedProofs = [...proofs].sort((a, b) => { if (!a.created || !b.created) return 0; return new Date(a.created).getTime() - new Date(b.created).getTime(); }); for (let i = 1; i < sortedProofs.length; i++) { const prev = sortedProofs[i - 1]; const curr = sortedProofs[i]; if (!prev.created || !curr.created) { errors.push(`Proof ${i} is missing created timestamp`); continue; } const prevTime = new Date(prev.created).getTime(); const currTime = new Date(curr.created).getTime(); if (currTime < prevTime) { errors.push(`Proof ${i} created at ${curr.created} is before proof ${i - 1} created at ${prev.created}`); } } return { valid: errors.length === 0, errors: errors.length > 0 ? errors : undefined }; } /** * Remove expired proofs * @param document The document to clean * @returns The document with expired proofs removed */ static removeExpiredProofs(document, now = new Date()) { const proofs = this.getProofs(document); const validProofs = proofs.filter(p => { if (!p.expires) return true; return new Date(p.expires) > now; }); if (validProofs.length === proofs.length) { return document; // No changes needed } const documentCopy = { ...document }; if (validProofs.length === 0) { delete documentCopy.proof; } else if (validProofs.length === 1) { documentCopy.proof = validProofs[0]; } else { documentCopy.proof = validProofs; } return documentCopy; } /** * Merge proofs from multiple documents * @param documents Array of documents with proofs * @returns Array of all unique proofs */ static mergeProofs(...documents) { const allProofs = []; const seenProofs = new Set(); for (const doc of documents) { const proofs = this.getProofs(doc); for (const proof of proofs) { // Create a unique key for the proof const key = `${proof.type}:${proof.verificationMethod}:${proof.created || 'no-date'}`; if (!seenProofs.has(key)) { seenProofs.add(key); allProofs.push(proof); } } } return allProofs; } /** * Check if a document has a valid proof for a given purpose * @param document The document to check * @param purpose The proof purpose required * @param verifierDIDs Optional list of acceptable verifier DIDs * @returns Whether a valid proof exists */ static hasValidProofForPurpose(document, purpose, verifierDIDs) { const proofs = this.findProofsByPurpose(document, purpose); if (proofs.length === 0) { return false; } // If no specific verifiers required, any proof with the purpose is valid if (!verifierDIDs || verifierDIDs.length === 0) { return true; } // Check if any proof is from an acceptable verifier return proofs.some(proof => { const proofDID = proof.verificationMethod.split('#')[0]; return verifierDIDs.includes(proofDID); }); } } exports.ProofManager = ProofManager; //# sourceMappingURL=proof-manager.js.map