tripledes encryption not yielding same results in PHP and C#
public static string Encrypt(string toEncrypt, string key, bool useHashing)
{
byte[] keyArray;
byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);
if (useHashing)
{
MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
}
else
keyArray = UTF8Encoding.UTF8.GetBytes(key);
TripleDESCryptoServiceProvider tdes
= new TripleDESCryptoServiceProvider();
tdes.Key = keyArray;
tdes.Mode = CipherMode.ECB;
tdes.Padding = PaddingMode.PKCS7;
ICryptoTransform cTransform = tdes.CreateEncryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0,
toEncryptArray.Length);
return Convert.ToBase64String(resultArray, 0, resultArray.Length);
}
上面的帖子和代码有一些非常简单的(或者我认为)逻辑来使用3DES和私钥加密/解密字符串。
我发现了一些如何使用crypt库在nodejs中实现类似功能的例子,但到目前为止我尝试过的所有内容都产生了垃圾(理所当然)。
思想?
UPDATE1:
以下是一些C#代码,用于生成我正在使用的数据:
String key = "abcdefghijklmnop";
String text = "12345";
String encrypted = Encrypt(text, key, false);
//Returns "QI3I65+aWSk="
这是我正在使用的nodejs代码的最新版本:
var crypto = require('crypto');
var key = 'abcdefghijklmnop';
var encrypted = 'QI3I65+aWSk=';
var expected = '12345';
var algs = [ 'des3', 'des-ede', 'des-ede3', 'des-ecb', 'aes-128-ecb'];
for(var i in algs)
{
var decipher = crypto.createDecipher(algs[i], key);
var result = ''
result += decipher.update(encrypted, 'hex', 'binary');
result += decipher.final('binary');
console.log('Algorithm: ' + algs[i]
+ ', Matched Expected: ' + (result === expected));
}
..返回
Algorithm: des3, Matched Expected: false
Algorithm: des-ede, Matched Expected: false
Algorithm: des-ede3, Matched Expected: false
Algorithm: des-ecb, Matched Expected: false
Algorithm: aes-128-ecb, Matched Expected: false
我不确定要使用哪种算法(我的列表在以前的尝试中显着更长)现在我确定要使用哪种编码组合(二进制/十六进制)。
再次感谢。
UPDATE2: 从引用的帖子复制加密方法:
tripledes encryption not yielding same results in PHP and C#
答案 0 :(得分:1)
好吧,我花了一段时间才弄明白。
首先关于DES算法,DES算法需要 IV (初始向量)加密,以及密钥。 System.Security.Cryptography
中的DES算法在未指定时将生成IV randomly。解密时,您需要键和 IV 。
这就是为什么你的代码永远不会工作的原因,因为你的解密程序只是不知道IV在加密中使用了什么,并且会生成另一个IV本身,它与随机的不匹配。
其次,你的javascript代码在很多地方都是错误的:
decipher.update(encrypted, 'hex', 'binary')
其中encrypted
不是以十六进制编码,而是以base64编码,您需要将结果输出为base64而不是二进制。 阅读document。
['des3','des-ede','des-ede3','des-ecb','aes-128-ecb']
所有这些算法与您使用的加密算法不同。正如您指定使用的CipherMode.ECB
not recommended而openssh根本不支持,因此无法解密。
全部加起来,你的代码将无效。
这是正确的做法:
using System;
using System.Text;
using System.Security.Cryptography;
public class Test
{
public static string Encrypt(string toEncrypt, string key, bool useHashing)
{
byte[] keyArray;
byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);
if (useHashing)
{
MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
}
else
keyArray = UTF8Encoding.UTF8.GetBytes(key);
var tdes = new TripleDESCryptoServiceProvider();
tdes.Key = keyArray;
// tdes.Mode = CipherMode.CBC; // which is default
// tdes.Padding = PaddingMode.PKCS7; // which is default
Console.WriteLine("iv: {0}", Convert.ToBase64String(tdes.IV));
ICryptoTransform cTransform = tdes.CreateEncryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0,
toEncryptArray.Length);
return Convert.ToBase64String(resultArray, 0, resultArray.Length);
}
public static void Main()
{
Console.WriteLine("encrypted as: {0}", Encrypt("12345", "abcdefghijklmnop", false));
}
}
输出
iv: pdMBMjdeFdo=
encrypted as: 3uDkdT6aQ3c=
在node.js中使用正确的算法 des-ede-cbc :
var crypto = require('crypto');
var alg = 'des-ede-cbc';
var key = new Buffer('abcdefghijklmnop', 'utf-8');
var iv = new Buffer('pdMBMjdeFdo=', 'base64');
var encrypted = new Buffer('3uDkdT6aQ3c=', 'base64');
var source = '12345';
var cipher = crypto.createCipheriv(alg, key, iv);
var encoded = cipher.update(source, 'ascii', 'base64');
encoded += cipher.final('base64');
console.log(encoded, encrypted.toString('base64'));
var decipher = crypto.createDecipheriv(alg, key, iv);
var decoded = decipher.update(encrypted, 'binary', 'ascii');
decoded += decipher.final('ascii');
console.log(decoded, source);
输出
3uDkdT6aQ3c= 3uDkdT6aQ3c=
12345 12345
现在问题解决了。
答案 1 :(得分:0)
您的输入编码看起来应该是'base64'...值得注意的是,在您的链接问题中提到,填充技术也可能存在差异。