Skip to content

Archive

Encryption

11 articles
Cybersecurity 08 Sep 2026 11 min read

Use Envelope Encryption to Limit Key Exposure

Encrypting sensitive data is only part of the design problem. The application also needs access to the encryption key, and that key must be stored, rotated, authorized, backed up, and eventually retired. If one long-lived key directly encrypts every record, changing how that key is protected can become tightly coupled to re-encrypting all of the data. Envelope encryption separates those jobs. Data is encrypted with a data-encryption key, while that data key is itself protected by another key. This extra layer does not make encryption magically stronger. Its value is operational: it lets a system protect many data keys behind a smaller set of tightly controlled key-encryption keys and change the outer protection without necessarily rewriting the underlying data.

Cybersecurity 08 Sep 2026 10 min read

Use Authenticated Encryption for Data You Must Trust

Encrypting sensitive data can hide its contents while still leaving an important question unanswered: has the encrypted data been changed? If an application decrypts modified ciphertext without a reliable integrity check, it may consume attacker-influenced plaintext even though the attacker never learned the encryption key. That distinction matters anywhere decrypted data affects a security decision, a payment amount, a permission, a destination, or another meaningful application state. Confidentiality answers who can read the data. Integrity answers whether the protected data is the same data that an authorized key holder produced.

Cybersecurity 06 Sep 2026 9 min read

Rotate Encryption Keys Without Losing Access to Data

Encrypting stored data creates a second problem that is easy to overlook: the application must keep the right decryption key available for as long as the protected data still needs to be read. If an application replaces an encryption key and immediately deletes the old one, existing ciphertext may become permanently unreadable. If it never replaces keys, one long-lived key can accumulate more data and more operational exposure than intended. A practical design needs to support both change and continuity.

Cybersecurity 05 Sep 2026 9 min read

Rotate Encryption Keys Without Losing Access to Existing Data

Encrypting sensitive data creates a long-term dependency that is easy to overlook: the application must retain the right decryption capability for as long as the ciphertext remains useful. Replacing an encryption key without planning for that dependency can make old data unreadable. Keeping one key forever avoids that immediate problem but makes future key changes harder and can increase the amount of data tied to one key. The practical solution is key versioning. Each ciphertext records which key version protects it. New encryption uses the current key, while decryption can temporarily use older versions for data that has not yet been migrated.

Cybersecurity 05 Sep 2026 11 min read

Design Encryption for Cryptographic Erasure

Deleting a database row or object does not necessarily remove every physical copy of its bytes. Storage systems may keep replicas, snapshots, backups, or blocks that are no longer visible through the application. When sensitive data must become inaccessible, finding and overwriting every copy can therefore be difficult. Encryption can change this problem. If data is encrypted under a key that can be reliably destroyed, destroying that key can make the remaining ciphertext infeasible to decrypt. This technique is called cryptographic erasure.

Cybersecurity 04 Sep 2026 8 min read

Rotate Encryption Keys Without Losing Data

Encryption keys are long-lived security dependencies. A key may need replacement because its access policy changed, an operator left, a cryptographic policy changed, or there is reason to suspect exposure. The difficult part is not generating a new key. It is changing keys without making existing ciphertext unreadable or quietly continuing to depend on the old key forever. This process is called key rotation: introducing a new key for a defined cryptographic role and moving the system away from the old one in a controlled way.

Cybersecurity 04 Sep 2026 11 min read

Keep Encryption Nonces Unique

Modern authenticated encryption can protect both the confidentiality and integrity of data, but some algorithms depend on a small operational rule that is easy to overlook: do not reuse a nonce with the same key. A nonce is a value supplied to a cryptographic operation for a particular invocation. The word comes from “number used once,” but a nonce is not necessarily secret and is not necessarily a simple counter. What matters is the requirement of the algorithm using it. For widely used authenticated-encryption schemes such as AES-GCM and ChaCha20-Poly1305, nonce reuse under the same key can invalidate important security guarantees.

Cybersecurity 03 Sep 2026 10 min read

Protect Encryption Keys with Envelope Encryption

