处理加密异常

时间:2013-03-29 18:40:20

标签: java security exception encryption cryptography

在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

3 个答案:

答案 0 :(得分:16)

您指出了以下例外情况:

NoSuchPaddingException, NoSuchAlgorithmException
InvalidAlgorithmParameterException, InvalidKeyException,
BadPaddingException, IllegalBlockSizeException

现在所有这些都是GeneralSecurityException,所以很容易抓住它们。但是看一下用例,你可能不想这样做。

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

现在最后两个例外BadPaddingExceptionIllegalBlockSizeException不同。它们取决于实际的密文,因此它们依赖于算法的输入。现在,通常应该在将输入提供到Cipher实例中之前验证输入的完整性,然后启动解密,例如首先验证HMAC校验和。因此,从这个意义上说,你仍然可以逃避运行时异常。

如果不检查完整性,则应该对异常执行不同的操作,例如将其重新抛出为(不同的?)已检查异常。如果你采取这条路线,你应该了解填充oracle攻击;如果攻击者可以多次尝试和解密密文,并且可以发现填充是否正确,那么该消息的机密性就会丢失。

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


最后一些注意事项:

答案 1 :(得分:2)

如果你愿意失去一些特殊性,那么所有加密例外都会扩展GeneralSecurityException,你可以改为抓住它。

答案 2 :(得分:-1)

处理这种情况的最佳方法是创建一个bussines异常(MyModuleException或其他),然后重新抛出该异常,添加Crypto异常以导致部分。这样,您的方法只会抛出一个异常,而不是六个异常,在应用程序的其他层中更容易管理。

public void myMethod(...) throws MyModuleException {
  try {
    final Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
    cipher.init(Cipher.ENCRYPT_MODE, key, iv);
    cipher.doFinal(*something*);
  } catch(Crypto1Ex ex){
    throw new MyModuleException("something is wrong", ex); //ex added, so it is not lost and visible in stacktraceses
  } catch(Crypto1Ex ex){
    throw new MyModuleException("something is wrong", ex);
  } //etc.
}

在Java 7中,您可以更轻松地处理它(请参阅:http://docs.oracle.com/javase/7/docs/technotes/guides/language/catch-multiple.html