duanhan7001 2015-12-03 09:01
浏览 100
已采纳

JavaScript中的三重DES加密和PHP中的解密

I am using JavaScript to encrypt and php to decrypt the string and vice versa but the problem is that on both the platforms the output being generated is different say If I encrypt a string "abc" on both the platforms they will produce different results although I am sure my encryption is correct because the string I am encrypting is decrypted in same language.

I understands that in this case there has to be something different in key or iv but do not know what it

Javascript code to encrypt string

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 + '
');
console.log('iv: ' + iv + '
');
console.log('hexadecimal iv: ' + ivHex + '
');
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 + '
');
var decrypted = CryptoJS.TripleDES.decrypt({
    ciphertext: CryptoJS.enc.Base64.parse(base64String)
}, keyHex, options);
console.log('decrypted: ' + decrypted.toString(CryptoJS.enc.Utf16));

PHP code to encrypt string

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

Example If I encrypt the string "admin" from javascript it gives me "U2FsdGVkX1+y/zo1FJEZZ0aqPMQuwilOydbJjzIKpYw="

Where as php give me "AzZFzbnwp2Y="

Note I am using CryptoJSv3 plugin for triple DES*

  • 写回答

1条回答 默认 最新

  • duanli6618 2015-12-03 13:40
    关注

    MD5 produces output of 128 bit, but a Triple DES key should be 192 bit long. That is why your PHP code copies the first 64 bits of the produced hash to the back. PHP and CryptoJS both use the EDE and this key copy leads to the key layout of K1 || K2 || K1.

    You can do the same thing in CryptoJS. Since CryptoJS uses a WordArray to manage binary data internally as words of 32 bit, you can directly copy the first two words to the back of the internal array.

    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>


    This code is not very secure for those reasons:

    • It uses Triple DES which only provides 112 bit of security, at best. You should use AES.
    • It uses a static IV. This is not semantically secure, because an attacker might see whether you sent the same message only by observing the ciphertexts. You need to use a random IV for each encryption and send it along with the ciphertext.
    • It doesn't use authentication. This system might be vulnerable to the padding oracle attack. It is an online attack which enables the attacker to decrypt any ciphertext with multiple tries. You either need to use an authenticated mode like GCM/EAX (not advisable for Triple DES) or run an HMAC-SHA256 over the ciphertext to produce the authentication tag and send it along with the ciphertext to verify it on the receiving end.
    </div>
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 下图接收小电路,谁知道原理
  • ¥15 装 pytorch 的时候出了好多问题,遇到这种情况怎么处理?
  • ¥20 IOS游览器某宝手机网页版自动立即购买JavaScript脚本
  • ¥15 手机接入宽带网线,如何释放宽带全部速度
  • ¥30 关于#r语言#的问题:如何对R语言中mfgarch包中构建的garch-midas模型进行样本内长期波动率预测和样本外长期波动率预测
  • ¥15 ETLCloud 处理json多层级问题
  • ¥15 matlab中使用gurobi时报错
  • ¥15 这个主板怎么能扩出一两个sata口
  • ¥15 不是,这到底错哪儿了😭
  • ¥15 2020长安杯与连接网探