【问题标题】:what do I miss to decrypt code that encoded in java?我想念什么来解密用java编码的代码?
【发布时间】:2022-01-26 23:16:15
【问题描述】:

我正在尝试解密 nodejs 中的加密数据,并且数据是由其他身份验证服务提供商在 java 中加密的。

解密代码可以很好地处理在 nodejs 中加密的数据,就像他们的指南一样。但是,它会对来自服务的数据产生错误。

首先,这是他们的加密代码

String res_data = ""
String key = "" //16bytes encoded string which is made when I call their auth module
String iv = "" //16bytes encoded string which is made when I call their auth module

SecretKey secureKey = new SecretKeySpec(key.getBytes(), "AES");
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
c.init(Cipher.ENCRYPT_MODE, secureKey, new IvParameterSpec(iv.getBytes()));
byte[] encrypted = c.doFinal(enc_data.trim().getBytes());
Encoder encoder = Base64.getEncoder();
byte[] encodedBytes = encoder.encode(encrypted);
String resDataEnc = new String(encodedBytes)

对应的nodejs加密代码工作正常且没有错误

//variables same as above
const res_data = "" 
const key = "" 
const iv = "" 

const cipher = crypto.createCipheriv("aes-128-cbc", key, iv);
const encrypted = cipher.update(enc_data, "utf8", "base64")
const resDataEnc = encrypted + cipher.final("base64")

这是我的解密代码,导致错误

const enc_data = "" //encoded data from service
const key = "" //same as above
const iv = "" //same as above

const decipher = crypto.createDecipheriv("aes-128-cbc", key, iv);
const decrypted = decipher.update(enc_data, "base64", "utf8")
//decrypted.toString() returns successfully decoded data

//here's what I tried
const resData = decrypted + decipher.final("utf8")
//it returns Error "wrong final block length" at decipher.final

//another try
const resData = Buffer.concat([decrypted + decipher.final("utf8")])
const euckrDecode = iconv.decode(response, "euc-kr")
//it returns same error

这是他们的解密指南代码

//same data as written above
String enc_data = ""
String key = ""
String iv = ""

SecretKey secureKey = new SecretKeySpec(key.getBytes(), "AES");
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
c.init(Cipher.DECRYPT_MODE, secureKey, new IvParameterSpec(iv.getBytes()));
byte[] cipherEnc = Base64Util.decode(encData.trim().getBytes());
String resData = new String(c.doFinal(cipherEnc), "euc-kr");

正如我所寻找的,java和nodejs在加密时有不同类型的填充,这是问题吗? 它在java中解码得很好,但在nodejs中却没有。 从 java 转换到 nodejs 有问题还是我想念的其他事实?

请分享您的知识。 谢谢

【问题讨论】:

  • 用发布的 Java 代码加密和用 NodeJS 代码解密对我有用(除了 another try 分支,它实现不正确)。也许服务做的比你想象的要多。也许它与编码有关(euc-kr)。由于您对错误只字未提(...但是,服务中的数据会出错...),因此只能进行猜测。描述错误/发布错误消息并分享测试数据:密钥、IV、明文、密文。
  • Padding 是一样的顺便说一句:PKCS#7(对于 NodeJS 默认,在 Java 中称为 PKCS#5)。
  • 感谢您的回答 Topaco 错误是库:'数字信封例程',> 函数:'EVP_DecryptFinal_ex',> 原因:'错误的最终块长度',> 代码:'ERR_OSSL_EVP_WRONG_FINAL_BLOCK_LENGTH'
  • 示例数据是encData =“SMVARP + 1DHWOftmmjqNeU4n53CmNgwZzTTPzt0X4uBUNUoJf2bzsGQtYnC7IxACzJFzDlX96xGmDphUAfKSJfn34OMRUcLxi + / sAcHV6r1Rt3Z2M7jeCzZlGEmlsKuAxl / PySVn + j365XnikG + / 9jB1ij9aI1Z0J6S / kvTIxeo2AN6nHPTV + flrjfck1uXlQgDivKGZDHlPj + WhCq6z8DgSvgOgxRR8097 / Yjfa9gODY6C2gzq0vrCU664OdPcNrMi4JrvOufj4PBu1bc51Kh / mQZpronbu9I9GYCNVV0gjQbm1VjcLkxoDy56XUokCPwW51DlhUKC / Lv0ZDU22V6GrZhcbm37EOwduAyRCVXL70qpil1feZoZc55rdIQXVtsSbjGNgVTZ43VacNyhvzGR / yFO3oIZvNCJn75t8W / HxunuW / rHKjTD12TLrkn + nLWCzBfVXIkEt9OOgxHZ / ssxWz4 + qHKoTm / 782VgM2IHafG4prH96tR0z4g04MrMgQLDSanDw1r5WmZja6HIhVcQ=="
  • key = "Wq0Dl8QtLimteOFJ" iv = "XUgZRXB883TcEEg="

标签: java node.js encryption


【解决方案1】:

此代码存在多个问题:

String key = "" //16bytes 编码字符串,当我调用他们的 auth 模块时生成
String iv = "" //16bytes 编码字符串,当我调用他们的 auth 模块时生成

对于 CBC 模式,IV 需要是随机的(不可预测的),没有固定的,否则一些攻击向量是可能的。

直接字符串类型中的密钥和 IV 假定使用限制密钥安全性(强度)的可打印字符。

const encrypted = cipher.update(enc_data, "utf8", "base64")
const resDataEnc = 加密 + cipher.final("base64")
....
const resData = 解密 + decipher.final("utf8")
//它在 decipher.final 处返回错误“错误的最终块长度”

连接两个 base64 编码字符串不一定会产生另一个有效的 base64 编码字符串。当输入长度为 3 的倍数时,它可能会意外发生。如果未使用 base64 填充,则不会提前发现它。这对 utf-8 也有效,主要是在处理多字节字符集时,例如来自亚洲的。

在加密/解密时,您应该使用字节数组(Buffer),然后对结果进行编码或解码,例如

  const resDataEnc  = Buffer.concat(
    [ cipher.update( Buffer.from(enc_data, 'base64')), cipher.final()  ]
    ).toString('utf-8');

const resData = 解密 + decipher.final("utf8")
//它在 decipher.final 处返回错误“错误的最终块长度”

尝试解密无效输入(连接两个 base64 编码字符串),解码后的输入可能没有所需的长度(16 的倍数)。

基本上 - 检查解码后的输入必须是块大小的倍数(16 字节)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-04-18
    • 2020-05-24
    • 2012-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多