justinooo icon

C# AES-256-CBC w/ PKCS7

justinooo | PRO | 07/26/19 09:27:37 AM UTC | 0 ⭐ | 1022 👁️ | Never ⏰ | []
C# |

3.16 KB

|

None

|

0 👍

/

0 👎

using System;
using System.IO;
using System.Security.Cryptography;
 
// https://stackoverflow.com/a/2791259
// AES-256-CBC
public class Crypto {
 
    /*
        
        notes:
        - key size = 256 bits (32 bytes)
        - block/iv size = 128 bits (16 bytes)
 
    */
 
    private static void WriteBytes(byte[] bytes) {
        for (int i = 0; i < bytes.Length; i++) {
            byte b = bytes[i];
            Console.Write("0x" + b.ToString("x2"));
            bool last = i == bytes.Length - 1;
            Console.Write(last ? Environment.NewLine : ", ");
        }
    }
 
    // https://www.random.org/bytes/
    private static byte[] _salt = { 0x28, 0x7c, 0x6a, 0xa2, 0x2e, 0xa6, 0x46, 0x4b, 0x68, 0xef, 0x91, 0xec, 0x0e, 0x8c, 0x3e, 0x50 };
 
    public static string EncryptString(string plainText, string sharedSecret) {
        string outStr = null;
        RijndaelManaged algorithm = null;
        try {
            Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(sharedSecret, _salt);
            algorithm = new RijndaelManaged();
            algorithm.Key = key.GetBytes(algorithm.KeySize / 8); // 32 bytes for a key
            ICryptoTransform encryptor = algorithm.CreateEncryptor(algorithm.Key, algorithm.IV);
            using (MemoryStream msEncrypt = new MemoryStream()) {
                msEncrypt.Write(algorithm.IV, 0, algorithm.IV.Length);
                using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                    using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                        swEncrypt.Write(plainText);
                outStr = Convert.ToBase64String(msEncrypt.ToArray());
            }
        } finally {
            if (algorithm != null)
                algorithm.Clear();
        }
        return outStr;
    }
 
    public static string DecryptString(string cipherText, string sharedSecret) {
        RijndaelManaged algorithm = null;
        string plaintext = null;
        try {
            Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(sharedSecret, _salt);          
            byte[] bytes = Convert.FromBase64String(cipherText);
            using (MemoryStream msDecrypt = new MemoryStream(bytes)) {
                algorithm = new RijndaelManaged();
                algorithm.Key = key.GetBytes(algorithm.KeySize / 8);
                algorithm.IV = DeriveIV(msDecrypt, algorithm.BlockSize / 8);
                ICryptoTransform decryptor = algorithm.CreateDecryptor(algorithm.Key, algorithm.IV);
                using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                        plaintext = srDecrypt.ReadToEnd();
            }
        } finally {
            if (algorithm != null)
                algorithm.Clear();
        }
        return plaintext;
    }
 
    private static byte[] DeriveIV(Stream s, int length) {
        byte[] iv = new byte[length];
        if (s.Read(iv, 0, length) != length)
            throw new Exception("Failed to derive IV from stream.");
        return iv;
    }
 
}

Comments