Cloud Computing Tutorial · Identity and Security · Lesson 9 of 24
Encryption and Key Management
Encryption at rest and in transit, managed key services (KMS, Key Vault, Cloud KMS), and envelope encryption.
Encryption at rest and in transit
- In transit: TLS for every connection, including internal service-to-database traffic.
- At rest: storage, databases, backups and logs encrypted on disk. Most managed services encrypt by default; you choose who controls the key.
Managed key services
AWS KMS, Azure Key Vault and Google Cloud KMS store master keys in hardware security modules. Keys never leave the service: you ask it to encrypt or decrypt, every use is logged (CloudTrail, Azure Monitor, Cloud Audit Logs), and key policies control who may use each key.
| Key type | Who manages | Use when |
|---|---|---|
| Provider-owned keys | Provider, invisible to you | Default; fine for most data |
| Customer-managed keys (CMK) | You control policy, rotation, disabling | Regulated data; need to revoke access or audit use |
| Customer-supplied / external keys | You hold the key outside the cloud | Strict sovereignty requirements |
Envelope encryption
Encrypting large data directly with the KMS key would mean sending all data to KMS. Instead, services generate a data key, encrypt the data locally with it, and store the data key encrypted by the KMS key next to the data. To read, they ask KMS to decrypt the small data key.
import hashlib
import secrets
def toy_cipher(key: bytes, data: bytes) -> bytes:
# Illustration only: XOR with a hash-derived keystream. Real systems use AES-GCM.
stream = hashlib.sha256(key).digest() * (len(data) // 32 + 1)
return bytes(a ^ b for a, b in zip(data, stream))
kms_master_key = secrets.token_bytes(32) # never leaves KMS in reality
data_key = secrets.token_bytes(32) # generated per object
ciphertext = toy_cipher(data_key, b"card ending 4242")
wrapped_key = toy_cipher(kms_master_key, data_key) # stored next to the ciphertext
print("stored: ciphertext + wrapped data key (sizes", len(ciphertext), "and", len(wrapped_key), "bytes)")
unwrapped = toy_cipher(kms_master_key, wrapped_key) # "KMS Decrypt" on the small key only
print("decrypted:", toy_cipher(unwrapped, ciphertext).decode())
Output
stored: ciphertext + wrapped data key (sizes 16 and 32 bytes) decrypted: card ending 4242
Test yourself
In envelope encryption, what does the KMS key encrypt?
The whole data setThe data keyThe TLS certificateNothing; it only signs
Show answer
Answer: The data key
Data is encrypted locally with a data key; only the small data key is encrypted by KMS.