Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/376.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java RSA BadPaddingException_Java_Encryption_Cryptography_Rsa - Fatal编程技术网

Java RSA BadPaddingException

Java RSA BadPaddingException,java,encryption,cryptography,rsa,Java,Encryption,Cryptography,Rsa,我试图与客户机和服务器进行Diffie-Hellman密钥交换,但由于某种原因,当我解密发送到服务器的消息时。我得到以下例外情况: Unable to decrypt ciphertext. -> Decryption error javax.crypto.BadPaddingException: Decryption error at java.base/sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:378) a

我试图与客户机和服务器进行Diffie-Hellman密钥交换,但由于某种原因,当我解密发送到服务器的消息时。我得到以下例外情况:

Unable to decrypt ciphertext. -> Decryption error
javax.crypto.BadPaddingException: Decryption error
    at java.base/sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:378)
    at java.base/sun.security.rsa.RSAPadding.unpad(RSAPadding.java:290)
    at java.base/com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:359)
    at java.base/com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:392)
    at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2205)
    at server.Server.decrypt(Server.java:354)
    at server.Server.performDHKEX(Server.java:242)
    at server.Server.<init>(Server.java:145)
    at server.Driver.main(Driver.java:15)
服务器

private SecretKey performDHKEX()
    {      
        SecretKey sharedKey = null;
        
        try
        {
            KeyAgreement ecdhKex = KeyAgreement.getInstance("ECDH");
            KeyPairGenerator gen = KeyPairGenerator.getInstance("EC");
            KeyPair keyPair = gen.genKeyPair();
            
            byte[] recvMessage = (byte[]) inputStream.readObject();
            X509Certificate clientCert = (X509Certificate) inputStream
                    .readObject();
            
            // Decrypt the ciphertext.
            byte[] plainText = decrypt(recvMessage); // EXCEPTION THROWN HERE
             
            // If the signature and certificate verify, complete the KEX.
            if (verify(recvMessage, plainText, clientCert))
            {
                System.out.println("inside verify");
                // Send the Server's Public Value.
                byte[] sign = sign(keyPair.getPublic().getEncoded());
                byte[] cText = encrypt(keyPair.getPublic().getEncoded());  
                byte[][] sendArray = {cText, sign};
                outputStream.writeObject(sendArray);
                outputStream.writeObject(X509_CERTIFICATE);
                
                PublicKey pub = KeyFactory.getInstance("EC")
                        .generatePublic(new X509EncodedKeySpec(plainText));
                
                // Start the exchange with the server's Private Value and then
                // doPhase with the Client's public Value.
                ecdhKex.init(keyPair.getPrivate());
                ecdhKex.doPhase(pub, true);
                
                // Use the first 16 bytes of the generate secret for a key.
                sharedKey = new SecretKeySpec(Arrays.copyOfRange(ecdhKex
                        .generateSecret(), 0, 16), "AES");
            }
            
        } catch (IOException | ClassNotFoundException | IllegalStateException | 
                InvalidKeyException | NoSuchAlgorithmException | 
                InvalidKeySpecException ex)
        {
            System.err.println("Error during DH-KEX -> " + ex.getMessage());
        }
        
        System.out.println(Base64.getEncoder().encodeToString(sharedKey.getEncoded()));
        
        return sharedKey;
    }
加密

private SecretKey performDHKEX()
    {   
        SecretKey sharedKey = null;
        
        try
        {
            // Send a message telling the server to get ready for a DH-KEX.
            outputStream.writeObject("DO_DH_KEX");
            
            KeyAgreement ecdhKex = KeyAgreement.getInstance("ECDH");
            KeyPairGenerator gen = KeyPairGenerator.getInstance("EC");
            KeyPair keyPair = gen.genKeyPair();
            
            // Send the Client's Public Value.
            byte[] cText = encrypt(keyPair.getPublic().getEncoded());
            decrypt(encrypt(keyPair.getPublic().getEncoded()));
            byte[] sign = sign(keyPair.getPublic().getEncoded());
            outputStream.writeObject(cText);
            outputStream.writeObject(X509_CERTIFICATE);
            
            
            // Start the exchange with Private Key.
            ecdhKex.init(keyPair.getPrivate());
            
            /* Wait for the response from the Server, then decrypt and load the
            public value the Server sent. */
            byte[][] recvCipherText = (byte[][]) inputStream.readObject();  
            X509Certificate serverCert = (X509Certificate) inputStream
                    .readObject();
            byte[] plainText = decrypt(recvCipherText[0]);
            
            // If the signature verifies, build a keyspec from the public value.
            if (verify(recvCipherText[1], plainText, serverCert))
            {
                // Create a new PublicKey from the Server's Public Value.
                PublicKey pub = KeyFactory.getInstance("EC")
                        .generatePublic(new X509EncodedKeySpec(plainText));
               
                // Perform the last step of the KEX and create a new SecretKey.
                ecdhKex.doPhase(pub, true);
                
                // Use the first 16 bytes of the generate secret for a key.
                sharedKey = new SecretKeySpec(Arrays.copyOfRange(ecdhKex
                        .generateSecret(), 0, 16), "AES");
            }
            else
                System.err.println("Error verifying signature.");
            
        } catch (IOException | ClassNotFoundException | IllegalStateException | 
                InvalidKeyException | NoSuchAlgorithmException | 
                InvalidKeySpecException ex)
        {
            System.err.println("Error during DH-KEX -> " + ex.getMessage());
        }
        
        System.out.println(Base64.getEncoder().encodeToString(sharedKey.getEncoded()));
        return sharedKey;
    }

 private byte[] encrypt(byte[] message)
    {
        byte[] cipherText = null;
        
        try
        {
            rsaCipher.init(Cipher.ENCRYPT_MODE, PRIV_KEY);
            cipherText = rsaCipher.doFinal(message);
        } catch (InvalidKeyException | BadPaddingException | 
                IllegalBlockSizeException ex)
        {
            System.err.println("Error encrypting message. -> " + ex
                    .getMessage());
            ex.printStackTrace();
        }
        
        return cipherText;
    }
