110,550
社区成员
发帖
与我相关
我的任务
分享
using (var aes = new AesCryptoServiceProvider() {Key = key, IV = iv})
using (var encryptor = aes.CreateEncryptor())
byte[] encryptedBytes = encryptor.TransformFinalBlock(bytes, 0, bytes.Length).ToArray();
二、以下是按照5楼大神提供的思路实现的AES加密与解密方法,可供大家参考使用:
class Program
{
static void Main()
{
var ciphertext = CryptoJsEncrypt("hello"); // 输出类似:U2FsdGVkX19lNcn2s3GN35rz565eW5E50paqPatgiV8=
var plaintext = CryptoJsDecrypt(ciphertext); // 输出:hello
var ciphertext2 = CryptoJsEncrypt_New("hello"); // 输出类似:aes256:uIrriP5/zbH3fYHDVOga7XfI0Bt3xD1j64+Zmw68XQ4=
var plaintext2 = CryptoJsDecrypt_New(ciphertext2); // 输出:hello
}
/// <summary>
/// 加密 (常用思路)
/// </summary>
/// <param name="content">明文</param>
/// <param name="passphase">密码</param>
/// <returns>密文(base64)</returns>
static string CryptoJsEncrypt(string content, string passphase = "123456789")
{
// openssl aes-256-cbc -k 123456789 -md md5 -e -base64
//
byte[] bytes = Encoding.UTF8.GetBytes(content);
byte[] key, iv, salt = new byte[8];
using (var rng = new RNGCryptoServiceProvider())
{
rng.GetBytes(salt); // 产生8个字节的随机salt
}
using (var md5 = new MD5CryptoServiceProvider())
{
var preHash = Encoding.UTF8.GetBytes(passphase).Concat(salt).ToArray();
var bs1 = md5.ComputeHash(preHash);
var bs2 = md5.ComputeHash(bs1.Concat(preHash).ToArray());
var bs3 = md5.ComputeHash(bs2.Concat(preHash).ToArray());
key = bs1.Concat(bs2).ToArray();
iv = bs3;
}
using (var aes = new AesCryptoServiceProvider() { Key = key, IV = iv })
using (var encryptor = aes.CreateEncryptor())
{
var encryptedBytes = encryptor.TransformFinalBlock(bytes, 0, bytes.Length);
var concated = Encoding.UTF8.GetBytes("Salted__").Concat(salt).Concat(encryptedBytes);
return Convert.ToBase64String(concated.ToArray());
}
}
/// <summary>
/// 解密 (常用思路)
/// </summary>
/// <param name="content">密文(base64)</param>
/// <param name="passphase">密码</param>
/// <returns>明文</returns>
static string CryptoJsDecrypt(string content, string passphase = "123456789")
{
// openssl aes-256-cbc -k 123456789 -md md5 -e -base64
//
byte[] bytes = Convert.FromBase64String(content);
byte[] key, iv, salt = new byte[8], encryptedBytes = new byte[bytes.Length - 8 - 8];
//提取 salt
Array.ConstrainedCopy
(
sourceArray: bytes,
sourceIndex: 8, //剔除开头的 "Salted__"
destinationArray: salt,
destinationIndex: 0,
length: salt.Length
);
//提取 encryptedBytes
Array.ConstrainedCopy
(
sourceArray: bytes,
sourceIndex: 8 + 8, //并剔除开头的 salt
destinationArray: encryptedBytes,
destinationIndex: 0,
length: encryptedBytes.Length
);
using (var md5 = new MD5CryptoServiceProvider())
{
var preHash = Encoding.UTF8.GetBytes(passphase).Concat(salt).ToArray();
var bs1 = md5.ComputeHash(preHash);
var bs2 = md5.ComputeHash(bs1.Concat(preHash).ToArray());
var bs3 = md5.ComputeHash(bs2.Concat(preHash).ToArray());
key = bs1.Concat(bs2).ToArray();
iv = bs3;
}
using (var aes = new AesCryptoServiceProvider() { Key = key, IV = iv })
using (var decryptor = aes.CreateDecryptor())
{
byte[] decryptedBytes = decryptor.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length);
return Encoding.UTF8.GetString(decryptedBytes);
}
}
/// <summary>
/// 加密 (新的思路)
/// </summary>
/// <param name="content">明文</param>
/// <param name="passphase">密码(固定32位)</param>
/// <returns>密文(base64)</returns>
static string CryptoJsEncrypt_New(string content, string passphase = "12345678123456781234567812345678")
{
byte[] bytes = Encoding.UTF8.GetBytes(content);
byte[] key = Encoding.UTF8.GetBytes(passphase); //32位的key
byte[] iv = new byte[16];
using (var rng = new RNGCryptoServiceProvider())
rng.GetBytes(iv); // 产生16个字节的随机iv
using (var aes = new AesCryptoServiceProvider() { Key = key, IV = iv })
using (var encryptor = aes.CreateEncryptor())
{
var encryptedBytes = encryptor.TransformFinalBlock(bytes, 0, bytes.Length);
var concated = iv.Concat(encryptedBytes);
return "aes256:" + Convert.ToBase64String(concated.ToArray());
}
}
/// <summary>
/// 解密 (新的思路)
/// </summary>
/// <param name="content">密文(base64)</param>
/// <param name="passphase">密码(固定32位)</param>
/// <returns>明文</returns>
static string CryptoJsDecrypt_New(string content, string passphase = "12345678123456781234567812345678")
{
byte[] bytes = Convert.FromBase64String(content.Substring(7)); //剔除开头的 "aes256:"
byte[] key = Encoding.UTF8.GetBytes(passphase); //32位的key
byte[] iv = new byte[16];
byte[] encryptedBytes = new byte[bytes.Length - 16];
//提取 iv
Array.ConstrainedCopy
(
sourceArray: bytes,
sourceIndex: 0,
destinationArray: iv,
destinationIndex: 0,
length: iv.Length
);
//提取 加密结果
Array.ConstrainedCopy
(
sourceArray: bytes,
sourceIndex: 16, //并剔除开头的 iv
destinationArray: encryptedBytes,
destinationIndex: 0,
length: encryptedBytes.Length
);
using (var aes = new AesCryptoServiceProvider() { Key = key, IV = iv })
using (var decryptor = aes.CreateDecryptor())
{
byte[] decryptedBytes = decryptor.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length);
return Encoding.UTF8.GetString(decryptedBytes);
}
}
}
class Program
{
static void Main(string[] args)
{
var o = CryptoJsEncrypt("hello"); // 输出类似:U2FsdGVkX19lNcn2s3GN35rz565eW5E50paqPatgiV8=
}
static string CryptoJsEncrypt(string content, string passphase = "123456789")
{
// openssl aes-256-cbc -k 123456789 -md md5 -e -base64
//
byte[] bytes = Encoding.UTF8.GetBytes(content);
byte[] key, iv, salt = new byte[8];
using (var rng = new RNGCryptoServiceProvider())
{
rng.GetBytes(salt); // 产生8个字节的随机salt
}
using (var md5 = new MD5CryptoServiceProvider())
{
var preHash = Encoding.UTF8.GetBytes(passphase).Concat(salt).ToArray();
var bs1 = md5.ComputeHash(preHash);
var bs2 = md5.ComputeHash(bs1.Concat(preHash).ToArray());
var bs3 = md5.ComputeHash(bs2.Concat(preHash).ToArray());
key = bs1.Concat(bs2).ToArray();
iv = bs3;
}
using (var aes = new AesCryptoServiceProvider() {Key = key, IV = iv})
using (var encryptor = aes.CreateEncryptor())
{
var encryptedBytes = encryptor.TransformFinalBlock(bytes, 0, bytes.Length);
var concated = Encoding.UTF8.GetBytes("Salted__").Concat(salt).Concat(encryptedBytes);
return Convert.ToBase64String(concated.ToArray());
}
}
}
建议你不要沿用那两个网站的加密方法。可以模仿他们的输出格式。
或者,(建议)你跳过密码短文到实际密码的计算,而是直接用32字节的密码。用随机的IV来扰动每一次传输。比如结果为(我经常用的格式):
输出 = aes256:<base64(字节数组)>
字节数组 = (16个字节的IV)(加密结果)
加密结果 = Aes(内容,32字节密码,16字节IV)
对方解密时,
1、把aes256:的scheme标头去除
2、把剩下的base64反编码,得到字节数组
3、字节数组的前面16个字节为每次传输的IV,后面的密文
4、用32个字节的密码,和16个字节的IV,来解密密文。