在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
您指出了以下例外情况:
现在所有这些都是GeneralSecurityException,因此很容易抓住它们。但是查看用例,您可能不想这样做。
GeneralSecurityException
如果您查看导致异常的原因,那么您会发现,仅在生成算法或键的实现时才会抛出这些异常中的任何一个(最后两个除外)。我认为在测试了应用程序之后,这些值或多或少保持静态是合理的。因此,抛出异常(例如)是合乎逻辑的IllegalStateException。IllegalStateException是运行时异常,不需要抛出(在方法签名中)或捕获。当然,您应将安全异常作为异常的 原因 。
IllegalStateException
现在最后两个例外,BadPaddingException并且IllegalBlockSizeException有所不同。它们取决于实际的密文,因此取决于算法的输入。现在,通常情况下,您应该始终在将输入输入Cipher实例之前验证输入的完整性,例如通过首先验证HMAC校验和来初始化输入。因此从这种意义上讲,您仍然可以摆脱运行时异常。如果您不对完整性进行单独检查,则不应将其转换为RuntimeException。相反,您可以让用户处理异常,也可以将其作为用例特定的异常重新抛出。
BadPaddingException
IllegalBlockSizeException
Cipher
RuntimeException
如果BadPaddingException通过(重新)抛出来处理,则应该了解纯文本oracle攻击,例如padding oracle攻击。对于CBC模式下的填充oracle攻击:如果攻击者可以尝试让您多次解密密文,并且收到解密成功(或失败)的提示,那么他们可以 检索消息的明文而不会破坏密文 。因此,在可以处理身份验证标签的其他16个字节的情况下,最好使用诸如GCM模式之类的身份验证模式。
最好使用单独的try/ catch块来构造和初始化Cipher以及解密本身。你也可以捕捉到的异常BadPaddingException和IllegalBlockSizeException处理之前GeneralSecurityException。从Java 7开始,您也可以使用多捕获语句(例如catch(final BadPaddingException | IllegalBlockSizeException e))。
try
catch
catch(final BadPaddingException | IllegalBlockSizeException e)
最后一些注意事项: