Encryption
Tayra uses AES-256-GCM (Galois/Counter Mode) for all field-level encryption. This is an authenticated encryption algorithm that provides both confidentiality and integrity -- if the ciphertext or bound context is tampered with, decryption fails with a CryptographicException.
AES-256-GCM
AES-GCM is the recommended symmetric encryption mode for modern applications:
- Authenticated -- The authentication tag detects any modification to the ciphertext.
- Non-deterministic -- Each encryption produces different ciphertext because a fresh random nonce is used every time.
- Performance -- Hardware-accelerated on modern CPUs via AES-NI instructions.
- Standard -- NIST SP 800-38D, widely adopted in TLS 1.3, IPsec, and SSH.
Tayra uses the .NET System.Security.Cryptography.AesGcm class, which delegates to the OS cryptographic provider (OpenSSL on Linux, CNG on Windows, CommonCrypto on macOS).
Wire Format
Every encrypted value produced by Tayra follows a versioned binary format:
┌───────────┬──────────┬──────────────┬──────────────┐
│ Version │ Nonce │ Ciphertext │ Auth Tag │
│ (1 byte) │ (12 B) │ (N bytes) │ (16 bytes) │
└───────────┴──────────┴──────────────┴──────────────┘| Component | Size | Description |
|---|---|---|
| Version | 1 byte | Format version. 0x01 is legacy (no context binding). 0x02 adds associated-data context binding for stronger misuse resistance. |
| Nonce | 12 bytes (96 bits) | Randomly generated per encryption operation using RandomNumberGenerator. |
| Ciphertext | N bytes | The encrypted data. Same length as the plaintext input. |
| Auth Tag | 16 bytes (128 bits) | GCM authentication tag for tamper detection. |
Total overhead: 29 bytes per encrypted value (1 + 12 + 16).
For string fields, the binary output is Base64-encoded before being stored in the property, which adds approximately 33% to the encoded size.
Associated Data Context Binding
Version 0x02 payloads bind encryption to field context using AES-GCM associated data (AAD).
- AAD is authenticated but not encrypted.
- Tayra binds encrypted values to context components: entity type, field name, and field group.
- Moving ciphertext between fields with the same key scope fails authentication at decrypt time.
This reduces substitution/mix-and-match attacks in scenarios where one subject/group key protects multiple fields.
Backward compatibility is preserved:
- Existing
0x01payloads remain decryptable. - New field-level encryptions use
0x02.
Nonce Generation
Each encryption operation generates a fresh 12-byte (96-bit) nonce using System.Security.Cryptography.RandomNumberGenerator:
- The nonce is never reused for the same key. AES-GCM security depends on nonce uniqueness.
- The nonce is stored alongside the ciphertext (in the wire format), so it does not need to be tracked separately.
- With 96-bit random nonces and AES-256 keys, the probability of a collision is negligible for practical data volumes (birthday bound: ~2^48 encryptions per key).
Nonce Reuse
Reusing a nonce with the same key completely breaks AES-GCM security, allowing an attacker to recover plaintext and forge authentication tags. Tayra prevents this by generating a cryptographically random nonce for every encryption operation.
Key Sizes
Tayra supports three AES key sizes:
| Key Size | Bytes | Configuration |
|---|---|---|
| 128 bits | 16 bytes | opts.KeySizeInBits = 128 |
| 192 bits | 24 bytes | opts.KeySizeInBits = 192 |
| 256 bits | 32 bytes | opts.KeySizeInBits = 256 (default) |
AES-256 is the default and recommended setting. All three sizes use the same wire format -- the key size is determined by the key itself, not stored in the ciphertext.
String Encryption
For [PersonalData] string fields, Tayra:
- Encodes the string to UTF-8 bytes.
- Encrypts the bytes using AES-GCM (producing a versioned wire format,
0x02for new writes). - Encodes the result as a Base64 string.
- Stores the Base64 string back in the property.
Decryption reverses this: Base64 decode, AES-GCM decrypt, UTF-8 decode.
Binary Encryption
For [SerializedPersonalData] fields, Tayra:
- Serializes the value to bytes using a built-in binary serializer.
- Encrypts the bytes using AES-GCM (version
0x02for new writes). - Stores the raw encrypted bytes (not Base64) in the companion
byte[]?property.
Partial Redaction
When a redaction strategy is set on a [PersonalData] attribute (via the Redaction property), Tayra embeds the redacted value in the ciphertext string using a prefix format:
TAYRA_M:{redacted_value}\n{base64_ciphertext}During decryption:
- If the key exists, the prefix is stripped and the ciphertext is decrypted normally.
- If the key has been deleted (crypto-shredding), the redacted value is extracted and returned.
Searchable Encrypted Fields
Since AES-256-GCM is non-deterministic, you cannot query encrypted fields directly. Tayra provides HMAC blind indexes as a companion feature — one-way hashes stored alongside encrypted fields that enable equality queries without exposing plaintext.
See Also
- Crypto Engine -- Key management and caching
- Key Store -- Key persistence
- Field Encrypter -- How fields are processed
- Options -- Key size configuration
