Symmetric cipher encryption

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.