在unity c#中加密RijndaelManaged 128,在Node.JS中解密
本文关键字:Node JS 解密 RijndaelManaged unity 加密 | 更新日期: 2023-09-27 18:17:54
我正在寻找一种方法在统一c#中加密字节数组并在node.js服务器上解密。
我对任何实现都持开放态度,但我目前已经使用了以下加密/解密统一的代码,但我收到错误:
TypeError: error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length
当解密使用RijndaelManaged 128统一加密的文件
查找加密和解密代码:
Unity c# Encrypt
private void GenerateEncryptionKey(string userID)
{
//Generate the Salt, with any custom logic and using the user's ID
StringBuilder salt = new StringBuilder();
for (int i = 0; i < 8; i++)
{
salt.Append("," + userID.Length.ToString());
}
Rfc2898DeriveBytes pwdGen = new Rfc2898DeriveBytes (Encoding.UTF8.GetBytes(userID), Encoding.UTF8.GetBytes(salt.ToString()), 100);
m_cryptoKey = pwdGen.GetBytes(KEY_SIZE / 8);
m_cryptoIV = pwdGen.GetBytes(KEY_SIZE / 8);
}
public void Save(string path)
{
string json = MiniJSON.Json.Serialize(m_saveData);
using (RijndaelManaged crypto = new RijndaelManaged())
{
crypto.BlockSize = KEY_SIZE;
crypto.Padding = PaddingMode.PKCS7;
crypto.Key = m_cryptoKey;
crypto.IV = m_cryptoIV;
crypto.Mode = CipherMode.CBC;
ICryptoTransform encryptor = crypto.CreateEncryptor(crypto.Key, crypto.IV);
byte[] compressed = null;
using (MemoryStream compMemStream = new MemoryStream())
{
using (StreamWriter writer = new StreamWriter(compMemStream, Encoding.UTF8))
{
writer.Write(json);
writer.Close();
compressed = compMemStream.ToArray();
}
}
if (compressed != null)
{
using (MemoryStream encMemStream = new MemoryStream(compressed))
{
using (CryptoStream cryptoStream = new CryptoStream(encMemStream, encryptor, CryptoStreamMode.Write))
{
using (FileStream fs = File.Create(GetSavePath(path)))
{
byte[] encrypted = encMemStream.ToArray();
fs.Write(encrypted, 0, encrypted.Length);
fs.Close();
}
}
}
}
}
}
忽略被压缩的位,我最终将压缩数据进行加密,但在本例中我已经删除了它。
node . js解密
var sUserID = "hello-me";
var sSalt = "";
for (var i = 0; i < 8; i++)
{
sSalt += "," + sUserID.length;
}
var KEY_SIZE = 128;
crypto.pbkdf2(sUserID, sSalt, 100, KEY_SIZE / 4, function(cErr, cBuffer){
var cKey = cBuffer.slice(0, cBuffer.length / 2);
var cIV = cBuffer.slice(cBuffer.length / 2, cBuffer.length);
fs.readFile("save.sav", function (cErr, cData){
try
{
var cDecipher = crypto.createDecipheriv("AES-128-CBC", cKey, cIV);
var sDecoded = cDecipher.update(cData, null, "utf8");
sDecoded += cDecipher.final("utf8");
console.log(sDecoded);
}
catch(e)
{
console.log(e.message);
console.log(e.stack);
}
});
});
我认为问题与填充有关!我没有使用:
cryptoStream.FlushFinalBlock();
当保存文件在c#土地,因为某种原因后,c#不能解密它了,它并没有真正对节点解密它的能力的影响,但也许我只是错过了一些东西在它的填充解密?
感谢您的帮助
一个问题是,您使用的PasswordDeriveBytes
,根据本文是PBKDF1,而Rfc2898DeriveBytes
是PBKDF2。您正在节点脚本中使用PBKDF2。
然后你应该检查你的key和cIV值在c#和node之间是否匹配。
在使用RijndaelManaged进行加密和解密时,操作顺序似乎非常重要。
下面是在Unity中加密和解密的代码,并与问题中发布的node.js代码一起工作。
public void Save(string path)
{
string json = MiniJSON.Json.Serialize(m_saveData);
using (RijndaelManaged crypto = new RijndaelManaged())
{
crypto.BlockSize = KEY_SIZE;
crypto.Padding = PaddingMode.PKCS7;
crypto.Key = m_cryptoKey;
crypto.IV = m_cryptoIV;
crypto.Mode = CipherMode.CBC;
ICryptoTransform encryptor = crypto.CreateEncryptor(crypto.Key, crypto.IV);
byte[] compressed = null;
using (MemoryStream compMemStream = new MemoryStream())
{
using (StreamWriter writer = new StreamWriter(compMemStream, Encoding.UTF8))
{
writer.Write(json);
writer.Close();
//compressed = CLZF2.Compress(compMemStream.ToArray());
compressed = compMemStream.ToArray();
}
}
if (compressed != null)
{
using (MemoryStream encMemStream = new MemoryStream())
{
using (CryptoStream cryptoStream = new CryptoStream(encMemStream, encryptor, CryptoStreamMode.Write))
{
cryptoStream.Write(compressed, 0, compressed.Length);
cryptoStream.FlushFinalBlock();
using (FileStream fs = File.Create(GetSavePath(path)))
{
encMemStream.WriteTo(fs);
}
}
}
}
}
}
public void Load(string path)
{
path = GetSavePath(path);
try
{
byte[] decrypted = null;
using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
{
using (RijndaelManaged crypto = new RijndaelManaged())
{
crypto.BlockSize = KEY_SIZE;
crypto.Padding = PaddingMode.PKCS7;
crypto.Key = m_cryptoKey;
crypto.IV = m_cryptoIV;
crypto.Mode = CipherMode.CBC;
// Create a decrytor to perform the stream transform.
ICryptoTransform decryptor = crypto.CreateDecryptor(crypto.Key, crypto.IV);
using (CryptoStream cryptoStream = new CryptoStream(fs, decryptor, CryptoStreamMode.Read))
{
using (MemoryStream decMemStream = new MemoryStream())
{
var buffer = new byte[512];
var bytesRead = 0;
while ((bytesRead = cryptoStream.Read(buffer, 0, buffer.Length)) > 0)
{
decMemStream.Write(buffer, 0, bytesRead);
}
//decrypted = CLZF2.Decompress(decMemStream.ToArray());
decrypted = decMemStream.ToArray();
}
}
}
}
if (decrypted != null)
{
using (MemoryStream jsonMemoryStream = new MemoryStream(decrypted))
{
using (StreamReader reader = new StreamReader(jsonMemoryStream))
{
string json = reader.ReadToEnd();
Dictionary<string, object> saveData = MiniJSON.Json.Deserialize(json) as Dictionary<string, object>;
if (saveData != null)
{
m_saveData = saveData;
}
else
{
Debug.LogWarning("Trying to load invalid JSON file at path: " + path);
}
}
}
}
}
catch (FileNotFoundException e)
{
Debug.LogWarning("No save file found at path: " + path);
}
}