PBKDF计算使用的是Jither.PBKDF2库 github地址:https://github.com/Anti-weakpasswords/PBKDF2-CSharp-DeriveBytes-custom-A
这个库支持.NET Framework 4.5.1.即Unity可用
可与javascripts的CryptoJS互通与以下api调用效果一致
CryptoJS.lib.WordArray.random(xxx);
CryptoJS.PBKDF2(xxx, xxx, { hasher: CryptoJS.algo.xxx, keySize: xx, iterations: xxxx });
CryptoJS.AES.encrypt(xxx, xxx, {iv: xxx});
0.需要的引用
using System;
using System.Text;
using System.Security.Cryptography;
using Jither.PBKDF2;
1.生成随机盐
/// <summary>
/// 生成随机的Hash值
/// </summary>
/// <param name="length">Hash的长度</param>
/// <returns></returns>
private Byte[] GenerateRandomHash(Int32 length)
{
Byte[] tempByte = new byte[length];
RandomNumberGenerator.Create().GetBytes(tempByte);
return tempByte;
}
将字节数组哈希转换为HEX字符串
/// <summary>
/// 将字节数组哈希转换为HEX字符串
/// </summary>
/// <param name="hash">Hash byte</param>
/// <returns>16进制的字符串</returns>
private string HashBytesToHexString(Byte[] hash)
{
var hex = new StringBuilder(hash.Length * 2);
foreach (var b in hash)
hex.AppendFormat("{0:x2}", b);
return hex.ToString();
}
2. PBKDF2迭代密钥(需要其他HMAC修改HMACPseudoRandomFunction<HMACSHAXXX>()即可支持SHA1、SHA256、SHA512)
/// <summary>
/// 隐藏密钥
/// </summary>
/// <param name="password">密钥</param>
/// <param name="salt">盐</param>
/// <param name="iteration">迭代次数</param>
/// <returns></returns>
private Byte[] PBKDF2DeriveBytes(Byte[] password, Byte[] salt,Int32 iteration)
{
using (var prf = new HMACPseudoRandomFunction<HMACSHA256>(password))
{
using (var hash = new PBKDF2DeriveBytes(prf, salt, iteration))
{
return hash.GetBytes(32);
}
}
}
3.AES256CBC加密内容
/// <summary>
/// AES 256 CBC 加密
/// </summary>
/// <param name="encryptStr">内容</param>
/// <param name="key">密钥</param>
/// <param name="iv">偏移</param>
/// <returns></returns>
private string AESEncrypt(String encryptStr, Byte[] key, Byte[] iv)
{
var aes = new System.Security.Cryptography.AesCryptoServiceProvider();
aes.BlockSize = 128;
aes.KeySize = 256;
aes.FeedbackSize = 128;
aes.Key = key;
aes.IV = iv;
aes.Padding = System.Security.Cryptography.PaddingMode.PKCS7;
aes.Mode = System.Security.Cryptography.CipherMode.CBC;
var crypto = aes.CreateEncryptor(aes.Key, aes.IV);
byte[] encrypted = crypto.TransformFinalBlock(new UTF8Encoding(false).GetBytes(encryptStr), 0, System.Text.Encoding.UTF8.GetBytes(encryptStr).Length);
crypto.Dispose();
return System.Convert.ToBase64String(encrypted);
}
4.AES256CBC解密
/// <summary>
/// AES解密
/// </summary>
/// <param name="decryptStr">密文</param>
/// <param name="key">密钥</param>
/// <param name="iv">偏移</param>
/// <returns></returns>
protected string AESDecrypt(String decryptStr, Byte[] key, Byte[] iv)
{
var aes = new AesCryptoServiceProvider();
aes.BlockSize = 128;
aes.KeySize = 256;
aes.FeedbackSize = 128;
aes.Key = key;
aes.IV = iv;
aes.Padding = PaddingMode.PKCS7;
aes.Mode = CipherMode.CBC;
var crypto = aes.CreateDecryptor(aes.Key, aes.IV);
byte[] decrypted = crypto.TransformFinalBlock(
System.Convert.FromBase64String(decryptStr), 0, System.Convert.FromBase64String(decryptStr).Length);
crypto.Dispose();
return Encoding.UTF8.GetString(decrypted);
}
5.验证
/// <summary>
/// 验证
/// </summary>
void Verification()
{
String content = "这里写需要加密的内容";
String passwordStr = "&!_password_110_112_@_*";
Byte[] passwordByte = Encoding.UTF8.GetBytes(passwordStr);
Byte[] saltByte = GenerateRandomHash(128);
Byte[] ivByte = GenerateRandomHash(16);
Byte[] keyByte = PBKDF2DeriveBytes(passwordByte, saltByte, 5000);
String keyStr = HashBytesToHexString(keyByte);
String encryptContent = AESEncrypt(content, keyByte, ivByte);
Debug.Log("salt: " + HashBytesToHexString(saltByte));
Debug.Log("iv: " + HashBytesToHexString(ivByte));
Debug.Log("key: " + keyStr);
Debug.Log("加密后的内容: " + encryptContent);
Byte[] key = PBKDF2DeriveBytes(passwordByte, saltByte, 5000);
if (HashBytesToHexString(key) == keyStr)
{
Debug.Log("验证key正确");
}
else
{
Debug.Log("验证key失败");
return;
}
String decryptContent = AESDecrypt(encryptContent, key, ivByte);
Debug.Log("解密后的内容: " + decryptContent);
}
6.输出结果:
salt:3aa40a5641ec40e23c9d10b6d75aebb1cf4cb04aba76e854f88a198a66c96fd42cc30e1ad2f0be2aa7242eb7a0a4b6e4460a28fd09aea56dcae8da97e019582aef1c0d1e525ac75ce1bec95fc44dd308f06038cdf8aff7a867f171d61244fd10c35c3600e885a53070e33a82c47db0b8992cfe09c8c1ec6fc39f6f08e0aad192
iv: 0dc13452da863252b385f8e19753f1f4
key: b503aeab5220a50b30208263f207761dcbc6348f2d28b5f76f9c553c707b09a2
验证key正确
加密后的内容: KqwUtAy5JgwDWrRdNvJuVvGfQ9ikXd7LsAEvjGxoILU=
解密后的内容: 这里写需要加密的内容
我工程文件包含unitypackage及cs脚本:https://download.csdn.net/download/qq_33537945/87255889