2016-10-26 47 views
2

我在C#中有遗留的加密代码,现在我必须在JavaScript中执行相同的加密。 我已经做了一些研究,并尝试了3个不同的库,但无法得到相同的结果。我使用的最后一个库是CryptoJS,我必须弄清楚为什么我会得到不同的结果。C#&JS加密方法返回不同的结果

这里都是代码段:

C#代码:

text = "chocolate"; 

    PasswordHash = "hashhash"; 
    SaltKey = "saltsaltsaltsa"; 
    VIKey = "iviviviviviviviv"; 

    byte[] plainTextBytes = Encoding.UTF8.GetBytes(text); 

    byte[] keyBytes = new Rfc2898DeriveBytes(PasswordHash, Encoding.ASCII.GetBytes(SaltKey)).GetBytes(256/8); 
    var symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC, Padding = PaddingMode.Zeros }; 
    var encryptor = symmetricKey.CreateEncryptor(keyBytes, Encoding.ASCII.GetBytes(VIKey)); 

    byte[] cipherTextBytes; 

    using (var memoryStream = new MemoryStream()) 
    { 
     using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write)) 
     { 
     cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length); 
     cryptoStream.FlushFinalBlock(); 
     cipherTextBytes = memoryStream.ToArray(); 
     cryptoStream.Close(); 
     } 
     memoryStream.Close(); 
    } 
    var result = Convert.ToBase64String(cipherTextBytes); 

结果==> “8AbNsyyqHHfi/PEF/bbiew ==”

JavaScript代码:

pass = 'chocolate'; 
//Creating the Vector Key 
var iv = CryptoJS.enc.Utf8.parse('iviviviviviviviv'); 
//Encoding the Password in from UTF8 to byte array 
var passHash = CryptoJS.enc.Utf8.parse('hashhash'); 
//Encoding the Salt in from UTF8 to byte array 
var Salt = CryptoJS.enc.Utf8.parse("saltsaltsaltsa"); 

//Creating the key in PBKDF2 format to be used during the encryption 
var key128Bits1000Iterations = CryptoJS.PBKDF2(passHash, Salt, { keySize: 256/8, iterations: 1000 }); 

//Encrypting the string contained in cipherParams using the PBKDF2 key 
var encrypted = CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(pass), key128Bits1000Iterations, { mode: CryptoJS.mode.CBC, iv: iv, padding: CryptoJS.pad.ZeroPadding }); 
var result = encrypted.ciphertext.toString(CryptoJS.enc.Base64); 

result =“dpgTA41PD yrM8ef9C1c8iA ==“

+0

你似乎在C#中使用'Encoding.ASCII'和'.. CryptoJS.enc.Utf8' in JS ..? – stuartd

+0

@stuartd - 想过它,在给定场景中对于ASCII和UTF8同样的行为 – Niro

回答

0

终于找到了解决办法。感谢Luke Park,他告诉我CryptoJS使用4字节(字)结构。

导致不同结果的问题是密钥大小(显然)不同。 在C#中256/8实际上是32字节长度,但是在CryptoJS中,由于使用4字节,因此256/8实际上转换为128字节长度:(

一旦我将JS片段中的密钥大小更改为256/32((32分之256)* 4 = 32),它的工作完美和回声相同的结果C#加密方法。

谢谢大家 尼尔

0

问题在于您的PBKDF2盐。 CryptoJS使用WordArray作为存储盐的基元。也就是说,一个32位值的数组。作为C#使用8位值(显然,它是一个byte数组)。

注意那么,在JS:

var Salt = CryptoJS.lib.WordArray.create([1, 2]); 

是,在C#中,同为:

byte[] Salt = new byte[] { 0, 0, 0, 1, 0, 0, 0, 2 }; 

您可以通过输出证明这一点的JS如下:

var Salt = CryptoJS.lib.WordArray.create([1, 2]); 
console.log(Salt.toString(CryptoJS.enc.Base64)); 
-> AAAAAQAAAAI= 

CryptoJS不喜欢将字符串用作盐。它根本不喜欢它。您不应该使用字符串或短语作为盐,它应该随机生成并与密码哈希一起存储。

+0

这正是“CryptoJS.enc.Utf8.parse”所做的:将字符串转换为它的字数组表示 – Niro

+0

是的,所以C#vs JS中的salt是不同的。 –

+0

你错了,盐是一样的。一个用字节表示,另一个用字表示,但数据完全相同。然而 - 你给了我一个方向,这导致我的解决方案,所以非常感谢你:) – Niro

相关问题