【问题标题】:cryptojs aes 256 encryption and java decryptioncryptojs aes 256加密和java解密
【发布时间】:2014-06-25 16:41:16
【问题描述】:

我在客户端使用 cryptojs aes 256 加密了消息。但无法在java端解密它。首先,我将密钥作为十六进制直接传递给服务器端,然后将其从十六进制转换为 java bytearray。它没有用。然后我将短语 salt, iv 作为十六进制传递给服务器。然后生成密钥。它仍然没有工作。总是抱怨密钥长度不对。

客户端:

var salt = CryptoJS.lib.WordArray.random(16);
var salt_hex = CryptoJS.enc.Hex.stringify(salt);

var iv = CryptoJS.lib.WordArray.random(256/32);
var iv_hex = CryptoJS.enc.Hex.stringify(iv);


var key = CryptoJS.PBKDF2(secret, salt, { keySize: 256/32, iterations: 10 });
var key_hex=CryptoJS.enc.Hex.stringify(key);

var encrypted = CryptoJS.AES.encrypt(plaintext, key, { iv: iv });    

var encryptedtxt = secret+":"+salt_hex+":"+iv_hex+":"+encrypted.ciphertext.toString(CryptoJS.enc.Base64)+":"+key_hex;

服务器端:

    if (encrypted != null)
    {
        //Get the passphras, salt, IV and msg
        String data[] = encrypted.split(":");
        String passphrase = data[0];
        String salt_hex = data[1];
        String iv_hex = data[2];
        String msg64 = data[3];
        String jskey_hex = data[4];
        byte[] jskey = hexStringToByteArray(jskey_hex);
        byte[] iv = hexStringToByteArray(iv_hex);
        byte[] salt = hexStringToByteArray(salt_hex);
        BASE64Decoder decoder = new BASE64Decoder();
        byte[] msg = decoder.decodeBuffer(msg64);

        try {
             //theClear = AES.decrypt(encrypted);
            /* Decrypt the message, given derived key and initialization vector. */
            SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
            KeySpec spec = new PBEKeySpec(passphrase.toCharArray(), salt, 10, 256/32);
            SecretKey key = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
            String plaintext = new String(cipher.doFinal(msg), "UTF-8");
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

【问题讨论】:

  • 如果“密钥长度不正确”,那么您的问题可能是前导零。 stringify() 方法是否将[0x01, 0x02, 0x03] 转换为"123"?您的解密代码可能假定为"010203"。 "123" 可能会给出一个两字节数组[0x12, 0x03],它与输入不匹配并且长度错误。这对加密密钥来说是致命的。
  • 256/32 == 8,而 AES 支持的密钥大小为 16、24 或 32 字节。您必须修改 JS 和 Java 代码以使用至少 16 字节的密钥。
  • rossum - 十六进制字符串化密钥就像 010203。但我在 java 端进行十六进制解码到字节数组。我想知道JS上的单词数组如何与java上的字节数组匹配?
  • 您的 IV 在 CryptoJS 中的大小也不正确。 AES 使用 128 位块,因此 IV 也应该是 128 位。
  • Owlstead - 你在 IV 上是绝对正确的。改变它。

标签: java aes cryptojs


【解决方案1】:

终于明白了。默认情况下,JRE 7 不支持 256 位密钥。我必须从http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html 下载新的 jar 包并将它们覆盖在 jre/lib/security 文件夹中。您将不得不对 Websphere 6 或 7 执行类似的操作。如果您不执行此操作,则会提示“非法密钥大小”。我还看到了“非法密钥大小 x”,其中 x 是一个数字。这意味着密钥大小不正确。下面是代码。

服务器端:

//@Override
public String getClearText() throws IOException {
    // Get the body
    String encrypted = super.getParameter("aes"); //base64

    if (encrypted != null)
    {
        //Get the passphras, salt, IV and msg
        String data[] = encrypted.split(":");
        String passphrase = data[0];
        String salt_hex = data[1];
        String iv_hex = data[2];
        String msg64 = data[3];
        String jskey_hex = data[4];
        byte[] jskey = hexStringToByteArray(jskey_hex);
        byte[] iv = hexStringToByteArray(iv_hex);
        byte[] salt = hexStringToByteArray(salt_hex);
        BASE64Decoder decoder = new BASE64Decoder();
        byte[] msg = decoder.decodeBuffer(msg64);
        String plaintext = "";
        try {
            SecretKey key = new SecretKeySpec(jskey, "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
            plaintext = new String(cipher.doFinal(msg), "UTF-8");
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("in filter, decrypted: " +plaintext);
    }
    return plaintext;
}

客户:

$(function() {

$('#test').on('submit', function() {

var plaintext = $('#text').val();
var secret = '0123456789abcdef';

var salt = CryptoJS.lib.WordArray.random(16);
var salt_hex = CryptoJS.enc.Hex.stringify(salt);

var iv = CryptoJS.lib.WordArray.random(16);
var iv_hex = CryptoJS.enc.Hex.stringify(iv);


var key = CryptoJS.PBKDF2(secret, salt, { keySize: 256/32, iterations: 1 });
//var key_hex=CryptoJS.enc.Hex.stringify(key);
var key_hex= key;

var encrypted = CryptoJS.AES.encrypt(plaintext, key, { iv: iv });    


//decrypt
var decrypted = CryptoJS.AES.decrypt(
      encrypted,
      CryptoJS.enc.Hex.parse(key_hex),
      { iv: CryptoJS.enc.Hex.parse(iv_hex) });

var text = decrypted.toString( CryptoJS.enc.Utf8 );
//console.log(encrypted);

// ----- base64 encoding ----------
var encryptedtxt =     secret+":"+salt_hex+":"+iv_hex+":"+encrypted.ciphertext.toString(CryptoJS.enc.Base64)+":"+key_hex;
console.log('html - ciphere txt : ' +encryptedtxt);

// ---- testing ----
//var decrypted = CryptoJS.AES.decrypt(encrypted, key,{iv: CryptoJS.enc.Utf8.parse(iv)});
//console.log(decrypted.toString(CryptoJS.enc.Utf8));

post ('/E2Efilter/TheServlet', encryptedtxt);
return false;
});

【讨论】:

  • 看起来您正在使用所有其他参数(iv/salt/加密数据)存储您的密钥,那么您为什么首先要加密呢?攻击者可以同样轻松地解密数据。
猜你喜欢
  • 1970-01-01
  • 2013-07-20
  • 2022-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-13
  • 1970-01-01
相关资源
最近更新 更多