A newer version of this documentation is available.

View Latest

Field Level Encryption from the .NET SDK

Field Level Encryption is available in Couchbase Data Platform 5.5, from .NET SDK version 2.6.0.

Packaging

The Couchbase .NET SDK uses .NET Attributes to declaratively define which fields will be encrypted on a POCO (Plain Old CSharp Object) that matches the structure of your JSON document.

Field Level Encryption (FLE) for .NET is available as a NuGet package for download. The name of the package is Couchbase.Extensions.Encryption. Using the NuGet Package Manager, it can be installed using the following command:

Install-Package Couchbase.Extensions.Encryption -Version 1.0.0-dp1

If you are using the .NET CLI, then it can be installed using this command:

dotnet add package Couchbase.Extensions.Encryption --version 1.0.0-dp1

If you are using Visual Studio, just type Couchbase.Extensions.Encryption into the NuGet Package Manager search box; locate the package, and install it.

field level encryption nuget
Figure 1. Installing Couchbase.Extensions.Encryption via NuGET

This will also include the dependency on the Couchbase .NET SDK, which is required by the Field Level Encryption extension.

Configuring Field Level Encryption

Once you have included the FLE package in your Visual Studio or CodeVS project, you’ll need to configure the SDK to use it. FLE currently doesn’t allow for config file configuration; this has to be done programmatically using the ClientConfiguration found in the Couchbase.Configuration.Client namespace. Note that all of code snippets below can be found in full in our devguide-examples repo in GitHub.

First, add the following namespaces to your code file:

using System.Collections.Generic;
using Couchbase.Configuration.Client;
using Couchbase.Extensions.Encryption;
using Couchbase.Extensions.Encryption.Providers;
using Couchbase.Extensions.Encryption.Stores;

Then, add the configuration required to enable FLE to use the SDK:

const string publicKey = "!mysecretkey#9^5usdk39d&dlf)03sL";
const string publicKeyName = "publickey";

const string signingKey = "myauthpassword";
const string signingKeyName = "mysecret";

var keystore = new InsecureKeyStore(
      new KeyValuePair<string, string>(publicKeyName, publicKey),
      new KeyValuePair<string, string>(signingKeyName, signingKey));

var cryptoProvider = new AesCryptoProvider(keystore)
{
      PublicKeyName = publicKeyName,
      SigningKeyName = signingKeyName
};

var config = new ClientConfiguration();
config.EnableFieldEncryption(cryptoProvider);
var cluster = new Cluster(config);

First the keystore is created with a public key and a signing key; the signing key is required for ensuring that the encrypted data or any part of the message is not tampered with. Then an AesCryptoProvider instance is created which takes the keystore as a constructor parameter. Finally the configuration is created and the extension method EnableFieldEncryption is called passing in the ICryptoProvider instance. Once this is done, configuration is complete!

Note, that this example uses the InsecureKeyStore class which is an in-memory keystore that stores the keys unprotected; this is fine for testing and examples, but for real world applications the FileSystemKeyStore, which uses the DAPI, is a better choice.

Once we have setup our configuration, we’ll open a cluster and bucket object. Note that for a real-world application, you’ll want to tie the scope of both the cluster and the bucket to the lifespan of the application - see the Managing Connections documentation for more information.

Specifying what to Encrypt

In order to specify which field to encrypt, a special .NET attribute is used to annotate a property on a POCO (Plain Old Csharp Object) For cross-sdk support, although any property on a POCO can be encrypted, this must be a root-level property.

public class Person
{
      [EncryptedField(Provider = "AES-256-HMAC-SHA256")]
      public string Password { get; set; }
      public string FirstName { get; set; }
      public string LastName { get; set; }
      public string UserName { get; set; }
      public int Age { get; set; }
}

In the POCO above, we have a field which we wish to encrypt called Password which represents a person’s password. This property is annotated with EncryptedFieldAttribute and the ICryptoProvider.Provider name we are using. Note, this must match the type of ICryptoProvider we supplied in our configuration (“AES-256-HMAC-SHA256").

Storing and Retrieving Documents with Encrypted Fields

Once this is done, it’s simply a matter of using the basic CRUD operations that Couchbase supports to insert or fetch the document from the database. For example, assuming a Person class annotated with the EncryptedField attribute on a Password property:

var teddy = new Person
{
     Age = 33,
     FirstName = "Ted",
     LastName = "DeBloss",
     Password = "ssloBeD12345"
};

var bucket = cluster.OpenBucket();
var insert = bucket.Upsert("person::1", teddy);

Retrieving a document with an encrypted field is no different than any other get assuming you use an annotated POCO:

var get = bucket.Get<Person>("person::2");
if (get.Success)
{
       Console.WriteLine("Fetched person...");
}

It’s important to note that the data is encrypted for transport and storage only. When you retrieve the document the value for Password will be in its unencrypted format.