atp-sdk
Version:
Official TypeScript SDK for Agent Trust Protocol™ - Build secure, verifiable, and trustworthy applications with decentralized identity, verifiable credentials, and robust access control
225 lines • 7.75 kB
JavaScript
import { CryptoUtils } from './crypto.js';
/**
* DID utilities for ATP™ SDK
*/
export class DIDUtils {
/**
* Generate a new ATP DID
*/
static async generateDID(options) {
const network = options?.network || 'mainnet';
const method = options?.method || 'atp';
const keyPair = await CryptoUtils.generateKeyPair();
const fingerprint = CryptoUtils.createKeyFingerprint(keyPair.publicKey);
const did = `did:${method}:${network}:${fingerprint}`;
const document = {
id: did,
'@context': ['https://www.w3.org/ns/did/v1'],
verificationMethod: [{
id: `${did}#key-1`,
type: 'Ed25519VerificationKey2020',
controller: did,
publicKeyMultibase: this.encodeMultibase(keyPair.publicKey)
}],
authentication: [`${did}#key-1`],
assertionMethod: [`${did}#key-1`],
keyAgreement: [`${did}#key-1`]
};
return {
did,
document,
keyPair
};
}
/**
* Parse a DID string
*/
static parseDID(did) {
const didRegex = /^did:([^:]+):([^:]+):([^#]+)(?:#(.+))?$/;
const match = did.match(didRegex);
if (!match) {
return null;
}
return {
method: match[1],
network: match[2],
identifier: match[3],
fragment: match[4]
};
}
/**
* Validate DID format
*/
static isValidDID(did) {
return this.parseDID(did) !== null;
}
/**
* Extract public key from DID document
*/
static extractPublicKey(document, keyId) {
const targetKeyId = keyId || `${document.id}#key-1`;
const verificationMethod = document.verificationMethod?.find(vm => vm.id === targetKeyId);
if (!verificationMethod) {
return null;
}
if (verificationMethod.publicKeyMultibase) {
return this.decodeMultibase(verificationMethod.publicKeyMultibase);
}
if (verificationMethod.publicKeyJwk) {
// Convert JWK to hex (simplified)
const jwk = verificationMethod.publicKeyJwk;
if (jwk.x) {
return Buffer.from(jwk.x, 'base64url').toString('hex');
}
}
return null;
}
/**
* Add verification method to DID document
*/
static addVerificationMethod(document, publicKey, purposes = ['authentication']) {
const keyNumber = document.verificationMethod.length + 1;
const keyId = `${document.id}#key-${keyNumber}`;
const verificationMethod = {
id: keyId,
type: 'Ed25519VerificationKey2020',
controller: document.id,
publicKeyMultibase: this.encodeMultibase(publicKey)
};
const updatedDocument = { ...document };
updatedDocument.verificationMethod = [...document.verificationMethod, verificationMethod];
// Add to specified purposes
purposes.forEach(purpose => {
if (!updatedDocument[purpose]) {
updatedDocument[purpose] = [];
}
updatedDocument[purpose].push(keyId);
});
return updatedDocument;
}
/**
* Create DID resolution result
*/
static createResolutionResult(document, metadata) {
return {
'@context': 'https://w3id.org/did-resolution/v1',
didDocument: document,
didDocumentMetadata: {
created: new Date().toISOString(),
updated: new Date().toISOString(),
...metadata
},
didResolutionMetadata: {
contentType: 'application/did+ld+json'
}
};
}
/**
* Sign DID document
*/
static async signDIDDocument(document, privateKey, keyId) {
const targetKeyId = keyId || `${document.id}#key-1`;
const documentJson = JSON.stringify(document, null, 2);
const signature = await CryptoUtils.signData(documentJson, privateKey);
// Add proof to document
const signedDocument = {
...document,
proof: {
type: 'Ed25519Signature2020',
created: new Date().toISOString(),
verificationMethod: targetKeyId,
proofPurpose: 'assertionMethod',
proofValue: signature
}
};
return signedDocument;
}
/**
* Verify DID document signature
*/
static async verifyDIDDocument(document) {
if (!document.proof) {
return false;
}
const { proof, ...documentWithoutProof } = document;
const publicKey = this.extractPublicKey(document, proof.verificationMethod);
if (!publicKey) {
return false;
}
const documentJson = JSON.stringify(documentWithoutProof, null, 2);
return CryptoUtils.verifySignature(documentJson, proof.proofValue, publicKey);
}
/**
* Create service endpoint
*/
static createServiceEndpoint(id, type, serviceEndpoint) {
return {
id,
type,
serviceEndpoint
};
}
/**
* Encode public key as multibase
*/
static encodeMultibase(publicKeyHex) {
// Simplified multibase encoding (base58btc)
const publicKeyBuffer = Buffer.from(publicKeyHex, 'hex');
// In a real implementation, this would use proper multibase encoding
return 'z' + publicKeyBuffer.toString('base64url');
}
/**
* Decode multibase public key
*/
static decodeMultibase(multibase) {
// Simplified multibase decoding
if (multibase.startsWith('z')) {
const base64url = multibase.slice(1);
return Buffer.from(base64url, 'base64url').toString('hex');
}
throw new Error('Unsupported multibase encoding');
}
/**
* Generate DID from public key
*/
static didFromPublicKey(publicKey, options) {
const network = options?.network || 'mainnet';
const method = options?.method || 'atp';
const fingerprint = CryptoUtils.createKeyFingerprint(publicKey);
return `did:${method}:${network}:${fingerprint}`;
}
/**
* Validate DID document structure
*/
static validateDIDDocument(document) {
const errors = [];
if (!document.id || typeof document.id !== 'string') {
errors.push('Missing or invalid id');
}
if (!document['@context'] || !Array.isArray(document['@context'])) {
errors.push('Missing or invalid @context');
}
if (!document.verificationMethod || !Array.isArray(document.verificationMethod)) {
errors.push('Missing or invalid verificationMethod');
}
if (!document.authentication || !Array.isArray(document.authentication)) {
errors.push('Missing or invalid authentication');
}
// Validate verification methods
if (document.verificationMethod) {
document.verificationMethod.forEach((vm, index) => {
if (!vm.id || !vm.type || !vm.controller) {
errors.push(`Invalid verification method at index ${index}`);
}
if (!vm.publicKeyMultibase && !vm.publicKeyJwk) {
errors.push(`Missing public key in verification method at index ${index}`);
}
});
}
return {
valid: errors.length === 0,
errors
};
}
}
//# sourceMappingURL=did.js.map