- 1. Introduction
- 2. Phase 1: Key Generation
- 3. Phase 2: DNS Configuration
- 4. Phase 3: TLS Server Configuration
- 5. Phase 4: Client Verification
- 6. Phase 5: Maintenance
- 7. Troubleshooting
- 8. Quick Reference Commands
- 9. Appendix: DNS Provider Support Matrix
- 10. Next Steps
This guide walks you through deploying the Explicit Trust Plane from scratch—from key generation to DNS publication to TLS configuration and client verification.
-
A registered domain with DNS hosting that supports:
-
CERT records
-
IPSECKEY records
-
TLSA records
-
DNSSEC signing
-
-
OpenSSL 3.0+ installed
-
GnuPG 2.2+ installed
-
A server for TLS deployment
git clone https://github.com/hyperpolymath/explicit-trust-plane.git
cd explicit-trust-plane|
Caution
|
The Root CA private key must be kept offline after generation. Consider:
|
# Replace with your actual domain
export DOMAIN="example.com"
# Generate Root CA (10 years) and Intermediate CA (5 years)
./scripts/generate-ca.sh "${DOMAIN}"Expected output:
=== Explicit Trust Plane - CA Generation ===
Domain: example.com
Root validity: 3650 days
Intermediate validity: 1825 days
[1/4] Generating Ed448 Root CA private key...
[2/4] Generating Root CA certificate...
[3/4] Generating Ed448 Intermediate CA private key...
[4/4] Generating Intermediate CA certificate...
=== CA Generation Complete ===
Root CA:
Private key: ca/root/ca-ed448.key (KEEP OFFLINE!)
Certificate: ca/root/ca-ed448.crt
DNS (Base64): ca/root/ca-ed448.crt.b64
Intermediate CA:
Private key: ca/intermediate/intermediate-ed448.key
Certificate: ca/intermediate/intermediate-ed448.crt
Chain: ca/intermediate/chain.crt
DNS (Base64): ca/intermediate/intermediate-ed448.crt.b64
Root CA fingerprint (SHA256):
SHA256 Fingerprint=AB:CD:12:34:...
SECURITY REMINDER:
- Move ca-ed448.key to offline/HSM storage immediately
- Never store root CA key on networked systems# Generate Ed25519 server certificate (1 year validity)
./scripts/generate-cert.sh "${DOMAIN}" 365This creates:
* certs/example.com.key - Private key (Ed25519)
* certs/example.com.crt - Certificate
* certs/example.com.fullchain.crt - Full chain for web servers
* certs/example.com.crt.b64 - Base64 for DNS CERT record
./scripts/generate-kex.sh "${DOMAIN}"This creates:
* kex/example.com.x25519.key - Private key
* kex/example.com.x25519.pub.b64 - Base64 public key for IPSECKEY
./scripts/generate-pgp.sh "Your Name" "admin@${DOMAIN}"This creates:
* pgp/admin_at_example_com.asc - ASCII armored public key
* pgp/admin_at_example_com.pgp.b64 - Base64 for DNS CERT record
|
Warning
|
DNSSEC must be enabled before publishing cryptographic records. Without DNSSEC, attackers can spoof your keys via DNS cache poisoning. |
The DNSSEC setup process varies by provider:
-
Go to DNS → Settings → DNSSEC
-
Click "Enable DNSSEC"
-
Add the DS record to your registrar
# Create KSK
aws route53 create-key-signing-key \
--hosted-zone-id Z123456789 \
--name example-com-ksk \
--key-management-service-arn arn:aws:kms:...
# Enable DNSSEC
aws route53 enable-hosted-zone-dnssec \
--hosted-zone-id Z123456789Open dns/records/example.com.zone and add the records to your DNS provider.
# Extract the CERT record content
cat dns/records/example.com.zone | grep -A5 "_server._cert"ZONE_ID="your-zone-id"
API_TOKEN="your-api-token"
CERT_DATA=$(cat certs/example.com.crt.b64)
curl -X POST "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records" \
-H "Authorization: Bearer ${API_TOKEN}" \
-H "Content-Type: application/json" \
--data '{
"type": "CERT",
"name": "_server._cert",
"data": {
"type": 1,
"key_tag": 0,
"algorithm": 0,
"certificate": "'"${CERT_DATA}"'"
},
"ttl": 3600
}'KEX_DATA=$(cat kex/example.com.x25519.pub.b64)
# For BIND
echo "_ipsec IN IPSECKEY 10 0 2 . ${KEX_DATA}"The export script generates TLSA records automatically:
_443._tcp IN TLSA 3 1 1 abcd1234... ; SHA256 of SPKIRestrict certificate issuance:
@ IN CAA 0 issue "letsencrypt.org"
@ IN CAA 0 issuewild ";"
@ IN CAA 0 iodef "mailto:security@example.com"Wait for DNS propagation (typically 5-60 minutes), then verify:
# Check CERT record
dig +short CERT _server._cert.example.com
# Check IPSECKEY record
dig +short IPSECKEY _ipsec.example.com
# Check TLSA record
dig +short TLSA _443._tcp.example.com
# Verify DNSSEC
dig +dnssec +short example.com# /etc/nginx/sites-available/example.com
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com;
# Ed25519 Certificate Chain
ssl_certificate /path/to/explicit-trust-plane/certs/example.com.fullchain.crt;
ssl_certificate_key /path/to/explicit-trust-plane/certs/example.com.key;
# Modern TLS configuration
ssl_protocols TLSv1.3;
ssl_prefer_server_ciphers off;
# HSTS
add_header Strict-Transport-Security "max-age=63072000" always;
# ... rest of configuration
}|
Note
|
Nginx requires OpenSSL 1.1.1+ for Ed25519 certificate support.
Check with: |
# /etc/caddy/Caddyfile
example.com {
tls /path/to/certs/example.com.fullchain.crt /path/to/certs/example.com.key
# ... rest of configuration
}# /etc/apache2/sites-available/example.com.conf
<VirtualHost *:443>
ServerName example.com
SSLEngine on
SSLCertificateFile /path/to/certs/example.com.crt
SSLCertificateKeyFile /path/to/certs/example.com.key
SSLCertificateChainFile /path/to/ca/intermediate/chain.crt
# Modern TLS
SSLProtocol -all +TLSv1.3
# ... rest of configuration
</VirtualHost># Test connection
openssl s_client -connect example.com:443 -servername example.com < /dev/null 2>/dev/null | \
openssl x509 -text -noout | head -20
# Verify certificate chain
openssl s_client -connect example.com:443 -servername example.com -showcerts < /dev/null 2>/dev/null
# Check certificate algorithm
openssl s_client -connect example.com:443 -servername example.com < /dev/null 2>/dev/null | \
openssl x509 -noout -text | grep "Public Key Algorithm"# Fetch certificate from DNS
CERT_B64=$(dig +short CERT _server._cert.example.com | awk '{print $4}')
# Decode and display
echo "${CERT_B64}" | base64 -d | openssl x509 -inform DER -text -noout
# Compare with TLS certificate
TLS_CERT=$(openssl s_client -connect example.com:443 -servername example.com < /dev/null 2>/dev/null | \
openssl x509 -outform DER | base64 -w0)
if [ "${CERT_B64}" = "${TLS_CERT}" ]; then
echo "DNS certificate matches TLS certificate"
else
echo "WARNING: Certificates do not match!"
fi# Get TLSA record
TLSA_HASH=$(dig +short TLSA _443._tcp.example.com | awk '{print $4}')
# Calculate hash from live certificate
LIVE_HASH=$(openssl s_client -connect example.com:443 -servername example.com < /dev/null 2>/dev/null | \
openssl x509 -pubkey -noout | \
openssl pkey -pubin -outform DER | \
sha256sum | cut -d' ' -f1)
if [ "${TLSA_HASH}" = "${LIVE_HASH}" ]; then
echo "TLSA validation passed"
else
echo "WARNING: TLSA hash mismatch!"
fi# Fetch PGP key from DNS
PGP_B64=$(dig +short CERT _pgp.example.com | awk '{print $4}')
# Import to GPG
echo "${PGP_B64}" | base64 -d | gpg --import
# Verify key
gpg --list-keys admin@example.comCreate scripts/verify-deployment.sh:
#!/usr/bin/env bash
# Verify Explicit Trust Plane deployment
set -euo pipefail
DOMAIN="${1:-example.com}"
ERRORS=0
echo "=== Verifying Explicit Trust Plane for ${DOMAIN} ==="
echo ""
# Check DNSSEC
echo -n "[DNSSEC] "
if dig +dnssec +short "${DOMAIN}" | grep -q "RRSIG"; then
echo "PASS - DNSSEC enabled"
else
echo "FAIL - DNSSEC not detected"
((ERRORS++))
fi
# Check CERT record
echo -n "[CERT] "
if dig +short CERT "_server._cert.${DOMAIN}" | grep -q "PKIX"; then
echo "PASS - CERT record found"
else
echo "FAIL - CERT record not found"
((ERRORS++))
fi
# Check IPSECKEY record
echo -n "[IPSEC] "
if dig +short IPSECKEY "_ipsec.${DOMAIN}" | grep -q "10"; then
echo "PASS - IPSECKEY record found"
else
echo "WARN - IPSECKEY record not found (optional)"
fi
# Check TLSA record
echo -n "[TLSA] "
if dig +short TLSA "_443._tcp.${DOMAIN}" | grep -q "3 1 1"; then
echo "PASS - TLSA record found"
else
echo "WARN - TLSA record not found"
fi
# Check TLS connection
echo -n "[TLS] "
if openssl s_client -connect "${DOMAIN}:443" -servername "${DOMAIN}" < /dev/null 2>/dev/null | grep -q "Verify return code: 0"; then
echo "PASS - TLS connection verified"
else
echo "WARN - TLS verification issue (may be expected with self-signed CA)"
fi
echo ""
if [ "${ERRORS}" -eq 0 ]; then
echo "=== All critical checks passed ==="
else
echo "=== ${ERRORS} critical check(s) failed ==="
exit 1
fiRun the rotation script before certificates expire:
# Rotate server certificate
./scripts/rotate-keys.sh example.com cert
# Update DNS records
./scripts/export-dns.sh example.com
# Deploy new certificate to server
# (copy to server and reload nginx/caddy/apache)
# Update TLSA record in DNSSet up alerts for:
-
Certificate expiration (30 days warning)
-
DNSSEC signature expiration
-
TLSA record mismatches
Example cron job for monitoring:
# /etc/cron.daily/check-certs
#!/bin/bash
DOMAIN="example.com"
DAYS=30
# Check certificate expiration
openssl s_client -connect "${DOMAIN}:443" -servername "${DOMAIN}" < /dev/null 2>/dev/null | \
openssl x509 -checkend $((DAYS * 86400)) || \
echo "Certificate expires within ${DAYS} days" | mail -s "Cert Alert: ${DOMAIN}" admin@${DOMAIN}-
Verify record syntax:
dig +trace CERT _server._cert.example.com -
Check if DNS provider supports CERT records
-
Ensure DNSSEC is properly configured
-
Verify OpenSSL/Nginx supports Ed25519:
openssl version -
Check certificate chain completeness
-
Verify key and certificate match:
openssl x509 -noout -modulus -in cert.crt
-
Ensure TLSA record matches current certificate
-
Check DNSSEC chain is intact
-
Verify selector (1 = SPKI) and matching type (1 = SHA256)
# Generate all materials
./scripts/generate-ca.sh example.com
./scripts/generate-cert.sh example.com
./scripts/generate-kex.sh example.com
./scripts/generate-pgp.sh "Name" "email@example.com"
./scripts/export-dns.sh example.com
# Verify DNS records
dig +short CERT _server._cert.example.com
dig +short IPSECKEY _ipsec.example.com
dig +short TLSA _443._tcp.example.com
dig +dnssec +short example.com
# Verify TLS
openssl s_client -connect example.com:443
# Rotate keys
./scripts/rotate-keys.sh example.com cert
./scripts/export-dns.sh example.com| Provider | CERT | IPSECKEY | TLSA | DNSSEC | Notes |
|---|---|---|---|---|---|
Cloudflare |
Yes |
Yes |
Yes |
Yes |
Full support via API |
AWS Route 53 |
Yes |
Yes |
Yes |
Yes |
KMS integration available |
Google Cloud DNS |
Yes |
Yes |
Yes |
Yes |
Full support |
DigitalOcean |
Limited |
No |
Limited |
No |
Consider alternative |
Namecheap |
No |
No |
No |
No |
Use external DNS |
GoDaddy |
No |
No |
No |
Limited |
Not recommended |
After completing this deployment:
-
Document your setup - Record all generated fingerprints
-
Set up monitoring - Automated expiration alerts
-
Plan key rotation - Calendar reminders for certificate renewal
-
Security audit - Review the deployment with your security team
-
Publish documentation - Let users know how to verify your identity