Java 中的 AES 加密有效,但 JavaScript 中的解密不起作用? [英] AES Encryption in Java working, but Decryption in JavaScript not working?

查看:28
本文介绍了Java 中的 AES 加密有效,但 JavaScript 中的解密不起作用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试加密值服务器端,然后从浏览器端解密.这是我用来加密的 Java 代码,它工作正常:

I am trying to encrypt a value server side and then decrypt from the browser side. This is the Java code I'm using to encrypt, which is working correctly:

package aes;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Base64;
 
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

public class AesEncryption {

    private static SecretKeySpec secretKey;
    private static byte[] key;
 
    public static void setKey(String myKey) {
        MessageDigest sha = null;
        try {
            key = myKey.getBytes("UTF-8");
            sha = MessageDigest.getInstance("SHA-1");
            key = sha.digest(key);
            key = Arrays.copyOf(key, 16); 
            secretKey = new SecretKeySpec(key, "AES");
        } 
        catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } 
        catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }

    public static String encrypt(String strToEncrypt, String secret) {
        try {
            setKey(secret);
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
            return Base64.getEncoder().encodeToString(cipher.doFinal(strToEncrypt.getBytes("UTF-8")));
        } 
        catch (Exception e) 
        {
            System.out.println("Error while encrypting: " + e.toString());
        }
        return null;
    }

然后我调用了一个 JavaScript 方法来解密加密的值:

I then have a JavaScript method I call to decrypt the encrypted value:

  aesDecrypt(encryptedValue) {
    console.log("TESTING ENCRYPTED VALUE : " , encryptedValue)
    var bytes = CryptoJS.AES.decrypt(encryptedValue, secretAesKey, {
      mode: CryptoJS.mode.ECB,
      padding: CryptoJS.pad.Pkcs7
    })
    console.log("TESTING BYTES : " , bytes)
    var originalValue = bytes.toString(CryptoJS.enc.Utf8);
    console.log("TESTING ORIGINAL VALUE : " , originalValue)
    return originalValue
  }

记录解密的每个步骤时,尝试打印原始值时,它只是空白.我知道必须以与最初加密相同的方式将 encryptedValue 转换回字节,然后必须使用 UTF-8 编码以返回原始字符串.我还能缺少什么导致这种情况?

When logging each step of the decryption, when trying to print the original value, it's just blank. I know that the encryptedValue has to be converted back to bytes in the same way that it was originally encrypted and then has to be encoded with UTF-8 to get back to the original string. What else could I be missing that is causing this?

推荐答案

使用 CryptoJS 可以通过 SHA-1 进行密钥派生,例如如下:

Key derivation via SHA-1 is possible with CryptoJS e.g. as follows:

var passphrase = '<your passphrase>';
var sha1Hash = CryptoJS.SHA1(passphrase);                                           // Create SHA1 hash
var secretAesKey = CryptoJS.lib.WordArray.create(sha1Hash.words.slice(0, 16 / 4));  // Use the first 4 words (= 16 bytes) of the hash

用Java代码生成的密文进行测试:

Test with a ciphertext generated by the Java code:

function aesDecrypt(encryptedValue) {
    console.log("TESTING ENCRYPTED VALUE : " , encryptedValue);
    var bytes = CryptoJS.AES.decrypt(
        encryptedValue, 
        secretAesKey, 
        {
            mode: CryptoJS.mode.ECB,
            padding: CryptoJS.pad.Pkcs7
        }
    );
    console.log("TESTING BYTES : " , bytes);
    var originalValue = bytes.toString(CryptoJS.enc.Utf8);
    console.log("TESTING ORIGINAL VALUE : " , originalValue);
    return originalValue;
  }

var passphrase = 'my secret passphrase';
var sha1Hash = CryptoJS.SHA1(passphrase)
var secretAesKey = CryptoJS.lib.WordArray.create(sha1Hash.words.slice(0, 16 / 4));
var ciphertext = 'hjC0d3sEGJ/3SBTPyV5RrbiIi5jCfhj9T2ZbeWNyBHqmCrVaKLYN94ouiMOz8d4x';
aesDecrypt(ciphertext);

<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>

正确地将密文解密为原始明文.

which correctly decrypts the ciphertext into the original plaintext.

请注意,正如评论中所提到的,ECB 模式是不安全的,而且密钥通过摘要从密码中派生出来(即使它不会被破坏).相反,应该使用可靠的密钥派生函数,如 Argon2 或 PBKDF2.

Note that, as mentioned in the comments, the ECB mode is insecure and also the key derivation from a password via a digest (even if it would not be broken). Instead, a reliable key derivation function like Argon2 or PBKDF2 should be used.

这篇关于Java 中的 AES 加密有效,但 JavaScript 中的解密不起作用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