Encryption

Encryption

Encryption transforms readable data (plaintext) into unreadable ciphertext using a key. Only parties with the correct key can decrypt it. Encryption protects data confidentiality — it does not guarantee integrity or authenticity (use signing for that). In .NET, encryption is provided by System.Security.Cryptography.

Symmetric Encryption

The same key encrypts and decrypts. Fast. Suitable for large data volumes. The key distribution problem: how do you securely share the key?

AES-256-GCM is the standard choice. GCM (Galois/Counter Mode) provides both encryption and authentication (AEAD — Authenticated Encryption with Associated Data). It detects tampering without a separate HMAC.

using System.Security.Cryptography;

// Encrypt with AES-256-GCM
var key = new byte[32]; // 256-bit key
RandomNumberGenerator.Fill(key);
var nonce = new byte[12]; // 96-bit nonce (never reuse with same key)
RandomNumberGenerator.Fill(nonce);
var tag = new byte[16]; // 128-bit authentication tag

var plaintext = System.Text.Encoding.UTF8.GetBytes("sensitive data");
var ciphertext = new byte[plaintext.Length];

using var aes = new AesGcm(key, 16);
aes.Encrypt(nonce, plaintext, ciphertext, tag);
// Store: nonce + tag + ciphertext (all needed for decryption)

Pitfall — ECB mode: AES-ECB encrypts each block independently, producing identical ciphertext for identical plaintext blocks. This leaks patterns (the "ECB penguin" problem). Never use ECB. Use GCM or CBC with HMAC.

Asymmetric Encryption

Two mathematically linked keys: a public key (encrypt) and a private key (decrypt). Slower than symmetric. Used for key exchange and digital signatures, not bulk data encryption.

RSA: The classic asymmetric algorithm. Use RSA-OAEP for encryption (not PKCS#1 v1.5, which is vulnerable to padding oracle attacks). Key size: 2048-bit minimum, 4096-bit for long-lived keys.

using var rsa = RSA.Create(2048);
var publicKey = rsa.ExportRSAPublicKey();
var privateKey = rsa.ExportRSAPrivateKey();

// Encrypt with public key
var encrypted = rsa.Encrypt(plaintext, RSAEncryptionPadding.OaepSHA256);
// Decrypt with private key
var decrypted = rsa.Decrypt(encrypted, RSAEncryptionPadding.OaepSHA256);

TLS — Encryption in Transit

TLS (Transport Layer Security) combines asymmetric and symmetric encryption:

  1. Handshake: Client and server use asymmetric crypto (RSA or ECDH) to agree on a shared symmetric key
  2. Data transfer: All subsequent data is encrypted with the symmetric key (AES-GCM)

In .NET, TLS is handled automatically by HttpClient and ASP.NET Core. Enforce HTTPS with app.UseHttpsRedirection() and app.UseHsts().

Pitfalls

Nonce reuse with AES-GCM: Reusing a nonce with the same key in GCM mode completely breaks confidentiality and authentication. Always generate a fresh random nonce for each encryption operation.

Key management: The hardest part of encryption is not the algorithm — it is key storage and rotation. Never hardcode keys. Use Azure Key Vault, AWS KMS, or .NET Data Protection API for key management.

Rolling your own crypto: Do not implement cryptographic algorithms yourself. Use System.Security.Cryptography or a well-audited library (libsodium via NSec). Custom implementations almost always have subtle vulnerabilities.

Tradeoffs

Symmetric (AES-GCM) Asymmetric (RSA)
Speed Fast (hardware-accelerated) Slow (10-100× slower)
Key distribution Hard (must share secret key) Easy (public key is public)
Use case Bulk data encryption Key exchange, signatures
Key size 256 bits 2048-4096 bits

Hybrid encryption (used in TLS, PGP): Use asymmetric crypto to exchange a symmetric key, then use the symmetric key for bulk data. Best of both worlds.

Questions

References


Whats next