RSA cryptography

DidiSoft OpenSSL Library for .NET offers RSA cryptography methods located in the DidiSoft.OpenSsl.OpenSslRsa class, designed to provide compatibility with the classic OpenSSL tool openssl rsautl , openssl genrsa and openssl rsa commands.

Table of contents

RSA encryption

RSA encryption is done with the OpenSSL command openssl rsautl -encrypt. Here we are going to shown how to accomplish the same result with .NET. The public RSA key provided as encryption parameter can be in PEM, DER format or as X.509 certificate.

C# example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
using System;
using DidiSoft.OpenSsl.Rsa;
 
class RsaEncryptDemo
{
 public static void Main(string[] args)
 {
	OpenSslRsa rsa = new OpenSslRsa();
 
	bool base64Encode = true;
	OpenSslRsa.Padding padding = OpenSslRsa.Padding.Pkcs1;
 
	string encryptedString = rsa.EncryptString("Hello world", @"Data\public_key.pem", base64Encode, padding); }
}

VB.NET example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Imports System
Imports DidiSoft.OpenSsl.Rsa
 
Class RsaEncryptDemo
 Public Shared Sub Main(args As String())
	Dim rsa As New OpenSslRsa()
 
	Dim base64Encode As Boolean = True
	Dim padding As OpenSslRsa.Padding = OpenSslRsa.Padding.Pkcs1
 
	Dim encryptedString As String = _
             rsa.EncryptString("Hello world", "Data\public_key.pem", base64Encode, padding) End Sub
End Class

RSA decryption

Private key
In order to decrypt RSA encrypted data, we need the private RSA key corresponding to the public key used to encrypt the input data. If the private key is protected with a password it shall also be specified.

Base-64 or hexadecimal format
When decrypting data the OpenSslRsa.Decrypt methods auto-detect if the data is base-64 encoded and will automatically decode it before decrypting.

Padding 
The padding of the encrypted data if different from PKCS#1 shall also be specified explicitly.

C# example

1
2
3
4
5
6
7
8
9
10
11
12
13
using System;
using DidiSoft.OpenSsl;
 
class RsaDecryptDemo
{
 public static void Main(string[] args)
 {
	OpenSslRsa rsa = new OpenSslRsa();
 
	string encryptedString = rsa.EncryptString("Hello world", @"Data\public_key.pem");
        string decryptedString = rsa.DecryptString(encryptedString, @"Data\private_key.pem"); }
}

VB.NET example

1
2
3
4
5
6
7
8
9
10
11
Imports System
Imports DidiSoft.OpenSsl
 
Class RsaDecryptDemo
 Public Shared Sub Main(args As String())
	Dim rsa As New OpenSslRsa()
 
	Dim encryptedString As String = rsa.EncryptString("Hello world", "Data\public_key.pem")
        Dim decryptedString As String = rsa.DecryptString(encryptedString, "Data\private_key.pem")
 End SubEnd Class

RSA digital signatures

In order to create an RSA signature we need a private RSA key (if password-protected, the password must be specified as well). Another optional parameter is the Hash digest algorithm for the signature (later we are gonna need it again in order to verify the signature).

C# example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
using System;
using DidiSoft.OpenSsl;
 
class RsaSignDemo
{
 public static void Main(string[] args)
 {
	OpenSslRsa rsa = new OpenSslRsa();
 
        bool base64Encode = true;
        // create the signature as Base-64 encoded string
        string signatureString = rsa.SignString("Hello world", @"Data\private_key.pem", HashAlgorithm.Sha1, base64Encode); 
        // or we may need the raw signature bytes
        byte[] signatureBytes = rsa.SignStringRaw("Hello world", @"Data\private_key.pem", HashAlgorithm.Sha1);
 }
}

VB.NET example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Imports System
Imports DidiSoft.OpenSsl
 
Class RsaSignDemo
 Public Shared Sub Main(args As String())
	Dim rsa As New OpenSslRsa()
 
        Dim base64Encode As Boolean = True
        ' create the signature as Base-64 encoded string
        Dim signatureString As String = rsa.SignString("Hello world", "Data\private_key.pem", HashAlgorithm.Sha1, base64Encode) 
        ' or we may need the raw signature bytes
        Dim signatureBytes As Byte() = rsa.SignStringRaw("Hello world", "Data\private_key.pem", HashAlgorithm.Sha1)
 End Sub
End Class

Verify signatures

Signature verification is the opposite of the signing process. It takes the correct public key and uses it to calculate again the signature hash and compare it with the provided signature.

Unfortunately, the plain RSA signatures don’t make any difference between tempered signature and wrong public key, so both cases are considered a signature verification failure.

C# example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
using System;
using DidiSoft.OpenSsl;
 
class RsaSignDemo
{
 public static void Main(string[] args)
 {
  OpenSslRsa rsa = new OpenSslRsa();
 
  string signatureString = rsa.SignString("Hello world", @"Data\private_key.pem", HashAlgorithm.Sha1);
 
  bool signatureOk = rsa.VerifyString("Hello world", signatureString, @"Data\public_key.pem", HashAlgorithm.Sha1); }
}

VB.NET example

1
2
3
4
5
6
7
8
9
10
11
12
Imports System
Imports DidiSoft.OpenSsl
 
Class RsaSignDemo
 Public Shared Sub Main(args As String())
	Dim rsa As New OpenSslRsa()
 
        Dim signatureString As String = rsa.SignString("Hello world", "Data\private_key.pem", HashAlgorithm.Sha1)
 
        Dim signatureOk As Boolean = rsa.VerifyString("Hello world", signatureString, "Data\public_key.pem", HashAlgorithm.Sha1) End Sub
End Class

RSA_private_encrypt

The method OpenSslRsa.PrivateEncrypt is equivalent of RSA_private_encrypt. It is a low-level signature creation routine that expects the input tu be already hashed (although this is not mandatory). In the example below we are going to create RSA signature this way:

DidiSoft.OpenSsl.Rsa.OpenSslRsa rsa = new DidiSoft.OpenSsl.Rsa.OpenSslRsa();
byte[] data = new byte[] { 10, 20, 21, 32, 22, 45, 67, 93, 76, 90, 91, 03, 56 };
byte[] signed = rsa.PrivateEncrypt(data, File.ReadAllBytes(Keys.privKeyLocation), OpenSslRsa.Padding.None);

RSA_public_decrypt

RSA_public_decrypt extracts data created with RSA_private_encrypt. It is a low-level version of Verifying a signature.

In the example below in addition to invoking OpenSslRsa.PublicDecrypt we are going to create the RSA public key by specifying the modulus and exponent explicitly (instead of loading the key from a file):

DidiSoft.OpenSsl.Rsa.OpenSslRsa rsa = new DidiSoft.OpenSsl.Rsa.OpenSslRsa();
 
// load data cerated with RSA_private_encrypt/PrivateEncrypt
byte[] privateEncryptedData = ...;
 
// create public key on the fly
string pubModulusHex = "...";
long pubExponentLong = 65537;
DidiSoft.OpenSsl.Rsa.RsaPublicKey pubKey = new DidiSoft.OpenSsl.Rsa.RsaPublicKey(pubModulusHex, pubExponentLong);
 
byte[] decrypted = rsa.PublicDecrypt(privateEncryptedData, pubKey, OpenSslRsa.Padding.None);

Summary

This tutorial illustrated how to perform OpenSSL compatible RSA cryptographic operations in .NET Framework.