java - Spring 4 加密器与 cryptojs

标签 java javascript spring encryption cryptojs

我正在使用 Spring 4 Encryptors 类以这种方式处理加密:

String salt = KeyGenerators.string().generateKey();
TextEncryptor textEncryptor = Encryptors.text("MY_SECRET_KEY", salt);
textEncryptor.encrypt(json);

在客户端 javascript 中,我尝试使用 CryptoJS 解密

var uncrypted = CryptoJS.AES.decrypt(serverEncrypted, "MY_SECRET_KEY");
$("#encrypted-data").val(uncrypted);

我猜我需要还原十六进制编码部分,但我不明白需要做什么。

我尝试在解密之前进行解析,但没有任何好处。

CryptoJS.enc.Hex.parse(serverEncrypted)

spring 文档说文本方法将使用“标准”加密方法以十六进制值加密,这是使用 PKCS #5 的 PBKDF2 的 256 位 AES

[搜索进度]

这就是 Spring 创建其 key 的方式:

PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, 1024, 256);
SecretKey secretKey = newSecretKey("PBKDF2WithHmacSHA1", keySpec);
SecretKeySpec secretKey = new SecretKeySpec(secretKey.getEncoded(), "AES");

还有加密:

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(iv));

iv 是一个 8 字节的安全随机数组,并添加到加密数据之前。

最佳答案

经过一些研究,我找到了一个解决方案,即如何结合 Spring 4 Encryptors 和 CryptoJS。 Spring 在使用 PKCS #5 的 PBKDF2 的加密器 256 位 AES 中使用文档中提供的 - Spring Crypto docs IV 大小等于 16 字节。在 CryptoJS 中创建代码时,该信息至关重要。要记住的另一件事是在整个加密/解密过程中使用相同的 salt 和 iv one message。有了这些信息,我们就可以开始编码了(在这个例子中,我在 CryptoJS 中加密消息并在 Spring 中解密): CryptoJS

const keySize = 256;
const ivSize = 128;
const iterations = 1024;

function encrypt(msg, pass) {
    const salt = CryptoJS.lib.WordArray.random(128 / 8);

    const key = CryptoJS.PBKDF2(pass, salt, {
        keySize: keySize / 32,
        iterations: iterations
    });

    const iv = CryptoJS.lib.WordArray.random(ivSize / 8);

    const encrypted = CryptoJS.AES.encrypt(msg, key, {
        iv: iv,
        padding: CryptoJS.pad.Pkcs7,
        mode: CryptoJS.mode.CBC

    });

    // salt, iv will be hex 32 in length
    // append them to the ciphertext for use  in decryption
    return salt.toString() + iv.toString() + encrypted.ciphertext.toString();
}

如您所见,所有加密的结果都是 salt + iv + encryptedMessage 的串联。同样重要的是,在 Spring 代码中,我发现 key 的创建长度为 256,迭代次数为 1024:

PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray(), Hex.decode(salt), 1024, 256);

现在我们可以将这个准备好的结果带到我们的 Spring 代码中并解密:

private static String decrypt(String encryptedData, String keyStr) {
        final String salt = encryptedData.substring(0, 32);
        final String encryptedPart = encryptedData.substring(32);
        final TextEncryptor textEncryptor = Encryptors.text(keyStr, salt);
        return textEncryptor.decrypt(encryptedPart);
}

Spring AES 加密器会将 IV 的一部分切掉,单独用于解密过程。当然,一切都必须是十六进制编码,但这就是 Spring TextEncrytpors 的工作方式。

相反的过程(在 Spring 中加密,在 CryptoJS 中解密)几乎是一样的。在 CryptoJS 中,我们必须提取 saltiv:

const keySize = 256;

function decrypt (encryptedMessage, pass) {
  var salt = CryptoJS.enc.Hex.parse(encryptedMessage.substr(0, 32));
  var iv = CryptoJS.enc.Hex.parse(encryptedMessage.substr(32, 32))
  var encrypted = encryptedMessage.substring(64);

  var key = CryptoJS.PBKDF2(pass, salt, {
      keySize: keySize / 32,
      iterations: iterations
    });

  var decrypted = CryptoJS.AES.decrypt(encrypted, key, { 
    iv: iv, 
    padding: CryptoJS.pad.Pkcs7,
    mode: CryptoJS.mode.CBC

  })
  return decrypted;
}

希望对大家有所帮助:)

干杯!

关于java - Spring 4 加密器与 cryptojs,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29927385/

相关文章:

java - 为什么 Cryptoki.C_OpenSession 有时会与 HSM 断开连接

java - 销毁 Nuance session

java - Spring/Grails - 使用新属性重新加载 bean

javascript - rails teaspoon 在引擎中测试未加载 *_spec.js

java - Http 请求的 Spring Kafka 监听器

java - 似乎无法插入二叉搜索树

javascript - 如何在 localStorage (Javascript) 中存储带有数组的 JSON?

javascript - 如何设置 JavaScript 对象的类

java - Spring Boot 应用程序如何在没有 @Configuration 类的情况下创建 bean

java - 依赖问题 "SpringBootServletInitializer cannot be resolved to a type"