实现一:RijndaelManaged 实现, 不过好心情马上被破坏,vs提示已经被弃用
/// <summary>
/// Aes加密
/// </summary>
/// <param name="str"></param>
/// <param name="key"></param>
/// <returns></returns>
public static string AesEncrypt(this string str, string key)
{
if (string.IsNullOrEmpty(str)) return null;
Byte[] toEncryptArray = Encoding.UTF8.GetBytes(str);
RijndaelManaged rm = new RijndaelManaged
{
Key = Encoding.UTF8.GetBytes(key),
Mode = CipherMode.ECB,
Padding = PaddingMode.PKCS7
};
ICryptoTransform cTransform = rm.CreateEncryptor();
Byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
return Convert.ToBase64String(resultArray);
}
/// <summary>
/// aes解密
/// </summary>
/// <param name="str"></param>
/// <param name="key"></param>
/// <returns></returns>
public static string AesDecrypt(string str, string key)
{
if (string.IsNullOrEmpty(str)) return null;
Byte[] toEncryptArray = Convert.FromBase64String(str);
RijndaelManaged rm = new RijndaelManaged
{
Key = Encoding.UTF8.GetBytes(key),
Mode = CipherMode.ECB,
Padding = PaddingMode.PKCS7
};
ICryptoTransform cTransform = rm.CreateDecryptor();
Byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
return Encoding.UTF8.GetString(resultArray);
}
实现二:使用推荐的Aes.Create(),网上找的代码,修改了下变成类扩展。
string str = "abc123一二三";
string key = "一二67890123456789012345678912";
string iv = "zxb";
string estr = str.Encrypt(key, iv);
string dstr = estr.Decrypt(key, iv);
/// <summary>
/// 字符串转字节数组
/// </summary>
/// <param name="str"></param>
/// <param name="length"></param>
/// <returns></returns>
public static byte[] ToUTF8Bytes(this string str, int length)
{
byte[] bytes = Encoding.UTF8.GetBytes(str);
Array.Resize(ref bytes, length);
return bytes;
}
/// <summary>
/// 字符串转字节数组
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public static byte[] ToUTF8Bytes(this string str)
{
byte[] bytes = Encoding.UTF8.GetBytes(str);
return bytes;
}
/// <summary>
/// 字节数组转字符串
/// </summary>
/// <param name="bytes"></param>
/// <returns></returns>
public static string ToUTF8String(this byte[] bytes)
{
string str = Encoding.UTF8.GetString(bytes);
return str;
}
/// <summary>
/// base64加密
/// </summary>
/// <param name="bytes"></param>
/// <returns></returns>
public static string ToBase64String(this byte[] bytes)
{
return Convert.ToBase64String(bytes);
}
/// <summary>
/// 加密-String转String
/// key转为utf8字节数组后
/// </summary>
/// <param name="str"></param>
/// <param name="key"></param>
/// <param name="iv"></param>
/// <returns></returns>
public static string Encrypt(this string str, string key, string iv)
{
return str.ToUTF8Bytes().Encrypt(key, iv).ToBase64String();
}
/// <summary>
/// 加密-Bytes转Bytes
/// </summary>
/// <param name="bytes"></param>
/// <param name="key"></param>
/// <param name="iv"></param>
/// <returns></returns>
public static byte[] Encrypt(this byte[] bytes, string key, string iv)
{
using (Aes aes = Aes.Create())
{
aes.Key = key.ToUTF8Bytes(32);
aes.IV = iv.ToUTF8Bytes(16);
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
byte[] encryptedBytes;
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
csEncrypt.Write(bytes, 0, bytes.Length);
}
encryptedBytes = msEncrypt.ToArray();
}
return encryptedBytes;
}
}
public static byte[] ToBase64Bytes(this string str)
{
return Convert.FromBase64String(str);
}
/// <summary>
/// 解密-String转String
/// </summary>
/// <param name="str"></param>
/// <param name="key"></param>
/// <param name="iv"></param>
/// <returns></returns>
public static string Decrypt(this string str, string key, string iv)
{
return str.ToBase64Bytes().Decrypt(key, iv).ToUTF8String();
}
/// <summary>
/// 解密-Bytes转Bytes
/// </summary>
/// <param name="bytes"></param>
/// <param name="key"></param>
/// <param name="iv"></param>
/// <returns></returns>
public static byte[] Decrypt(this byte[] bytes, string key, string iv)
{
using (Aes aes = Aes.Create())
{
aes.Key = key.ToUTF8Bytes(32);
aes.IV = iv.ToUTF8Bytes(16);
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
using (MemoryStream msDecrypt = new MemoryStream(bytes))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (MemoryStream msOutput = new MemoryStream())
{
csDecrypt.CopyTo(msOutput);
return msOutput.ToArray();
}
}
}
}
}
方法三:还是使用Aes.Create(),不过找到了更简单的写法
/// <summary>
/// 加密-Bytes转Bytes
/// </summary>
/// <param name="bytes"></param>
/// <param name="key"></param>
/// <param name="iv"></param>
/// <returns></returns>
public static byte[] Encrypt(this byte[] bytes, string key, string iv)
{
using Aes aes = Aes.Create();
aes.Key = key.ToUTF8Bytes(32);
var retbytes = aes.EncryptCbc(bytes, iv.ToUTF8Bytes(16));
return retbytes;
}
/// <summary>
/// 解密-Bytes转Bytes
/// </summary>
/// <param name="bytes"></param>
/// <param name="key"></param>
/// <param name="iv"></param>
/// <returns></returns>
public static byte[] Decrypt(this byte[] bytes, string key, string iv)
{
using Aes aes = Aes.Create();
aes.Key = key.ToUTF8Bytes(32);
var retbytes = aes.DecryptCbc(bytes, iv.ToUTF8Bytes(16));
return retbytes;
}
看一下运行结果:好像没问题,加密后,然后解密,得到明名是对的。
高兴的太早了吧:既然是加密吗,当然要和其他工具的结果对比一下了。
使用这个对比:验证过了,两个在线加密工具得到密文一致,可能是用的同一个库吧。
2、AES在线加密工具 | AES解密 | AES在线加解密工具- 在线工具
然后同样的key和iv我们看结果:!!怎么加密后的结果完全不一样呢??,同样的明文,key,iv,模式,填充,我能看到的参数都有一模一样了啊。为什么呢?????
解惑:只能带着疑问去看看AES的原理了,发现key的话长度分为128位(比特)、192位和256位也就是分别为16,24,32个字节。向量IV长度只能是16个字节,再看C#实现代码,我们输入的key和iv都转base64字节后有对字节组resize到32和16。C#实现方式是,不够的字节补零,在线工具使用的crypthoj-s,能到使用的时候是把key转成base64给他内部怎么处理没看到。
这就说明了,key32不补位不一样,当然结果就是不一样了
验证:怎么验证呢,crypthoj-s没有源码,看了半天网页上js,也没看出来他是怎么处理key。后来想既然key是32位,iv是16位,那我按照这个字节数(UTF8),给你不就行了了。果然~~~~,我们看结果,加密结果是一致的~~
小细节:在线使用在线工具的时候,key,和iv 随便输入,点加密后,然后解密是解不了密的,只有输入32key和16iv(iv其实不需要一定是16位),加密后才能解密,这一点是不是侧面验证了呢。。。
在此,提醒前后台aes加解密的时候,一样要注意key和iv的补位规则。。。