【问题标题】:Need help converting encryption logic from Js to Java需要帮助将加密逻辑从 Js 转换为 Java
【发布时间】:2021-05-08 17:01:46
【问题描述】:

我正在尝试重新创建从 JS 到 Java 的代码 sn-p,但输出不同。我究竟做错了什么? 这是来自 JS 的代码 sn-p:

var randomKey = 2116781760886580;

var key = CryptoJS.enc.Utf8.parse(randomKey);

var iv = CryptoJS.enc.Utf8.parse(randomKey);

var encrypt = CryptoJS.AES
    .encrypt(CryptoJS.enc.Utf8.parse("Text to encrypt"), key,
        {
            keySize: 128 / 8,
            iv: iv,
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7
        });

var out = btoa(encrypt);   //SGpJSWhDUXNmMEMzSk0vbmovaGZyQT09

以下是Java代码sn-p:

String randomKey = "2116781760886580";

String plainText = "Text to encrypt";

byte[] keyBytes = randomKey.getBytes(StandardCharsets.UTF_8);

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

IvParameterSpec ivSpec = new IvParameterSpec(keyBytes);

SecretKeySpec sKey = new SecretKeySpec(keyBytes,"AES");

cipher.init(Cipher.ENCRYPT_MODE, sKey, ivSpec);

byte[] encryptedBytes = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));

String out = Base64.getEncoder().encodeToString(encryptedBytes);    //HjIIhCQsf0C3JM/nj/hfrA==

【问题讨论】:

  • 您的密钥在 JS 中看起来像一个数字,而在 Java 中它是一个字符串(至少类型是这样说的,因为代码不是有效的 Java)。会不会有区别?
  • 我认为,您在 js 代码中加密了两次。 CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse("Text to encrypt") .... 但是在java代码中,你加密一次。
  • 该错误在 CryptoJS 代码中。 CryptoJS.AES.encrypt() 返回一个 CipherParams 对象,该对象封装了各种数据,包括密文。我不知道btoa 对这个对象做了什么,但它不会返回 Base64 编码的密文。您可以使用encrypt.ciphertext.toString(CryptoJS.enc.Base64) 或更短的encrypt.toString() 获取它,它对应于Java 代码的Base64 编码密文。顺便说一句,使用密钥作为 IV 通常是不安全的。
  • @marstran 我在 JS 中通过使用字符串和数字类型打印单词数组来仔细检查,两个结果都是一样的。
  • @Topaco 好的,我正在尝试从 CryptoJs 中现有的实现在 Java 中重新创建相同的逻辑。

标签: javascript java encryption


【解决方案1】:

CryptoJS.AES.encrypt() 返回一个CipherParams 对象,该对象封装了多个数据,尤其是密文。如果将CipherParams 对象传递给btoa(),则首先使用toString() 将其隐式转换为字符串,默认情况下返回CipherParams 对象的Base64 编码密文,至少在不涉及盐的情况下如此案子。与btoa() 的Base64 编码一起,密文因此被Base64 编码两次

为了使 Java 代码提供与 JavaScript 代码相同的结果,因此密文也必须经过两次 Base64 编码,例如:添加以下内容:

String out2 = Base64.getEncoder().encodeToString(out.getBytes(StandardCharsets.UTF_8));

注意,冗余的 Base64 编码实际上是没有用的,只会增加数据量(Base64 has 33% overhead)。此外,使用密钥作为 IV 通常是不安全的,here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-06
    • 2019-12-23
    • 1970-01-01
    • 2022-06-12
    • 2016-02-07
    • 2020-07-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多