#ssh #key-derivation #bip-32 #ed25519 #ssh-key

bin+lib hdpki

Hierarchical deterministic key derivation for OpenSSH and X.509

2 unstable releases

0.4.0 Feb 16, 2026
0.3.0 Feb 13, 2026

#4 in #bip-32

Apache-2.0

48KB
1K SLoC

hdpki

Hierarchical deterministic key derivation for OpenSSH and X.509. Derives ed25519 keys from a master seed using HMAC-SHA512 chain codes (BIP-32 style), producing both OpenSSH keys and X.509 certificates from the same deterministic key tree.

Features

  • BIP-32-style HD derivation with HMAC-SHA512 chain codes for ed25519
  • BIP-39 mnemonic generation and recovery
  • OpenSSH key output (private key + authorized_keys format)
  • X.509 certificate generation (self-signed or CA-signed)
  • Canonical path validation: m/ssh/<principal>/<domain>/<host>/<bucket>

CLI usage

The hdpki binary supports generating master seeds, deriving SSH keys, and creating X.509 certificates.

# Generate a new master seed and write it to master.seed (base64 encoded)
hdpki master --output master.seed

# Create a BIP-39 mnemonic and print it alongside the seed
hdpki master --bip39

# Derive an SSH key for a canonical HD path
hdpki derive \
  -m master.seed \
  -p m/ssh/user:alice/example.com/bastion.example.com/1700000000 \
  -o id_ed25519 \
  -A id_ed25519.pub

# Generate a self-signed X.509 certificate
hdpki cert \
  -m master.seed \
  -p m/ssh/user:alice/example.com/bastion.example.com/1700000000 \
  --cn "alice@example.com" \
  --san-dns bastion.example.com \
  -o cert.pem \
  -k key.pem

# Generate a CA certificate
hdpki cert \
  -m master.seed \
  -p m/ssh/user:ca/example.com/ca.example.com/1 \
  --cn "Example CA" --org "Example Corp" \
  --ca --days 3650 \
  -o ca.pem -k ca-key.pem

# Sign a leaf certificate with the CA
hdpki cert \
  -m master.seed \
  -p m/ssh/user:web/example.com/web.example.com/1 \
  --cn "web.example.com" \
  --san-dns web.example.com \
  --issuer-path m/ssh/user:ca/example.com/ca.example.com/1 \
  --issuer-cert ca.pem \
  --days 90 \
  -o leaf.pem -k leaf-key.pem

Library usage

use hdpki::{master, X509Params};

let seed = b"my-secret-master-seed-material";
let root = master(seed).unwrap();

// Derive a node and get SSH material
let node = root.derive("m/ssh/user:alice/example.com/bastion.example.com/1").unwrap();
let material = node.ed25519().unwrap();

// Generate a self-signed X.509 certificate
let params = X509Params {
    common_name: "alice@example.com".to_string(),
    san_dns_names: vec!["bastion.example.com".to_string()],
    ..Default::default()
};
let cert = node.x509_self_signed(&params).unwrap();
println!("{}", cert.cert_pem);

Path format

The canonical derivation path follows this structure:

m/ssh/<principal>/<domain>/<host>/<bucket>
  • principal: user:<name> or host:<name>
  • domain: Fully qualified domain (e.g., example.com)
  • host: Must be within the domain (e.g., bastion.example.com)
  • bucket: Numeric value for key rotation (e.g., epoch timestamp)

Use --raw-path (or -r) to bypass strict validation.

License

Apache-2.0

Dependencies

~16–30MB
~525K SLoC