2015-12-03 2 views
0

Я использую JavaScript для шифрования и php для расшифровки строки и наоборот, но проблема в том, что на обеих платформах генерируемый вывод отличается от другого. Если я шифрую строку «abc «на обеих платформах они будут давать разные результаты, хотя я уверен, что мое шифрование правильно, потому что строка, которую я шифрую, расшифровывается на том же языке.Тройное шифрование DES в JavaScript и дешифрование в PHP

я понимает, что в этом случае должно быть что-то другое в ключ или внутривенно, но не знаю, что это

код

Javascript для шифрования строки

var encrypted = CryptoJS.TripleDES.encrypt("Message", "SecretPassphrase"); 
console.log(encrypted);console.log(String(encrypted)); 

var text = "<some plain text goes here>"; 
var key = "00f74597de203655b1ebf5f410f10eb8"; 
var useHashing = true; 

if (useHashing) { 
    key = CryptoJS.MD5(key).toString(); 
    key += key.substring(1, 16); 
    console.log(key); 
} 
var textWordArray = CryptoJS.enc.Utf16.parse(text); 
var keyHex = CryptoJS.enc.Hex.parse(key); 
var iv = String.fromCharCode(0) + String.fromCharCode(0) + String.fromCharCode(0) + String.fromCharCode(0) + String.fromCharCode(0) + String.fromCharCode(0) + String.fromCharCode(0) + String.fromCharCode(0); 
var ivHex = CryptoJS.enc.Hex.parse(iv); 
console.log('hexadecimal key: ' + keyHex + '\n'); 
console.log('iv: ' + iv + '\n'); 
console.log('hexadecimal iv: ' + ivHex + '\n'); 
var options = { 
    mode: CryptoJS.mode.CBC, 
    padding: CryptoJS.pad.Pkcs7, 
    iv: ivHex 
}; 
var encrypted = CryptoJS.TripleDES.encrypt(textWordArray, keyHex, options); 
var base64String = encrypted.toString(); 
console.log('base64: ' + base64String + '\n'); 
var decrypted = CryptoJS.TripleDES.decrypt({ 
    ciphertext: CryptoJS.enc.Base64.parse(base64String) 
}, keyHex, options); 
console.log('decrypted: ' + decrypted.toString(CryptoJS.enc.Utf16)); 

PHP код для шифрования снабжать струной, тетивой и т.п.

//Generate a key from a hash 
$key = md5(utf8_encode("00f74597de203655b1ebf5f410f10eb8"), true); 

//Take first 8 bytes of $key and append them to the end of $key. 
$key .= substr($key, 0, 8); 
//Padding for 3DES   
$blockSize = mcrypt_get_block_size('tripledes', 'ecb'); 
$len = strlen($value); 
$pad = $blockSize - ($len % $blockSize); 
$value .= str_repeat(chr($pad), $pad); 

//Generating iv for 3DES 
$iv = chr(0) . chr(0) . chr(0) . chr(0) . chr(0) . chr(0) . chr(0) . chr(0); 

//Encrypt data 
$encData = mcrypt_encrypt(MCRYPT_3DES, $key, $value, MCRYPT_MODE_CBC, $iv); 

$value = base64_encode($encData); 

Пример Если я шифрую строку «admin» из javascript, она дает мне «U2 FsdGVkX1 + у/zo1FJEZZ0aqPMQuwilOydbJjzIKpYw =»

Где, как PHP дать мне "AzZFzbnwp2Y ="

Примечание Я использую CryptoJSv3 плагин для тройного DES *

+0

Почему вы используете Triple DES в наши дни? Используйте AES: [Примеры] (http://stackoverflow.com/questions/24337317/encrypt-with-php-decrypt-with-javascript-cryptojs) –

+0

Это часть проекта из прошлого, и я не должен изменять это :) – Arpita

+0

Какую часть вы не должны менять? Можете ли вы показать примерную строку, чтобы было легче найти соответствующее расшифрование? –

