Appendix C: Cryptography Basics

Security Fundamentals for Edge ML

This appendix covers cryptographic concepts needed for LAB06 (Edge Security).

Symmetric Encryption

Same key encrypts and decrypts data.

flowchart LR
    P[Plaintext] -->|Key| E[Encrypt]
    E --> C[Ciphertext]
    C -->|Same Key| D[Decrypt]
    D --> P2[Plaintext]

AES (Advanced Encryption Standard)

The most widely used symmetric cipher:

  • Block size: 128 bits (16 bytes)
  • Key sizes: 128, 192, or 256 bits
  • Security: No practical attacks known
Code
from cryptography.fernet import Fernet

# Generate key (do this once, store securely)
key = Fernet.generate_key()
cipher = Fernet(key)

# Encrypt
message = b"Sensor reading: 42.5"
encrypted = cipher.encrypt(message)
print(f"Encrypted: {encrypted[:50]}...")

# Decrypt
decrypted = cipher.decrypt(encrypted)
print(f"Decrypted: {decrypted}")
ModuleNotFoundError: No module named 'cryptography'

Use in Edge ML

Encrypt model files to protect intellectual property:

def encrypt_model(model_path, key):
    cipher = Fernet(key)
    with open(model_path, 'rb') as f:
        model_bytes = f.read()
    return cipher.encrypt(model_bytes)

def load_encrypted_model(encrypted_path, key):
    cipher = Fernet(key)
    with open(encrypted_path, 'rb') as f:
        encrypted = f.read()
    model_bytes = cipher.decrypt(encrypted)
    return tf.lite.Interpreter(model_content=model_bytes)

Hashing

Produces a fixed-size digest from any input. One-way function.

flowchart LR
    D1[Data 1] --> H[Hash Function]
    D2[Data 2] --> H
    H --> Hash1[a7f3b2...]
    H --> Hash2[9c4e1d...]

SHA-256

Code
import hashlib

# Hash some data
data = b"Model weights version 1.0"
hash_digest = hashlib.sha256(data).hexdigest()
print(f"SHA-256: {hash_digest}")

# Even small changes produce completely different hashes
data_modified = b"Model weights version 1.1"
hash_modified = hashlib.sha256(data_modified).hexdigest()
print(f"Modified: {hash_modified}")
SHA-256: 27aeb1e8d3eb7f15131bfdaf567d4bee37544432afe18d643f13777708103838
Modified: 3b76e889e5fe3cdbd7910e6d89a832ad11ea27e7baa3828ec186fc6c8badadf5

Integrity Verification

Use hashes to detect tampering:

// Arduino: Simple checksum for model integrity
uint32_t calculateChecksum(const uint8_t* data, size_t length) {
    uint32_t checksum = 0;
    for (size_t i = 0; i < length; i++) {
        checksum = (checksum << 1) | (checksum >> 31);  // Rotate
        checksum ^= data[i];
    }
    return checksum;
}

bool verifyModel(const uint8_t* model, size_t size,
                 uint32_t expected_checksum) {
    uint32_t actual = calculateChecksum(model, size);
    return actual == expected_checksum;
}

Key Management

Critical Security Principle

Encryption is only as strong as your key protection!

Bad Practices

// DON'T DO THIS - key in source code
const char* KEY = "my_secret_key_123";  // ❌ Exposed in binary

Better Approaches

Method Description Use Case
Hardware secure element Dedicated crypto chip High-security devices
Key derivation Generate from device-specific values Production devices
Secure boot Verify firmware before execution Critical systems
Environment variables Runtime injection Development/testing
import os

# Load key from environment (better)
key = os.environ.get('MODEL_ENCRYPTION_KEY')
if key is None:
    raise ValueError("Encryption key not set!")

Message Authentication (HMAC)

Verify both integrity AND authenticity:

Code
import hmac
import hashlib

# Shared secret
secret_key = b"shared_secret_between_devices"

# Create MAC
message = b"Temperature: 25.5C"
mac = hmac.new(secret_key, message, hashlib.sha256).hexdigest()
print(f"HMAC: {mac}")

# Verify (receiver side)
received_mac = mac  # Would come with message
expected_mac = hmac.new(secret_key, message, hashlib.sha256).hexdigest()
is_valid = hmac.compare_digest(received_mac, expected_mac)
print(f"Valid: {is_valid}")
HMAC: e542747795e876e58e93fd9b1284806748fd34e522852a93a2475398c48da70f
Valid: True

Asymmetric Encryption

Different keys for encryption (public) and decryption (private).

flowchart LR
    P[Plaintext] -->|Public Key| E[Encrypt]
    E --> C[Ciphertext]
    C -->|Private Key| D[Decrypt]
    D --> P2[Plaintext]

Use Case: Secure Key Exchange

  1. Device generates key pair
  2. Sends public key to server
  3. Server encrypts symmetric key with public key
  4. Only device can decrypt with private key
Edge Devices

Asymmetric crypto is computationally expensive. Typically used only for: - Initial key exchange - Firmware signing - Certificate verification

Quick Reference

Concept Algorithm Use Case
Symmetric encryption AES-256 Encrypt models, data
Hashing SHA-256 Integrity checks
Key derivation PBKDF2, Argon2 Generate keys from passwords
MAC HMAC-SHA256 Authenticate messages
Asymmetric RSA, ECDSA Key exchange, signatures

Further Reading