3.2.2 • Published 5 months ago

@empe/empe-did-resolver v3.2.2

Weekly downloads
-
License
MIT
Repository
github
Last release
5 months ago

@empe/empe-did-resolver

A TypeScript implementation of a DID resolver for the did:empe method, following the W3C Decentralized Identifiers (DIDs) specification.

Overview

This package provides a resolver for the Empe DID method (did:empe), enabling resolution of DIDs to their corresponding DID Documents. It implements the did-resolver interface, making it compatible with the broader DID ecosystem.

The resolver supports both off-chain and blockchain-based resolution strategies, providing flexibility in how DIDs are managed and resolved. It serves as a critical component in the Empe Self-Sovereign Identity (SSI) infrastructure, enabling verification of identities and credentials.

Features

  • DID Resolution: Resolve DIDs using the did:empe method
  • Blockchain Integration: Support for resolving DIDs stored on the blockchain
  • Off-chain Resolution: Support for resolving DIDs stored off-chain
  • Verification Method Validation: Comprehensive validation of verification methods and cryptographic proofs
  • VC/VP Validation: Robust validators for Verifiable Credentials and Verifiable Presentations
  • Error Handling: Standardized error handling for resolution failures
  • Network Support: Configuration for different networks (testnet, mainnet)

Installation

npm install @empe/empe-did-resolver
# or
yarn add @empe/empe-did-resolver

Dependencies

This package has the following peer dependencies:

  • did-resolver: ^4.1.0
  • @empe/blockchain-client: ^3.1.0

Usage

Basic Usage

import { Resolver } from 'did-resolver';
import { resolveDid } from '@empe/empe-did-resolver';

// Create a resolver with the empe method
const resolver = new Resolver({
    empe: resolveDid,
});

// Resolve a DID
const didDocument = await resolver.resolve('did:empe:testnet:97eec7696b23ee18aece64af6c6cfc595af94fd4');
console.log(didDocument);

Using the DidResolver Class

import { DidResolver } from '@empe/empe-did-resolver';

// Create a resolver that only supports the 'empe' method
const resolver = new DidResolver(['empe']);

// Resolve a DID
const didDocument = await resolver.resolve('did:empe:testnet:97eec7696b23ee18aece64af6c6cfc595af94fd4');
console.log(didDocument);

Verifying Verifiable Credentials

import { DidResolver, VcValidators } from '@empe/empe-did-resolver';
import { VerifiableCredential, CoreDID } from '@empe/identity';

const resolver = new DidResolver(['empe']);
const vcValidator = new VcValidators(resolver);

// Load a credential and validate it
const credential = VerifiableCredential.fromJSON(vcJson);
const holderDid = CoreDID.parse('did:empe:testnet:97eec7696b23ee18aece64af6c6cfc595af94fd4');

try {
    await vcValidator.validateVc(credential, holderDid);
    console.log('Credential is valid');
} catch (error) {
    console.error('Credential validation failed:', error.message);
}

Verifying Verifiable Presentations

import { DidResolver, VpValidator } from '@empe/empe-did-resolver';
import { VerifiablePresentation } from '@empe/identity';

const resolver = new DidResolver(['empe']);
const vpValidator = new VpValidator(resolver);

// Load a presentation and validate it
const presentation = VerifiablePresentation.fromJSON(vpJson);

try {
    await vpValidator.validateVp(presentation);
    console.log('Presentation is valid');
} catch (error) {
    console.error('Presentation validation failed:', error.message);
}

Real-World Example: Verifier Service

Here's a complete example of how to use the resolver in a verifier service that validates presentations:

import express from 'express';
import { DidResolver, VpValidator } from '@empe/empe-did-resolver';
import { VerifiablePresentation } from '@empe/identity';

const app = express();
app.use(express.json());

// Initialize the resolver and validator
const didResolver = new DidResolver(['empe']);
const vpValidator = new VpValidator(didResolver);

// Endpoint to verify a presentation
app.post('/verify', async (req, res) => {
    try {
        const { presentation } = req.body;

        if (!presentation) {
            return res.status(400).json({ error: 'Missing presentation in request body' });
        }

        // Parse the presentation
        const vp = VerifiablePresentation.fromJSON(presentation);

        // Validate the presentation
        await vpValidator.validateVp(vp);

        // Extract credentials for further processing
        const credentials = vp.verifiableCredentials();

        // Process the credentials as needed
        const credentialInfo = credentials.map(vc => {
            const vcJson = vc.toJSON();
            return {
                id: vc.id(),
                type: vcJson.type,
                issuer: vcJson.issuer.id,
                issuanceDate: vcJson.issuanceDate,
            };
        });

        return res.status(200).json({
            status: 'valid',
            holder: vp.holder().toString(),
            credentials: credentialInfo,
        });
    } catch (error) {
        console.error('Verification failed:', error);
        return res.status(400).json({
            status: 'invalid',
            error: error.message,
        });
    }
});

app.listen(3000, () => {
    console.log('Verifier service running on port 3000');
});

Resolution Process

The resolver follows a specific process when resolving a DID:

  1. Parse the DID: The DID is parsed to extract the method, network, and identifier
  2. Blockchain Resolution: First, the resolver attempts to find the DID document on the blockchain
  3. Off-chain Fallback: If not found on the blockchain, it attempts to resolve the DID off-chain
  4. Document Transformation: The resolved document is transformed into the standard DID Document format
  5. Verification Method Processing: Verification methods are processed and validated

