【问题标题】:Getting garbage after tripledes_cbc encryption with NoPadding scheme使用 NoPadding 方案进行 Tripledes_cbc 加密后获取垃圾
【发布时间】:2017-10-27 20:06:42
【问题描述】:

我正在解密一些加密数据。说数据是高度机密的信息。信息用tripledes_cbc算法加密。用于加密信息的秘钥采用rsa算法加密。

但是当我尝试使用DESede/CBC/NoPadding 算法解密信息时,我得到了原始数据以及一些在前面和结尾填充的垃圾字符。

当我尝试使用 DES/CBC/PKCS5Padding 而不是 DESede/CBC/NoPadding 时,出现“未正确填充最终块”异常。

下面是代码sn-p。请让我知道我可以做些什么来获得没有额外填充的正确文本:

        KeyStore ks = KeyStore.getInstance("jks");
        FileInputStream fis = new FileInputStream(ksFile);
        ks.load(fis, "testing".toCharArray());

        PrivateKey privateKey = (PrivateKey) ks.getKey("keys", "1234".toCharArray());

        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] kekBytes = cipher.doFinal(Base64.decodeBase64(encKey.getBytes("UTF-8")));

        SecureRandom random = new SecureRandom();
        byte[] iv = new byte[8];
        random.nextBytes(iv);

        SecretKey key = new SecretKeySpec(kekBytes, "DESede");
        Cipher cipher1 = Cipher.getInstance("DESede/CBC/NoPadding");
        cipher1.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
        byte[] out = cipher1.doFinal(Base64.decodeBase64(data.getBytes("UTF-8")));

        System.out.println("Data Length: " + out.length);
        String result = new String(out, "UTF-8");

【问题讨论】:

  • 1. 3DES 不应该用于新工作,AES 是当前使用的对称方法。但我猜,这是一个学校项目,学校比现实世界落后了十年左右。 2.提供十六进制格式的预期和解密数据示例。
  • 显然你需要找出加密端使用了什么填充。另外,您使用的是 DES 还是 DESede?因为DES/CBC/PKCS5Padding 不是DESede/CBC/NoPadding 的明智替代品。也许你的意思是DESede/CBC/PKCS5Padding

标签: java encryption cryptography rsa tripledes


【解决方案1】:

如果中间部分正确,则您的密钥是正确的。开头的块可能是密文前缀的IV。如果您尝试解密,那么您将得到垃圾。之后,IV 本身被用作下一个块的向量,因此 CBC 密码设法自我纠正并正确继续。理论上:CBC 限制了错误传播

最后的部分是使用的填充方案。你应该试试"DESede/CBC/PKCS5Padding"。如果这不起作用,您需要查看二进制值(实际上,例如十六进制编码)并找出使用的填充方案,以便您可以取消填充数据。

请注意,Java 的标准加密提供程序中没有那么多填充方案。因此,您要么必须找到提供例如位填充,或者您可以使用"NoPadding" 并自己执行取消填充。

如果这是针对在线协议的,那么可能是时候学习填充预言机攻击了,事实上,还有更新的协议,例如 AES/GCM 和 RSA/OAEP。

【讨论】:

  • 如何从解密消息的十六进制表示中识别填充字符?十六进制结果看起来像(这里只给出第一个和最后几个字符):“5368f1b5beaa10ec3c6e73313a5061796d656e7443616c6c6261636b496e707574 ........7443616c6c6261636b496e7075743ec9de7pandc99f43”
  • @K.Nath 允许在上述十六进制编码数据中出现一些无意的不可见字符,格式为 8 字节的前导码,后跟 ASCII 编码的文本,后跟 8 字节的数据。为什么你认为这是不正确的?
  • @zaph - 我并不是说输出不正确。我只是想提取不包括填充垃圾的文本。我可以通过消除前 16 个字符(在上面的注释中 - '5368f1b5beaa10ec' )来克服在输出字符串前面填充的垃圾,因为我看到每次运行 java 代码时前 16 个字符总是不同。但是我无法从输出字符串的尾部删除垃圾,因为除了提到的前 16 个字符之外,每次运行 java 代码时所有其他字符都保持不变。
  • @K.Nath 所以这不是解密问题,只是字节操作问题。似乎您想要的总是以“>”字符(0x3e)结尾,所以只需从末尾找到第一个“>”并删除它。
  • 它可能是 ISO 填充,这意味着填充字节的数量被编码在最后一个字节中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-18
  • 2011-07-16
  • 1970-01-01
  • 1970-01-01
  • 2015-03-11
相关资源
最近更新 更多