2016-10-26 48 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

相關問題