Symmetric symmetric cipher encryption uses only one key for both encryption and decryption and is available in the DidiSoft.OpenSsl.OpenSslCipher class. The equivalent OpenSSL commands are:
openssl enc -<algorithm name>…
openssl enc -d -<algorithm name>…
Compatibility with OpenSSL before version 1.1.0
OpenSSL after version 1.1.0 uses SHA-256 as default password hash algorithm, which is the default for OpenSSL Library for .NET too.
OpenSSL prior version 1.1.0 uses MD-5, and if we need compatibility with OpenSSL prior 1.1.0 we have to set:
1 2 | OpenSslCipher cipher = new OpenSslCipher(); cipher.PasswordHashMethod = PasswordHashAlgorithm.Md5; |
before any invocation of Encryption or Decryption with a password.
Common terminology
Keys are provided as byte arrays or string pass phrases converted internally to byte array keys with a Hash function.
Padding mode is PKCS#5 (the same as in OpenSSL)
Block mode is used to protect inspection and analyzing of encrypted data.
Basics
Algorithm to be used (AES, Blowfish, DES, Triple-DES, Cast-5, IDEA, RC2, RC4, RC5, GOST)
Keys and IV
Keys as password
Base-64 encoding
Examples
Encrypt and Decrypt File
Encrypt and Decrypt string
Encrypt and Decrypt byte array
Encrypt and Decrypt Stream
Algorithm to be used
The symmetric cipher algorithms and block modes are listed in the DidiSoft.OpenSsl.CipherAlgorithm enum. They are specified as the first parameter of the OpenSslCipher class methods:
1 2 3 | OpenSslCipher cipher = new OpenSslCipher(); cipher.EncryptFile(CipherAlgorithm.Aes_128_Cfb, ... cipher.DecryptFile(CipherAlgorithm.Aes_128_Cfb, ... |
Check below for Blowfish, Cast-5, DES, Triple DES, IDEA, RC-2, RC-4, RC-5, GOST.
Keys and IV (Initialization vector)
A typical key and the optional IV (Initialization vector) are byte arrays. In OpenSSL they are specified with the -K and -iv parameters:
openssl enc -aes-128-cbc -K 010203040506070800000000 -iv 01000000
With OpenSslCipher we can provide the above parameters like:
1 2 | byte[] key = new byte[] { 1, 2, 3, 4, 5, ,6, 7, 8 }; byte[] iv = new byte[] { 1, 0, 0, 0 }; |
or
1 2 | byte[] key = DidiSoft.OpenSsl.OpenSslUtil.HexToByteArray("01020304050607080")byte[] iv = DidiSoft.OpenSsl.OpenSslUtil.HexToByteArray("01000000"); |
Keys as password
Keys as pass phrases can be remembered more easily and they are converted to a byte array key with a hash function (default is SHA-1). We can change the hash function with the property:
1 2 | OpenSslCipher cipher = new OpenSslCipher(); cipher.PasswordHashMethod = HashAlgorithm.Sha256; |
Base-64 encoding
Base-64 encoding is used widely with OpenSSL and the methods of the OpenSslCipher class can be set to produce base-64 encoded data like:
1 2 3 4 | OpenSslCipher cipher = new OpenSslCipher(); bool base64Encode = true; byte[] key = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }; cipher.EncryptFile(CipherAlgorithm.Aes_256_Cbc, inputFile, outputFile, key, base64Encode); |
When decrypting there is no need to specify explicitly is the input data in base-64 encoded format or not. The library will silently determine this.
Encrypt and Decrypt File
The example code below illustrates how to encrypt and decrypt a File using AES 128 bit in CBC block mode with keys as a byte array or passphrase:
C# example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | using System; using DidiSoft.OpenSsl; class AesFileDemo { public static void Main(string[] args) { OpenSslCipher cipher = new OpenSslCipher(); // 16 bytes long key for AES-128 bit encryption byte[] key = { 50, 199, 10, 159, 132, 55, 236, 189, 51, 243, 244, 91, 17, 136, 39, 230 }; // the initialization vector is optional and can be skipped byte[] IV = { 150, 9, 112, 39, 32, 5, 136, 219, 251, 43, 44, 191, 217, 236, 3, 106 }; // AES Encrypting : openssl enc -aes-128-cbc -K ... cipher.EncryptFile(CipherAlgorithm.Aes_128_Cbc, @"Data\Input.txt", @"Data\Encrypted.dat", key); // with key and IV : openssl enc -aes-128-cbc -K ... -iv ... cipher.EncryptFile(CipherAlgorithm.Aes_128_Cbc, @"Data\Input.txt", @"Data\EncryptedWithIV.enc", key, IV); // with pass phrase : with key and IV : openssl enc -aes-128-cbc -k ... cipher.EncryptFile(CipherAlgorithm.Aes_128_Cbc, @"Data\Input.txt", @"Data\EncryptedWithPassword.enc", "pass phrase"); // explicitly set Hash function used to create key from the pass phrase cipher.EncryptFile(CipherAlgorithm.Aes_128_Cbc, @"Data\Input.txt", @"Data\EncryptedWithPassword2.enc", "pass phrase", HashAlgorithm.Sha512); // AES Decrypting : openssl enc -d -aes-128-cbc -K ... cipher.DecryptFile(CipherAlgorithm.Aes_128_Cbc, @"Data\Encrypted.dat", @"Data\Output.txt", key); // openssl enc -d -aes-128-cbc -K ... -iv ... cipher.DecryptFile(CipherAlgorithm.Aes_128_Cbc, @"Data\EncryptedWithIV.enc", @"Data\Output.txt", key, IV); // openssl enc -d -aes-128-cbc -k ... cipher.DecryptFile(CipherAlgorithm.Aes_128_Cbc, @"Data\EncryptedWithPassword.enc", @"Data\Output.txt", "pass phrase"); cipher.DecryptFile(CipherAlgorithm.Aes_128_Cbc, @"Data\EncryliptedWithPassword.enc", @"Data\Output.txt", "pass phrase"); cipher.DecryptFile(CipherAlgorithm.Aes_128_Cbc, @"Data\EncryptedWithPassword2.enc", @"Data\Output.txt", "pass phrase", HashAlgorithm.Sha512); } } |
VB.NET example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | Imports System Imports DidiSoft.OpenSsl Class AesFileDemo Public Shared Sub Main(args As String()) Dim cipher As New OpenSslCipher() ' 16 bytes long key for AES-128 bit encryption Dim key As Byte() = {50, 199, 10, 159, 132, 55, 236, 189, 51, 243, 244, 91, 17, 136, 39, 230} ' the initialization vector is optional and can be skipped Dim IV As Byte() = {150, 9, 112, 39, 32, 5, 136, 219, 251, 43, 44, 191, 217, 236, 3, 106} ' Base-64 encoded format Dim base64Encode As Boolean = True ' AES Encrypting cipher.EncryptFile(CipherAlgorithm.Aes_128_Cbc, "Data\Input.txt", "Data\Encrypted.dat", key) ' with key and IV cipher.EncryptFile(CipherAlgorithm.Aes_128_Cbc, "Data\Input.txt", "Data\EncryptedWithIV.enc", key, IV) ' with pass phrase and base-64 encode cipher.EncryptFile(CipherAlgorithm.Aes_128_Cbc, "Data\Input.txt", "Data\EncryptedWithPassword.enc", "pass phrase", base64Encode) ' explicitly set Hash function used to create key from the pass phrase cipher.EncryptFile(CipherAlgorithm.Aes_128_Cbc, "Data\Input.txt", "Data\EncryptedWithPassword2.enc", "pass phrase", _ HashAlgorithm.Sha512) ' AES Decrypting cipher.DecryptFile(CipherAlgorithm.Aes_128_Cbc, "Data\Encrypted.dat", "Data\Output.txt", key) cipher.DecryptFile(CipherAlgorithm.Aes_128_Cbc, "Data\EncryptedWithIV.enc", "Data\Output.txt", key, IV) cipher.DecryptFile(CipherAlgorithm.Aes_128_Cbc, "Data\EncryptedWithPassword.enc", "Data\Output.txt", "pass phrase") cipher.DecryptFile(CipherAlgorithm.Aes_128_Cbc, "Data\EncryptedWithPassword.enc", "Data\Output.txt", "pass phrase") cipher.DecryptFile(CipherAlgorithm.Aes_128_Cbc, "Data\EncryptedWithPassword2.enc", "Data\Output.txt", "pass phrase", _ HashAlgorithm.Sha512) End Sub End Class |
Encrypt and Decrypt string
When encrypting a String message, OpenSslCipher will either convert the decrypted result into hexadecimal string format (default) or base-64 format. This is specified with the base64 parameter. When decrypting the input format (base-64 or hexadecimal) is determined automatically.
C# example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | using System; using DidiSoft.OpenSsl; class AesStringDemo { public static void Main(string[] args) { OpenSslCipher cipher = new OpenSslCipher(); // 16 bytes long key for AES-128 bit encryption byte[] key = { 50, 199, 10, 159, 132, 55, 236, 189, 51, 243, 244, 91, 17, 136, 39, 230 }; // optional 16 byte long initialization vector byte[] IV = { 150, 9, 112, 39, 32, 5, 136, 219, 251, 43, 44, 191, 217, 236, 3, 106 }; string message = "Hello World"; // encrypted strings are either in Base-64 encoded format or in hexadecimal representation bool base64Encode = true; // encrypt with a key only string encryptedMessage = cipher.EncryptString(CipherAlgorithm.Aes_128_Cfb, message, key, base64Encode); // encrypt with a key and IV string encryptedMessageWithIV = cipher.EncryptString(CipherAlgorithm.Aes_128_Cfb, message, key, IV); // encrypt with a password string encryptedMessageWithPassword = cipher.EncryptString(CipherAlgorithm.Aes_128_Cfb, message, "my password"); // encrypt with a password and custom Hash function string encryptedMessageWithPasswordAndIV = cipher.EncryptString(CipherAlgorithm.Aes_128_Cfb, message, "my password", HashAlgorithm.Sha512); message = cipher.DecryptString(CipherAlgorithm.Aes_128_Cfb, encryptedMessage, key); message = cipher.DecryptString(CipherAlgorithm.Aes_128_Cfb, encryptedMessageWithIV, key, IV); message = cipher.DecryptString(CipherAlgorithm.Aes_128_Cfb, encryptedMessageWithPassword, "my password"); message = cipher.DecryptString(CipherAlgorithm.Aes_128_Cfb, encryptedMessageWithPasswordAndIV, "my password", HashAlgorithm.Sha512); } } |
VB.NET example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | Imports System Imports DidiSoft.OpenSsl Class AesStringDemo Public Shared Sub Main(args As String()) Dim cipher As New OpenSslCipher() ' 16 bytes long key for AES-128 bit encryption Dim key As Byte() = {50, 199, 10, 159, 132, 55, 236, 189, 51, 243, 244, 91, 17, 136, 39, 230} ' the initialization vector is optional and can be skipped Dim IV As Byte() = {150, 9, 112, 39, 32, 5, 136, 219, 251, 43, 44, 191, 217, 236, 3, 106} Dim message As String = "Hello World" ' encrypted strings are either in Base-64 encoded format or in hexadecimal representation Dim base64Encode As Boolean = True ' encrypt with a key only Dim encryptedMessage As String = cipher.EncryptString(CipherAlgorithm.Aes_128_Cfb, message, key, base64Encode) ' encrypt with a key and IV Dim encryptedMessageWithIV As String = cipher.EncryptString(CipherAlgorithm.Aes_128_Cfb, message, key, IV) ' encrypt with a password Dim encryptedMessageWithPassword As String = cipher.EncryptString(CipherAlgorithm.Aes_128_Cfb, message, "my password") ' encrypt with a password and custom Hash function Dim encryptedMessageWithPasswordAndIV As String = cipher.EncryptString(CipherAlgorithm.Aes_128_Cfb, message, "my password", _ HashAlgorithm.Sha512) message = cipher.DecryptString(CipherAlgorithm.Aes_128_Cfb, encryptedMessage, key) message = cipher.DecryptString(CipherAlgorithm.Aes_128_Cfb, encryptedMessageWithIV, key, IV) message = cipher.DecryptString(CipherAlgorithm.Aes_128_Cfb, encryptedMessageWithPassword, "my password") message = cipher.DecryptString(CipherAlgorithm.Aes_128_Cfb, encryptedMessageWithPasswordAndIV, "my password", _ HashAlgorithm.Sha512) End Sub End Class |
Encrypt and Decrypt byte array
Encrypting a raw byte array is done with the EncryptBytes methods:
C# example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | using System; using DidiSoft.OpenSsl; class AesBytesDemo { public static void Main(string[] args) { OpenSslCipher cipher = new OpenSslCipher(); // 16 bytes long key for AES-128 bit encryption byte[] key = { 50, 199, 10, 159, 132, 55, 236, 189, 51, 243, 244, 91, 17, 136, 39, 230 }; // optional 16 bytes long initialization vector byte[] IV = { 150, 9, 112, 39, 32, 5, 136, 219, 251, 43, 44, 191, 217, 236, 3, 106 }; byte[] data = { 150, 9, 112, 39, 32, 5, 136, 219, 251, 43, 44, 191, 217, 236, 3, 106 }; // encrypt with a key only byte[] encryptedBytes = cipher.EncryptBytes(CipherAlgorithm.Aes_128_Cfb, data, key); // encrypt with a key and IV byte[] encryptedBytesWithIV = cipher.EncryptBytes(CipherAlgorithm.Aes_128_Cfb, data, key, IV); // encrypt with a password byte[] encryptedBytesWithPassword = cipher.EncryptBytes(CipherAlgorithm.Aes_128_Cfb, data, "my password"); // encrypt with a password and custom Hash function byte[] encryptedBytesWithPasswordAndIV = cipher.EncryptBytes(CipherAlgorithm.Aes_128_Cfb, data, "my password", HashAlgorithm.Sha512); byte[] decryptedBytes = cipher.DecryptBytes(CipherAlgorithm.Aes_128_Cfb, encryptedBytes, key); decryptedBytes = cipher.DecryptBytes(CipherAlgorithm.Aes_128_Cfb, encryptedBytesWithIV, key, IV); decryptedBytes = cipher.DecryptBytes(CipherAlgorithm.Aes_128_Cfb, encryptedBytesWithPassword, "my password"); decryptedBytes = cipher.DecryptBytes(CipherAlgorithm.Aes_128_Cfb, encryptedBytesWithPasswordAndIV, "my password", HashAlgorithm.Sha512); } } |
VB.NET example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | Imports System Imports DidiSoft.OpenSsl Class AesBytesDemo Public Shared Sub Main(args As String()) Dim cipher As New OpenSslCipher() ' 16 bytes long key for AES-128 bit encryption Dim key As Byte() = {50, 199, 10, 159, 132, 55, 236, 189, 51, 243, 244, 91, 17, 136, 39, 230} ' the initialization vector is optional and can be skipped Dim IV As Byte() = {150, 9, 112, 39, 32, 5, 136, 219, 251, 43, 44, 191, 217, 236, 3, 106} Dim data As Byte() = {150, 9, 112, 39, 32, 5, 136, 219, 251, 43, 44, 191, 217, 236, 3, 106} ' Base-64 encoded format Dim base64Encode As Boolean = True ' encrypt with a key only Dim encryptedBytes As Byte() = cipher.EncryptBytes(CipherAlgorithm.Aes_128_Cfb, data, key) ' encrypt with a key and IV Dim encryptedBytesWithIV As Byte() = cipher.EncryptBytes(CipherAlgorithm.Aes_128_Cfb, data, key, IV) ' encrypt with a password and base-64 encode Dim encryptedBytesWithPassword As Byte() = cipher.EncryptBytes(CipherAlgorithm.Aes_128_Cfb, data, "my password", base64Encode) ' encrypt with a password and custom Hash function Dim encryptedBytesWithPasswordAndIV As Byte() = cipher.EncryptBytes(CipherAlgorithm.Aes_128_Cfb, data, "my password", HashAlgorithm.Sha512) Dim decryptedBytes As Byte() = cipher.DecryptBytes(CipherAlgorithm.Aes_128_Cfb, encryptedBytes, key) decryptedBytes = cipher.DecryptBytes(CipherAlgorithm.Aes_128_Cfb, encryptedBytesWithIV, key, IV) decryptedBytes = cipher.DecryptBytes(CipherAlgorithm.Aes_128_Cfb, encryptedBytesWithPassword, "my password") decryptedBytes = cipher.DecryptBytes(CipherAlgorithm.Aes_128_Cfb, encryptedBytesWithPasswordAndIV, "my password", HashAlgorithm.Sha512) End Sub End Class |
Encrypt and Decrypt Stream
The OpenSslCipher class provides EncryptStream and DecryptStream methods. An important side effect of these methods is that the Position of the output Stream parameter is at its end after the method call.
C# example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | using System; using DidiSoft.OpenSsl; class AesStreamDemo { public static void Main(string[] args) { OpenSslCipher cipher = new OpenSslCipher(); // 16 bytes long key for AES-128 bit encryption byte[] key = { 50, 199, 10, 159, 132, 55, 236, 189, 51, 243, 244, 91, 17, 136, 39, 230 }; // optional 16 bytes long initialization vector byte[] IV = { 150, 9, 112, 39, 32, 5, 136, 219, 251, 43, 44, 191, 217, 236, 3, 106 }; using (Stream dataStream = File.OpenRead(@"Data\Input.txt")) using (Stream encryptedStream = File.Create(@"Data\Encrypted.aes")) { cipher.EncryptStream(CipherAlgorithm.Aes_128_Cfb, dataStream, encryptedStream, key, IV); } Stream decryptedStream = new MemoryStream(); using (Stream encryptedStream = File.OpenRead(@"Data\Encrypted.aes")) { cipher.DecryptStream(CipherAlgorithm.Aes_128_Cfb, encryptedStream, decryptedStream, key, IV); } // the output stream Position must be reset in order to read the decrypted data afterwards decryptedStream.Position = 0; } } |
VB.NET example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | Imports System Imports DidiSoft.OpenSsl Class AesStreamDemo Public Shared Sub Main(args As String()) Dim cipher As New OpenSslCipher() ' 16 bytes long key for AES-128 bit encryption Dim key As Byte() = {50, 199, 10, 159, 132, 55, 236, 189, 51, 243, 244, 91, 17, 136, 39, 230} ' the initialization vector is optional and can be skipped Dim IV As Byte() = {150, 9, 112, 39, 32, 5, 136, 219, 251, 43, 44, 191, 217, 236, 3, 106} Using dataStream As Stream = File.OpenRead("Data\Input.txt") Using encryptedStream As Stream = File.Create("Data\Encrypted.aes") cipher.EncryptStream(CipherAlgorithm.Aes_128_Cfb, dataStream, encryptedStream, key, IV) End Using End Using Dim decryptedStream As Stream = New MemoryStream() Using encryptedStream As Stream = File.OpenRead("Data\Encrypted.aes") cipher.DecryptStream(CipherAlgorithm.Aes_128_Cfb, encryptedStream, decryptedStream, key, IV) End Using ' the output stream Position must be reset in order to read the decrypted data afterwards decryptedStream.Position = 0 End Sub End Class |
Blowfish
In order to use Blowfish just replace AES in the examples above with Blowfish like:
1 2 3 | OpenSslCipher cipher = new OpenSslCipher(); cipher.EncryptFile(CipherAlgorithm.BlowfishCfb, ... cipher.DecryptFile(CipherAlgorithm.BlowfishCfb, ... |
Cast-5
Cast-5 can be used the same way specifying it at first place
1 2 3 | OpenSslCipher cipher = new OpenSslCipher(); cipher.EncryptFile(CipherAlgorithm.Cast5Ecb, ... cipher.DecryptFile(CipherAlgorithm.Cast5Ecb, ... |
DES
DES is used with:
1 2 3 | OpenSslCipher cipher = new OpenSslCipher(); cipher.EncryptFile(CipherAlgorithm.DesCbc, ... cipher.DecryptFile(CipherAlgorithm.DesCbc, ... |
Triple DES
1 2 3 | OpenSslCipher cipher = new OpenSslCipher(); cipher.EncryptFile(CipherAlgorithm.DesEde3Cbc, ... cipher.DecryptFile(CipherAlgorithm.DesEde3Cbc, ... |
GOST
GOST 28147-89 can be specified with:
1 2 3 | OpenSslCipher cipher = new OpenSslCipher(); cipher.EncryptFile(CipherAlgorithm.Gost89, ... cipher.DecryptFile(CipherAlgorithm.Gost89, ... |
IDEA algorithm
1 2 3 | OpenSslCipher cipher = new OpenSslCipher(); cipher.EncryptFile(CipherAlgorithm.IdeaCfb, ... cipher.DecryptFile(CipherAlgorithm.IdeaCfb, ... |
RC-2 algorithm
1 2 3 | OpenSslCipher cipher = new OpenSslCipher(); cipher.EncryptFile(CipherAlgorithm.Rc2_128_Cbc, ... cipher.DecryptFile(CipherAlgorithm.Rc2_128_Cbc, ... |
RC-4 algorithm
1 2 3 | OpenSslCipher cipher = new OpenSslCipher(); cipher.EncryptFile(CipherAlgorithm.Rc4_128_Cbc, ... cipher.DecryptFile(CipherAlgorithm.Rc4_128_Cbc, ... |
RC-5 algorithm
1 2 3 | OpenSslCipher cipher = new OpenSslCipher(); cipher.EncryptFile(CipherAlgorithm.Rc5Cfb, ... cipher.DecryptFile(CipherAlgorithm.Rc5Cfb, ... |
Summary
This chapter illustrated OpenSSL cryptography with DidiSoft OpenSSL Library for .NET. A set of OpenSSL compatible algorithms are available in the DidiSoft.OpenSsl.CipherAlgorithm enum. In order to exchange data with OpenSSL the key and initialization vector (IV), or pass phrase must be known upfront. Also when sending encrypted data to OpenSSL the optional base-64 encoding of the data must also be established upfront.