Skip to content

Key Management

import { vvs } from '@venmail/vsm';
const keyPair = vvs.generateKeyPair();
console.log('Public key (base64url):', keyPair.publicKeyBase64url);
console.log('Private key length:', keyPair.privateKey.length); // DER-encoded
// Store privateKey securely (e.g., environment variable, vault)
// Publish publicKeyBase64url via well-known or DNS
Section titled “Method 1: Well-known endpoint (recommended)”

Serve a JSON response at:

GET https://yourdomain.com/.well-known/venmail-agent/{agent-name}

Response:

{
"agent_id": "[email protected]",
"public_key": "MCowBQYDK2VwAyEA...",
"key_version": 1,
"status": "active",
"algorithm": "ed25519"
}

The SDKs include middleware to serve this automatically:

import { venmailWellKnown } from '@venmail/vsm';
app.use(venmailWellKnown(async (agentName) => {
const key = await db.getAgentKey(agentName);
if (!key) return null;
return {
agent_id: `${agentName}@yourdomain.com`,
public_key: key.publicKeyBase64url,
key_version: key.version,
status: 'active',
algorithm: 'ed25519',
};
}));

Add a TXT record on _venmail.yourdomain.com:

v=VVS1; agent=billing; pubkey=MCowBQYDK2VwAyEA...; kv=1; status=active

Generate the record with the SDK:

import { generateDnsRecord } from '@venmail/vsm';
const record = generateDnsRecord('billing', keyPair.publicKeyBase64url, 1);
// "v=VVS1; agent=billing; pubkey=MCowBQYDK2VwAyEA...; kv=1; status=active"

Method 3: Embedded header (bootstrapping only)

Section titled “Method 3: Embedded header (bootstrapping only)”

Include the public key directly in the email via X-Venmail-Public-Key. This is lowest trust — use only when well-known/DNS aren’t yet propagated.

  1. Generate a new keypair with an incremented key_version
  2. Publish the new key at well-known/DNS at least 24 hours before retiring the old key
  3. Start signing with the new key
  4. Keep the old key resolvable for up to 7 days for messages in transit
  5. Set old key status to rotated

Set status: "revoked" in your well-known response or DNS record. This takes effect immediately for any receiver that resolves the key after that point.

{
"agent_id": "[email protected]",
"public_key": "MCowBQYDK2VwAyEA...",
"key_version": 1,
"status": "revoked"
}