-
Notifications
You must be signed in to change notification settings - Fork 0
XChaChaAeadCipher
Parameter | Value |
---|---|
Encryption Algorithm | XChaCha20 |
Authentication Algorithm | Poly1305-MAC |
Key Size | 32 bytes |
Nonce Size | 24 bytes |
Max Message Size | 2^64-1 bytes |
The XChaChaAeadCipher
class wraps the crypto_aead_xchacha20poly1305_ietf_*
functions provided in libsodium. The following description of the algorithm is taken from the libsodium documentation [2018-05-30]:
The XChaCha20-Poly1305 construction can safely encrypt a practically unlimited number of messages with the same key, without any practical limit to the size of a message (up to ~ 2^64 bytes).
As an alternative to counters, its large nonce size (192-bit) allows random nonces to be safely used.
The following example demonstrates how to encrypt/decrypt a single message:
using (var key = XChaChaKey.Generate())
{
var aeadCipher = new XChaChaAeadCipher();
var nonce = XChaChaNonce.Generate();
var message = Encoding.UTF8.GetBytes("Test Message");
var ciphertext = aeadCipher.Encrypt(message, key, nonce);
}
var keyBytes = Convert.FromBase64String("XPRT6QuYZDdytKM55WW+gnZklhaJBcDnOWi1kEI2we4=");
var nonceBytes = Convert.FromBase64String("2eQuiE8Fy70rwlCAi5T2oVEj5MrwxJaT");
var ciphertext = Convert.FromBase64String("w2jUPkWL0PfvnNFM7xq4o9gcVKrMTkd6SsYhLQ==");
using (var key = new XChaChaKey(keyBytes))
{
var aeadCipher = new XChaChaAeadCipher();
var nonce = new XChaChaNonce(nonceBytes);
var message = aeadCipher.Decrypt(ciphertext, key, nonce);
}
Decrypt
will throw a CryptographicException
if the decryption fails. Instead, TryDecrypt will return true or false depending on whether the decryption succeeded:
...
bool success = aeadCipher.TryDecrypt(ciphertext, message, key, nonce);
Overloads of Encrypt
/Decrypt
/TryDecrypt
allow passing in a buffer for the ciphertext/plaintext as demonstrated in the following examples:
using (var key = XChaChaKey.Generate())
{
var aeadCipher = new XChaChaAeadCipher();
var nonce = XChaChaNonce.Generate();
var message = Encoding.UTF8.GetBytes("Test Message");
var ciphertext = new byte[aeadCipher.GetCipherTextLength(message.Length)];
aeadCipher.Encrypt(message, ciphertext, key, nonce);
}
var keyBytes = Convert.FromBase64String("XPRT6QuYZDdytKM55WW+gnZklhaJBcDnOWi1kEI2we4=");
var nonceBytes = Convert.FromBase64String("2eQuiE8Fy70rwlCAi5T2oVEj5MrwxJaT");
var ciphertext = Convert.FromBase64String("w2jUPkWL0PfvnNFM7xq4o9gcVKrMTkd6SsYhLQ==");
using (var key = new XChaChaKey(keyBytes))
{
var aeadCipher = new XChaChaAeadCipher();
var nonce = new XChaChaNonce(nonceBytes);
var message = new byte[aeadCipher.GetPlaintextLength(ciphertext.Length)];
aeadCipher.Decrypt(ciphertext, message, key, nonce);
}
Overloads of Encrypt/Decrypt/TryDecrypt allow passing Additional Authenticated Data to be used when computing the authentication tag:
...
var aad = Encoding.UTF8.GetBytes(DateTime.Now.ToString());
var ciphertext = aeadCipher.Encrypt(message, key, nonce, aad);
...
var aad = Encoding.UTF8.GetBytes(DateTime.Now.ToString());
var message = aeadCipher.Decrypt(ciphertext, key, nonce, aad);