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:

  1. Root CA = The ultimate authority (Amazon)
  2. Intermediate CA = Department authority (AWS IoT)
  3. 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

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!