Veriglob

A Dart implementation of the Veriglob decentralized identity protocol. This library provides core functionality for creating and managing Decentralized Identifiers (DIDs), Verifiable Credentials (VCs), and Verifiable Presentations (VPs).

Features

  • DID Operations: Create and resolve did:key identifiers using Ed25519 keys
  • Verifiable Credentials: Issue and verify W3C-compliant verifiable credentials
  • Verifiable Presentations: Create and verify presentations for selective disclosure
  • Encrypted Wallet: Secure storage for keys and credentials using AES-256-GCM
  • Revocation Registry: Track credential revocation status
  • Mnemonic Support: Derive keys from BIP39 mnemonic phrases

Getting Started

Add the dependency to your pubspec.yaml:

dependencies:
  veriglob: ^1.0.0

Usage

Generate Keys and Create a DID

import 'package:veriglob/veriglob.dart';

// Generate a new key pair
final keyPair = generateEd25519KeyPair();

// Create a DID from the public key
final did = createDIDKey(keyPair.publicKey);
print('DID: ${did.did}');
// Output: did:key:z6Mk...

Derive Keys from Mnemonic

const mnemonic = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about';

final derivedKeys = deriveKeysFromMnemonic(mnemonic);
final did = createDIDKey(derivedKeys.publicKey);

Issue a Verifiable Credential

// Create a credential subject
final subject = IdentitySubject(
  id: holderDid,
  givenName: 'Alice',
  familyName: 'Smith',
  dateOfBirth: '1990-01-15',
  nationality: 'US',
);

// Issue the credential
final vcToken = issueVC(
  issuerDid.did,       // Issuer's DID
  holderDid,           // Subject's DID
  issuerKeys.privateKey,
  subject,
  credentialId: generateCredentialId(),
);

Verify a Credential

try {
  final claims = verifyVC(vcToken, issuerPublicKey);
  print('Issuer: ${claims.issuer}');
  print('Subject: ${claims.vc.credentialSubject}');
} on VerificationException catch (e) {
  print('Verification failed: $e');
}

Create a Verifiable Presentation

// Generate a nonce for the verifier challenge
final nonce = generateNonce();

// Create a presentation containing one or more credentials
final vpToken = createPresentation(
  holderDid.did,
  holderKeys.privateKey,
  [vcToken],              // List of VC tokens
  'did:key:verifier123',  // Verifier's DID (audience)
  nonce,
);

Verify a Presentation

final vpClaims = verifyPresentation(
  vpToken,
  holderPublicKey,
  expectedAudience: 'did:key:verifier123',
  expectedNonce: nonce,
);

print('Holder: ${vpClaims.vp.holder}');
print('Credentials: ${vpClaims.vp.verifiableCredential.length}');

Wallet Management

// Create a new wallet
final wallet = await Wallet.create('/path/to/wallet.json', mnemonic);

// Store keys
await wallet.setKeys(keyPair.publicKey, keyPair.privateKey, did.did);

// Add a credential
await wallet.addCredential(StoredCredential(
  id: credentialId,
  type: 'IdentityCredential',
  issuerDid: issuerDid,
  token: vcToken,
  issuedAt: DateTime.now(),
  expiresAt: DateTime.now().add(Duration(days: 365)),
  storedAt: DateTime.now(),
));

// Open an existing wallet
final existingWallet = await Wallet.open('/path/to/wallet.json', mnemonic);

// Export wallet for backup
final backupJson = wallet.export();

Wallet Recovery

The library provides multiple ways to recover a wallet:

// Check if wallet exists
final exists = await Wallet.exists('/path/to/wallet.json');

// Recover wallet from mnemonic (DID and keys only)
// Use this when you've lost the wallet file but have your mnemonic
final recoveredWallet = await Wallet.recover('/path/to/new-wallet.json', mnemonic);

// Recover wallet from backup (includes credentials)
// Use this when you have a backup created via wallet.export()
final restoredWallet = await Wallet.recoverFromBackup(
  '/path/to/new-wallet.json',
  mnemonic,
  backupJson,
);

// Open or recover (tries to open first, recovers if not found)
// Convenient for app startup
final wallet = await Wallet.openOrRecover('/path/to/wallet.json', mnemonic);

Important: The mnemonic phrase is the only way to recover your wallet. Store it securely offline. Credentials cannot be recovered from the mnemonic alone - create regular backups using wallet.export() to preserve your credentials.

Revocation Registry

// Create a registry
final registry = RevocationRegistry();

// Register a credential
await registry.register(credentialId, issuerDid, subjectDid);

// Check if revoked
final isRevoked = registry.isRevoked(credentialId);

// Revoke a credential
await registry.revoke(credentialId, 'Credential compromised');

Credential Subject Types

The library includes four predefined credential subject types:

Type Description
IdentitySubject KYC/identity verification credentials
EducationSubject Educational credentials (degrees, certificates)
EmploymentSubject Employment verification credentials
MembershipSubject Organization membership credentials

Enterprise Features

Verification Request Widgets

These Flutter widgets enable enterprise verification flows where verifiers can request credential presentations from holders via QR codes.

Note: Enterprise features require a verifier public key obtained from the Veriglob enterprise dashboard.

VerificationQrDisplay

