C#实现微信AES-128-CBC加解密数据

用C# (.NET Core 3.1 or above)实现微信或小程序AES-128-CBC加解密数据

直接上代码

其中引用的测试数据和Key来自 [https://git.weixin.qq.com/wxa_iot/deviceProtocol/blob/master/device_card_document.md]

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace console
{
    /// <summary>
    /// 实现微信AES-128-CBC加解密数据
    /// </summary>
    public class WXBizDataCrypt
    {
        /*
         * [C#实现微信AES-128-CBC加密数据的解密](https://www.cnblogs.com/jetz/p/6384809.html)
         */

        /// <summary>
        /// AES解密
        /// </summary>
        /// <param name="text">带解密文本</param>
        /// <param name="aesKey">密钥</param>
        /// <param name="aesIV">16位初始向量</param>
        /// <returns></returns>
        public static string AESDecrypt(string text, string aesKey, string aesIV)
        {
            //16进制数据转换成byte
            byte[] encryptedData = Convert.FromBase64String(text); // strToToHexByte(text);
            using (var cipher = Aes.Create("AesManaged"))
            {
                cipher!.Key = Convert.FromBase64String(aesKey); // Encoding.UTF8.GetBytes(AesKey);
                cipher.IV = Convert.FromBase64String(aesIV); // Encoding.UTF8.GetBytes(AesIV);
                cipher.Mode = CipherMode.CBC;
                cipher.Padding = PaddingMode.PKCS7;
                ICryptoTransform transform = cipher.CreateDecryptor();
                byte[] plainText = transform.TransformFinalBlock(encryptedData, 0, encryptedData.Length);
                string result = Encoding.Default.GetString(plainText);
                return result;
            }
        }

        /// <summary>
        /// AES加密
        /// reference to https://www.cnblogs.com/xyz0835/p/5775850.html
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static string AesEncrypt(string data, string aesKey, string aesIV)
        {
            byte[] keyBytes = Convert.FromBase64String(aesKey);

            using (var cipher = Aes.Create("AesManaged"))
            {
                cipher!.Mode = CipherMode.CBC;
                cipher.Padding = PaddingMode.PKCS7;
                cipher.KeySize = 128;
                cipher.BlockSize = 128;
                cipher.Key = keyBytes;
                cipher.IV = Convert.FromBase64String(aesIV);

                byte[] valueBytes = Encoding.UTF8.GetBytes(data);

                byte[] encrypted;
                using (ICryptoTransform encryptor = cipher.CreateEncryptor())
                {
                    using (MemoryStream ms = new MemoryStream())
                    {
                        using (CryptoStream writer = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                        {
                            writer.Write(valueBytes, 0, valueBytes.Length);
                            writer.FlushFinalBlock();
                            encrypted = ms.ToArray();
                            var encryptedBase64 = Convert.ToBase64String(encrypted);
                            return encryptedBase64;
                        }
                    }
                }
            }
        }

        public static void Test()
        {
            var data = "{\"action\":\"fetch_device_state\",\"model_id\":\"xxx\",\"sn\":\"xxx\"}";
            var sessionKey = "uIAxYsHTlCcnmJcaWP00Ig==";
            var encryptedData =
                "bOCfk9esztFBDvxP19s2WB679AtTWTZIUOQFHRJyCL/MF7iDi1MCFKrzkgtNNLRkDErpBBUGNpIVeAtMyCndgg==";
            var iv = "xCxTwX7F/Hxq8o3LnGF27g==";

            string decrypted = AESDecrypt(encryptedData, sessionKey, iv);

            Console.WriteLine($"decrypted: {decrypted}");
            Console.WriteLine(decrypted == data ? "decrypted succeed" : "decrypted failed");

            string encrypted = AesEncrypt(data, sessionKey, iv);
            Console.WriteLine($"encrypted: {encrypted}");
            Console.WriteLine(encrypted == encryptedData ? "encrypted succeed" : "encrypted failed");
        }
    }
}

运行结果

result

扩展一下通过读取文件来加解密

using System;
using System.IO;
using System.Text.Json;
using System.Text.Json.Nodes;

namespace console
{
    class Program
    {
        static void Main(string[] args)
        {
            DecryptFromFile("encrypted_data.json");
            EncryptFromFile("clear_data.json");
        }

        public static void DecryptFromFile(string fileName)
        {
            var sessionKey = "uIAxYsHTlCcnmJcaWP00Ig==";
            
            var encryptedFileData = File.ReadAllText(fileName);
            var node = JsonNode.Parse(encryptedFileData);
            var encryptedData = (string)node!["encrypted_data"];
            var iv = (string)node!["iv"];

            var decrypted = WXBizDataCrypt.AESDecrypt(encryptedData, sessionKey, iv);
            var deNode = JsonNode.Parse(decrypted);
            var options = new JsonSerializerOptions { WriteIndented = true };
            Console.WriteLine(deNode!.ToJsonString(options));
        }
        
        public static void EncryptFromFile(string fileName)
        {
            var sessionKey = "uIAxYsHTlCcnmJcaWP00Ig==";
            var iv = "xCxTwX7F/Hxq8o3LnGF27g==";
            
            var clearFileData = File.ReadAllText(fileName);
            clearFileData = JsonNode.Parse(clearFileData)!.ToJsonString();
            var encryptedData = WXBizDataCrypt.AesEncrypt(clearFileData, sessionKey, iv);

            var node = new JsonObject()
            {
                ["encrypted_data"] = encryptedData,
                ["iv"] = iv,
                ["encrypted_type"] = "AES/CBC/PKCS7Padding"
            };
            var options = new JsonSerializerOptions { WriteIndented = true };
            Console.WriteLine(node!.ToJsonString(options));
        }
    }
}

执行结果

posted @ 2022-06-10 16:33  bingliang  阅读(173)  评论(0编辑  收藏  举报