C# AES 加密解密,微信敏感数据解密


 

2022-12-16重新编辑C# AES加密解密

在调用RijndaelManaged 时发现生成加密的时候设置参数的顺序和解密赋值参数的顺序不一致时解密不了。这可能是因为RijndaelManaged封装的get/set时加了处理。

所以要统一加密和解密的RijndaelManaged 对象

 1 /// <summary>
 2 /// 统一创建加密和解密参数顺序设置
 3 /// </summary>
 4 /// <param name="key">key 是明文,不需要bas64这些</param>
 5 /// <param name="sha1">是否对key进行sha1,是的话key值只需要大于16位即可,取keySize/8的值</param>
 6 /// <returns></returns>
 7 private static RijndaelManaged CreateAES(string key, bool sha1 = false)
 8 {
 9     if (sha1 == false)
10     {
11         if (key.Length != 16 && key.Length != 24)
12         {
13             throw new Exception("key的位数必须是16或24");
14         }
15     }
16     else
17     {
18         if (key.Length < 16)
19         {
20             throw new Exception("key的位数必须是大于16");
21         }
22     }
23     RijndaelManaged rm = new RijndaelManaged
24     {
25         Mode = CipherMode.ECB,
26         Padding = PaddingMode.PKCS7,
27         KeySize = 128,
28         BlockSize = 128
29     };
30     if (sha1 == false)
31     {
32         rm.Key = Encoding.UTF8.GetBytes(key);
33     }
34     else
35     {
36         rm.Key = GetSecretKey(key, rm.KeySize / 8);
37     }
38     return rm;
39 }

key应该是16或24位。但是这就比较局限性了,所以在我们不经意间设置了不是这个长度的key时,就会报错啦。为了决解这个问题,我们就要固定这个key的长度。通过哈希来实现。

 1 /// <summary>
 2 /// .NET与JAVA的AES互通【SecureRandom.getInstance("SHA1PRNG")】
 3 /// </summary>
 4 /// <param name="password"></param>
 5 /// <returns></returns>
 6 private static byte[] GetSecretKey(string password, int size = 16)
 7 #region
 8 {
 9     byte[] keyArray;
10     byte[] seed = Encoding.UTF8.GetBytes(password);
11     using (var st = new SHA1CryptoServiceProvider())
12     {
13         using (var nd = new SHA1CryptoServiceProvider())
14         {
15             var rd = nd.ComputeHash(st.ComputeHash(seed));
16             keyArray = rd.Take(size).ToArray();
17         }
18     }
19     return keyArray;
20 }
21 #endregion
SHA1:返回一个160位的byte[]数组,20字节,我们取前面16位刚好满足。

创建加密实例:
1 public static string Encrypt(string text, string key, bool keyNeedHash = false)
2 {
3     var rm = CreateAES(key, keyNeedHash);
4     ICryptoTransform transform = rm.CreateEncryptor();
5     byte[] plainText = Encoding.UTF8.GetBytes(text);
6     byte[] cipherBytes = transform.TransformFinalBlock(plainText, 0, plainText.Length);
7     return Convert.ToBase64String(cipherBytes);
8 }

解密方法:

public static string Decrypt(string base64_encodeText, string key, bool keyNeedHash = false)
{
    var rm = CreateAES(key, keyNeedHash);
    ICryptoTransform transform = rm.CreateDecryptor();
    byte[] plainText = Convert.FromBase64String(base64_encodeText);
    byte[] cipherBytes = transform.TransformFinalBlock(plainText, 0, plainText.Length);
    return Encoding.UTF8.GetString(cipherBytes);
}

以上是新整理的笔记。

以下是之前的笔记,做个对比。

