处理加密异常

Mat*_*ils 13 java security encryption cryptography exception

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

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

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

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

编辑

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

例外情况是

NoSuchPaddingException, NoSuchAlgorithmException
InvalidAlgorithmParameterException, InvalidKeyException,
BadPaddingException, IllegalBlockSizeException
Run Code Online (Sandbox Code Playgroud)

Maa*_*wes 17

您指出了以下例外情况:

NoSuchPaddingException, NoSuchAlgorithmException
InvalidAlgorithmParameterException, InvalidKeyException,
BadPaddingException, IllegalBlockSizeException
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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


最后一些说明: