1381  Cryptography for IoT

1381.1 Learning Objectives

By the end of this chapter, you should be able to:

  • Implement symmetric encryption (AES) for IoT data protection
  • Apply asymmetric encryption (RSA, ECC) for key exchange and digital signatures
  • Use cryptographic hash functions for message integrity verification
  • Select appropriate cryptographic algorithms based on device constraints
  • Implement HMAC for authenticated messages

What is Cryptography? Cryptography is the science of protecting information by transforming it into an unreadable format (encryption) that can only be converted back (decryption) by someone with the correct key. It’s like a secret code that only authorized parties can understand.

Why does it matter for IoT? IoT devices transmit sensitive data (health readings, location, home activities) over networks where attackers can intercept traffic. Cryptography ensures that even if attackers capture the data, they cannot read or modify it.

Key terms: | Term | Definition | |——|————| | Encryption | Converting readable data (plaintext) into unreadable format (ciphertext) | | Decryption | Converting ciphertext back to plaintext using a key | | Symmetric encryption | Same key for encryption and decryption (fast, for bulk data) | | Asymmetric encryption | Different keys for encryption (public) and decryption (private) | | Hash function | One-way function that creates a fixed-size fingerprint of data |

1381.2 Prerequisites

Before diving into this chapter, you should be familiar with:

1381.3 Symmetric Encryption

Definition: Same key for encryption and decryption

Use Cases: Data confidentiality, session encryption, bulk data protection

Common Algorithms: - AES: Advanced Encryption Standard (128/192/256-bit) - ChaCha20: Fast on devices without AES hardware acceleration

1381.3.1 How Symmetric Encryption Works

Plaintext → [Encryption Algorithm + Key] → Ciphertext
Ciphertext → [Decryption Algorithm + Same Key] → Plaintext

Advantages: - Very fast (50-100 MB/s on microcontrollers) - Low computational overhead - Suitable for constrained IoT devices

Challenges: - Key distribution: How do both parties get the same secret key? - Key storage: Where do you securely store the key on the device?

1381.3.2 AES-128 Implementation Example (ESP32)

// AES-128 encryption for sensor data
#include "mbedtls/aes.h"

mbedtls_aes_context aes;
unsigned char key[16] = {0x2b, 0x7e, 0x15, 0x16, /* ... 16 bytes */};
unsigned char iv[16] = {0};  // Initialization vector

void setup() {
  Serial.begin(115200);
  mbedtls_aes_init(&aes);
  mbedtls_aes_setkey_enc(&aes, key, 128);
}

String encryptData(String plaintext) {
  unsigned char input[16];
  unsigned char output[16];

  // Pad to 16 bytes
  plaintext.getBytes(input, 16);

  // Encrypt
  mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_ENCRYPT, 16, iv, input, output);

  // Convert to hex string
  String encrypted = "";
  for (int i = 0; i < 16; i++) {
    encrypted += String(output[i], HEX);
  }

  return encrypted;
}

1381.3.3 AES Performance Comparison

Algorithm Speed (MB/s) Key Size Security Level IoT Suitability
AES-128 50-100 128-bit High Excellent
AES-256 40-80 256-bit Very High Good
ChaCha20 80-150 256-bit Very High Excellent (no HW accel)

When to use each: - AES-128: Default choice for most IoT applications - AES-256: High-security environments (medical, financial) - ChaCha20: Devices without AES hardware acceleration

1381.4 Asymmetric Encryption

Definition: Different keys for encryption (public) and decryption (private)

Use Cases: Key exchange, digital signatures, authentication

Public key (asymmetric) encryption diagram showing the complete encryption and decryption workflow. On the sender side, an unencrypted plaintext message is processed through an encryption algorithm using the receiver's public key to produce encrypted ciphertext. The ciphertext travels across the network to the receiver, where the decryption algorithm uses the receiver's private key to recover the original plaintext message. Key insight: anyone can encrypt using the public key (freely distributed), but only the private key holder can decrypt, enabling secure communication without pre-shared secrets.
Figure 1381.1: Source: University of Edinburgh IoT Security Course

Common Algorithms: - RSA: 2048/4096-bit keys - ECC: Elliptic Curve Cryptography (256-bit = RSA 3072-bit security)

1381.4.1 How Asymmetric Encryption Works

Public Key: Can be shared with anyone
Private Key: Must be kept secret

Encryption: Plaintext + Public Key → Ciphertext
Decryption: Ciphertext + Private Key → Plaintext

Digital Signature:
Sign: Hash + Private Key → Signature
Verify: Signature + Public Key → Valid/Invalid

1381.4.2 RSA Digital Signature Implementation

// Sign firmware update with RSA
#include "mbedtls/pk.h"
#include "mbedtls/sha256.h"

bool signFirmware(const uint8_t* firmware, size_t len,
                   const uint8_t* private_key, uint8_t* signature) {
  mbedtls_pk_context pk;
  mbedtls_pk_init(&pk);

  // Load private key
  mbedtls_pk_parse_key(&pk, private_key, key_len, NULL, 0);

  // Compute SHA-256 hash
  uint8_t hash[32];
  mbedtls_sha256(firmware, len, hash, 0);

  // Sign hash
  size_t sig_len;
  mbedtls_pk_sign(&pk, MBEDTLS_MD_SHA256, hash, 32,
                  signature, &sig_len, NULL, NULL);

  mbedtls_pk_free(&pk);
  return true;
}

bool verifyFirmware(const uint8_t* firmware, size_t len,
                     const uint8_t* public_key, const uint8_t* signature) {
  mbedtls_pk_context pk;
  mbedtls_pk_init(&pk);

  // Load public key
  mbedtls_pk_parse_public_key(&pk, public_key, key_len);

  // Compute hash
  uint8_t hash[32];
  mbedtls_sha256(firmware, len, hash, 0);

  // Verify signature
  int ret = mbedtls_pk_verify(&pk, MBEDTLS_MD_SHA256, hash, 32,
                               signature, sig_len);

  mbedtls_pk_free(&pk);
  return (ret == 0);
}

1381.4.3 ECC vs RSA Comparison

Feature ECC (256-bit) RSA (2048-bit)
Key Size 256 bits 2048 bits
Signature Size 64 bytes 256 bytes
Speed Faster Slower
Security Equivalent Equivalent
IoT Suitability Excellent Good
Battery Impact Lower Higher

Recommendation: Use ECC (specifically Ed25519 or ECDSA P-256) for IoT devices due to smaller key sizes and faster operations.

1381.4.4 Cryptographic Algorithm Selection Guide

%% fig-alt: "Cryptographic algorithm selection guide for IoT showing decision paths based on use case and device constraints. For data confidentiality: if device has AES hardware acceleration use AES-128-GCM or AES-256-GCM, if no hardware acceleration use ChaCha20-Poly1305. For digital signatures: if device is highly constrained (under 32KB RAM) use Ed25519, if moderate resources use ECDSA P-256, if legacy compatibility required use RSA-2048. For key exchange: if perfect forward secrecy needed use ECDHE, if session keys precomputed use static ECDH. For password hashing: on server use Argon2id or bcrypt, never use MD5 or SHA-1."
%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#2C3E50', 'primaryTextColor': '#fff', 'primaryBorderColor': '#16A085', 'lineColor': '#16A085', 'secondaryColor': '#E67E22', 'tertiaryColor': '#7F8C8D'}}}%%
flowchart TD
    START["Select Cryptographic<br/>Algorithm"] --> USE{Use Case?}

    USE -->|"Data Encryption"| ENC{Has AES<br/>Hardware?}
    USE -->|"Digital Signature"| SIG{Device<br/>Resources?}
    USE -->|"Key Exchange"| KEX{Forward<br/>Secrecy?}
    USE -->|"Password Hash"| HASH["Argon2id or bcrypt<br/>Never MD5/SHA-1"]

    ENC -->|Yes| AESGCM["AES-128-GCM<br/>or AES-256-GCM"]
    ENC -->|No| CHACHA["ChaCha20-Poly1305<br/>Software optimized"]

    SIG -->|"<32KB RAM"| ED25519["Ed25519<br/>Fast, small keys"]
    SIG -->|"Moderate"| ECDSA["ECDSA P-256<br/>NIST standard"]
    SIG -->|"Legacy"| RSA["RSA-2048<br/>Wide compatibility"]

    KEX -->|"Yes (PFS)"| ECDHE["ECDHE<br/>Ephemeral keys"]
    KEX -->|"No"| ECDH["Static ECDH<br/>Pre-computed"]

    AESGCM --> NOTE1["12-byte nonce<br/>16-byte auth tag"]
    CHACHA --> NOTE2["96-bit nonce<br/>20% faster on ARM"]
    ED25519 --> NOTE3["64-byte signature<br/>32-byte public key"]
    ECDSA --> NOTE4["64-byte signature<br/>TLS compatible"]
    RSA --> NOTE5["256-byte signature<br/>Slower operations"]

    style START fill:#2C3E50,stroke:#16A085,color:#fff
    style USE fill:#E67E22,stroke:#d35400,color:#fff
    style ENC fill:#E67E22,stroke:#d35400,color:#fff
    style SIG fill:#E67E22,stroke:#d35400,color:#fff
    style KEX fill:#E67E22,stroke:#d35400,color:#fff
    style HASH fill:#16A085,stroke:#0e6655,color:#fff
    style AESGCM fill:#16A085,stroke:#0e6655,color:#fff
    style CHACHA fill:#16A085,stroke:#0e6655,color:#fff
    style ED25519 fill:#16A085,stroke:#0e6655,color:#fff
    style ECDSA fill:#16A085,stroke:#0e6655,color:#fff
    style RSA fill:#7F8C8D,stroke:#5a6b6d,color:#fff
    style ECDHE fill:#16A085,stroke:#0e6655,color:#fff
    style ECDH fill:#16A085,stroke:#0e6655,color:#fff

Quick Reference: - Resource-constrained devices: Ed25519 + ChaCha20-Poly1305 - TLS/DTLS compatible: ECDSA P-256 + AES-128-GCM - Maximum security: AES-256-GCM + ECDHE + Argon2id

1381.5 Hash Functions

Definition: One-way functions that produce a fixed-size output (digest) from any input

Use Cases: Message integrity, password storage, checksums, digital signatures

Common Algorithms: - SHA-256: 256-bit hash, standard choice - SHA-3: Latest NIST standard - BLAKE2: Faster alternative to SHA-2

1381.5.1 Properties of Good Hash Functions

Property Description Example
Deterministic Same input always produces same output SHA256(“hello”) always = 2cf24…
One-way Cannot reverse hash to get original input Cannot get “hello” from 2cf24…
Collision-resistant Hard to find two inputs with same hash SHA256(“a”) ≠ SHA256(“b”)
Avalanche effect Small input change = completely different output SHA256(“hello”) ≠ SHA256(“hellp”)

1381.5.2 SHA-256 Implementation for Message Integrity

// SHA-256 for message integrity
#include "mbedtls/sha256.h"

String computeHash(const uint8_t* data, size_t len) {
  uint8_t hash[32];
  mbedtls_sha256(data, len, hash, 0);

  // Convert to hex
  String hashStr = "";
  for (int i = 0; i < 32; i++) {
    hashStr += String(hash[i], HEX);
  }
  return hashStr;
}

// Example usage
void verifyDataIntegrity() {
  String sensorData = "temperature=25.5,humidity=60";
  String hash = computeHash((uint8_t*)sensorData.c_str(), sensorData.length());

  Serial.println("Data: " + sensorData);
  Serial.println("Hash: " + hash);

  // Send both data and hash
  // Receiver computes hash and compares to verify integrity
}

1381.5.3 HMAC for Authenticated Messages

HMAC (Hash-based Message Authentication Code) combines a hash function with a secret key to provide both integrity AND authentication.

// HMAC for authenticated messages
#include "mbedtls/md.h"

bool computeHMAC(const uint8_t* data, size_t data_len,
                  const uint8_t* key, size_t key_len,
                  uint8_t* hmac) {
  mbedtls_md_context_t ctx;
  mbedtls_md_init(&ctx);
  mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1);

  mbedtls_md_hmac_starts(&ctx, key, key_len);
  mbedtls_md_hmac_update(&ctx, data, data_len);
  mbedtls_md_hmac_finish(&ctx, hmac);

  mbedtls_md_free(&ctx);
  return true;
}

Hash vs HMAC:

Feature Hash (SHA-256) HMAC (HMAC-SHA256)
Integrity Yes Yes
Authentication No Yes
Requires secret key No Yes
Use case Verify data hasn’t changed Verify data came from authorized sender
NoteKnowledge Check: Cryptography Selection

Question: An IoT temperature sensor needs to send encrypted readings every 30 seconds to a cloud server. Which cryptographic approach provides the BEST balance of security and performance?

A. RSA-2048 asymmetric encryption for all sensor readings B. SHA-256 hashing without encryption C. AES-128 symmetric encryption with periodic key rotation D. No encryption but send over HTTPS only

Click to reveal answer

Answer: C - AES-128 symmetric encryption with periodic key rotation

Why? - AES-128 is fast (50-100 MB/s), uses minimal CPU, and provides strong security - RSA is too slow for frequent encryption (every 30 seconds) - SHA-256 provides integrity but NOT confidentiality (anyone can read the data) - HTTPS adds overhead; a persistent encrypted MQTT session is more efficient

Periodic key rotation (e.g., daily) maintains security even if a key is compromised.

1381.6 Per-Device vs Global Keys

WarningTradeoff: Per-Device Keys vs Global Keys

Option A (Global Key): All 1,000 sensors share one AES encryption key - Simpler key management - Single key to rotate - Risk: If ANY sensor is compromised, ALL sensor data is exposed

Option B (Per-Device Keys): Each sensor has unique AES key - More complex key management (1,000 keys) - Requires automated provisioning - Benefit: Compromised sensor only exposes that one device’s data

Decision: Always use per-device keys. The complexity is worth the isolation benefit. Modern IoT platforms (AWS IoT Core, Azure IoT Hub) enforce per-device credentials.

1381.7 Chapter Summary

Cryptography provides the technical foundation for IoT data protection. Symmetric encryption (AES) offers fast, efficient bulk data encryption suitable for resource-constrained devices. Asymmetric encryption (RSA, ECC) enables secure key exchange and digital signatures without pre-shared secrets. Hash functions provide data integrity verification, while HMAC adds authentication to ensure messages come from authorized senders.

Algorithm selection depends on device capabilities and security requirements: use AES-128 or ChaCha20 for data encryption, ECC (Ed25519 or ECDSA P-256) for signatures, and SHA-256 for hashing. Always use per-device keys rather than global keys to limit the blast radius of any single device compromise.

1381.8 What’s Next

With cryptographic fundamentals in place, the next chapter examines Authentication Methods where you’ll learn to implement password-based, certificate-based, and token-based authentication systems for IoT devices.

Continue to Authentication Methods