Displays a QR code containing a verification request. Used by verifiers (enterprises) to request credentials from holders.

import 'package:veriglob/veriglob.dart';

// Create a verification request
final request = VerificationRequest(
  requestId: generateUuid(),
  verifierDid: verifierDid,
  verifierName: 'Acme Corporation',
  claimDemands: [
    ClaimDemand(
      claimType: ClaimType.identity,
      required: true,
      fields: ['givenName', 'familyName', 'dateOfBirth'],
    ),
  ],
  callbackUrl: 'https://api.acme.com/verify',
  expiresAt: DateTime.now().add(Duration(minutes: 5)),
);

// Display the QR code
VerificationQrDisplay(
  request: request,
  size: 280,
  title: 'Scan to Verify Identity',
  subtitle: 'Present your identity credential',
  onExpired: () {
    // Handle expiration - regenerate request
  },
);

VerificationScanner

Scans verification request QR codes. Used by credential holders to receive verification requests.

VerificationScanner(
  onRequestScanned: (VerificationRequest request) {
    // Handle the scanned verification request
    print('Verifier: ${request.verifierName}');
    print('Requesting: ${request.claimDemands.length} credentials');
  },
  onError: (String error) {
    // Handle scan errors
    print('Scan error: $error');
  },
  overlayText: 'Scan verification QR code',
);

CredentialPresentationSheet

A bottom sheet that allows users to select which credentials to present in response to a verification request.

// Show the presentation sheet
showModalBottomSheet(
  context: context,
  isScrollControlled: true,
  builder: (context) => CredentialPresentationSheet(
    request: verificationRequest,
    availableCredentials: userCredentials,  // List<StoredCredential>
    holderDid: holderDid,
    holderPrivateKey: holderPrivateKey,
    onPresentationCreated: (String vpToken) async {
      // Send the presentation to the verifier's callback URL
      await sendPresentation(vpToken, verificationRequest.callbackUrl);
    },
    onCancel: () => Navigator.pop(context),
  ),
);

Complete Verification Flow

// 1. VERIFIER: Create and display verification request
final request = VerificationRequest(
  requestId: generateUuid(),
  verifierDid: enterpriseDid,
  verifierName: 'Enterprise Name',
  claimDemands: [
    ClaimDemand(claimType: ClaimType.identity, required: true),
  ],
  callbackUrl: 'https://api.enterprise.com/verify',
  expiresAt: DateTime.now().add(Duration(minutes: 5)),
);

// Display QR code widget...

// 2. HOLDER: Scan the QR code
VerificationScanner(
  onRequestScanned: (request) {
    // Show credential selection sheet
    showCredentialSheet(request);
  },
);

// 3. HOLDER: Select and present credentials
CredentialPresentationSheet(
  request: request,
  availableCredentials: myCredentials,
  holderDid: myDid,
  holderPrivateKey: myPrivateKey,
  onPresentationCreated: (vpToken) async {
    // Send to verifier
    await http.post(
      Uri.parse(request.callbackUrl!),
      body: jsonEncode(VerificationResponse(
        requestId: request.requestId,
        presentationToken: vpToken,
        holderDid: myDid,
      ).toJson()),
    );
  },
);

// 4. VERIFIER: Verify the presentation on backend
final vpClaims = verifyPresentation(
  vpToken,
  holderPublicKey,
  expectedAudience: enterpriseDid,
  expectedNonce: request.nonce,
);

API Reference

Crypto

  • generateEd25519KeyPair() - Generate a new Ed25519 key pair
  • generateEd25519KeyPairFromSeed(seed) - Generate keys from a 32-byte seed
  • deriveKeysFromMnemonic(mnemonic) - Derive keys from a BIP39 mnemonic
  • signEd25519(message, privateKey) - Sign a message
  • verifyEd25519(message, signature, publicKey) - Verify a signature

DID

  • createDIDKey(publicKey) - Create a did:key from a public key
  • resolveDID(did) - Resolve a DID to its public key

Credentials

  • issueVC(issuerDid, subjectDid, privateKey, subject, {credentialId}) - Issue a VC
  • verifyVC(token, publicKey) - Verify a VC token

Presentations

  • createPresentation(holderDid, privateKey, credentials, audience, nonce) - Create a VP
  • verifyPresentation(token, publicKey, {expectedAudience, expectedNonce}) - Verify a VP
  • generateNonce() - Generate a random challenge nonce

Storage

  • Wallet.create(path, mnemonic) - Create a new encrypted wallet
  • Wallet.open(path, mnemonic) - Open an existing wallet
  • Wallet.exists(path) - Check if a wallet exists at the given path
  • Wallet.recover(path, mnemonic) - Recover wallet from mnemonic (DID/keys only)
  • Wallet.recoverFromBackup(path, mnemonic, backupJson) - Recover from exported backup
  • Wallet.openOrRecover(path, mnemonic) - Open if exists, otherwise recover
  • wallet.export() - Export wallet data as JSON for backup

Revocation

  • RevocationRegistry() - Create an in-memory registry
  • RevocationRegistry.withFile(path) - Create a file-backed registry
  • generateCredentialId() - Generate a unique credential ID

License

MIT License - see LICENSE file for details.

Libraries

veriglob
Veriglob decentralized identity protocol - Dart implementation.