Java 如果密码编码失败,重试也将失败

Java 如果密码编码失败,重试也将失败,java,encryption,cryptography,rsa,Java,Encryption,Cryptography,Rsa,假设您有一些字符串要用公钥加密,然后再解密,它们彼此不相关。但是其中一个没有达到标准(它比密钥位长度可以处理的长度长),您希望抛出一个错误并继续解码其他错误 嗯,问题是如果抛出数据长度不能超过x字节的异常,那么下一个异常也将失败 为什么会发生这种情况?我如何防止这种情况发生 我制作了一个自我解释的代码,可以用来重现错误: Cipher encrypter; Cipher decrypter; Key pubKey; Key privKey;

假设您有一些字符串要用公钥加密,然后再解密,它们彼此不相关。但是其中一个没有达到标准(它比密钥位长度可以处理的长度长),您希望抛出一个错误并继续解码其他错误

嗯,问题是如果抛出
数据长度不能超过x字节的异常,那么下一个异常也将失败

为什么会发生这种情况?我如何防止这种情况发生

我制作了一个自我解释的代码,可以用来重现错误:

Cipher encrypter;
        Cipher decrypter;

        Key pubKey;
        Key privKey;

        KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");

        kpg.initialize(1024);
        KeyPair kp = kpg.generateKeyPair();

        pubKey = kp.getPublic();
        privKey = kp.getPrivate();

        encrypter = Cipher.getInstance("RSA");
        encrypter.init(Cipher.ENCRYPT_MODE, pubKey);

        decrypter = Cipher.getInstance("RSA");
        decrypter.init(Cipher.DECRYPT_MODE, privKey);

        byte[] encryptedData;
        byte[] decryptedData;


        System.out.println("Starting short test 1");
        encryptedData = encrypter.doFinal("SHORT TEST 1".getBytes());
        decryptedData = decrypter.doFinal(encryptedData);
        System.out.println(new String(decryptedData)); //SHORT TEST

        System.out.println("Starting short test 2");
        encryptedData = encrypter.doFinal("SHORT TEST 2".getBytes());
        decryptedData = decrypter.doFinal(encryptedData);
        System.out.println(new String(decryptedData)); //SHORT TEST 2

        System.out.println("Starting short test 3");
        encryptedData = encrypter.doFinal("SHORT TEST 3".getBytes());
        decryptedData = decrypter.doFinal(encryptedData);
        System.out.println(new String(decryptedData)); //SHORT TEST 3

        try {

            encryptedData = encrypter.doFinal(("LONG TEST LONG TEST LONG TEST LONG TEST LONG TEST LONG TEST" +
                    " LONG TEST LONG TEST LONG TEST LONG TEST LONG TEST LONG TEST LONG TEST LONG TEST LONG TEST" +
                    " LONG TEST LONG TEST LONG TEST LONG TEST LONG TEST LONG TEST LONG TEST LONG TEST LONG TEST ").getBytes());
            decryptedData = decrypter.doFinal(encryptedData);
            System.out.println(new String(decryptedData)); // IT DOESN'T REACH HERE, WHICH IS OK

        } catch (IllegalBlockSizeException e){
            System.out.println(e.toString());  // Data must not be longer than 117 bytes (OK, fair enough, my bad)
        }

        System.out.println("Starting short test 4");
        encryptedData = encrypter.doFinal("SHORT TEST 4".getBytes());
        decryptedData = decrypter.doFinal(encryptedData);
        System.out.println(new String(decryptedData)); // THROWS THE SAME EXCEPTION THAN IN PREVIOUS TEST
控制台打印:

Starting short test 1
SHORT TEST 1
Starting short test 2
SHORT TEST 2
Starting short test 3
SHORT TEST 3
javax.crypto.IllegalBlockSizeException: Data must not be longer than 117 bytes
Starting short test 4
Exception in thread "main" javax.crypto.IllegalBlockSizeException: Data must not be longer than 117 bytes
    at java.base/com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:347)
    at java.base/com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:392)
    at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2202)
    at main.main(main.java:66)
:

注意:如果引发任何异常,则可能需要删除此密码对象 在重新使用之前重置

因为没有<代码> Reale>代码>方法,我想你必须再次调用它<代码> init >代码。

当然是好的,但是有一些事情要考虑。
应尽可能避免异常(在发布的代码中)。重新加密相同的消息将无法工作,因为您将获得相同的异常,因此对于该特定消息,您将没有选择。如果使用混合加密(下一点),则可以轻松避免此问题


RSA不是用来传输大量数据的。了解如何结合AES/GCM和RSA/OAEP创建一个能够高效加密/解密任意数量数据的混合密码系统


Cipher
类的实例通常是轻量级的。它们实例化和初始化的成本相对较低,并且不携带太多的状态。因此,简单地生成一个新实例比重用一个旧实例更不容易出错

例如,这意味着您应该在类的字段中存储密钥,而不是
密码
实例本身。由于密钥是不可变的,这意味着无论
密码
实例发生什么情况,类的状态都保持有效


关于代码/密码: 这不再被认为是一个足够好的键大小。试试3072或更高。或者选择椭圆曲线密码(ECC)

永远不要忘记指定full算法,不要使用默认值。上面使用了
“RSA/ECB/pkcs1p添加”
,但应该首选OAEP(但开销更大)



String.getBytes()
新字符串(byte[])
:始终从
StandardCharsets
中指定字符集,除非您绑定到平台默认编码(以及其他平台上的后续解码错误)。

大多数内容都包含在我的原始代码中,但为了简洁起见跳过。例如,我使用自己的密钥,而不是生成它们。不管怎样,我很感激。“例外永远不会好的,你不应该在测试之外遇到它们。”对不起,但我不能同意。异常确实发生在非常好的代码中,并且确实(并且将会)发生在测试之外。这可能是硬件问题。这可能是一个网络问题。在任何情况下,异常都是完全正常的,如果可能的话,您的代码应该能够正常地从中恢复。例外不是你的敌人,他们是你的朋友。好吧,我把它改写了一点,也许这被夸大了。我现在已经写过,应该尽可能避免它们。老实说,作为我的朋友,我在运行时没有看到异常。我从来没有想过,哦,酷,除了故障排除之外,还有一个例外。现在异常机制。。。我是一个超级粉丝(尽管我并不总是喜欢检查异常,尤其是w.r.t Java
Cipher
)。甚至不会使用没有它的语言。是的,我指的当然是机制:)
kpg.initialize(1024);
encrypter = Cipher.getInstance("RSA");