Skip to content

Instantly share code, notes, and snippets.

@doncadavona
Last active October 29, 2023 09:30
  • Star 5 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save doncadavona/19bf1423daf2790276dc0a823cd8c579 to your computer and use it in GitHub Desktop.
A sample C# class to encrypt and decrypt texts using the cipher AES-256-CBC used in Laravel.
using System;
using System.Text;
using System.Security.Cryptography;
using System.Web.Script.Serialization;
using System.Collections.Generic;
namespace Aes256CbcEncrypterApp
{
class MainClass
{
public static void Main(string[] args)
{
Console.WriteLine("Hello, world!");
// The sample encryption key. Must be 32 characters.
string Key = "8UHjPgXZzXCGkhxV2QCnooyJexUzvJrO";
// The sample text to encrypt and decrypt.
string Text = "Here is some text to encrypt!";
// Encrypt and decrypt the sample text via the Aes256CbcEncrypter class.
string Encrypted = Aes256CbcEncrypter.Encrypt(Text, Key);
string Decrypted = Aes256CbcEncrypter.Decrypt(Encrypted, Key);
// Show the encrypted and decrypted data and the key used.
Console.WriteLine("Original: {0}", Text);
Console.WriteLine("Key: {0}", Key);
Console.WriteLine("Encrypted: {0}", Encrypted);
Console.WriteLine("Decrypted: {0}", Decrypted);
}
}
/**
* A class to encrypt and decrypt strings using the cipher AES-256-CBC.
*/
class Aes256CbcEncrypter
{
private static readonly Encoding encoding = Encoding.UTF8;
public static string Encrypt(string plainText, string key)
{
try
{
RijndaelManaged aes = new RijndaelManaged();
aes.KeySize = 256;
aes.BlockSize = 128;
aes.Padding = PaddingMode.PKCS7;
aes.Mode = CipherMode.CBC;
aes.Key = encoding.GetBytes(key);
aes.GenerateIV();
ICryptoTransform AESEncrypt = aes.CreateEncryptor(aes.Key, aes.IV);
byte[] buffer = encoding.GetBytes(plainText);
string encryptedText = Convert.ToBase64String(AESEncrypt.TransformFinalBlock(buffer, 0, buffer.Length));
String mac = "";
mac = BitConverter.ToString(HmacSHA256(Convert.ToBase64String(aes.IV) + encryptedText, key)).Replace("-", "").ToLower();
var keyValues = new Dictionary<string, object>
{
{ "iv", Convert.ToBase64String(aes.IV) },
{ "value", encryptedText },
{ "mac", mac },
};
JavaScriptSerializer serializer = new JavaScriptSerializer();
return Convert.ToBase64String(encoding.GetBytes(serializer.Serialize(keyValues)));
}
catch (Exception e)
{
throw new Exception("Error encrypting: " + e.Message);
}
}
public static string Decrypt(string plainText, string key)
{
try
{
RijndaelManaged aes = new RijndaelManaged();
aes.KeySize = 256;
aes.BlockSize = 128;
aes.Padding = PaddingMode.PKCS7;
aes.Mode = CipherMode.CBC;
aes.Key = encoding.GetBytes(key);
// Base 64 decode
byte[] base64Decoded = Convert.FromBase64String(plainText);
string base64DecodedStr = encoding.GetString(base64Decoded);
// JSON Decode base64Str
JavaScriptSerializer serializer = new JavaScriptSerializer();
var payload = serializer.Deserialize<Dictionary<string, string>>(base64DecodedStr);
aes.IV = Convert.FromBase64String(payload["iv"]);
ICryptoTransform AESDecrypt = aes.CreateDecryptor(aes.Key, aes.IV);
byte[] buffer = Convert.FromBase64String(payload["value"]);
return encoding.GetString(AESDecrypt.TransformFinalBlock(buffer, 0, buffer.Length));
}
catch (Exception e)
{
throw new Exception("Error decrypting: " + e.Message);
}
}
static byte[] HmacSHA256(String data, String key)
{
using (HMACSHA256 hmac = new HMACSHA256(encoding.GetBytes(key)))
{
return hmac.ComputeHash(encoding.GetBytes(data));
}
}
}
}
@danarrib
Copy link

danarrib commented Apr 7, 2023

Hey, thank you so much for this routine. You can't imagine how much time I spent looking for this.

Just to give something back: Here's a version that works on .NET 6 (it replaces the JavaScriptSerializer by the JsonSerializer from the System.Text.Json)

using System;
using System.Text;
using System.Security.Cryptography;
using System.Collections.Generic;
using System.Text.Json;

namespace Junkyard
{
    /**
	 * A class to encrypt and decrypt strings using the cipher AES-256-CBC.
	 */
    public class Aes256CbcEncrypter
    {
        private static readonly Encoding encoding = Encoding.UTF8;

        public static string Encrypt(string plainText, string key)
        {
            try
            {
                RijndaelManaged aes = new RijndaelManaged();
                aes.KeySize = 256;
                aes.BlockSize = 128;
                aes.Padding = PaddingMode.PKCS7;
                aes.Mode = CipherMode.CBC;

                aes.Key = encoding.GetBytes(key);
                aes.GenerateIV();

                ICryptoTransform AESEncrypt = aes.CreateEncryptor(aes.Key, aes.IV);
                byte[] buffer = encoding.GetBytes(plainText);

                string encryptedText = Convert.ToBase64String(AESEncrypt.TransformFinalBlock(buffer, 0, buffer.Length));

                String mac = "";

                mac = BitConverter.ToString(HmacSHA256(Convert.ToBase64String(aes.IV) + encryptedText, key)).Replace("-", "").ToLower();

                var keyValues = new Dictionary<string, object>
                {
                    { "iv", Convert.ToBase64String(aes.IV) },
                    { "value", encryptedText },
                    { "mac", mac },
                };

                var serializedKeyValues = JsonSerializer.Serialize(keyValues);

                return Convert.ToBase64String(encoding.GetBytes(serializedKeyValues));
            }
            catch (Exception e)
            {
                throw new Exception("Error encrypting: " + e.Message);
            }
        }

        public static string Decrypt(string plainText, string key)
        {
            try
            {
                RijndaelManaged aes = new RijndaelManaged();
                aes.KeySize = 256;
                aes.BlockSize = 128;
                aes.Padding = PaddingMode.PKCS7;
                aes.Mode = CipherMode.CBC;
                aes.Key = encoding.GetBytes(key);

                // Base 64 decode
                byte[] base64Decoded = Convert.FromBase64String(plainText);
                string base64DecodedStr = encoding.GetString(base64Decoded);

                // JSON Decode base64Str
                var payload = JsonSerializer.Deserialize<Dictionary<string, string>>(base64DecodedStr);
                aes.IV = Convert.FromBase64String(payload["iv"]);

                ICryptoTransform AESDecrypt = aes.CreateDecryptor(aes.Key, aes.IV);
                byte[] buffer = Convert.FromBase64String(payload["value"]);

                return encoding.GetString(AESDecrypt.TransformFinalBlock(buffer, 0, buffer.Length));
            }
            catch (Exception e)
            {
                throw new Exception("Error decrypting: " + e.Message);
            }
        }

        static byte[] HmacSHA256(String data, String key)
        {
            using (HMACSHA256 hmac = new HMACSHA256(encoding.GetBytes(key)))
            {
                return hmac.ComputeHash(encoding.GetBytes(data));
            }
        }
    }
}

Thank you.

@doncadavona
Copy link
Author

Glad this helped. Thank you too @danarrib.

@ntprohd
Copy link

ntprohd commented Oct 29, 2023

I used the above code but got an error when decoding it on laravel, or an error about "The MAC is invalid." or the error "unserialize(): Error at offset 0 of 34 bytes". Can someone help me fix it. thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment