Spring 4 Encryptors vs cryptojs

时间:2015-04-28 18:41:32

标签: 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创建密钥的方式:

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字节的安全随机数组,并且是加密数据的前缀。

1 个答案:

答案 0 :(得分:1)

经过一番研究,我找到了一个解决方案,如何结合Spring 4加密器和CryptoJS。 Spring在其加密器256位AES中使用PKCS#5的PBKDF2,如文档中提供的那样 - Spring Crypto docs,IV大小等于16字节。在CryptoJS中创建代码时,该信息至关重要。要记住的另一件事是在加密/解密的整个过程中使用相同的盐和iv 一条消息。有了这个信息,我们可以开始编码(在这个例子中,我加密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代码中我发现密钥是以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切割部分并将其用于解密过程。当然,所有内容都必须是 Hex编码,但这就是Spring TextEncrytpors的工作方式。

相反的过程(在Spring中加密和在CryptoJS中解密)将完全相同。在CryptoJS中,我们必须提取 salt iv

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;
}

我希望它能帮到某人:)

干杯!