处理加密exception

在Java中处理加密\解密时,这个非常基本的代码段很常见。

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

仅这三行,可能会抛出六个exception,我不确定处理它们的最干净(在代码可读性方面)是什么。 尝试六个catch子句对我来说真的很像。

在使用这些物体时,是否有微图案或最佳实践,我显然是缺失的?

编辑

对不起,我想我没有很好地解释自己。 我的问题不是关于避免try \ catch子句,而是如果有一种常见的方法来处理类似的情况。

例外情况是

 NoSuchPaddingException, NoSuchAlgorithmException InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException 

您指出了以下例外情况:

 NoSuchPaddingException, NoSuchAlgorithmException InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException 

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

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

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

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

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


最后一些说明:

  • 请注意,如果未安装无限加密文件,则可能会因为AES密钥大小为192位和256位而抛出exception(有关详细信息,请查看Oracle JavaSE站点 ); 您应该检查应用程序启动时是否允许密钥大小;
  • BadPaddingExceptionIllegalBlockSizeException可能因为攻击或因为数据不完整而被创建;
  • 如果密钥不正确,也可能抛出BadPaddingException

如果您愿意丢失一些特定内容,所有Cryptoexception都会扩展GeneralSecurityException ,您可以将其捕获。

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

 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 )