Azure Key Vault & HMAC Signing
Azure Key Vault is the root of trust for VeriProof’s key material. Every secret, encryption key, signing key, and connection string is stored in Key Vault and accessed at runtime via Azure Managed Identity — no credentials live in configuration files, environment variables, or version control.
What is stored in Key Vault
| Secret | Pattern | Used by |
|---|---|---|
| PostgreSQL connection strings | {env}-pg-connection-{schema} | All Function Apps |
| Content encryption master key | {env}-content-encryption-key | Ingest Functions |
| Deployment context signing key | {env}-deployment-context-signing-key | Customer Portal API, static config generator |
| Webhook HMAC signing key | {env}-webhook-hmac-key | Customer Portal Functions |
| Solana treasury keypair | {env}-solana-treasury-keypair | Treasury Functions |
| JWT signing key | {env}-jwt-signing-key | Customer Portal Functions |
{env} is the deployment environment prefix (dev, staging, prod).
Access pattern: Managed Identity
Applications access Key Vault using Azure Managed Identity — a cryptographic identity assigned to each Function App by Azure Active Directory. No client ID/secret pair is ever stored in code:
// In Program.cs — the managed identity is resolved automatically from the environment
var keyVaultUri = new Uri(configuration["KeyVault:Uri"]);
var credential = new DefaultAzureCredential();
builder.Configuration.AddAzureKeyVault(keyVaultUri, credential);In local development, DefaultAzureCredential falls through to the developer’s Azure CLI login or VS Code credential. In production, it uses the Function App’s system-assigned managed identity.
Dynamic key rotation with ApiKeyProvider
For the VeriProof API key used by the .NET SDK in customer applications, the ApiKeyProvider delegate pattern allows seamless rotation:
services.AddVeriproof(options =>
{
options.ApiKeyProvider = async (ct) =>
{
var secret = await secretClient.GetSecretAsync("veriproof-api-key", cancellationToken: ct);
return secret.Value.Value;
};
options.ApiKeyProviderTtl = TimeSpan.FromMinutes(5); // Cache for 5 minutes
});When you rotate the key in Key Vault, the SDK picks up the new value within the TTL window without requiring a restart.
HMAC-SHA256 signing
VeriProof uses HMAC-SHA256 for two purposes:
Webhook payload signing
Every outbound webhook request includes an X-VeriProof-Signature header:
X-VeriProof-Signature: sha256=<hex-digest>The hex digest is HMAC-SHA256 of the raw request body, using the account’s webhook signing key. Verify it in your receiver:
import hmac
import hashlib
def verify_webhook(body: bytes, signature_header: str, secret: str) -> bool:
expected = "sha256=" + hmac.new(
secret.encode(),
body,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature_header)Use hmac.compare_digest (or its equivalent in your language) to prevent timing attacks.
Deployment context signing
The static deployment-config.json file served by the Customer Portal is signed with HMAC-SHA256 to prevent tampering. The frontend validates the signature before trusting any field in the file. The signing key is a 64-byte base64-encoded key stored in Key Vault, never in the static file itself.
Encryption key hierarchy
Azure Key Vault
└── Content encryption master key (per-environment)
│
▼ HKDF-SHA256(master, tenant_id + session_id)
│
Per-session content sub-key (in-memory only, never stored)
│
▼ AES-256-GCM
│
Encrypted ciphertext in PostgreSQLThe master key never leaves Key Vault — HKDF derivation is performed in-process using the key material returned by Key Vault. The per-session sub-key exists only in application memory during the encryption/decryption operation.
Customer-managed keys (Enterprise)
Enterprise customers who deploy VeriProof as an Azure Managed Application can configure customer-managed keys (CMK) for their Key Vault, giving them full control over the key lifecycle:
- Key generation: Customer generates keys in their own Azure subscription’s Key Vault
- Access grant: Customer grants VeriProof’s managed application identity access to specific keys with minimum required permissions (
get,wrapKey,unwrapKey) - Rotation: Customer performs key rotation; VeriProof’s application picks up the new version automatically
- Revocation: Customer can revoke the key grant at any time, rendering encrypted data undecryptable
CMK deployment is configured during Azure Managed Application provisioning via the provisioning wizard.
CMK revocation is a destructive, irreversible action for the data protected by that key. Revoke only when the intent is permanent data destruction (e.g., as part of GDPR erasure or contract termination).
Next steps
- Encryption at Rest — how the master key is used to encrypt stored data
- Deployment Context Security — signing the static deployment config
- GDPR Cryptographic Erasure — using CMK revocation as part of erasure