Smartcrypt Structured Data
The Smartcrypt Structured Data component is particularly useful when encrypting data stored in a structured container such as in a JSON property or a database column. The component makes it easy to work with specific types of data and offers the ability to store encryption key information with minimal cipher text size increases.
There are 3 specific encryption offerings for structured data: authenticated, length preserving, and format preserving. For most use cases, authenticated encryption is the best option; unless you have specific needs requiring other types of encryption, use authenticated.
Authenticated Encryption
Authenticated encryption uses AES-GCM. When using authenticated encryption, not only is your data encrypted, but its authenticity is validated during decryption, making it impossible for the cipher text to be tampered with undetected. The SDK takes care of correctly generating nonce values.
var metaClient = new MetaClient.Builder
{
AppName = nameof(AuthenticatedEncryptionSample),
AppVersion = "1.0.0"
}.Build();
var keyManagement = new SmartcryptKeyManagement.Builder()
.MetaClient(metaClient)
.PersistenceCallback(new InMemoryPersistenceCallback())
.Build();
var accountManagement = keyManagement.AccountManagement();
accountManagement.LoginManagedAccount("<your username>", "<your password>");
var smartkeys = keyManagement.Smartkeys();
var smartkey = smartkeys.ListAll()
.Select(set => set.FirstOrDefault(key =>
key is PrivateSmartkey
&& key.CanEncrypt
&& key.CanDecrypt)
)
.Where(key => key != null);
var smartcryptStructuredData = new SmartcryptStructuredData.Builder()
.DataStorage(keyManagement.DataStorage())
.Build();
var ae = smartcryptStructuredData.NewAuthenticatedEncryption(smartkey);
var encrypted = ae.Encrypt("Hello, world!".Utf8());
// Be sure to save all the information returned from Encrypt
Console.WriteLine($"Nonce: {encrypted.Nonce}");
Console.WriteLine($"Key revision: {encrypted.KeyRevision}");
Console.WriteLine($"Ciphertext in Base64: {encrypted.EncryptedContent.Base64()}");
var decrypted = ae.Decrypt(encrypted.EncryptedContent, encrypted.Nonce, encrypted.KeyRevision);
Console.WriteLine($"Decrypted message: {decrypted.Utf8()}");
Length Preserving Encryption
Length preserving encryption produces a cipher text that has the same number of bytes as the input text. This is useful if you do not have control over the size of the cipher text storage container such as the size of the database column. However, there are risks to using length preserving encryption.
Note that length preserving encryption in C# cannot be used with .NET Core projects.
Format Preserving Encryption
Format preserving encryption produces cipher text in the same format as the plain text. For example, if encrypting credit card numbers, the cipher text for each encryption will still be in the format of a valid credit card number. For some input types such as credit cards and social security numbers, the cipher text will still pass relevant checksum tests such as the Luhn check.
Format preserving encryption is useful if you do not have control over the size of the cipher text storage container such as the size of the database column. However, there are risks to using format preserving encryption.
Note that format preserving encryption cannot be used with .NET Core projects.
var metaClient = new MetaClient.Builder
{
AppName = nameof(FormatPreservingEncryptionSample),
AppVersion = "1.0.0"
}.Build();
var keyManagement = new SmartcryptKeyManagement.Builder()
.MetaClient(metaClient)
.PersistenceCallback(new InMemoryPersistenceCallback())
.Build();
var accountManagement = smartcryptKeyManagement.AccountManagement();
accountManagement.LoginManagedAccount("<your username>", "<your password>");
var smartkeys = smartcryptKeyManagement.Smartkeys();
var smartkey = smartkeys.ListAll()
.Select(keys => keys.FirstOrDefault(key =>
key.Features.Any(feature => Feature.NameNonRotatable == feature.Name)
&& key.CanEncrypt
&& key.CanDecrypt)
)
.Where(key => key != null);
var smartcryptStructuredData = new SmartcryptStructuredData.Builder()
.DataStorage(smartcryptKeyManagement.DataStorage())
.Build();
var fpe = smartcryptStructuredData.NewFormatPreservingEncryption(smartkey);
var encrypted1 = fpe.EncryptAlphanumeric("Hello, world!", "1");
var encrypted2 = fpe.EncryptAlphanumeric("Hello, world!", "1");
var encrypted3 = fpe.EncryptAlphanumeric("Hello, world!", "2");
Console.WriteLine($"The tweak is important! Encrypted1: {encrypted1}, Encrypted2: {encrypted2}, Encrypted3: {encrypted3}");
var decrypted1 = fpe.DecryptAlphanumeric(encrypted1, "1");
var decrypted2 = fpe.DecryptAlphanumeric(encrypted2, "2");
var decrypted3 = fpe.DecryptAlphanumeric(encrypted3, "2");
Console.WriteLine($"The tweak is important! Decrypted1: {decrypted1}, Decrypted2: {decrypted2}, Decrypted3: {decrypted3}");