簡體   English   中英

如何通過 Crypto-JS 解密 AES 128-CBC?

[英]How to decrypt AES 128-CBC by Crypto-JS?

我有一個 PHP 代碼,它使用密鑰解密有效負載,我正在嘗試使用crypto-js庫在 JavaScript 中編寫完全相同的代碼,但我得到了錯誤的結果。

有效載荷中的前 16 個字節 - 是向量,其余部分 - 是有用的信息。

PHP - https://ideone.com/NJXkRK中的工作代碼

function getPayload($app_secret_key, $data) {
  // Get the encryption key (16 first bytes of the app's client_secret key)
  $encryption_key = substr($app_secret_key, 0, 16);
 
  // Decrypt payload
  $json_data = aes_128_decrypt($encryption_key, $data);
 
  // Decode json
  $json_decoded = json_decode($json_data, true);
  return $json_data;
}
 
function aes_128_decrypt($key, $data) {
  // Ecwid sends data in url-safe base64. Convert the raw data to the original base64 first
  $base64_original = str_replace(array('-', '_'), array('+', '/'), $data);
 
  // Get binary data
  $decoded = base64_decode($base64_original);
 
  // Initialization vector is the first 16 bytes of the received data
  $iv = substr($decoded, 0, 16);
 
  // The payload itself is is the rest of the received data
  $payload = substr($decoded, 16);
 
  // Decrypt raw binary payload
  $json = openssl_decrypt($payload, "aes-128-cbc", $key, OPENSSL_RAW_DATA, $iv);
  //$json = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $payload, MCRYPT_MODE_CBC, $iv); // You can use this instead of openssl_decrupt, if mcrypt is enabled in your system
 
  return $json;
}
 
// Get payload from the GET and process it
$ecwid_payload = "ng7W9c9jLhkX7ATMpafNAd5Vt_skEaFAqnQaw0Ing1iwYQOwB0Q_CuCS8yQeHeorTdCpZWDTNrzhcq_umX7IaAFUPPgs0zyddY7Er1tA0aze5kWGHUV54fJHoVEJHMmVEi-G5g8ZnNopIFu0YQgQqLpCq8TP2zFJunSTA7VXHTmqHNAD2JXaUb-VylcJWzgV0vaCoGyHqaPbsNNw6HSWkAzhh8dLmsYB0uzsZ_zl3wVXubCL4p2N53PmNPBLCgoC";
$client_secret = "zcKf1Zt0UsO43S46Un3pxIgs91R1xMGs"; 
 
$result = getPayload($client_secret, $ecwid_payload);
 
print($result);

不工作的JS代碼

 function getPayload() { const payload = "ng7W9c9jLhkX7ATMpafNAd5Vt_skEaFAqnQaw0Ing1iwYQOwB0Q_CuCS8yQeHeorTdCpZWDTNrzhcq_umX7IaAFUPPgs0zyddY7Er1tA0aze5kWGHUV54fJHoVEJHMmVEi-G5g8ZnNopIFu0YQgQqLpCq8TP2zFJunSTA7VXHTmqHNAD2JXaUb-VylcJWzgV0vaCoGyHqaPbsNNw6HSWkAzhh8dLmsYB0uzsZ_zl3wVXubCL4p2N53PmNPBLCgoC"; const key = "zcKf1Zt0UsO43S46Un3pxIgs91R1xMGs"; // Get the encryption key (16 first bytes of the app's client_secret key) const encryption_key = key.substr(0, 16); // Decrypt payload const base64_original = payload.replace(/-/gi, "+").replace(/_/gi, "/"); const data = aes_128_decrypt(encryption_key, base64_original); console.log(data); } function aes_128_decrypt(password, data) { const decoded = atob(data); let iv = decoded.substr(0, 16); let payload = decoded.substr(16); iv = CryptoJS.enc.Hex.parse(iv); const decrypted = CryptoJS.AES.decrypt(payload, password, { iv: iv, padding: CryptoJS.pad.NoPadding }); return decrypted.toString(); } window.onload = function() { getPayload(); };
 <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>

請幫我改進這個JS代碼

JavaScript 代碼中有幾個問題:

  • 密鑰不能作為字符串傳遞,而是作為WordArray (否則 CryptoJS 使用密鑰派生函數)。
  • IV和密文沒有正確確定。
  • 密文必須作為CipherParams object(或 Base64 編碼字符串)傳遞。
  • 填充必須是 PKCS7(解密也可以使用NoPadding ,但不會刪除填充字節)。
  • 明文必須是 Utf8 解碼(默認為 .toString toString()十六進制編碼)

有關詳細信息,請參閱 CryptoJS 文檔,尤其是密碼輸入密碼 Output 章節

以下 JavaScript 代碼解密密文:

 function getPayload() { const payload = "ng7W9c9jLhkX7ATMpafNAd5Vt_skEaFAqnQaw0Ing1iwYQOwB0Q_CuCS8yQeHeorTdCpZWDTNrzhcq_umX7IaAFUPPgs0zyddY7Er1tA0aze5kWGHUV54fJHoVEJHMmVEi-G5g8ZnNopIFu0YQgQqLpCq8TP2zFJunSTA7VXHTmqHNAD2JXaUb-VylcJWzgV0vaCoGyHqaPbsNNw6HSWkAzhh8dLmsYB0uzsZ_zl3wVXubCL4p2N53PmNPBLCgoC"; const key = "zcKf1Zt0UsO43S46Un3pxIgs91R1xMGs"; // Get the encryption key (16 first bytes of the app's client_secret key) //const encryption_key = key.substr(0, 16); const encryption_key = CryptoJS.enc.Utf8.parse(key.substr(0, 16)); // Parse the key into a WordArray // Decrypt payload const base64_original = payload.replace(/-/gi, "+").replace(/_/gi, "/"); const data = aes_128_decrypt(encryption_key, base64_original); console.log(data.replace(/(.{56})/g,'$1\n')); // {"store_id":20553036,"access_token":"secret_a9TmTJfRt3gyvxjJ9UwYjs9VQip3F7rp","public_token":"public_QQ99gUwVGdvKuZbLLyNZzDsvXF5iF3gh","view_mode":"PAGE","lang":"ru"} //console.log(JSON.parse(data)); // Convert JSON string into JavaScript object (optional) } function aes_128_decrypt(password, data) { /* const decoded = atob(data); let iv = decoded.substr(0, 16); let payload = decoded.substr(16); iv = CryptoJS.enc.Hex.parse(iv); */ var ivCiphertext = CryptoJS.enc.Base64.parse(data); // Parse data into a WordArray var iv = CryptoJS.lib.WordArray.create(ivCiphertext.words.slice(0, 16 / 4)); // Separate iv var payload = CryptoJS.lib.WordArray.create(ivCiphertext.words.slice(16 / 4)); // and ciphertext //const decrypted = CryptoJS.AES.decrypt(payload, password, { const decrypted = CryptoJS.AES.decrypt( { ciphertext: payload // Pass CipherParams object }, password, { iv: iv //padding: CryptoJS.pad.NoPadding // Apply PKCS7 padding }); //return decrypted.toString(); return decrypted.toString(CryptoJS.enc.Utf8); // Utf8 decode plaintext } window.onload = function() { getPayload(); };
 <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM