CryptoHeader Module
This section describes how to install, configure, and use CryptoHeader Module for .NET.
CryptoHeader Module allows one to programmatically encrypt and decrypt data with and without header information in .NET using AES keys stored and managed in CipherTrust Manager as well as to generate and verify HMACs using HMAC keys stored in CipherTrust Manager.
This module can perform four main functions:
Encryption - Data encryption can be performed with or without headers. Encrypted data with headers includes key and IV info, simplifying decryption. Without headers, no key or IV info is included (using a zero-byte IV), mainly for legacy system
Decryption - Decryption also can be performed with or without headers. You can specify the type, or the module attempts header decryption first, falling back if needed. If decryption fails, an exception is thrown.
HMAC generation - HMAC generation require header information and use the algorithm defined by the key. It is only supported with non-versioned keys.
HMAC verification - Similar to HMAC generation, HMAC verification requires header information and use the algorithm defined by the key.
Note
All encryption and decryption is done using AES. PKCS7 Padding or NoPadding can be applied in either CBC or ECB mode.
HMAC is only supported using non-versioned keys.
Prerequisites
.NET 6.0 or higher installed
CADP for .NET Core version 8.15.0 installed and configured
Installation and Configuration
The client application need to install the CADP for .NET Core version 8.15.0. On installing the CADP for .NET Core, the CryptoHeaderModule.dll will be placed in the C:\Users\user profile\.nuget\packages\ciphertrust.cadp.netcore\<latest version>\utility
folder. The user must explicitly add reference of CryptoHeaderModule.dll to the application.
To configure your application, you must:
configure the client application with at least the list of key names that are considered valid. Refer to app.config.
update Properties file
As the library is build on version .NetStandard 2.1, the client application version must be developed to support the same. Kindly refer to .Net Standard 2.1.
The possible configuration values are:
Name | Description | Default Value |
---|---|---|
CryptoHeaderKeyNameList | A default list of key names that are considered valid. | N/A |
CryptoHeaderKeyNameListFile | The full path (including file name) of the location to persist key names that have been retrieved from the Key Manager. | N/A |
Mode | The block mode used for encryption/decryption. | ECB |
Padding | The padding mode used for encryption/decryption. | PKCS7PADDING |
IV | The base 64 encoded value of the IV to use for encryption/decryption. | All zeros |
KeyName | This will set the LegacyKeyName while creating encryption handler | null |
The below parameters need to be added in the properties file (CADP.NETCore_Properties.xml) manually:
Name | Value | Description |
---|---|---|
Keylist_Enabled | Yes or No, Default is No (True or False, Default is False) | If required to read the keys from the file or key name list |
Nae_Username | username | The username for user specific session |
Nae_Password | password | The password for user specific session |
Note
Below statements are applicable to CryptoHeader Module:
To create a user-specific session, do not set the client cert property in the property file
To create a global session, the client cert property is required to be set in the property file
You can choose appropriate mode on CipherTrust Manager to establish the desired connection
Usage
Before using the module's functionality, you need to perform the following:
Initialization
Before using the module’s functionality, it must be initialized. Initializing is as simple as constructing a CryptoFactory object as shown below:
CryptoFactory cryptoFactory = new CryptoFactory();
During construction, this class will construct an NaeSession object from your properties file and will handle the connections to the CipherTrust Manager.
Note
It only supports client-certificate authentication with or without persistent key caching being enabled.
An alternative initialization method is available if you choose to use an alternate properties file with the NaeSession.
CryptoFactory cryptoFactory = new CryptoFactory(<PathToPropertiesFile>);
It is useful when the default properties file is not desired. This allows for any number of NaeSessions, each corresponding to the appropriate properties file provided.
Creating an EncryptionHandler
Once the CryptoFactory is initialized, the next step is to retrieve an encryption handler. The handlers currently supported allow operations with AES keys in CBC and ECB cipher mode, using PKCS7PADDING and NOPADDING choices for both ciphers.
CryptoFactory cryptoFactory = new CryptoFactory(); IEncryptionHandler handler = cryptoFactory.GetEncryptionHandler(“AES/CBC/PKCS7PADDING”);
The full set of transformations that can be supplied to GetEncryptionHandler()
are:
AES/CBC/PKCS7PADDING
AES/CBC/NOPADDING
AES/ECB/PKCS7PADDING
AES/ECB/NOPADDING
Note
if you select a transformation that does not use padding, the ciphertext must be a multiple of 16 bytes OR an exception will be thrown.
Optionally, an encryption handler can be built to use a default key name if the one specified in the app settings file is incorrect for these operations.
IEncryptionHandler handler = cryptoFactory.GetEncryptionHandler(“AES/CBC/PKCS7PADDING”, “<KeyName>”);
Here are the usage of this module:
Encryption
The Encrypt function is used to encrypt data and apply header information to the resulting ciphertext.
It takes on two arguments:
Plaintext to encrypt
Name of the key to encrypt
It returns the ciphertext with header information applied to it. Below is an example of how to use the Encrypt function for AES/CBC/PKCS7PADDING:
CryptoFactory cryptoFactory = new CryptoFactory();
IEncryptionHandler handler = cryptoFactory.GetEncryptionHandler(“AES/CBC/PKCS7PADDING”);
string keyName = "<insert_key_name>";
string plaintext = "this is the data to encrypt";
byte[] toEncrypt = Encoding.ASCII.GetBytes(plaintext);
byte[] ciphertextWithHeaderInfo = handler.Encrypt(toEncrypt, keyName);
Data Encryption Without Header
The EncryptWithoutHeader function is used to encrypt data in ECB mode using PKCS7PADDING but does not apply header information to the resulting ciphertext.
It takes on one argument: the plaintext to encrypt and requires the module to be initialized with a key name or used the GetEncryptionHandler method variant with the provided key name. It returns the ciphertext without any header information applied to it.
Below is an example of how to use the EncryptWithoutHeader function:
CryptoFactory cryptoFactory = new CryptoFactory();
IEncryptionHandler handler = cryptoFactory.GetEncryptionHandler(KeyName);
string plaintext = "this is the data to encrypt";
byte[] toEncrypt = Encoding.ASCII.GetBytes(plaintext);
byte[] ciphertextWithoutHeaderInfo = handler.EncryptWithoutHeader(toEncrypt);
Decryption
The Decrypt function is used to decrypt encrypted data that has header information.
It takes on one argument: the ciphertext to decrypt. If the module is initialized with a key name without header and an error occurs during decryption, this function will automatically attempt to decrypt using the key without header (see Data Decryption Without Header). If an error occurs but the module was not initialized with a key name, an exception will be thrown.
Here is an example of how to use the Decrypt function:
byte[] ciphertext = ***;
byte[] decrypted = handler.Decrypt(ciphertext);
Note
In this example, the module will attempt data decryption if an error occurs during decryption, as it is initialized with a key name.
Data Decryption Without Header
The DecryptWithoutHeader function is used to decrypt data that does not have header information applied to it in ECB mode using PKCS7PADDING.
It takes on one argument: the ciphertext to decrypt - and requires the module to be initialized with a key name. It returns the plaintext (decrypted value).
Here is an example of how to use the DecryptWithoutHeader function:
CryptoFactory cryptoFactory = new CryptoFactory();
IEncryptionHandler handler = cryptoFactory.GetEncryptionHandler(KeyName);
byte[] legacyCiphertext = …;
byte[] decrypted = handler.DecryptWithoutHeader(legacyCiphertext);
Note
If you are not sure whether the data to be decrypted is legacy or not, call the Decrypt function as it will automatically call DecryptWithoutHeader function if it is unable to find the appropriate header information.
HMAC Generation
The GenerateHMAC function is used to generate an HMAC on the given data and apply header information to the output. It takes on two arguments:
Data to HMAC
Name of the key to use
Note
The key must be a non-versioned HMAC key
It returns the HMAC value with the header information applied (key name).
Here is an example of how to use the GenerateHMAC function:
CryptoFactory cryptoFactory = new CryptoFactory();
IHMACHandler handler = cryptoFactory.GetHmacHandler();
string keyName = "<insert_key_name>";
string plaintext = "this is the data to HMAC";
byte[] toHMAC = Encoding.ASCII.GetBytes(plaintext);
byte[] hmac = handler.GenerateHMAC(toHMAC, keyName);
HMAC Verification
The VerifyHMAC function is used to verify an HMAC against a given plaintext. It takes on two arguments: the HMAC and the plaintext. It outputs a Boolean value indicating success or failure of the verification.
Here is an example of how to use the VerifyHMAC function:
CryptoFactory cryptoFactory = new CryptoFactory();
IHMACHandler handler = cryptoFactory.GetHmacHandler();
byte[] hmac = …;
string plaintext = "this is the data to verify against";
Boolean verified = handler.VerifyHMAC(plaintext, hmac);
Key List Functionality
The header module supports the ability to keep a collection of keys which are known to the user. This functionality is disabled by default, such as when it is not specified in the properties. To enable it, the following must be available in the CADP.NETCore_Properties.xml properties file:
<Keylist_Enabled>true</Keylist_Enabled>
When using this functionality, you must configure your application’s settings file with either of the following:
An appSetting key of CryptoHeaderKeyNameListFile, which refers to a file containing a comma-separated list of acceptable key names.
An appSetting key of CryptoHeaderKeyNameList and a corresponding value of a comma-separated list of the acceptable key names. Failure to do so will result in an exception being thrown at runtime.
Priority is assigned to the file. If it is not found, processing will fallback to the app settings Key Name List.
Example Configuration
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="CryptoHeaderKeyNameListFile" value="knownkeys.txt" />
<add key="CryptoHeaderKeyNameList" value="header_module_key" />
<add key="Mode" value="" />
<add key="Padding" value="" />
<add key="IV" value="" />
<add key="KeyName" value="testkey"/>
</appSettings>
</configuration>
Limitations
Cert_File in PA.Net is set as
*.pem
format while in .NET Core the property is ClientCert with values as*.pfx
or thumbprint installed in MSCertStore.AllowedKeys_RefreshTime is not present in the new property file.
There is no
DotNetHeaderModuleInstaller.exe
provided with this package currently, so the client needs to manually update the following properties in the property fileCADP.NETCore_Properties.xml
:Keylist_Enabled
Nae_Username
Nae_Password
The persistent file already created using old KSHeader Module will not be utilized by new CryptoHeaderModule.
Sample
For sample, refer to GitHub.
Additional Information
The Persistent Key Passphrase will be set based on the type of Operating System:
On Windows, the passphrase is generated using productID
Software\Microsoft\Windows NT\CurrentVersion
On Mac or RHEL, the passphrase is generated using productID
uname -s -r
example: Linux 3.10.0-693.17.1.el7.x86_64
It is recommended to use a single session with the default property file as CADP for .NetCore is designed only for one session and one property file.
Caution
Using multiple property might impact the behavior of the library.
For the case CryptoFactory (propertyFileName), the logs will be generated in the log file set in default properties file and not the values set in propertyFileName passed. This behavior is same as old KeySecureHeaderModule.
Logs file
CryptoHeaderModuleLogs.log
is generated on the path where the Sample.exe file is placed.
To know about the steps to migrate from KeySecureHeaderModule to CryptoHeaderModule, click here.