private byte[] decrypt(byte[] cipherText)
    {
        try
        {
            rsaCipher.init(Cipher.DECRYPT_MODE, PUB_KEY);
            return rsaCipher.doFinal(cipherText);
        } catch (InvalidKeyException | IllegalBlockSizeException | 
                BadPaddingException ex)
        {
            System.err.println("Unable to decrypt ciphertext. -> " + ex
                    .getMessage());
            ex.printStackTrace();
        }
        
        return null;
    }
解密

private SecretKey performDHKEX()
    {   
        SecretKey sharedKey = null;
        
        try
        {
            // Send a message telling the server to get ready for a DH-KEX.
            outputStream.writeObject("DO_DH_KEX");
            
            KeyAgreement ecdhKex = KeyAgreement.getInstance("ECDH");
            KeyPairGenerator gen = KeyPairGenerator.getInstance("EC");
            KeyPair keyPair = gen.genKeyPair();
            
            // Send the Client's Public Value.
            byte[] cText = encrypt(keyPair.getPublic().getEncoded());
            decrypt(encrypt(keyPair.getPublic().getEncoded()));
            byte[] sign = sign(keyPair.getPublic().getEncoded());
            outputStream.writeObject(cText);
            outputStream.writeObject(X509_CERTIFICATE);
            
            
            // Start the exchange with Private Key.
            ecdhKex.init(keyPair.getPrivate());
            
            /* Wait for the response from the Server, then decrypt and load the
            public value the Server sent. */
            byte[][] recvCipherText = (byte[][]) inputStream.readObject();  
            X509Certificate serverCert = (X509Certificate) inputStream
                    .readObject();
            byte[] plainText = decrypt(recvCipherText[0]);
            
            // If the signature verifies, build a keyspec from the public value.
            if (verify(recvCipherText[1], plainText, serverCert))
            {
                // Create a new PublicKey from the Server's Public Value.
                PublicKey pub = KeyFactory.getInstance("EC")
                        .generatePublic(new X509EncodedKeySpec(plainText));
               
                // Perform the last step of the KEX and create a new SecretKey.
                ecdhKex.doPhase(pub, true);
                
                // Use the first 16 bytes of the generate secret for a key.
                sharedKey = new SecretKeySpec(Arrays.copyOfRange(ecdhKex
                        .generateSecret(), 0, 16), "AES");
            }
            else
                System.err.println("Error verifying signature.");
            
        } catch (IOException | ClassNotFoundException | IllegalStateException | 
                InvalidKeyException | NoSuchAlgorithmException | 
                InvalidKeySpecException ex)
        {
            System.err.println("Error during DH-KEX -> " + ex.getMessage());
        }
        
        System.out.println(Base64.getEncoder().encodeToString(sharedKey.getEncoded()));
        return sharedKey;
    }

 private byte[] encrypt(byte[] message)
    {
        byte[] cipherText = null;
        
        try
        {
            rsaCipher.init(Cipher.ENCRYPT_MODE, PRIV_KEY);
            cipherText = rsaCipher.doFinal(message);
        } catch (InvalidKeyException | BadPaddingException | 
                IllegalBlockSizeException ex)
        {
            System.err.println("Error encrypting message. -> " + ex
                    .getMessage());
            ex.printStackTrace();
        }
        
        return cipherText;
    }
private byte[] decrypt(byte[] cipherText)
    {
        try
        {
            rsaCipher.init(Cipher.DECRYPT_MODE, PUB_KEY);
            return rsaCipher.doFinal(cipherText);
        } catch (InvalidKeyException | IllegalBlockSizeException | 
                BadPaddingException ex)
        {
            System.err.println("Unable to decrypt ciphertext. -> " + ex
                    .getMessage());
            ex.printStackTrace();
        }
        
        return null;
    }

为了澄清,RSA密码是RSA/ECB/PKCS1Padding,PRIV_KEY/PUB_KEY是从KeyTool生成的。当使用错误的密钥执行解密时,BadPadding异常是非常常见的故障模式

服务器必须使用客户端的公钥进行解码,同时使用自己的密钥进行编码

同样,客户端必须使用服务器的公钥进行解码,并使用自己的密钥进行编码


您执行的测试表明解码和编码使用的是本地公钥,而不是发送方的公钥。

客户端和服务器是否使用相同的RSA密钥对?您的
decrypt(encrypt(value))
测试显示解密和加密是使用一对匹配的密钥完成的。测试似乎是客户端使用客户端私钥加密,并使用客户端公钥解密。您确定服务器没有使用服务器的公钥解密吗?这就是问题所在!谢谢那我就把它作为答案,这样你就可以接受了。