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:keyidentifiers 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 pairgenerateEd25519KeyPairFromSeed(seed)- Generate keys from a 32-byte seedderiveKeysFromMnemonic(mnemonic)- Derive keys from a BIP39 mnemonicsignEd25519(message, privateKey)- Sign a messageverifyEd25519(message, signature, publicKey)- Verify a signature
DID
createDIDKey(publicKey)- Create a did:key from a public keyresolveDID(did)- Resolve a DID to its public key
Credentials
issueVC(issuerDid, subjectDid, privateKey, subject, {credentialId})- Issue a VCverifyVC(token, publicKey)- Verify a VC token
Presentations
createPresentation(holderDid, privateKey, credentials, audience, nonce)- Create a VPverifyPresentation(token, publicKey, {expectedAudience, expectedNonce})- Verify a VPgenerateNonce()- Generate a random challenge nonce
Storage
Wallet.create(path, mnemonic)- Create a new encrypted walletWallet.open(path, mnemonic)- Open an existing walletWallet.exists(path)- Check if a wallet exists at the given pathWallet.recover(path, mnemonic)- Recover wallet from mnemonic (DID/keys only)Wallet.recoverFromBackup(path, mnemonic, backupJson)- Recover from exported backupWallet.openOrRecover(path, mnemonic)- Open if exists, otherwise recoverwallet.export()- Export wallet data as JSON for backup
Revocation
RevocationRegistry()- Create an in-memory registryRevocationRegistry.withFile(path)- Create a file-backed registrygenerateCredentialId()- Generate a unique credential ID
License
MIT License - see LICENSE file for details.
Libraries
- veriglob
- Veriglob decentralized identity protocol - Dart implementation.