ответ

0

MD5 производит выход из 128 бит, но тройной DES должен иметь длину 192 бит. Вот почему ваш PHP-код копирует первые 64 бит произведенного хэша в обратную сторону. PHP и CryptoJS используют EDE, и эта ключевая копия приводит к расположению клавиш K1 || K2 || K1.

Вы можете сделать то же самое в CryptoJS. Поскольку CryptoJS использует WordArray для управления двоичными данными внутренне как слова 32 бит, вы можете напрямую скопировать первые два слова в обратную сторону внутреннего массива.

var pt = "admin"; 
 
document.querySelector("#pt").innerHTML = pt; 
 

 
var key = "00f74597de203655b1ebf5f410f10eb8"; 
 
key = CryptoJS.MD5(key); 
 

 
// copy 3DES subkey 1 to the last 64 bit to make a full 192-bit key 
 
key.words[4] = key.words[0]; 
 
key.words[5] = key.words[1]; 
 

 
// create a 64-bit zero filled 
 
var iv = CryptoJS.lib.WordArray.create(64/8); 
 
var encrypted = CryptoJS.TripleDES.encrypt(pt, key, {iv: iv}); 
 
var encryptedBase64 = encrypted.toString(); 
 

 
document.querySelector("#enc").innerHTML = encryptedBase64; 
 

 
var ct = { 
 
    ciphertext: CryptoJS.enc.Base64.parse(encryptedBase64) 
 
}; 
 
var decrypted = CryptoJS.TripleDES.decrypt(ct, key, {iv: iv}); 
 

 
document.querySelector("#dec").innerHTML = decrypted.toString(CryptoJS.enc.Utf8);
<script src="https://cdn.rawgit.com/CryptoStore/crypto-js/3.1.2/build/rollups/tripledes.js"></script> 
 
<script src="https://cdn.rawgit.com/CryptoStore/crypto-js/3.1.2/build/rollups/md5.js"></script> 
 
<p>Expected: "AzZFzbnwp2Y="<br/>Got: "<span id="enc"></span>"</p> 
 
<p>Expected: "<span id="pt"></span>"<br/>Got: "<span id="dec"></span>"</p>


Этот код не является очень безопасным по этим причинам:

  • Он использует Triple DES, который только обеспечивает 112 бит безопасности, в лучшем случае. Вы должны использовать AES.
  • Он использует статический IV. Это не является семантически безопасным, так как злоумышленник может увидеть, отправили ли вы одно и то же сообщение, только наблюдая за зашифрованными текстами. Для каждого шифрования вам необходимо использовать произвольный IV и отправить его вместе с зашифрованным текстом.
  • Он не использует аутентификацию. Эта система может быть уязвима для атаки оскорбления. Это онлайн-атака, которая позволяет злоумышленнику дешифровать любой зашифрованный текст с несколькими попытками. Вам необходимо либо использовать аутентифицированный режим, например GCM/EAX (не рекомендуется для Triple DES), либо запустить HMAC-SHA256 по зашифрованному тексту для создания тега аутентификации и отправить его вместе с зашифрованным текстом, чтобы проверить его на принимающей стороне.
+0

как бы вы создали Random IV для этого кода? –

+1

@MartinBarker CryptoJS предоставляет некриптографически безопасный генератор случайных байтов, используя «var iv = CryptoJS.lib.WordArray.random (8);» (IV для 3DES имеет длину 8 байтов). Однако вы должны использовать лучшую случайность. [Вот полиполк] (https://github.com/artjomb/cryptojs-extension/blob/master/src/random.js) для получения более качественных случайных чисел, если он доступен в вашем браузере. –

+0

спасибо за то, что я буду изучать его, я пытаюсь создать очень безопасный метод JSONRPC, поэтому я собираюсь шифровать с помощью Triple-DES внутри SSL-соединения, чтобы убедиться, что он безопасен :) –

Смежные вопросы