javascript - 为什么java无法解密CryptoJS加密数据?

标签 javascript java cryptography aes cryptojs

我有在Java中解密的功能

public String decrypt() throws Exception {
        SecretKey secretKey = getSecretKey("o9szYIOq1rRMiouNhNvaq96lqUvCekxR");

        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        return new String(cipher.doFinal(base64Decode("ASDASDADS")));
    }

public SecretKey getSecretKey(String secretKey) throws Exception {
        byte[] decodeSecretKey = base64Decode(secretKey);
        return new SecretKeySpec(decodeSecretKey, 0, decodeSecretKey.length, "AES");
    }

我尝试使用 CryptoJS 来加密数据

  function aesEncrypt(data, secretKey) {
    var encrypted = CryptoJS.AES.encrypt(data, secretKey, {
    mode: CryptoJS.mode.ECB,
    padding: CryptoJS.pad.Pkcs7
    });

    var ciphertext = encrypted.ciphertext.toString();

    var wordArray = CryptoJS.enc.Utf8.parse(ciphertext);
    var base64 = CryptoJS.enc.Base64.stringify(wordArray);
    return base64
  }
  //call the function
  aesEncrypt('Test' , 'o9szYIOq1rRMiouNhNvaq96lqUvCekxR');

当我将请求发送到 JAVA API 时,我得到

Given final block not properly padded. Such issues can arise if a bad key is used during decryption

我什至尝试过使用 Forge 库。它也不起作用。

function aesEncrypt(data, secretKey) {
    var cipher = forge.cipher.createCipher('AES-ECB', secretKey)

    cipher.start()
    cipher.update(forge.util.createBuffer(data))
    cipher.finish()

    return forge.util.encode64(cipher.output.data)
  }

当我输出数据时,我看到两者之间的差异来自伪造,即 console.log(cipher.output.data) 。我明白

uJ­@^$¿EÅKÖé1ÙN¢cÖúpxÇÅÂëv¥qè9Ï/¨§È5æý»¸,À¿ "y§¯:ßñ[®ÓjÃùØQèó÷à¯~6jØ¿óðn5»§Ñ ,A.ÛCeða©ëZÁR¸:­jy¹ScÃ6d#ÚÔí\N¤s~ã¯ÃÉ5d0U:©ªÕ"ã¾xx §F?ØïÅFÛbÒÓJ§j ¸²ä2½]Õç£ÿ#È&C! M¡ è ÁÖÈ ¾¦aÒc~: °j>yc6ÞÖú]OAÅÖ!x ìJu2ðΡ¦*õô±¤kÆ ÂTùû=|2^XAy5¹Êè?díXÝg ëq" %üSyÿO¾bzjc²·á­kÑî¼¾¡ÓV *Çr¢ rÎlòz°»yNûöCpã

但是从 CryptoJS 我得到 console.log(ciphertext)

ad423bc873ca1cc2f228c7158ccf95e67eae4029d5a2e9fbad42e7be7bcad23fcfb94217b90a84c4e6e9786d36edd337615c392a4d260dd68fb6bf45032a31fc6eec99a8f9b5e8efa6e5f2fe2a2b1e68e3a6a57cee0f12d42ff66c986d45da825398213361de9f448b7db0b8a38c79091519105b7c12a4d19998de8e0fb211d81fa1b3d1801d5c8eba907e7aacfa891fa7872e951ee645840e86699c93e98a355ea0f6331889663326f88f0d09b7a6245bd52443f98e6bb274edda32b7135e17d342db77759099688a14ac5edddc7c760e179ad4ad08d9d1fd3b11f1c96be0804c74bf9a9032d07af12e60a76dfddf28984901485e032b33e19db8332a8b49244c9c46081d13c6c632c8792c318a5cc8a7aa4612a76d0b6413367c248b3c0c6e53f301601b0f1bea6ee2b0b5344c445a1da32274c63e81f94dff3db98aae6348c936a2bbac6a3912595c981349556f161d12c843e516aadf95c8ab6be3aaa49d382e5af074575777e8d96964c2fd7a4cad03dd2a9137d8b4ffd85eaaabdd0f86

如何使用两者中的任何一个?为什么上面的输出有差异?

最佳答案

请在下面找到一个代码对,该代码对使用 Javascript 在 ECB 模式下使用静态 key 来加密和解密字符串。 Java代码 正在从 Javascript 获取密文(= 加密函数的输出)并解密 Base64 编码的密文。

安全警告:这两个代码都不安全,因为它们使用 ECB 模式和静态加密 key 。

Javascript 输出(通过此链接查看实时示例:https://playcode.io/682378)

plaintext: Test
ciphertext: oNP8t53ZTi1WUptGCDh5NQ==
decryptedtext: Test

Java 输出:

ciphertextFromJavascript: oNP8t53ZTi1WUptGCDh5NQ==
decrypted: Test

Javascript代码:

// *** Security warning **
// DO NOT USE THIS CODE IN PRODUCTION AS IT IS UNSECURE
// it uses ECB mode and static key

var plaintext = 'Test';
console.log('plaintext: ', plaintext);

/**
 * Encryption
 * @param word
 * @returns {*}
 */
function encrypt(word){
    const keyBase64 = "o9szYIOq1rRMiouNhNvaq96lqUvCekxR";
    var key = CryptoJS.enc.Base64.parse(keyBase64);
    var srcs = CryptoJS.enc.Utf8.parse(word);
    var encrypted = CryptoJS.AES.encrypt(srcs, key, {mode:CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});
    return encrypted.toString();
}
 
/**
   * Decrypt
 * @param word
 * @returns {*}
 */
function decrypt(word){
    const keyBase64 = "o9szYIOq1rRMiouNhNvaq96lqUvCekxR";
    var key = CryptoJS.enc.Base64.parse(keyBase64);
    var decrypt = CryptoJS.AES.decrypt(word, key, {mode:CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});
    return CryptoJS.enc.Utf8.stringify(decrypt).toString();
}

var ciphertext = encrypt(plaintext);
console.log('ciphertext: ', ciphertext);
var decryptedtext = decrypt(ciphertext);
console.log('decryptedtext: ', decryptedtext);

Java代码:

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

public class Main {
    public static void main(String[] args) throws Exception {
        System.out.println("Why can't java decrypt CryptoJS encrypted data ?");
        String ciphertextFromJavascript = "oNP8t53ZTi1WUptGCDh5NQ==";
        System.out.println("ciphertextFromJavascript: " + ciphertextFromJavascript);
        System.out.println("decrypted: " + decrypt(ciphertextFromJavascript));
    }
    public static String decrypt(String ciphertext) throws Exception {
        SecretKey secretKey = getSecretKey("o9szYIOq1rRMiouNhNvaq96lqUvCekxR");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        return new String(cipher.doFinal(Base64.getDecoder().decode(ciphertext)));
        //return new String(cipher.doFinal(base64Decode("ASDASDADS")));
    }

    public static SecretKey getSecretKey(String secretKey) throws Exception {
        byte[] decodeSecretKey = Base64.getDecoder().decode(secretKey);
        //byte[] decodeSecretKey = base64Decode(secretKey);
        return new SecretKeySpec(decodeSecretKey, 0, decodeSecretKey.length, "AES");
    }
}

关于javascript - 为什么java无法解密CryptoJS加密数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64125317/

相关文章:

javascript - UIWebView - 以编程方式设置默认日期

javascript - 如果...那么按钮按下的功能

java - paintComponent(g) 还是 paintComponent(g2)?

java - 停止阵列中正在运行的线程

go - 如何使用 golang.org/x/crypto/bn256 计算 e(g1^x,g1^x)?

hash - 是否有任何已发表的研究表明对 MD5 的原像攻击迫在眉睫?

javascript - 如何JSON格式化数组数组?

javascript - 使用 css、jquery/javascript 数组或开关创建警报

java - Selenium Webdriver (Java) - 从 css 选择器中排除特定标签

swift - CryptLib 解密返回错误值