2013-11-27 7 views
2

Мне нужно реплицировать следующий метод C# для шифрования некоторого текста из Javascript. В настоящее время я использую Crypto JS, но результат от JS не равен выходу C#.Реализация TripleDES в Javascript отличается от C#

const string EncryptKey = "hello"; 

private static String getHexStringFromArray(byte[] arr) { 
    StringBuilder sBuilder = new StringBuilder(); 

    for (int i = 0; i < arr.Length; i++) { 
     sBuilder.Append(arr[i].ToString("x2")); 
    } 

    return sBuilder.ToString(); 
}  

public void Encrypt(string toEncrypt, bool useHashing) { 
    byte[] keyArray; 
    byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt); 

    string key = EncryptKey; 

    if (useHashing) { 
     MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider(); 
     keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key)); 

     hashmd5.Clear(); 
    } else 
     keyArray = UTF8Encoding.UTF8.GetBytes(key); 

    Console.WriteLine("hexadecimal key: " + getHexStringFromArray(keyArray)); 

    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); 

    tdes.Clear(); 

    Console.WriteLine("hexadecimal encrypted: " + getHexStringFromArray(resultArray)); 

    //Return the encrypted data into unreadable string format 
    string test = Convert.ToBase64String(resultArray, 0, resultArray.Length); 

    Console.WriteLine("Output: " + test); 
} 

Выход для Encrypt("password", true) является:

hexadecimal key: 5d41402abc4b2a76b9719d911017c592 
hexadecimal encrypted: 069c44845e907b346b9d82d1d553f391 
Output: BpxEhF6QezRrnYLR1VPzkQ== 

Теперь реализация Javascript (пожалуйста, игнорировать глобальные переменные):

window.text = "password"; 
window.key = "hello"; 
var useHashing = true; 

if (useHashing){ 
    key = CryptoJS.MD5(key).toString(); 
} 

window.options = { 
    mode: CryptoJS.mode.ECB, 
    padding: CryptoJS.pad.Pkcs7 
}; 

window.textWordArray = CryptoJS.enc.Utf8.parse(text); 
window.keyHex = CryptoJS.enc.Hex.parse(key); 

console.log('hexadecimal key: ' + keyHex); 

window.encrypted = CryptoJS.TripleDES.encrypt(textWordArray, keyHex, options); 

var base64String = encrypted.toString(); 

console.log('base64: ' + base64String); 

window.decrypted = CryptoJS.TripleDES.decrypt({ 
    ciphertext: CryptoJS.enc.Base64.parse(base64String) 
}, keyHex, options); 

console.log('decrypted: ' + decrypted.toString(CryptoJS.enc.Utf8)); 

Производит этот результат:

hexadecimal key: 5d41402abc4b2a76b9719d911017c592 
base64: BK5f0AhEuUl9pYEy2Mliyw== 

, который отличается от реализации C#.

Here вы можете найти Javascript код.

Любая помощь?

+0

Обе подпрограммы шифруют * конечный * блок, т. Е. Так, что дополнение PKCS7 выполняется одинаково в обоих? –

+0

@DavidRTribble Я действительно не знаю. Я думаю, что PKCS7 является стандартным, а также tripleDES, поэтому обе реализации должны быть одинаковыми ... –

ответ

7

Для TripleDES требуется 24-байтовый ключ (k1 + k2 + k3). Ваш ключ составляет всего 16 байт. И .NET автоматически завершает работу с k3 = k1. Но Javascript не, k3 = 0. Пожалуйста, измените ключ:

if (useHashing){ 
    key = CryptoJS.MD5(key).toString(); 
    var k1 = key.substring(0, 16); 
    key = key + k1; 
} 
0

Вот Decrypter с использованием 3DES-ECB кузнечно JS. Поскольку я не смог найти решение forge js, добавляя его, чтобы другие могли его использовать.

var md = forge.md.md5.create(); 
md.update(window.key); 

var key = md.digest().getBytes(); 
//3DES-ECB requires 24byte of data and key returned from md5 is 16byte 
var k1 = key.substring(0, 8); 
var key1 = key + key1; 

var input = forge.util.createBuffer(forge.util.decode64(window.text)); 
var decTer = forge.cipher.createDecipher('3DES-ECB', key1); 
decTer.start(); 
decTer.update(input); 

return decTer.output.getBytes();