Digital Certificates: Your IoT Device’s Passport
Before reading this, understand Public Keys and Digital Signatures.
A digital certificate is like a passport for your IoT device — it proves identity and contains your public key. But unlike a passport, it’s mathematically impossible to forge.
What’s Inside a Certificate?
Think of a certificate as a signed form containing:
CERTIFICATE CONTENTS:
┌─────────────────────────────────────┐
│ Device Name: "ESP32-LivingRoom-001" │
│ Public Key: 04 1a 2b 3c 4d... │
│ Valid From: 2025-01-01 │
│ Valid Until: 2026-01-01 │
│ Issuer: AWS IoT CA │
│ Serial Number: 1234567890ABCDEF │
│ │
│ --- SIGNATURE BY AWS --- │
│ 30 45 02 20 1a 2b 3c... │
└─────────────────────────────────────┘
AWS’s signature on the bottom proves: “Yes, this device is who they claim to be.”
Real Certificate Example (PEM format)
-----BEGIN CERTIFICATE-----
MIIDdTCCAl2gAwIBAgIJAK1234567890MA0GCSqGSIb3DQEBCwUAMIGGMQswCQYD
VQQGEwJVUzELMAkGA1UECAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxEzARBgNVBAoM
CkFtYXpvbi5jb20xHDAaBgNVBAsME0FtYXpvbiBXZWIgU2VydmljZXMxJTAjBgNV
BAMMHEFXUyBJb1QgRGV2aWNlIENlcnRpZmljYXRlMB4XDTI1MDEwMTAwMDAwMFoX
...
[Many more lines of Base64 encoded data]
...
-----END CERTIFICATE-----
This Base64 blob contains all the passport information in a standardized format called X.509.
Certificate Formats You’ll See
PEM Format (ASCII, human-readable)
device_certificate.pem # Your device's cert
ca_certificate.pem # AWS root certificate
certificate_chain.pem # Full chain of trust
DER Format (Binary, compact)
device_certificate.der # Same content, binary format
ca_certificate.der # Smaller file size
In ESP32 Memory
// How certificates look in code
const char* device_cert =
"-----BEGIN CERTIFICATE-----\n"
"MIIDdTCCAl2gAwIBAgIJAK123...\n"
"-----END CERTIFICATE-----\n";
// Or loaded from SPIFFS
esp_err_t load_certificate() {
return load_pem_file("/spiffs/device_certificate.pem");
}
X.509 Structure Decoded
X.509 is the standard format. Here’s what each field means:
Version: v3 (modern certificates)
Serial Number: Unique ID for this certificate
Signature Algorithm: sha256WithRSAEncryption or ecdsa-with-SHA256
Issuer: CN=AWS IoT CA, O=Amazon.com, C=US
Validity:
Not Before: Jan 1 00:00:00 2025 GMT
Not After: Jan 1 00:00:00 2026 GMT
Subject: CN=ESP32-LivingRoom-001, O=CongruentTech
Public Key: ECC P-256 (65 bytes)
Extensions:
Key Usage: Digital Signature, Key Agreement
Extended Key Usage: TLS Web Client Authentication
How to Read Certificates (OpenSSL Commands)
# View certificate details
openssl x509 -in device_certificate.pem -text -noout
# Extract public key
openssl x509 -in device_certificate.pem -pubkey -noout
# Check expiration
openssl x509 -in device_certificate.pem -dates -noout
# Verify certificate chain
openssl verify -CAfile aws_root_ca.pem device_certificate.pem
Certificate Authority (CA) Hierarchy
graph TD
A[Root CA<br/>Amazon Root CA 1] --> B[Intermediate CA<br/>AWS IoT CA]
B --> C[Device Certificate<br/>ESP32-LivingRoom-001]
B --> D[Device Certificate<br/>ESP32-Kitchen-002]
B --> E[Device Certificate<br/>ESP32-Bedroom-003]
Chain of Trust:
- Root CA = The ultimate authority (Amazon)
- Intermediate CA = Department authority (AWS IoT)
- Device Certificate = Your device’s identity
Certificate Extensions (The Special Permissions)
Like endorsements on your driver’s license:
Key Usage:
Digital Signature ✅ Can sign messages
Key Encipherment ✅ Can receive encrypted data
Certificate Signing ❌ Cannot issue certificates
Extended Key Usage:
TLS Client Auth ✅ Can connect as MQTT client
Code Signing ❌ Cannot sign firmware
Certificate Lifecycle
graph LR
A[Generate CSR] --> B[Submit to CA]
B --> C[CA Issues Certificate]
C --> D[Install on Device]
D --> E[Use for 1 Year]
E --> F[Renew Before Expiry]
F --> D
Real ESP32 Lifecycle:
// Check if certificate expires soon
time_t now = time(NULL);
time_t expiry = certificate_get_expiry();
if ((expiry - now) < (30 * 24 * 3600)) { // 30 days
renew_certificate();
}
Common Certificate Problems
Expired Certificate
Error: certificate verify failed: certificate has expired
Solution: Renew certificate before expiry
Wrong Common Name (CN)
Error: hostname verification failed
Solution: Certificate CN must match device identifier
Broken Chain
Error: unable to get local issuer certificate
Solution: Install intermediate CA certificates
Clock Sync Issues
Error: certificate is not yet valid
Solution: Sync device clock with NTP
File Sizes (Real World)
RSA-2048 Certificate: ~1.5KB
ECC P-256 Certificate: ~1.2KB
CA Certificate Chain: ~3-5KB
Total IoT Certificate Storage: ~4-7KB
ESP32 Flash Layout:
/spiffs/certificates/
├── device_cert.pem # 1.2KB
├── device_key.pem # 1.1KB (private key)
├── aws_root_ca.pem # 1.8KB
└── intermediate_ca.pem # 1.5KB
Total: ~5.6KB
Certificate vs Public Key vs Private Key
| Item | Contains | Purpose | Shareable? |
|---|---|---|---|
| Private Key | Your secret number | Decrypt/Sign | ❌ Never |
| Public Key | Your public number | Encrypt/Verify | ✅ Yes |
| Certificate | Public Key + Identity + CA Signature | Prove ownership | ✅ Yes |
Certificate = Public Key + Passport Photo + Notary Stamp
ESP32 Certificate Storage
// PKCS#11 labels for certificate storage
#define DEVICE_CERTIFICATE_LABEL "Device Cert TLS"
#define CA_CERTIFICATE_LABEL "Root CA Cert"
// Store certificate in secure partition
esp_err_t store_certificate(const char* cert_pem) {
return pkcs11_store_certificate(
DEVICE_CERTIFICATE_LABEL,
(uint8_t*)cert_pem,
strlen(cert_pem)
);
}
Next Steps
- Learn about PKCS#11 Storage → (where certificates live)
- Understand Certificate Signing Requests → (how to get certificates)
A certificate is your device’s digital passport — it proves identity, contains your public key, and is signed by a trusted authority. Now you know what’s in those mysterious .pem files!