MongoDB
Tayra integrates with MongoDB through TayraMongoCollection<T> -- a lightweight wrapper around IMongoCollection<T> that transparently encrypts [PersonalData] fields on write and decrypts them on read. Dramatically simpler than MongoDB's native Client-Side Field Level Encryption (CSFLE), Tayra's attribute-driven approach requires no JSON schema configuration, no mongocryptd process, and works with any MongoDB deployment -- not just Atlas or Enterprise.
Prerequisites
Tayra.MongoDB requires the MongoDB.Driver 2.21+ NuGet package. Any MongoDB server version supported by the driver is compatible (MongoDB 4.4+).
Install
dotnet add package Tayra.MongoDBInstall-Package Tayra.MongoDBSetup
There are two ways to register Tayra with MongoDB: through dependency injection or directly on a collection instance.
DI-Based Setup (Recommended)
Register Tayra core services, a key store, and the MongoDB integration in your DI container:
services.AddTayra(opts => opts.LicenseKey = licenseKey); // defaults to InMemoryKeyStore; use PostgreSQL, Vault, etc. in production
services.AddTayraMongoDB(opts =>
{
opts.EncryptOnWrite = true; // default
opts.DecryptOnRead = true; // default
});Inject TayraMongoCollectionFactory to create wrapped collections:
public class CustomerRepository
{
private readonly TayraMongoCollection<CustomerDocument> _customers;
public CustomerRepository(
IMongoDatabase database,
TayraMongoCollectionFactory factory)
{
var collection = database.GetCollection<CustomerDocument>("customers");
_customers = factory.Wrap(collection);
}
public async Task CreateAsync(CustomerDocument customer)
{
await _customers.InsertOneAsync(customer);
// customer.Name and customer.Email are encrypted in MongoDB
// but the in-memory object retains cleartext values
}
}Collection-Based Setup
If you prefer to wrap collections directly (e.g., in a console app or outside of DI), call WithTayra() on any IMongoCollection<T>:
var tayra = serviceProvider.GetRequiredService<ITayra>();
var mongoClient = new MongoClient("mongodb://localhost:27017");
var database = mongoClient.GetDatabase("myapp");
var collection = database.GetCollection<CustomerDocument>("customers");
var tayraCollection = collection.WithTayra(tayra);You can also pass options:
var tayraCollection = collection.WithTayra(fieldEncrypter, new TayraMongoOptions
{
EncryptOnWrite = true,
DecryptOnRead = true,
});When to Use Collection-Based vs DI
Use the DI-based setup when you have a standard ASP.NET Core or hosted service application. Use the collection-based setup when you need fine-grained control, are configuring collections outside of DI, or want different options per collection.
Options
services.AddTayraMongoDB(opts =>
{
opts.EncryptOnWrite = true; // default
opts.DecryptOnRead = true; // default
});| Property | Type | Default | Description |
|---|---|---|---|
EncryptOnWrite | bool | true | Encrypt [PersonalData] fields before writing documents to MongoDB |
DecryptOnRead | bool | true | Decrypt [PersonalData] fields after reading documents from MongoDB |
Define Your Document
Annotate your MongoDB document classes with [DataSubjectId] and [PersonalData]:
public class CustomerDocument
{
public Guid Id { get; set; }
[DataSubjectId]
public string SubjectId { get; set; } = "";
[PersonalData]
public string Name { get; set; } = "";
[PersonalData(MaskValue = "redacted@example.com")]
public string Email { get; set; } = "";
public string AccountType { get; set; } = ""; // Not encrypted
}[DataSubjectId]onSubjectIdidentifies the data owner and determines the encryption key.[PersonalData]onNameandEmailmarks them for encryption.- The
MaskValueparameter onEmailspecifies the value returned after crypto-shredding. AccountTypehas no attribute and is stored as plaintext in MongoDB.
Wrapped Operations
TayraMongoCollection<T> wraps the most common IMongoCollection<T> operations with transparent encryption and decryption:
Write Operations
// Insert a single document -- PII encrypted before write
await tayraCollection.InsertOneAsync(customer);
// Insert multiple documents -- PII encrypted before write
await tayraCollection.InsertManyAsync(customers);
// Replace a document -- PII encrypted before write
await tayraCollection.ReplaceOneAsync(
c => c.Id == customer.Id, customer);Read Operations
// Find a single document -- PII decrypted after read
var customer = await tayraCollection.FindOneAsync(
c => c.SubjectId == "cust-42");
// Find multiple documents -- PII decrypted after read
var customers = await tayraCollection.FindAsync(
c => c.AccountType == "Premium");Delete and Count Operations
// Delete a document -- no encryption needed
await tayraCollection.DeleteOneAsync(c => c.Id == customerId);
// Delete multiple documents
await tayraCollection.DeleteManyAsync(c => c.AccountType == "Inactive");
// Count documents
var count = await tayraCollection.CountDocumentsAsync(
c => c.AccountType == "Premium");Accessing the Inner Collection
For operations not wrapped by TayraMongoCollection<T> (e.g., aggregation pipelines, bulk writes, index management), access the underlying IMongoCollection<T> via the Inner property:
// Use the unwrapped collection for unsupported operations
var pipeline = tayraCollection.Inner
.Aggregate()
.Group(c => c.AccountType, g => new { Type = g.Key, Count = g.Count() });Unwrapped Access
Operations performed through .Inner bypass Tayra's encryption and decryption. PII fields in documents returned by unwrapped operations will contain AES-256-GCM ciphertext.
How It Works
TayraMongoCollection<T> intercepts collection operations at the wrapper level:
Write operations -- Before writing a document to MongoDB, the wrapper encrypts all
[PersonalData]fields using the encryption key derived from the[DataSubjectId]value. After the write completes, it decrypts the in-memory object back to cleartext so your application code continues working with plaintext values.Read operations -- After reading a document from MongoDB, the wrapper decrypts all
[PersonalData]fields. The returned document contains cleartext values.Delete and count operations -- These pass through to the underlying collection without encryption or decryption, since they do not read or write document content.
Performance Note
The crypto engine caches encryption keys in memory after the initial fetch from the key store. After warmup, most encrypt and decrypt operations are memory-only lookups with no key store round trips. For high-throughput workloads, the overhead is typically sub-microsecond per field.
Crypto-Shredding
GDPR Article 17 "right to be forgotten" is implemented via crypto-shredding. Instead of finding and deleting every document containing a person's data across all collections, you delete their encryption key. All encrypted fields become permanently unreadable:
// Delete the data subject's encryption keys
await cryptoEngine.DeleteAllKeysAsync("cust-42");
// Subsequent reads return replacement values
var shredded = await tayraCollection.FindOneAsync(
c => c.SubjectId == "cust-42");
// shredded.Name == ""
// shredded.Email == "redacted@example.com"The documents remain in MongoDB (preserving referential integrity, audit trails, and non-PII fields like AccountType), but the PII fields are permanently unreadable.
Irreversible
Crypto-shredding is permanent. The encryption key is deleted from the key store and cannot be recovered. The original data is lost forever.
Comparison with MongoDB CSFLE
| Feature | Tayra.MongoDB | MongoDB CSFLE |
|---|---|---|
| Setup | Add attributes to your model | Configure JSON schema, key vault, mongocryptd |
| Server requirements | Any MongoDB deployment | Atlas or Enterprise only (for automatic encryption) |
| Encryption scope | Application-level, per-field | Driver-level, per-field |
| Key management | Tayra key stores (PostgreSQL, Vault, Azure, AWS) | MongoDB Key Vault (Atlas KMS, AWS, Azure, GCP) |
| Crypto-shredding | Built-in via key deletion | Manual key rotation |
| GDPR compliance | Built-in attributes and erasure patterns | Requires custom implementation |
| Additional processes | None | mongocryptd or crypt_shared library |
See Also
- Getting Started -- End-to-end encryption tutorial
- EF Core Integration -- Entity Framework Core integration
- Marten Integration -- Document database encryption with Marten
- Key Stores -- Production key store options
