eVault Key Delegation
This document explains how the eVault system delegates cryptographic keys for signing. It covers key generation, syncing public keys to eVault, and key binding certificates.
Overview
The eVault system enables users to sign data using keys stored in their eID wallet. The public keys are synced to eVault and bound to the user's eName (W3ID) through key binding certificates (issued by the Registry). This allows any service to verify signatures by retrieving the public key from eVault.
Key Delegation Flow
Key Generation
Keys are generated in the eID wallet during onboarding or pre-verification. The system supports two types of key managers:
- Hardware Key Manager: Uses Native iOS/Android APIs for hardware-backed keys
- Software Key Manager: Uses Web Crypto API to generate software keys
Both generate ECDSA P-256 key pairs with SHA-256 hashing.
The default key ID is "default" and is used for all signing operations.
Setting Keys During eVault Creation
During the eVault provisioning process (onboarding), the public key can be set directly when creating the eVault. The /provision endpoint accepts a publicKey parameter:
Provision Request:
POST /provision
Content-Type: application/json
{
"registryEntropy": "<entropy-token>",
"namespace": "<w3id>",
"verificationId": "<verification-code>",
"publicKey": "z3059301306072a8648ce3d020106082a8648ce3d03010703420004..."
}
When provisioning an eVault during onboarding, the eID wallet:
- Generates or retrieves the public key using
getApplicationPublicKey() - Includes the
publicKeyin the provision request - The eVault stores the public key and generates a key binding certificate automatically
This eliminates the need for a separate sync step when the eVault is first created.
Syncing Public Keys to eVault
The public key syncing is an autonomous process done by the eID Wallet when linking new devices to the same eName.
Key Binding Certificates
Key binding certificates are JWTs that cryptographically bind a public key to an eName. They are generated by the Registry service and stored in eVault.
Certificate Structure:
- Header:
{ alg: "ES256", kid: "entropy-key-1" } - Payload:
{ ename: "@user.w3id", publicKey: "z..." } - Signature: Signed by Registry's private key (ES256)
The certificate can be verified using the Registry's JWKS endpoint at /.well-known/jwks.json.
eVault Endpoints
The following endpoints are provided by eVault:
PATCH /public-key
Stores a public key in eVault for a given eName.
Request:
PATCH /public-key
X-ENAME: @user.w3id
Authorization: Bearer <token>
Content-Type: application/json
{
"publicKey": "z3059301306072a8648ce3d020106082a8648ce3d03010703420004..."
}
Response:
200 OK: Public key stored successfully400 Bad Request: Missing X-ENAME header or invalid request401 Unauthorized: Invalid or missing authentication token
GET /whois
Retrieves key binding certificates for a given eName.
Request:
GET /whois
X-ENAME: @user.w3id
Response:
{
"w3id": "@user.w3id",
"keyBindingCertificates": [
"eyJhbGciOiJFUzI1NiIsImtpZCI6ImVudHJvcHkta2V5LTEifQ.eyJlbmFtZSI6IkB1c2VyLnczaWQiLCJwdWJsaWNLZXkiOiJ6MzA1OTMwMTMwNjA3MmE4NjQ4Y2UzZDAyMDEwNjA4MmE4NjQ4Y2UzZDAzMDEwNzAzNDIwMDA0Li4uIn0..."
]
}
Code Examples
Setting Public Key During eVault Creation
// During onboarding - provision eVault with public key
const publicKey = await getApplicationPublicKey(); // Get public key from KeyService
const provisionResponse = await axios.post(
new URL("/provision", provisionerUrl).toString(),
{
registryEntropy,
namespace: uuidv4(),
verificationId,
publicKey: publicKey, // Public key included in provision request
}
);
// eVault is created with the public key already stored
const { w3id, uri } = provisionResponse.data;
Syncing a Public Key to eVault (After Creation)
// In eID wallet - sync public key to existing eVault
const vaultController = new VaultController(keyService, userController);
const eName = "@user.w3id";
// Sync public key (automatically checks if already exists)
await vaultController.syncPublicKey(eName);
Retrieving Key Binding Certificates
// Resolve eVault URL
const resolveUrl = new URL(
`/resolve?w3id=${encodeURIComponent(eName)}`,
registryBaseUrl
).toString();
const resolveResponse = await axios.get(resolveUrl);
const evaultUrl = resolveResponse.data.uri;
// Get certificates from eVault
const whoisUrl = new URL("/whois", evaultUrl).toString();
const whoisResponse = await axios.get(whoisUrl, {
headers: { "X-ENAME": eName }
});
const certificates = whoisResponse.data.keyBindingCertificates;
// Array of JWT tokens
Security Considerations
-
Key Storage: Private keys are never transmitted or stored in eVault. Only public keys are synced.
-
Certificate Validity: Key binding certificates expire after 1 hour. eVault regenerates them on-demand when requested.
-
Multiple Keys: Users can have multiple devices, each with its own key pair. All valid keys can verify signatures.
-
Key Rotation: When users add new devices, new keys are added without invalidating old ones, allowing graceful key rotation.
References
- eID Wallet - Key generation and syncing
- eVault - Storage,
/whois, and key binding - Registry - Key binding certificate issuance