

# AWS Encryption SDK for .NET
<a name="dot-net"></a>

The AWS Encryption SDK for .NET is a client-side encryption library for developers who are writing applications in C\$1 and other .NET programming languages. It is supported on Windows, macOS, and Linux.

**Note**  
Version 4.0.0 of the AWS Encryption SDK for .NET deviates from the AWS Encryption SDK Message Specification. As a result, messages encrypted by version 4.0.0 can only be decrypted by version 4.0.0 or later of the AWS Encryption SDK for .NET. They cannot be decrypted by any other programming language implementation.  
Version 4.0.1 of the AWS Encryption SDK for .NET writes messages according to the AWS Encryption SDK Message Specification, and is interoperable with other programming language implementations. By default, version 4.0.1 can read messages encrypted by version 4.0.0. However, if you do not want to decrypt messages encrypted by version 4.0.0, you can specify the [https://github.com/aws/aws-encryption-sdk/tree/mainline/AwsEncryptionSDK/runtimes/net/Examples/NetV4_0_0Example.cs](https://github.com/aws/aws-encryption-sdk/tree/mainline/AwsEncryptionSDK/runtimes/net/Examples/NetV4_0_0Example.cs) property to prevent the client from reading these messages. For more information, see the [v4.0.1 release notes](https://github.com/aws/aws-encryption-sdk/releases/tag/v4.0.1) in the aws-encryption-sdk repository on GitHub.

The AWS Encryption SDK for .NET differs from some of the other programming language implementations of the AWS Encryption SDK in the following ways:
+ No support for [data key caching](data-key-caching.md)
**Note**  
Version 4.*x* of the AWS Encryption SDK for .NET supports the [AWS KMS Hierarchical keyring](use-hierarchical-keyring.md), an alternative cryptographic materials caching solution.
+ No support for streaming data
+ [No logging or stack traces](#dot-net-debugging) from the AWS Encryption SDK for .NET
+ [Requires the AWS SDK for .NET](#dot-net-install)

The AWS Encryption SDK for .NET includes all of the security features introduced in versions 2.0.*x* and later of other language implementations of the AWS Encryption SDK. However, if you are using the AWS Encryption SDK for .NET to decrypt data that was encrypted by a pre-2.0.*x* version another language implementation of the AWS Encryption SDK, you might need to adjust your [commitment policy](concepts.md#commitment-policy). For details, see [How to set your commitment policy](migrate-commitment-policy.md#migrate-commitment-step1).

The AWS Encryption SDK for .NET is a product of the AWS Encryption SDK in [Dafny](https://github.com/dafny-lang/dafny/blob/master/README.md), a formal verification language in which you write specifications, the code to implement them, and the proofs to test them. The result is a library that implements the features of the AWS Encryption SDK in a framework that assures functional correctness.

**Learn More**
+ For examples showing how to configure options in the AWS Encryption SDK, such as specifying an alternate algorithm suite, limiting encrypted data keys, and using AWS KMS multi-Region keys, see [Configuring the AWS Encryption SDK](configure.md).
+ For details about programming with the AWS Encryption SDK for .NET, see the [https://github.com/aws/aws-encryption-sdk/tree/mainline/AwsEncryptionSDK/runtimes/net/](https://github.com/aws/aws-encryption-sdk/tree/mainline/AwsEncryptionSDK/runtimes/net/) directory of the aws-encryption-sdk repository on GitHub.

**Topics**
+ [Install and build](#dot-net-install)
+ [Debugging](#dot-net-debugging)
+ [Examples](dot-net-examples.md)

## Installing the AWS Encryption SDK for .NET
<a name="dot-net-install"></a>

The AWS Encryption SDK for .NET is available as the [https://www.nuget.org/packages/AWS.Cryptography.EncryptionSDK](https://www.nuget.org/packages/AWS.Cryptography.EncryptionSDK) package in NuGet. For details about installing and building the AWS Encryption SDK for .NET, see the [README.md](https://github.com/aws/aws-encryption-sdk/tree/mainline/AwsEncryptionSDK/runtimes/net/#readme) file in the `aws-encryption-sdk-net` repository.

**Version 3.x**  
Version 3.*x* of the AWS Encryption SDK for .NET supports .NET Framework 4.5.2 – 4.8 only on Windows. It supports .NET Core 3.0\$1 and .NET 5.0 and later on all supported operating systems.

**Version 4.x**  
Version 4.*x* of the AWS Encryption SDK for .NET supports .NET 6.0 and .NET Framework net48 and later. Version 4.*x* requires the AWS SDK for .NET v3.

**Version 5.x**  
Version 5.*x* of the AWS Encryption SDK for .NET supports .NET 6.0 and .NET Framework net48 and later. Version 5.*x* requires version 2.*x* of the Material Providers Library (MPL) and the AWS SDK for .NET v4.

The AWS Encryption SDK for .NET requires the SDK for .NET even if you aren't using AWS Key Management Service (AWS KMS) keys. It's installed with the NuGet package. However, unless you are using AWS KMS keys, AWS Encryption SDK for .NET does not require an AWS account, AWS credentials, or interaction with any AWS service. For help setting up an AWS account if you need it, see [Using the AWS Encryption SDK with AWS KMS](getting-started.md).

## Debugging the AWS Encryption SDK for .NET
<a name="dot-net-debugging"></a>

The AWS Encryption SDK for .NET does not generate any logs. Exceptions in the AWS Encryption SDK for .NET generate an exception message, but no stack traces.

To help you debug, be sure to enable logging in the SDK for .NET. The logs and error messages from the SDK for .NET can help you distinguish errors arising in the SDK for .NET from those in the AWS Encryption SDK for .NET. For help with SDK for .NET logging, see [AWSLogging](https://docs.aws.amazon.com/sdk-for-net/v4/developer-guide/net-dg-config-other.html#config-setting-awslogging) in the *AWS SDK for .NET Developer Guide*. (To see the topic, expand the **Open to view .NET Framework content** section.)

# AWS Encryption SDK for .NET examples
<a name="dot-net-examples"></a>

The following examples show the basic coding patterns that you use when programming with the AWS Encryption SDK for .NET. Specifically, you instantiate the AWS Encryption SDK and the material providers library. Then, before calling each method, you instantiate an object that defines the input for the method. This is much like the coding pattern you use in the SDK for .NET.

For examples showing how to configure options in the AWS Encryption SDK, such as specifying an alternate algorithm suite, limiting encrypted data keys, and using AWS KMS multi-Region keys, see [Configuring the AWS Encryption SDK](configure.md).

For more examples of programming with the AWS Encryption SDK for .NET, see the [examples](https://github.com/aws/aws-encryption-sdk/tree/mainline/AwsEncryptionSDK/runtimes/net/Examples) in the `aws-encryption-sdk-net` directory of the `aws-encryption-sdk` repository on GitHub.

## Encrypting data in the AWS Encryption SDK for .NET
<a name="dot-net-example-encrypt"></a>

This example shows the basic pattern for encrypting data. It encrypts a small file with data keys that are protected by one AWS KMS wrapping key.

Step 1: Instantiate the AWS Encryption SDK and the material providers library.  
Begin by instantiating the AWS Encryption SDK and the material providers library. You'll use the methods in the AWS Encryption SDK to encrypt and decrypt data. You'll use the methods in the material providers library to create the keyrings that specify which keys protect your data.  
The way you instantiate the AWS Encryption SDK and the material providers library differs between versions 3.*x* and 4.*x* of the AWS Encryption SDK for .NET. All of the following steps are the same for both version 3.*x* and 4.*x* of the AWS Encryption SDK for .NET.  

```
// Instantiate the AWS Encryption SDK and material providers
var encryptionSdk = AwsEncryptionSdkFactory.CreateDefaultAwsEncryptionSdk();
var materialProviders =
    AwsCryptographicMaterialProvidersFactory.CreateDefaultAwsCryptographicMaterialProviders();
```

```
// Instantiate the AWS Encryption SDK and material providers
var esdk =  new ESDK(new AwsEncryptionSdkConfig());
var mpl = new MaterialProviders(new MaterialProvidersConfig());
```

Step 2: Create an input object for the keyring.  
Each method that creates a keyring has a corresponding input object class. For example, to create the input object for the `CreateAwsKmsKeyring()` method, create an instance of the `CreateAwsKmsKeyringInput` class.  
Even though the input for this keyring doesn't specify a [generator key](use-kms-keyring.md#kms-keyring-encrypt), the single KMS key specified by the `KmsKeyId` parameter is the generator key. It generates and encrypts the data key that encrypts the data.   
This input object requires an AWS KMS client for the AWS Region of the KMS key. To create a AWS KMS client, instantiate the `AmazonKeyManagementServiceClient` class in the SDK for .NET. Calling the `AmazonKeyManagementServiceClient()` constructor with no parameters creates a client with the default values.  
In an AWS KMS keyring used for encrypting with the AWS Encryption SDK for .NET, you can [identify the KMS keys](use-kms-keyring.md#kms-keyring-id) by using the key ID, key ARN, alias name, or alias ARN. In an AWS KMS keyring used for decrypting, you must use a key ARN to identify each KMS key. If you plan to reuse your encryption keyring for decrypting, use a key ARN identifier for all KMS keys.  

```
string keyArn = "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab";

// Instantiate the keyring input object
var kmsKeyringInput = new CreateAwsKmsKeyringInput
{    
    KmsClient = new AmazonKeyManagementServiceClient(),
    KmsKeyId = keyArn
};
```

Step 3: Create the keyring.  
To create the keyring, call the keyring method with the keyring input object. This example uses the `CreateAwsKmsKeyring()` method, which takes just one KMS key.  

```
var keyring = materialProviders.CreateAwsKmsKeyring(kmsKeyringInput);
```

Step 4: Define an encryption context.  
An [encryption context](concepts.md#encryption-context) is an optional, but strongly recommended element of cryptographic operations in the AWS Encryption SDK. You can define one or more non-secret key-value pairs.  
With version 4.*x* of the AWS Encryption SDK for .NET, you can require an encryption context in all encrypt requests with the [required encryption context CMM](configure.md#config-required-encryption-context-cmm).

```
// Define the encryption context
var encryptionContext = new Dictionary<string, string>()
{
    {"purpose", "test"}
};
```

Step 5: Create the input object for encrypting.  
Before calling the `Encrypt()` method, create an instance of the `EncryptInput` class.  

```
string plaintext = File.ReadAllText("C:\\Documents\\CryptoTest\\TestFile.txt");
            
// Define the encrypt input
var encryptInput = new EncryptInput
{
    Plaintext = plaintext,
    Keyring = keyring,
    EncryptionContext = encryptionContext
};
```

Step 6: Encrypt the plaintext.  
Use the `Encrypt()` method of the AWS Encryption SDK to encrypt the plaintext using the keyring you defined.   
The `EncryptOutput` that the `Encrypt() `method returns has methods for getting the encrypted message (`Ciphertext`), encryption context, and algorithm suite.   

```
var encryptOutput = encryptionSdk.Encrypt(encryptInput);
```

Step 7: Get the encrypted message.  
The `Decrypt()` method in the AWS Encryption SDK for .NET takes the `Ciphertext` member of the `EncryptOutput` instance.  
The `Ciphertext` member of the `EncryptOutput` object is the [encrypted message](concepts.md#message), a portable object that includes the encrypted data, encrypted data keys, and metadata, including the encryption context. You can safely store the encrypted message for an extended time or submit it to the `Decrypt()` method to recover the plaintext.   

```
var encryptedMessage = encryptOutput.Ciphertext;
```

## Decrypting in strict mode in the AWS Encryption SDK for .NET
<a name="dot-net-decrypt-strict"></a>

Best practices recommend that you specify the keys that you use to decrypt data, an option known as *strict mode*. The AWS Encryption SDK uses only the KMS keys that you specify in your keyring to decrypt the ciphertext. The keys in your decryption keyring must include at least one of the keys that encrypted the data.

This example shows the basic pattern of decrypting in strict mode with the AWS Encryption SDK for .NET.

Step 1: Instantiate the AWS Encryption SDK and material providers library.  

```
// Instantiate the AWS Encryption SDK and material providers
var esdk =  new ESDK(new AwsEncryptionSdkConfig());
var mpl = new MaterialProviders(new MaterialProvidersConfig());
```

Step 2: Create the input object for your keyring.  
To specify the parameters for the keyring method, create an input object. Each keyring method in the AWS Encryption SDK for .NET has a corresponding input object. Because this example uses the `CreateAwsKmsKeyring()` method to create the keyring, it instantiates the `CreateAwsKmsKeyringInput` class for the input.  
In a decryption keyring, you must use a key ARN to identify KMS keys.  

```
string keyArn = "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab";

// Instantiate the keyring input object
var kmsKeyringInput = new CreateAwsKmsKeyringInput
{
    KmsClient = new AmazonKeyManagementServiceClient(),
    KmsKeyId = keyArn
};
```

Step 3: Create the keyring.  
To create the decryption keyring, this example uses the `CreateAwsKmsKeyring()` method and the keyring input object.  

```
var keyring = materialProviders.CreateAwsKmsKeyring(kmsKeyringInput);
```

Step 4: Create the input object for decrypting.  
To create the input object for the `Decrypt()` method, instantiate the `DecryptInput` class.  
The `Ciphertext` parameter of the `DecryptInput()` constructor takes the `Ciphertext` member of the `EncryptOutput` object that the `Encrypt()` method returned. The `Ciphertext` property represents the [encrypted message](concepts.md#message), which includes the encrypted data, encrypted data keys, and metadata that the AWS Encryption SDK needs to decrypt the message.  
With version 4.*x* of the AWS Encryption SDK for .NET, you can use the optional `EncryptionContext` parameter to specify your encryption context in the `Decrypt()` method.  
Use the `EncryptionContext` parameter to verify that the encryption context used on encrypt *is included* in the encryption context used to decrypt the ciphertext. The AWS Encryption SDK adds pairs to the encryption context, including the digital signature if you're using an algorithm suite with signing, such as the default algorithm suite.  

```
var encryptedMessage = encryptOutput.Ciphertext;

var decryptInput = new DecryptInput
{
    Ciphertext = encryptedMessage,
    Keyring = keyring,
    EncryptionContext = encryptionContext // OPTIONAL
};
```

Step 5: Decrypt the ciphertext.  

```
var decryptOutput = encryptionSdk.Decrypt(decryptInput);
```

Step 6: Verify the encryption context – Version 3.*x*  
The `Decrypt()` method of version 3.*x* of the AWS Encryption SDK for .NET does not take an encryption context. It gets the encryption context values from the metadata in the encrypted message. However, before returning or using the plaintext, it's a best practice to verify that encryption context that was used to decrypt the ciphertext includes the encryption context you provided when encrypting.   
Verify that the encryption context used on encrypt *is included* in the encryption context that used to decrypt the ciphertext. The AWS Encryption SDK adds pairs to the encryption context, including the digital signature if you're using an algorithm suite with signing, such as the default algorithm suite.  

```
// Verify the encryption context
string contextKey = "purpose";
string contextValue = "test";

if (!decryptOutput.EncryptionContext.TryGetValue(contextKey, out var decryptContextValue)
    || !decryptContextValue.Equals(contextValue))
{
    throw new Exception("Encryption context does not match expected values");
}
```

## Decrypting with a discovery keyring in the AWS Encryption SDK for .NET
<a name="dot-net-decrypt-discovery"></a>

Rather than specifying the KMS keys for decryption, you can provide a AWS KMS *discovery keyring*, which is a keyring that doesn't specify any KMS keys. A discovery keyring lets the AWS Encryption SDK decrypt the data by using whichever KMS key encrypted it, provided that the caller has decrypt permission on the key. For best practices, add a discovery filter that limits the KMS keys that can be used to those in particular AWS accounts of a specified partition. 

The AWS Encryption SDK for .NET provides a basic discovery keyring that requires an AWS KMS client and a discovery multi-keyring that requires you to specify one or more AWS Regions. The client and Regions both limit the KMS keys that can be used to decrypt the encrypted message. The input objects for both keyrings take the recommended discovery filter.

The following example shows the pattern for decrypting data with an AWS KMS discovery keyring and discovery filter.

Step 1: Instantiate the AWS Encryption SDK and the material providers library.  

```
// Instantiate the AWS Encryption SDK and material providers
var esdk =  new ESDK(new AwsEncryptionSdkConfig());
var mpl = new MaterialProviders(new MaterialProvidersConfig());
```

Step 2: Create the input object for the keyring.  
To specify the parameters for the keyring method, create an input object. Each keyring method in the AWS Encryption SDK for .NET has a corresponding input object. Because this example uses the `CreateAwsKmsDiscoveryKeyring()` method to create the keyring, it instantiates the `CreateAwsKmsDiscoveryKeyringInput` class for the input.  

```
List<string> accounts = new List<string> { "111122223333" };

var discoveryKeyringInput = new CreateAwsKmsDiscoveryKeyringInput
{
    KmsClient = new AmazonKeyManagementServiceClient(),
    DiscoveryFilter = new DiscoveryFilter()
    {
        AccountIds = accounts,
        Partition = "aws"
    }
};
```

Step 3: Create the keyring.  
To create the decryption keyring, this example uses the `CreateAwsKmsDiscoveryKeyring()` method and the keyring input object.  

```
var discoveryKeyring = materialProviders.CreateAwsKmsDiscoveryKeyring(discoveryKeyringInput);
```

Step 4: Create the input object for decrypting.  
To create the input object for the `Decrypt()` method, instantiate the `DecryptInput` class. The value of the `Ciphertext` parameter is the `Ciphertext` member of the `EncryptOutput` object that the `Encrypt()` method returns.  
With version 4.*x* of the AWS Encryption SDK for .NET, you can use the optional `EncryptionContext` parameter to specify your encryption context in the `Decrypt()` method.  
Use the `EncryptionContext` parameter to verify that the encryption context used on encrypt *is included* in the encryption context used to decrypt the ciphertext. The AWS Encryption SDK adds pairs to the encryption context, including the digital signature if you're using an algorithm suite with signing, such as the default algorithm suite.  

```
var ciphertext = encryptOutput.Ciphertext;

var decryptInput = new DecryptInput
{
    Ciphertext = ciphertext,
    Keyring = discoveryKeyring,
    EncryptionContext = encryptionContext // OPTIONAL
    
};
var decryptOutput = encryptionSdk.Decrypt(decryptInput);
```

Step 5: Verify the encryption context – Version 3.*x*  
The `Decrypt()` method of version 3.*x* of the AWS Encryption SDK for .NET does not take an encryption context on `Decrypt()`. It gets the encryption context values from the metadata in the encrypted message. However, before returning or using the plaintext, it's a best practice to verify that encryption context that was used to decrypt the ciphertext includes the encryption context you provided when encrypting.   
Verify that the encryption context used on encrypt *is included* in the encryption context that was used to decrypt the ciphertext. The AWS Encryption SDK adds pairs to the encryption context, including the digital signature if you're using an algorithm suite with signing, such as the default algorithm suite.   

```
// Verify the encryption context
string contextKey = "purpose";
string contextValue = "test";

if (!decryptOutput.EncryptionContext.TryGetValue(contextKey, out var decryptContextValue)
    || !decryptContextValue.Equals(contextValue))
{
    throw new Exception("Encryption context does not match expected values");
}
```