DEV Community

Abishek G.C
Abishek G.C

Posted on

Encryption & Decryption Using RSA

Data encryption is important given the fact that we are living in world where integrity of information is of utmost importance. One popular encryption method is RSA, a public-key cryptosystem that uses two keys: One of the keys is used for encrypting the data and the other for decrypting it; the two are known as the public and the private key respectively. In this post, we shall discuss how to apply encryption and decryption using RSA and how to involve digital sign to check the validity of data. We'll use .NET using some additional functions situated in the Helper_functions class.

What is RSA?
RSA is an asymmetric key cryptographic algorithm used to encrypt the data and also used to sign messages. Asymmetric means that it uses two different keys: The public key that is used to encrypt the data and the other key known as the private key that decrypts the data.
The Code Overview

We'll break down the functionality into three parts:

  1. Encryption and Decryption
  2. Generating and Verifying Signatures
  3. Base64 and Key Utilities

Now it is time to take a closer look at the presented code together with the actual functionality that has been put into practice.

1. Encryption and Decryption

To protect the data we apply a conventional symmetric encryption on the data then to protect the symmetric we apply RSA.

The EncryptionHelper class contains two methods:The EncryptionHelper class contains two methods:

Encrypt(string data, byte[] secretKey): Encrypts the data using AES with a secret key which is known only to the intended recipient of the message.
Encrypt(string data, string publicKey): Encrypts the secret key with the help of RSA public key.

AES Encryption Method

public static string Encrypt(string strToEncrypt, byte[] secretKey)
{
    byte[] iv = new byte[16];
    byte[] array;
    using (Aes aes = Aes.Create())
    {
        aes.Key = secretKey;
        aes.IV = iv;
        aes.Mode = CipherMode.ECB;
        aes.Padding = PaddingMode.PKCS7;
        ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
        using (MemoryStream memoryStream = new MemoryStream())
        {
            using (CryptoStream cryptoStream = new CryptoStream((Stream)memoryStream, encryptor, CryptoStreamMode.Write))
            {
                using (StreamWriter streamWriter = new StreamWriter((Stream)cryptoStream))
                {
                    streamWriter.Write(strToEncrypt);
                }
                array = memoryStream.ToArray();
            }
        }
    }
    return Convert.ToBase64String(array);
}
Enter fullscreen mode Exit fullscreen mode

In this method AES is applied with ECB mode along with PKCS7 padding. The secret key is used to encrypt the string data and the result is in form of a Base64 string.

RSA Encryption Method

public static byte[] Encrypt(string data, string publicKey)
{
    StringBuilder publicKeyPem = new StringBuilder();
    publicKeyPem.Append("-----BEGIN PUBLIC KEY-----\r\n");
    publicKeyPem.Append(publicKey);
    publicKeyPem.Append("\r\n-----END PUBLIC KEY-----");

    using TextReader publicKeyTextReader = new StringReader(publicKeyPem.ToString());
    RsaKeyParameters publicKeyParam = (RsaKeyParameters)new PemReader(publicKeyTextReader).ReadObject();
    RSAParameters rsaParams = DotNetUtilities.ToRSAParameters(publicKeyParam);

    using RSACryptoServiceProvider csp = new RSACryptoServiceProvider();
    csp.ImportParameters(rsaParams);

    var encryptedBytes = csp.Encrypt(Encoding.UTF8.GetBytes(data), false);
    return encryptedBytes;
}
Enter fullscreen mode Exit fullscreen mode

Here, we encrypt the data using RSA with a public key. The data is transformed into bytes, then encrypted using the RSA public key.

2. Signing and Verifying Data

Digital signatures guarantee the dataโ€™s authenticity since it serves as a way to check whether the data received has been changed.

The same process is implemented in the SignatureHelper class in which BouncyCastle is used to generate and verify the signature.

Generate Signature

public static string GenerateSignature(string data, string privateKeyPath)
{
    StringBuilder privateKeyPem = new StringBuilder();
    privateKeyPem.Append("-----BEGIN RSA PRIVATE KEY-----\r\n");
    privateKeyPem.Append(privateKeyPath);
    privateKeyPem.Append("\r\n-----END RSA PRIVATE KEY-----");

    using TextReader strReader = new StringReader(privateKeyPem.ToString());
    PemReader pemReader = new PemReader(strReader);
    AsymmetricCipherKeyPair keyPair = (AsymmetricCipherKeyPair)pemReader.ReadObject();
    RsaKeyParameters privateKey = (RsaKeyParameters)keyPair.Private;

    ISigner signer = SignerUtilities.GetSigner("SHA256withRSA");
    signer.Init(true, privateKey);
    signer.BlockUpdate(Encoding.ASCII.GetBytes(data), 0, data.Length);
    byte[] signedBytes = signer.GenerateSignature();

    return Base64Helper.Base64Encode(signedBytes);
}
Enter fullscreen mode Exit fullscreen mode

This method generates a signature for the data using the RSA private key. The signature ensures that the data has not been tampered with.

Verify Signature

public static bool VerifySignature(string data, string publicKeyPath, byte[] signature)
{
    StringBuilder publicKeyPem = new StringBuilder();
    publicKeyPem.Append("-----BEGIN PUBLIC KEY-----\r\n");
    publicKeyPem.Append(publicKeyPath);
    publicKeyPem.Append("\r\n-----END PUBLIC KEY-----");

    using TextReader publicKeyTextReader = new StringReader(publicKeyPem.ToString());
    RsaKeyParameters publicKey = (RsaKeyParameters)new PemReader(publicKeyTextReader).ReadObject();

    ISigner signer = SignerUtilities.GetSigner("SHA256withRSA");
    signer.Init(false, publicKey);
    signer.BlockUpdate(Encoding.ASCII.GetBytes(data), 0, data.Length);

    return signer.VerifySignature(signature);
}
Enter fullscreen mode Exit fullscreen mode

The VerifySignature method then validate the signature using the public key of RSA algorithm. Thus, if the signature is identical, then we can be certain of the dataโ€™s accuracy.

3. Utility Classes
Base64 Encoding and Decoding: To encode and decode the byte arrays from Base64 strings we use Base64Helper class.

AlphaNumericStringHelper This helper helps in creating a random Alpha Numeric String used in generating secrets keys.

public static string GetAlphaNumericString(int size)
{
    string AlphaNumericString = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvxyz";
    StringBuilder sb = new(size);
    Random rnd = new();
    for (int i = 0; i < size; i++)
    {
        sb.Append(AlphaNumericString[rnd.Next(AlphaNumericString.Length)]);
    }
    return sb.ToString();
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

In essence, when you use RSA encryption to encode data and use digital signatures to verify the data, then you are able to safely transport your information and also prove that it has not been tampered with. These two classes are the EncryptionHelper and SignatureHelper classes and they forms the basis of all encryption, decryption and verification in this system. Using such utilities, developers are able to encrypt the data and then sign it and decrypt the signed data only with using the correct private key.

AES is a symmetric key encryption algorithm used for encrypting and decrypting the data while RSA is an asymmetric key encryption algorithm, used when there is an exchange of keys between two stations; therefore, using AES and RSA provide extended security for most systems.

Please Check the Repository for More Details: Link

Top comments (0)