This multi-step approach ensures maximum flexibility and reliability in DID resolution.

Resolution Flow Diagram

┌─────────────┐     ┌─────────────────────┐     ┌───────────────────┐
│  Parse DID  │────▶│ Blockchain Resolution│────▶│ Off-chain Resolution│
└─────────────┘     └─────────────────────┘     └───────────────────┘
                              │                           │
                              │                           │
                              ▼                           ▼
                    ┌─────────────────────┐     ┌───────────────────┐
                    │ Document Found?     │     │ Document Found?   │
                    └─────────────────────┘     └───────────────────┘
                              │                           │
                              │                           │
                              ▼                           ▼
                    ┌─────────────────────┐     ┌───────────────────┐
                    │ Transform Document  │     │ Transform Document│
                    └─────────────────────┘     └───────────────────┘
                              │                           │
                              │                           │
                              ▼                           ▼
                    ┌─────────────────────────────────────────────┐
                    │              Return Result                  │
                    └─────────────────────────────────────────────┘

Network Configuration

The resolver supports different networks:

  • Testnet: Resolves DIDs on the Empe testnet (e.g., did:empe:testnet:97eec7696b23ee18aece64af6c6cfc595af94fd4)
  • Mainnet: Resolves DIDs on the Empe mainnet (e.g., did:empe:2dd09639bfbe85a8334c245d606cda48f70f6c82)

The network is specified in the DID itself. If no network is specified, the resolver defaults to mainnet.

API Reference

Core Resolution Functions

resolveDid(did: string, parsedDid: ParsedDID, _unused: Resolvable, _options: DIDResolutionOptions): Promise<DIDResolutionResult>

The main resolver function that implements the DID resolver interface. It attempts to resolve a DID document first from the blockchain, and if not found, falls back to off-chain resolution.

resolveOffChainDidDocument(did: string): Promise<DIDDocument | null>

Resolves a DID document stored off-chain.

resolveBlockchainDidDocument(did: string, parsedDid: ParsedDID): Promise<DIDDocument | null>

Resolves a DID document from the blockchain.

Classes

DidResolver

A class that provides DID resolution with the ability to specify supported methods.

class DidResolver {
    constructor(supportedMethods?: DidMethods, resolver?: Resolver);

    resolve(did: string): Promise<DIDDocument>;

    // Additional helper methods
}

VcValidators

A class for validating Verifiable Credentials, including proof validation.

class VcValidators {
    constructor(resolver: DidResolver);

    validateVc(vc: VerifiableCredential, holderDid: CoreDID): Promise<void>;

    // Additional validation methods
}

VpValidator

A class for validating Verifiable Presentations and their contained credentials.

class VpValidator {
    constructor(resolver: DidResolver);

    validateVp(vp: VerifiablePresentation): Promise<void>;

    validateVpHolderDid(vp: VerifiablePresentation): Promise<void>;

    // Additional validation methods
}

Utility Functions

  • transformCoreDocumentToDIDDocument: Transforms an internal document to standard format
  • transformCoreServiceToService: Transforms service endpoints to standard format
  • validateVerificationMethods: Validates verification methods in a DID document
  • filterVerificationMethods: Filters verification methods based on criteria
  • validateVerificationMethodPublicKey: Validates a verification method's public key
  • validateEcdsaSecp256k1RecoveryMethod2020: Validates ECDSA secp256k1 recovery methods
  • validateJsonWebKey: Validates JSON Web Keys

Error Handling

The resolver provides standardized error handling through the Errors object:

export const Errors = {
    notFound: 'notFound', // DID document not found
    invalidDid: 'invalidDid', // Invalid DID format
    unknownNetwork: 'unknownNetwork', // Network not supported
    unsupportedFormat: 'unsupportedFormat', // Document format not supported
};

Integration with Other Components

This resolver is designed to work seamlessly with other components in the Empe SSI ecosystem:

Verifier Service

The resolver is used by the verifier service to validate DIDs in Verifiable Presentations:

// In a verifier service
const didResolver = new DidResolver(['empe']);
const vpValidator = new VpValidator(didResolver);

// Validate a presentation
await vpValidator.validateVp(verifiablePresentation);

Issuer Service

The resolver is used by the issuer service to validate DIDs in authorization requests:

// In an issuer service
const didResolver = new DidResolver(['empe']);
const vcValidator = new VcValidators(didResolver);

// Validate a credential
await vcValidator.validateVc(verifiableCredential, holderDid);

Related Packages

This package works with other packages in the Empe ecosystem:

  • @empe/identity: Core identity types and utilities for DIDs, VCs, and VPs
  • @empe/blockchain-client: Client for interacting with the Empe blockchain
  • @empe/verifier-common: Common utilities for verifier services
  • @empe/verifier-client: Client for implementing verifier functionality

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT

3.2.2

5 months ago

3.2.1

5 months ago

3.2.0

5 months ago

3.1.0

8 months ago

3.0.0

8 months ago

2.3.0

8 months ago

2.2.0

8 months ago

2.1.0

8 months ago

2.0.3

9 months ago

2.0.2

9 months ago

2.0.1

9 months ago

2.0.0

9 months ago

1.0.0

11 months ago

0.0.5

11 months ago

0.0.4

1 year ago

0.0.3

1 year ago

0.0.2

1 year ago

0.0.1

1 year ago