New Deterministic queryable ciphertext, scheduled compliance reports, and environment-aware licence enforcement. See what's included →
Performance

Encryption you can leave on in the hot path.

Every number here was measured with BenchmarkDotNet on .NET 10, and the benchmark ships in the repository so you can rerun it on your own hardware before you believe any of it. A row with five encrypted fields costs about a microsecond to write.

Writes 3.7–5.8× faster Reads up to 36× faster Allocations 4–16× lower vs. the AES-CBC provider pattern
The comparison that matters

Against the pattern most EF Core encryption packages use.

The common approach constructs a fresh Aes instance, a MemoryStream and a CryptoStream for every single value. This package keeps one keyed AES-GCM instance for the process and writes into a single output buffer. Same hardware-accelerated AES underneath — the difference is everything around it.

Payload Encrypt Decrypt Allocation
64 B
Aadhaar, phone, postcode
899 → 244 ns 3.7× 4,619 → 129 ns 36× 11–16× less
1 KB
address, notes field
1,687 → 372 ns 4.5× 4,755 → 274 ns 17× 5× less
16 KB
document blob
14,365 → 2,476 ns 5.8× 8,375 → 2,538 ns 3.3× 4× less
Why decrypt gains most. The CBC pattern pays stream construction and teardown per value regardless of size, so the smaller the field the more of its time is overhead. At 64 bytes that overhead is almost all of it — which is exactly the size of the identifiers you most want encrypted.
Cost per value

What EF actually pays, per field, per row.

The value converter is the code that runs on every read and every write. These are its real costs — and the case for choosing your storage format deliberately.

Field Base64 write Binary write Base64 read Binary read Read gain
16 chars 240 ns 184 ns 233 ns 159 ns 1.5×
128 chars 291 ns 212 ns 467 ns 207 ns 2.3×
4 KB 2,129 ns 1,587 ns 6,429 ns 1,294 ns 5.0×

Take the free 5× if your schema allows it

Base64 is the default because it stores in an existing nvarchar column. Switching to binary drops the encode on write, the decode on read, and 33% of the bytes on the wire and in every backup.

// column becomes varbinary
[CryptoEncrypted(CryptoStorageFormat.Binary)]
public string? Aadhaar { get; set; }

What a row costs

Five encrypted short fields — Aadhaar, phone, email, name, address — measured end to end through the converter:

~1 µs
to write a row
~1M
such rows / second / core
The parts that cost nothing

Most of your application doesn't pay at all.

Operation Cost Why
Queries not touching encrypted columns Zero No converter is involved.
Projections that skip encrypted columns Zero Select(o => new { o.Id, o.Status }) never materializes them.
Sentinel telemetry per operation tens of ns One lock-free bounded-channel write, drop-on-full — it can never block a query.
Startup scan, per column O(1) Take(100) — the same cost on a thousand rows or five hundred million.
Storage overhead +30 B, ×1.33 Envelope plus Base64 expansion. Binary format drops the 1.33×.
The one real cliff. A randomized encrypted column cannot be filtered or sorted by the database, and the query returns zero rows rather than raising an error. Deterministic mode or a blind index restores exact-match lookups as a true index seek — how that works, and what it costs you.
Where the speed comes from

Three unglamorous decisions.

One cipher instance

The keyed AesGcm is created once per key ring and reused for the life of the process, instead of being constructed and torn down per value.

One output buffer

Version, key id, nonce, tag and ciphertext are written into a single allocation with spans — no intermediate streams, no copies.

Batched nonces

96-bit nonces are drawn from the system CSPRNG in 4 KiB blocks rather than one call per value, which alone made short-field writes 1.75× faster. Same randomness source, same collision bounds.

Don't take our word for it

Run the benchmark yourself.

It's in the repository, it takes a couple of minutes, and it reports on your hardware rather than ours.

dotnet run -c Release --project benchmarks/EntityFrameworkCore.Crypto.DataEncryption.Benchmarks

EncryptionBenchmarks

AES-CBC against AES-GCM at 64 B / 1 KiB / 16 KiB — the comparison at the top of this page.

ConverterBenchmarks

The Base64 and binary converter paths at 16 / 128 / 4096 characters, with allocation counts.

RowThroughputBenchmarks

Whole-row push and pull for a realistic five-field entity, plus a blind-index hash.

What we won't claim. Every .NET package encrypting a column ends in the same hardware-accelerated AES instructions, so nobody is an order of magnitude faster at AES itself. At 4 KB the cipher is already about half the total time, which caps what any amount of engineering around it can win. The gains above are real and reproducible precisely because they are gains over overhead, not over mathematics.

Free for your first project.

No key, no sign-up, no telemetry. Install it, call UseEncryption, and measure it against whatever you're using today.