Encrypting sensitive data is only useful if the keys are protected as carefully as the data itself. A common mistake is to focus on the encryption algorithm while treating key storage as a secondary detail. If an attacker can obtain both the ciphertext and the key that decrypts it, the encryption no longer provides the intended protection. Envelope encryption addresses this operational problem by using different keys for different jobs. A data encryption key encrypts the data, while a separate key-encryption key protects the data key. This separation makes it possible to encrypt many pieces of data without storing their plaintext data keys beside them.

Web Development 03 Sep 2025 3 min read

Automatically Encrypting Eloquent Model Attributes

Applications often store fields that deserve additional protection at rest. Laravel can encrypt selected Eloquent attributes before they are written to the database and decrypt them automatically when they are read. For modern Laravel applications, the built-in encrypted cast is preferable to overriding Eloquent’s magic __get() and __set() methods. It integrates with the model casting system and avoids interfering with Eloquent internals. Basic Implementation Define encrypted attributes in the model’s casts:

Go Updated 02 Sep 2025 3 min read

Implement HMAC Message Authentication in Go

When an application exchanges sensitive data, it is often important to verify both the integrity and authenticity of each message. If an attacker can modify a request in transit or replay an old valid request, the receiving service needs a reliable way to reject it. One common building block is HMAC (Hash-based Message Authentication Code). This article shows how to generate and verify an HMAC in Go with SHA-512, plus a nonce and timestamp to reduce replay risk.

Go Updated 02 Sep 2025 3 min read

Encrypt and Decrypt Data in Go with AES-GCM

Applications that store tokens, private configuration, or other sensitive values often need encryption at rest. Go includes everything required to implement modern symmetric encryption in its standard library. This example uses AES-GCM, an authenticated encryption mode that protects both confidentiality and integrity. That makes it a better default for new applications than older unauthenticated modes such as CFB. AES-GCM in Brief Symmetric encryption uses the same secret key for encryption and decryption. AES accepts 16-, 24-, or 32-byte keys for AES-128, AES-192, or AES-256. GCM adds authentication, so modified ciphertext is rejected during decryption. A fresh nonce must be used for every encryption operation with the same key. Complete Go Example package main import ( "crypto/aes" "crypto/cipher" "crypto/rand" "encoding/base64" "fmt" ) func generateRandomKey() ([]byte, error) { key := make([]byte, 32) // AES-256 if _, err := rand.Read(key); err != nil { return nil, err } return key, nil } func encrypt(plaintext, key []byte) ([]byte, error) { block, err := aes.NewCipher(key) if err != nil { return nil, err } gcm, err := cipher.NewGCM(block) if err != nil { return nil, err } nonce := make([]byte, gcm.NonceSize()) if _, err := rand.Read(nonce); err != nil { return nil, err } // Prefix the ciphertext with the nonce so decrypt can recover it. return gcm.Seal(nonce, nonce, plaintext, nil), nil } func decrypt(ciphertext, key []byte) ([]byte, error) { block, err := aes.NewCipher(key) if err != nil { return nil, err } gcm, err := cipher.NewGCM(block) if err != nil { return nil, err } nonceSize := gcm.NonceSize() if len(ciphertext) < nonceSize { return nil, fmt.Errorf("ciphertext too short") } nonce := ciphertext[:nonceSize] ciphertext = ciphertext[nonceSize:] return gcm.Open(nil, nonce, ciphertext, nil) } func main() { plaintext := []byte("Secret application data") key, err := generateRandomKey() if err != nil { panic(err) } ciphertext, err := encrypt(plaintext, key) if err != nil { panic(err) } fmt.Println("Ciphertext (base64):", base64.StdEncoding.EncodeToString(ciphertext)) decrypted, err := decrypt(ciphertext, key) if err != nil { panic(err) } fmt.Println("Decrypted text:", string(decrypted)) } How It Works generateRandomKey creates a cryptographically secure 32-byte key for AES-256. encrypt creates an AES cipher, wraps it with GCM, generates a random nonce, and encrypts the plaintext. The nonce is stored at the beginning of the returned byte slice. A nonce does not need to be secret, but it must not be reused with the same key. decrypt separates the nonce from the ciphertext and calls gcm.Open. If the ciphertext was modified, authentication fails and an error is returned. Key Management Matters The encryption code is only one part of a secure design. Do not hard-code real encryption keys in source control. In production, load keys from an appropriate secret-management system, protected environment, or key-management service.