处理Java加密异常

问题描述 投票:14回答:3

这是非常基本的代码,在用Java处理加密\解密时非常常见。

final Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, key, iv);
cipher.doFinal(*something*);

仅这三行,就可能引发六个异常,我不确定(从代码可读性的角度)最干净的处理方式是什么。尝试使用六个catch子句对我来说真的很难闻。

当使用此类对象时,是否存在微模式或最佳实践,我显然不见了?

编辑

对不起,我想我对自己的解释不是很好。我的问题不是真的要避免使用try \ catch子句,而是是否存在处理类似情况的通用方法。

例外是

NoSuchPaddingException, NoSuchAlgorithmException
InvalidAlgorithmParameterException, InvalidKeyException,
BadPaddingException, IllegalBlockSizeException
java security exception encryption cryptography
3个回答
17
投票

您指出了以下例外情况:

NoSuchPaddingException, NoSuchAlgorithmException
InvalidAlgorithmParameterException, InvalidKeyException,
BadPaddingException, IllegalBlockSizeException

现在所有这些都是GeneralSecurityException,因此很容易抓住它们。但是查看用例,您可能不想这样做。

如果查看异常的原因,那么您会发现,仅在生成算法或键的实现时才会抛出这些异常中的任何一个(最后两个除外)。我认为在测试了应用程序之后,这些值或多或少保持静态是合理的。因此,抛出一个GeneralSecurityException是合乎逻辑的。 IllegalStateException是运行时异常,不需要抛出或捕获。当然,您应该将安全性异常表示为该异常的cause

现在最后两个例外IllegalStateExceptionIllegalStateException不同。它们取决于实际的密文,因此取决于算法的输入。现在,通常,在将输入提供给BadPaddingException实例(为解密而启动,例如首先验证HMAC校验和)之前,应该始终验证输入的完整性。因此从这种意义上讲,您仍然可以摆脱运行时异常。

如果不检查完整性,则应对异常进行其他操作,例如将其作为(不同的?)检查异常重新抛出。如果采取这种方式,您应该了解有关填充oracle攻击的知识;如果攻击者可以尝试多次解密密文,并且可以确定填充是否正确,则消息的机密性会丢失。

[最好最好使用单独的BadPaddingException / IllegalBlockSizeException块来构造和初始化IllegalBlockSizeException和解密本身。您还可以在处理Cipher之前捕获异常Ciphertry。从Java 7开始,您也可以使用多捕获语句(例如catch)。


最后一些注意事项:

  • 请注意,如果未安装无限的加密文件,可能会为AES密钥大小192位和256位引发异常(请查看Cipher了解更多信息);您应在启动应用程序时检查是否允许密钥大小;
  • BadPaddingExceptionIllegalBlockSizeException可能由于攻击或数据不完全存在而创建;
  • 如果密钥不正确,也可能会抛出[GeneralSecurityException

2
投票

如果您愿意失去某些特定性,所有加密例外都扩展为GeneralSecurityException,您可以直接捕获它。


-1
投票

处理此问题的最佳方法是创建一个bussines异常(MyModuleException之类的东西),然后重新抛出该异常,并添加Crypto异常来引起该异常。这样,您的方法将只抛出一个异常,而不是六个异常,这将在应用程序的其他层中更容易管理。

catch(final BadPaddingException | IllegalBlockSizeException e)

在Java 7中,您可能会更轻松地处理它(请参阅:Oracle JavaSE site

© www.soinside.com 2019 - 2024. All rights reserved.