anon-identity
Version:
Decentralized identity framework with DIDs, Verifiable Credentials, and privacy-preserving selective disclosure
326 lines • 12.5 kB
JavaScript
"use strict";
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.FileStorageProvider = void 0;
const uuid_1 = require("uuid");
// Lazy-loaded Node.js dependencies
let fsModule;
let pathModule;
let cryptoModule;
class FileStorageProvider {
constructor(filePath, encryption = true, passphrase) {
this.encryption = encryption;
this.passphrase = passphrase;
this.data = {
dids: new Map(),
credentials: new Map(),
revocations: new Map(),
keyPairs: new Map(),
schemas: new Map(),
};
this.initialized = false;
this.initPromise = null;
this.filePath = filePath;
if (encryption && passphrase) {
this.encryptionKey = passphrase;
}
}
async initialize() {
if (this.initialized)
return;
if (this.initPromise)
return this.initPromise;
this.initPromise = this.doInitialize();
await this.initPromise;
this.initialized = true;
}
async doInitialize() {
try {
// Dynamic import of Node.js modules
[fsModule, pathModule, cryptoModule] = await Promise.all([
Promise.resolve().then(() => __importStar(require('fs'))).then(m => m.promises),
Promise.resolve().then(() => __importStar(require('path'))),
Promise.resolve().then(() => __importStar(require('crypto'))),
]);
await this.load();
}
catch (error) {
throw new Error(`Failed to initialize file storage: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
async ensureDirectoryExists(filePath) {
const dir = pathModule.dirname(filePath);
try {
await fsModule.access(dir);
}
catch {
await fsModule.mkdir(dir, { recursive: true });
}
}
encrypt(data) {
if (!this.encryptionKey)
return data;
const algorithm = 'aes-256-gcm';
const salt = cryptoModule.randomBytes(16);
const key = cryptoModule.pbkdf2Sync(this.encryptionKey, salt, 100000, 32, 'sha256');
const iv = cryptoModule.randomBytes(16);
const cipher = cryptoModule.createCipheriv(algorithm, key, iv);
let encrypted = cipher.update(data, 'utf8', 'hex');
encrypted += cipher.final('hex');
const authTag = cipher.getAuthTag();
return JSON.stringify({
encrypted,
salt: salt.toString('hex'),
iv: iv.toString('hex'),
authTag: authTag.toString('hex'),
});
}
decrypt(encryptedData) {
if (!this.encryptionKey)
return encryptedData;
try {
const { encrypted, salt, iv, authTag } = JSON.parse(encryptedData);
const algorithm = 'aes-256-gcm';
const key = cryptoModule.pbkdf2Sync(this.encryptionKey, Buffer.from(salt, 'hex'), 100000, 32, 'sha256');
const decipher = cryptoModule.createDecipheriv(algorithm, key, Buffer.from(iv, 'hex'));
decipher.setAuthTag(Buffer.from(authTag, 'hex'));
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
catch (error) {
// If decryption fails, assume data is not encrypted
return encryptedData;
}
}
async save() {
await this.ensureDirectoryExists(this.filePath);
const dataToSave = {
dids: Array.from(this.data.dids.entries()),
credentials: Array.from(this.data.credentials.entries()),
revocations: Array.from(this.data.revocations.entries()),
keyPairs: Array.from(this.data.keyPairs.entries()),
schemas: Array.from(this.data.schemas.entries()),
};
const jsonData = JSON.stringify(dataToSave, null, 2);
const dataToWrite = this.encrypt(jsonData);
await fsModule.writeFile(this.filePath, dataToWrite, 'utf8');
}
async load() {
try {
await this.ensureDirectoryExists(this.filePath);
const encryptedData = await fsModule.readFile(this.filePath, 'utf8');
const jsonData = this.decrypt(encryptedData);
const loadedData = JSON.parse(jsonData);
this.data.dids = new Map(loadedData.dids || []);
this.data.credentials = new Map(loadedData.credentials || []);
this.data.revocations = new Map(loadedData.revocations || []);
this.data.keyPairs = new Map(loadedData.keyPairs || []);
this.data.schemas = new Map(loadedData.schemas || []);
}
catch (error) {
// File doesn't exist or is corrupt, start fresh
this.data = {
dids: new Map(),
credentials: new Map(),
revocations: new Map(),
keyPairs: new Map(),
schemas: new Map(),
};
}
}
// DID Operations
async storeDID(did, document) {
await this.initialize();
this.data.dids.set(did, document);
await this.save();
}
async resolveDID(did) {
await this.initialize();
return this.data.dids.get(did) || null;
}
async listDIDs(owner) {
await this.initialize();
if (!owner) {
return Array.from(this.data.dids.keys());
}
const dids = [];
for (const [did, document] of this.data.dids) {
if (document.verificationMethod?.some(vm => vm.controller === owner)) {
dids.push(did);
}
}
return dids;
}
// Credential Operations
async storeCredential(credential) {
await this.initialize();
this.data.credentials.set(credential.id, credential);
await this.save();
}
async getCredential(id) {
await this.initialize();
return this.data.credentials.get(id) || null;
}
async listCredentials(holder) {
await this.initialize();
const credentials = [];
for (const credential of this.data.credentials.values()) {
if (credential.credentialSubject.id === holder) {
credentials.push(credential);
}
}
return credentials;
}
async deleteCredential(id) {
await this.initialize();
this.data.credentials.delete(id);
await this.save();
}
// Revocation Operations
async publishRevocation(issuerDID, revocationList) {
await this.initialize();
this.data.revocations.set(issuerDID, revocationList);
await this.save();
}
async checkRevocation(issuerDID, credentialId) {
await this.initialize();
const revocationList = this.data.revocations.get(issuerDID);
if (!revocationList)
return false;
return revocationList.revokedCredentialIds.includes(credentialId);
}
async getRevocationList(issuerDID) {
await this.initialize();
return this.data.revocations.get(issuerDID) || null;
}
// Key Management
async storeKeyPair(identifier, encryptedKeyPair) {
await this.initialize();
this.data.keyPairs.set(identifier, encryptedKeyPair);
await this.save();
}
async retrieveKeyPair(identifier) {
await this.initialize();
return this.data.keyPairs.get(identifier) || null;
}
async deleteKeyPair(identifier) {
await this.initialize();
this.data.keyPairs.delete(identifier);
await this.save();
}
// Schema Operations
async registerSchema(schema) {
await this.initialize();
const schemaId = schema.id || `schema:${(0, uuid_1.v4)()}`;
const schemaWithId = { ...schema, id: schemaId };
this.data.schemas.set(schemaId, schemaWithId);
await this.save();
return schemaId;
}
async getSchema(schemaId) {
await this.initialize();
return this.data.schemas.get(schemaId) || null;
}
async listSchemas(issuerDID) {
await this.initialize();
if (!issuerDID) {
return Array.from(this.data.schemas.values());
}
return Array.from(this.data.schemas.values()).filter(schema => schema.issuerDID === issuerDID);
}
// General operations
async clear() {
await this.initialize();
this.data = {
dids: new Map(),
credentials: new Map(),
revocations: new Map(),
keyPairs: new Map(),
schemas: new Map(),
};
await this.save();
}
// Phone Number Operations
async storePhoneNumber(userDID, phoneNumber) {
throw new Error('Phone number storage not implemented in file provider lazy loader');
}
async getPhoneNumber(userDID, phoneId) {
throw new Error('Phone number retrieval not implemented in file provider lazy loader');
}
async listPhoneNumbers(userDID) {
throw new Error('Phone number listing not implemented in file provider lazy loader');
}
async updatePhoneNumber(userDID, phoneId, phoneNumber) {
throw new Error('Phone number update not implemented in file provider lazy loader');
}
async deletePhoneNumber(userDID, phoneId) {
throw new Error('Phone number deletion not implemented in file provider lazy loader');
}
// Address Operations
async storeAddress(userDID, address) {
throw new Error('Address storage not implemented in file provider lazy loader');
}
async getAddress(userDID, addressId) {
throw new Error('Address retrieval not implemented in file provider lazy loader');
}
async listAddresses(userDID) {
throw new Error('Address listing not implemented in file provider lazy loader');
}
async updateAddress(userDID, addressId, address) {
throw new Error('Address update not implemented in file provider lazy loader');
}
async deleteAddress(userDID, addressId) {
throw new Error('Address deletion not implemented in file provider lazy loader');
}
// Email Address Operations
async storeEmailAddress(userDID, emailAddress) {
throw new Error('Email address storage not implemented in file provider lazy loader');
}
async getEmailAddress(userDID, emailId) {
throw new Error('Email address storage not implemented in file provider lazy loader');
}
async listEmailAddresses(userDID) {
throw new Error('Email address storage not implemented in file provider lazy loader');
}
async updateEmailAddress(userDID, emailId, emailAddress) {
throw new Error('Email address storage not implemented in file provider lazy loader');
}
async deleteEmailAddress(userDID, emailId) {
throw new Error('Email address storage not implemented in file provider lazy loader');
}
}
exports.FileStorageProvider = FileStorageProvider;
//# sourceMappingURL=file-storage-provider-lazy.js.map