javax.crypto.BadPaddingException:数据必须以零开头,客户端无法从服务器解密
运行代码时出现编译错误javax.crypto.BadPaddingException:数据必须以零开头,客户端无法从服务器解密,java,encryption,cryptography,rsa,public-key-encryption,Java,Encryption,Cryptography,Rsa,Public Key Encryption,运行代码时出现编译错误 Error: javax.crypto.BadPaddingException: Data must start with zero 在这一行testClient.java byte[] newPlainText = cipher.doFinal(cipherTextFromServer); 客户端无法解密从服务器加密的消息。 我的代码有错误吗 //TestServer.java public class TestServer { public static voi
Error: javax.crypto.BadPaddingException: Data must start with zero
在这一行testClient.java
byte[] newPlainText = cipher.doFinal(cipherTextFromServer);
客户端无法解密从服务器加密的消息。
我的代码有错误吗
//TestServer.java
public class TestServer {
public static void main(String[] args) throws Exception{
//set variables for port number, RSA key size
final int port = 3344;
final int RSAKeySize = 1024;
final String newline = "\n";
//set public key, sockets, server text, plain text
PublicKey pubKey = null;
PrivateKey priKey = null;
ServerSocket server = null;
Socket client = null;
String serverText = "Hello Client! This is an authentication message from server";
byte[] plainText = serverText.getBytes("UTF8");
//initialize RSA
try {
System.out.println("Start generating RSA key");
KeyPairGenerator RSAKeyGen = KeyPairGenerator.getInstance("RSA");
SecureRandom random = new SecureRandom();
RSAKeyGen.initialize(RSAKeySize,random);
KeyPair pair = RSAKeyGen.generateKeyPair();
System.out.println("Finish generating RSA key");
pubKey = pair.getPublic();
priKey = pair.getPrivate();
}catch (GeneralSecurityException e){
System.out.println(e.getLocalizedMessage() + newline);
System.out.println("Error initialising encryption. Exiting.\n");
System.exit(0);
}
//initialize cryptography, set cipherText
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
System.out.println("RSA cipher object and provider"+cipher.getProvider().getInfo());
System.out.println("Start Encryption for plainText");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
byte[] cipherText = cipher.doFinal(plainText);
System.out.println("Finish Encryption to cipherText: ");
BASE64Encoder base64 = new BASE64Encoder();
String encryptedValue = base64.encode(cipherText);
//String encryptedValue = new sun.misc.BASE64Encoder().encode(cipherText);
System.out.println(new String(cipherText,"UTF8"));
System.out.println("Base64");
System.out.println(encryptedValue);
//initialize socket connection
try{
server = new ServerSocket(port);
client = server.accept();
}catch(IOException e){
System.out.println("Error initialising I/O.\n");
System.exit(0);
}
//send server private key
try{
System.out.println("Send private key out");
System.out.println(DatatypeConverter.printHexBinary(priKey.getEncoded()));
ByteBuffer bb = ByteBuffer.allocate(4);
bb.putInt(priKey.getEncoded().length);
client.getOutputStream().write(bb.array());
client.getOutputStream().write(pubKey.getEncoded());
client.getOutputStream().flush();
}catch (IOException e){
System.out.println("I/O Error");
System.exit(0);
}
//send cipherText
ObjectOutputStream obOut = new ObjectOutputStream(client.getOutputStream());
obOut.writeObject(encryptedValue);
obOut.flush();
client.close();
}
}
//TestClient.java
public class TestClient {
public static void main(String[] args){
//throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, ClassNotFoundException,
//InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
//set variable for port, socket, server public key
final int port = 3344;
Socket sock = null;
Key serverPubKey = null;
final int RSAKeySize = 1024;
final String newline = "\n";
Key priKey = null;
//setup connection by creating socket
try{
sock = new Socket(InetAddress.getLocalHost(),port);
}catch(UnknownHostException e){
System.out.println("Unknown host.");
System.exit(1);
}catch(IOException e){
System.out.println("No I/O");
System.exit(1);
}
//get public key from server
try{
byte[] lenb = new byte[4];
sock.getInputStream().read(lenb,0,4);
ByteBuffer bb = ByteBuffer.wrap(lenb);
int len = bb.getInt();
System.out.println(len);
byte[] servPubKeyBytes = new byte[len];
sock.getInputStream().read(servPubKeyBytes);
System.out.println(DatatypeConverter.printHexBinary(servPubKeyBytes));
X509EncodedKeySpec ks = new X509EncodedKeySpec(servPubKeyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
serverPubKey = kf.generatePublic(ks);
System.out.println(DatatypeConverter.printHexBinary(serverPubKey.getEncoded()));
//PrivateKey privateKey = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(privateKeyBytes));
}catch (IOException e) {
System.out.println("Error obtaining server public key 1.");
System.exit(0);
} catch (NoSuchAlgorithmException e) {
System.out.println("Error obtaining server public key 2.");
System.exit(0);
} catch (InvalidKeySpecException e) {
System.out.println("Error obtaining server public key 3.");
System.exit(0);
}
try {
System.out.println("Start generating RSA key");
KeyPairGenerator RSAKeyGen = KeyPairGenerator.getInstance("RSA");
SecureRandom random = new SecureRandom();
RSAKeyGen.initialize(RSAKeySize, random);
KeyPair pair = RSAKeyGen.generateKeyPair();
System.out.println("Finish generating RSA key");
priKey = pair.getPrivate();
}catch (GeneralSecurityException e){
System.out.println(e.getLocalizedMessage() + newline);
System.out.println("Error initialising encryption. Exiting.\n");
System.exit(0);
}
try{
//Decrypt message from server
BufferedReader in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
String message = in.readLine();
//ObjectInputStream obIn = new ObjectInputStream(sock.getInputStream());
//Object obj = obIn.readObject();
System.out.println(message);
byte[] cipherTextFromServer = new BASE64Decoder().decodeBuffer(message);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
System.out.println("Start decryption");
cipher.init(Cipher.DECRYPT_MODE, priKey);
byte[] newPlainText = cipher.doFinal(cipherTextFromServer);
System.out.println("Finish decryption: ");
System.out.println(new String(newPlainText,"UTF8"));
sock.close();
}catch(Exception e){
e.printStackTrace();
}
}
}您的代码看起来完全崩溃了。使用服务器上生成的公钥加密数据,然后使用客户端上生成的私钥解密数据。这是行不通的,因为密钥对不匹配 为了进一步混淆问题,您似乎尝试在服务器和客户端之间发送密钥,但这看起来也坏了,例如
ByteBuffer bb = ByteBuffer.allocate(4);
bb.putInt(priKey.getEncoded().length);
client.getOutputStream().write(bb.array());
client.getOutputStream().write(pubKey.getEncoded()); // pubKey?!!
你应该彻底重新考虑你的设计。私钥通常不会集中生成并向外分发。相反,请考虑让客户端生成密钥对并将其公钥发送到服务器,服务器可以使用它来加密数据。 您的代码看起来完全被破坏了。使用服务器上生成的公钥加密数据,然后使用客户端上生成的私钥解密数据。这是行不通的,因为密钥对不匹配 为了进一步混淆问题,您似乎尝试在服务器和客户端之间发送密钥,但这看起来也坏了,例如
ByteBuffer bb = ByteBuffer.allocate(4);
bb.putInt(priKey.getEncoded().length);
client.getOutputStream().write(bb.array());
client.getOutputStream().write(pubKey.getEncoded()); // pubKey?!!
你应该彻底重新考虑你的设计。私钥通常不会集中生成并向外分发。相反,请考虑让客户端生成密钥对并将其公钥发送到服务器,服务器可以使用它来加密数据。 您忽略了<>代码>返回流(读)(< /代码>方法> < /p>的返回值。 您正在使用
ObjectOutputStream
在服务器端写入编码值,并使用InputStreamReader
在客户端读取编码值
最终的结果是servPubKeyBytes
和cipherTextFromServer
包含一些垃圾,当您将它们传递到密码中时,它会意外中断
首先,通过测试客户端是否正确读取所有数据来修复I/O代码
其次,检查加密和解密代码是否工作,方法是在同一应用程序中使用它,而不使用任何类型的I/O
第三,将工作I/O与工作enc/dec代码结合起来。您忽略了
InputStream.read()
方法的返回值
您正在使用ObjectOutputStream
在服务器端写入编码值,并使用InputStreamReader
在客户端读取编码值
最终的结果是servPubKeyBytes
和cipherTextFromServer
包含一些垃圾,当您将它们传递到密码中时,它会意外中断
首先,通过测试客户端是否正确读取所有数据来修复I/O代码
其次,检查加密和解密代码是否工作,方法是在同一应用程序中使用它,而不使用任何类型的I/O
<P>第三,将工作I/O与工作EnC/DEC代码结合。 CiffTraveServer为NULL/VALUE。你需要建立关于公钥的信任(例如使用PKI)。但是注意,只发送公钥容易受到中间人攻击;您还需要建立与公钥相关的信任(例如,通过使用PKI)。