处理 Java 加密异常 [英] Handling Java crypto exceptions

查看:29
本文介绍了处理 Java 加密异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

This, pretty basic, piece of code is quite common when handling encryption / decryption in Java.

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

仅这三行就可能引发六个异常,我不确定处理它们的最干净(在代码可读性方面)的方法是什么.使用六个 catch 子句的 try 对我来说真的很像.

These three lines alone, potentially throw six exceptions and I'm not sure what's the cleanest (in terms of code readability) way to handle them. A try with six catch clauses really looks like a smell to me.

在处理此类对象时,是否有微模式或最佳实践,我显然缺少?

Are there micropatterns or best practices, I am obviously missing, when working with such objects?

编辑

对不起,我想我没有很好地解释自己.我的问题并不是要避免使用 trycatch 子句,而是是否有处理类似情况的通用方法.

Sorry, I think I didn't explain myself very well. My question is not really about avoiding a trycatch clause, but if there is a common way to handle similar situations.

加密例外是

NoSuchPaddingException, NoSuchAlgorithmException
InvalidAlgorithmParameterException, InvalidKeyException,
BadPaddingException, IllegalBlockSizeException

推荐答案

您指出以下例外情况:

NoSuchPaddingException, NoSuchAlgorithmException
InvalidAlgorithmParameterException, InvalidKeyException,
BadPaddingException, IllegalBlockSizeException

现在所有这些都是GeneralSecurityException 的,所以很容易抓住它们.但是从用例来看,您可能不想这样做.

Now all of these are GeneralSecurityException's, so it would be easy to catch them all. But looking at the use case, you probably don't want to do that.

如果您查看异常的原因,那么您会发现这些异常中的任何一个 - 除了最后两个 - 只有在生成算法或密钥的实现时才会抛出.我认为,一旦您测试了您的应用程序,这些值或多或少地保持静态是合理的.因此,抛出 - 例如 - IllegalStateException.IllegalStateException 是您不需要抛出(在方法签名中)或捕获的运行时异常.当然,您应该将安全异常列为异常的原因.

If you look at the cause of the exceptions then you will find that any of these exceptions - except for the last two - are only thrown when generating an implementation of an algorithm or a key. I think it is reasonable that once you have tested your application that these values remain more or less static. Hence it would be logical to throw - for instance - an IllegalStateException. IllegalStateException is a runtime exception which you are not required to throw (in the method signature) or catch. Of course, you should include the security exception as being the cause of the exception.

现在是最后两个异常,BadPaddingExceptionIllegalBlockSizeException 是不同的.它们依赖于实际的密文,因此它们依赖于算法的输入.现在通常您应该始终验证输入的完整性,然后再将其输入到 Cipher 实例,为解密而启动,例如通过首先验证 HMAC 校验和).所以从这个意义上说,你仍然可以逃脱运行时异常.如果您不执行单独的完整性检查,那么您应该不应该转换为 RuntimeException.相反,您可以让用户处理异常,或者将其作为特定于用例的异常重新抛出.

Now the last two exceptions, BadPaddingException and IllegalBlockSizeException are different. They depend on the actual ciphertext, so they are dependent on the input of the algorithm. Now normally you should always verify the integrity of the input before you feed it into your Cipher instance, initiated for decryption, for instance by first validating a HMAC checksum). So in that sense you could still get away with a runtime exception. If you don't perform a separate check for integrity then you should do should not convert to a RuntimeException. Instead you could either let the user handle the exception, or re-throw it as a use case specific exception.

如果您通过(重新)抛出它来处理BadPaddingException,那么应该了解纯文本oracle 攻击,例如填充oracle 攻击.对于 CBC 模式下的填充预言机攻击:如果对手可以尝试让您多次解密密文并收到解密失败(或失败)的指示,那么他们可以在不破解密码的情况下检索消息的明文.因此,在可以处理身份验证标签的 16 个额外字节的情况下,应首选身份验证模式,例如 GCM 模式.

If you handle the BadPaddingException by (re-)throwing it then should understand about plaintext oracle attacks such as padding oracle attacks. For padding oracle attacks in CBC mode: if an adversary can try and let you decrypt ciphertext multiple times and receive an indication that decryption failed (or not) then they can retrieve the plaintext of the message without breaking the cipher. For this reason an authenticated mode such as GCM mode should be preferred in situations that can handle the 16 additional bytes for the authentication tag.

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

It is probably best to use separate try/catch blocks for the construction and initialization of the Cipher and the decryption itself. You could also catch the exceptions BadPaddingException and IllegalBlockSizeException before handling the GeneralSecurityException. Starting with Java 7 you may use multi-catch statements as well (e.g. catch(final BadPaddingException | IllegalBlockSizeException e)).

最后一些注意事项:

  • BadPaddingException and IllegalBlockSizeException may be thrown by Cipher because of because the data was not completely received, or because of an attacker messing with the data;
  • BadPaddingException may also be thrown if the key is incorrect.
  • Beware that an exception may be thrown for AES key sizes 192 bit and 256 bit if the unlimited crypto files are not being installed (check the Oracle JavaSE site for more info); you should check if the key size is permitted when the application is started (this is mainly true for old / deprecated versions of Java);

这篇关于处理 Java 加密异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