/// AES加密解密方式
/// ECB模式不许偏移量iv
/// 提供输出base64和Hex 16进制格式

  1 public class AES_Cipher
  2     {
  3         /// <summary>
  4         /// AES 算法加密(ECB模式) 将明文加密,加密后进行Hex编码,返回密文
  5         /// </summary>
  6         /// <param name="str">明文</param>
  7         /// <param name="key">密钥</param>
  8         /// <returns>加密后Hex编码的密文</returns>
  9         public static string AesEncryptor_ECB_Hex(string str, string key)
 10         {
 11             if (string.IsNullOrEmpty(str)) return null;
 12             Byte[] toEncryptArray = Encoding.UTF8.GetBytes(str);
 13 
 14             RijndaelManaged rm = new RijndaelManaged
 15             {
 16                 //Key = StrToHexByte(key),  //把key转成16进制
 17                 Key = Encoding.UTF8.GetBytes(key),
 18                 Mode = CipherMode.ECB,
 19                 Padding = PaddingMode.PKCS7
 20             };
 21 
 22             ICryptoTransform cTransform = rm.CreateEncryptor();
 23             Byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
 24 
 25             return ToHexString(resultArray);
 26         }
 27 
 28 
 29         /// <summary>
 30         ///AES 算法解密(ECB模式) 将密文Hex解码后进行解密,返回明文
 31         /// </summary>
 32         /// <param name="str">密文</param>
 33         /// <param name="key">密钥</param>
 34         /// <returns>明文</returns>
 35         public static string AesDecryptor_ECB_Hex(string str, string key)
 36         {
 37             if (string.IsNullOrEmpty(str)) return null;
 38             Byte[] toEncryptArray = StrToHexByte(str);
 39 
 40             RijndaelManaged rm = new RijndaelManaged
 41             {
 42                 //Key = StrToHexByte(key), //key16进制解码
 43                 Key = Encoding.UTF8.GetBytes(key),
 44                 Mode = CipherMode.ECB,
 45                 Padding = PaddingMode.PKCS7
 46             };
 47 
 48             ICryptoTransform cTransform = rm.CreateDecryptor();
 49             Byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
 50 
 51             return Encoding.UTF8.GetString(resultArray);
 52         }
 53 
 54         /// <summary>
 55         /// byte数组Hex编码
 56         /// </summary>
 57         /// <param name="bytes">需要进行编码的byte[]</param>
 58         /// <returns></returns>
 59         public static string ToHexString(byte[] bytes)
 60         {
 61             string hexString = string.Empty;
 62             if (bytes != null)
 63             {
 64                 StringBuilder strB = new StringBuilder();
 65                 for (int i = 0; i < bytes.Length; i++)
 66                 {
 67                     strB.Append(bytes[i].ToString("X2"));
 68                 }
 69                 hexString = strB.ToString();
 70             }
 71             return hexString;
 72         }
 73         /// <summary> 
 74         /// 字符串进行Hex解码(Hex.decodeHex())
 75         /// </summary> 
 76         /// <param name="hexString">需要进行解码的字符串</param> 
 77         /// <returns></returns> 
 78         public static byte[] StrToHexByte(string hexString)
 79         {
 80             hexString = hexString.Replace(" ", "");
 81             if ((hexString.Length % 2) != 0)
 82                 hexString += " ";
 83             byte[] returnBytes = new byte[hexString.Length / 2];
 84             for (int i = 0; i < returnBytes.Length; i++)
 85                 returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
 86             return returnBytes;
 87         }
 88 
 89 
 90         /// <summary>
 91         /// AES 算法加密(ECB模式) 将明文加密,加密后进行Base64编码,返回密文
 92         /// </summary>
 93         /// <param name="str">明文</param>
 94         /// <param name="key">密钥</param>
 95         /// <returns>加密后Base64编码的密文</returns>
 96         public static string AesEncryptor_ECB_Base64(string str, string key)
 97         {
 98             if (string.IsNullOrEmpty(str)) return null;
 99             Byte[] toEncryptArray = Encoding.UTF8.GetBytes(str);
100 
101             RijndaelManaged rm = new RijndaelManaged
102             {
103                 //Key = Convert.FromBase64String(key), //如果key是base64编码过的就解码转换,如果按照规范明文和key都应该传入base64
104                 Key = Encoding.UTF8.GetBytes(key),
105                 Mode = CipherMode.ECB,
106                 Padding = PaddingMode.PKCS7
107             };
108 
109             ICryptoTransform cTransform = rm.CreateEncryptor();
110             Byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
111 
112             return Convert.ToBase64String(resultArray);
113         }
114 
115         /// <summary>
116         ///AES 算法解密(ECB模式) 将密文Base64解码后进行解密,返回明文
117         /// </summary>
118         /// <param name="base64Str">密文(base64编码格式)</param>
119         /// <param name="key">密钥</param>
120         /// <returns>明文</returns>
121         public static string AesDecryptor_ECB_Base64(string base64Str, string key)
122         {
123             if (string.IsNullOrEmpty(base64Str)) return null;
124             Byte[] toEncryptArray = Convert.FromBase64String(base64Str);
125 
126             RijndaelManaged rm = new RijndaelManaged
127             {
128                 //Key = Convert.FromBase64String(key), //如果key是base64编码过的就解码转换,如果按照规范密文和key都应该传入base64
129                 Key = Encoding.UTF8.GetBytes(key),
130                 Mode = CipherMode.ECB,
131                 Padding = PaddingMode.PKCS7
132             };
133 
134             ICryptoTransform cTransform = rm.CreateDecryptor();
135             Byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
136 
137             return Encoding.UTF8.GetString(resultArray);
138         }

微信敏感数据解密

 1         /// <summary>
 2         /// 微信敏感数据解密
 3         /// </summary>
 4         /// <param name="encryptedData">密文</param>
 5         /// <param name="iv">加密算法的初始向量</param>
 6         /// <param name="sessionKey">登录获取的session_key</param>
 7         /// <returns></returns>
 8         public static string AESDecrypt(string encryptedData, string iv, string sessionKey)
 9         {
10             var encryptedDataByte = Convert.FromBase64String(encryptedData);
11             var rijndaelCipher = new RijndaelManaged
12             {
13                 Key = Convert.FromBase64String(sessionKey),
14                 IV = Convert.FromBase64String(iv),
15                 Mode = CipherMode.CBC,
16                 Padding = PaddingMode.PKCS7
17             };
18 
19             var transform = rijndaelCipher.CreateDecryptor();
20             var plainText = transform.TransformFinalBlock(encryptedDataByte, 0, encryptedDataByte.Length);
21             var result = Encoding.UTF8.GetString(plainText);
22             return result;
23         }

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM