【问题标题】:Decode(Base64) and Decrypt(AES/CBC/PKCS5PADDING) with CryptoJS - React使用 CryptoJS 解码(Base64)和解密(AES/CBC/PKCS5PADDING) - React
【发布时间】:2019-06-27 07:39:00
【问题描述】:

我正在开发 Web 应用程序,使用 react 作为前端,spring mvc 作为后端。我需要在浏览器的本地存储中存储一些用户信息。我不想将该信息作为纯文本存储在本地存储中。所以我想在服务器端进行 AES 加密并将这些数据推回 JS 端。为此,我需要客户端解密框架。我发现 crypto-js 对所有这些事情都非常有用。我无法理解我在客户端缺少解密和解码的地方。

我先解释一下我的 Spring Side Encryption Code,这绝对没问题:

public class EncryptDecrypt {

        private static final String SECRET_KEY_1 = "ssdkF$HUy2A#D%kd";
        private static final String SECRET_KEY_2 = "weJiSEvR5yAC5ftB";

        private IvParameterSpec ivParameterSpec;
        private SecretKeySpec secretKeySpec;
        private Cipher cipher;

        public EncryptDecrypt() throws UnsupportedEncodingException, NoSuchPaddingException, NoSuchAlgorithmException {
            ivParameterSpec = new IvParameterSpec(SECRET_KEY_1.getBytes("UTF-8"));
            secretKeySpec = new SecretKeySpec(SECRET_KEY_2.getBytes("UTF-8"), "AES");
            cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
        }

        public String encrypt(String toBeEncrypt) throws NoSuchPaddingException, NoSuchAlgorithmException, 
            InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
            byte[] encrypted = cipher.doFinal(toBeEncrypt.getBytes());
            return Base64.encodeBase64String(encrypted);
        }
}

在客户端,我无法用简单的东西解码和解密代码。这是我的客户端代码:

var CryptoJS = require("crypto-js");

var data = "Ggydx4oA1+SKBw+unA8BUUm2tnvkQbp1terdF2PEGFYSEZL/ye08op/0b0BauGtIl1dBIodrlKXo2de3MykYmocd3ctxFtIIki01V+M8XeQj6B384o0G+H7NpVx5tCJjPDvdqVRObtxCTqu3r8QRzYTNcMM5bRhbYxCYl8/NRyPQJnmcJDlRBeVOoJiQNA7Qd5UJD/mNivoyMUfYGV7/DlpylQWWwEAHVdgcb865i8jnf3vqURehAXYoaD6Bgodi1EM4H007uv0o6NEOk3H4jQ==";

var key = "weJiSEvR5yAC5ftB";

// Decode the base64 data so we can separate iv and crypt text.
var rawData = atob(data);
var iv = "ssdkF$HUy2A#D%kd";
var crypttext = rawData.substring(16);

console.log(rawData);

// Decrypt...
var plaintextArray = CryptoJS.AES.decrypt(
  { ciphertext: CryptoJS.enc.Base64.parse(crypttext) },
  key,
  { iv: iv }
);

console.log(plaintextArray);

console.log(CryptoJS.enc.Base64.stringify(plaintextArray));

var decryptedData = JSON.parse(CryptoJS.enc.Base64.stringify(plaintextArray).toString(CryptoJS.enc.Utf8));

console.log(decryptedData);

P.S:我已经将 JSON 发送到客户端,所以我最终会解析它。我是加密和解密的新手。我真的很纠结我的客户端代码应该是什么样子。请帮忙。

【问题讨论】:

  • @rhashimoto 你能帮我解决这个问题吗?
  • 1.您需要在rawData.substring(16); 2 之前解码64。Spring 端可能会将IV 附加到密文中。比较 Spring Encryption 的输入输出大小。如果它们相同,则 IV 没有预先添加,那么整个数据就是密文。如果反比解码后可以得到密文字节。
  • @kelalaka这就是我所做的。我已经在 rawData.substring(16); 之前解码了字符串
  • 您是否检查了 rawData 的前 16 个字节是 IV,如果是,则与您的 IV 匹配?

标签: encryption base64 aes decode cryptojs


【解决方案1】:

您不应该将字符串作为CryptoJS 中的键传递。在这种情况下,它认为这个字符串不是密钥,而是密码。并使用PBKDF 从密码生成密钥。下面的工作示例:

var data = "Ggydx4oA1+SKBw+unA8BUUm2tnvkQbp1terdF2PEGFYSEZL/ye08op/0b0BauGtIl1dBIodrlKXo2de3MykYmocd3ctxFtIIki01V+M8XeQj6B384o0G+H7NpVx5tCJjPDvdqVRObtxCTqu3r8QRzYTNcMM5bRhbYxCYl8/NRyPQJnmcJDlRBeVOoJiQNA7Qd5UJD/mNivoyMUfYGV7/DlpylQWWwEAHVdgcb865i8jnf3vqURehAXYoaD6Bgodi1EM4H007uv0o6NEOk3H4jQ==";
var rawData = CryptoJS.enc.Base64.parse(data);
var key = CryptoJS.enc.Latin1.parse("weJiSEvR5yAC5ftB");
var iv = CryptoJS.enc.Latin1.parse("ssdkF$HUy2A#D%kd");
var plaintextData = CryptoJS.AES.decrypt(
    { ciphertext: rawData },
    key,
    { iv: iv });
var plaintext = plaintextData.toString(CryptoJS.enc.Latin1);
console.log(plaintext);
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/crypto-js.js"></script>

顺便说一句,您不应该每次都使用相同的 IV。在这种情况下,您错过了 IV 和 CBC 模式的基本用途。您的整体安全性等于 ECB 模式。

【讨论】:

  • 非常感谢。你是救世主。是的,我会一直使用不同的静脉注射,也会使用盐。这只是示例数据。再次感谢您。
  • 很好的答案!如果你想支持非拉丁字符,你可以使用CryptoJS.enc.Utf8
  • @Zergatul 你知道如何在CryptoJSencrypt() 中使用GCM 作为modePKCS5Padding 作为padding
  • @CompaqLE2202x GCM 不使用填充。 GCM 的作用类似于流密码,这意味着它可以处理任何消息长度。当消息长度必须是某个值的倍数时,分组密码需要填充。从技术上讲,您可以使用填充,在使用 GCM 之前,它没有任何意义。
  • @CompaqLE2202x 这意味着 CryptoJS 不支持GCM
猜你喜欢
  • 2021-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-28
  • 2020-02-24
相关资源
最近更新 更多