使用 RSA 接收解密错误
Recieving Error from decryption with RSA
我在做一个小学校"project",就是一个聊天的小程序。您启动服务器,服务器向客户端发送一个 public 密钥,以便客户端可以发回加密数据。
问题是当我尝试在服务器端解密时收到错误消息。
javax.crypto.BadPaddingException: Decryption error
at sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:380)
at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:291)
我的服务器等待 socket.accept()
,当客户端连接时,它会向此套接字发送一个 public 密钥。
(这不是全部代码)
private Client client;
private JSONObject json;
//Connector is used as a listener for messages.
public Connector(Socket socket, ServerBroadCast SBC) throws IOException {
DIS = new DataInputStream(socket.getInputStream());
this.SBC = SBC;
this.client = SBC.AddClient(socket);
//Sending public RSA key to client to use to encrypt their message
this.client.sendPublicKey(RSA.getPublicKey()); //This is where I am sending RSA public key to client
}
我只是将一条消息发回服务器,看看它是否加密以及服务器是否可以解密。
使用这个class发送给客户
DataOutputStream DOS;
public Client(Socket s) throws IOException {
DOS = new DataOutputStream(s.getOutputStream());
}
public void sendPublicKey(PublicKey publicKey) throws IOException {
JSONObject json = new JSONObject();
json.put(JSONKeys.TYPE, JSONTypes.PUBLIC_KEY);
json.put(JSONKeys.MESSAGE, RSA.getEncodedPublicKey());
this.send(json);
}
public void send(JSONObject json) throws IOException{
this.DOS.writeUTF(json.toString());
System.out.println(json);
}
这是我的 RSA class 加密和解密
private static PrivateKey privateKey = null;
private static PublicKey publicKey = null;
public static void generateKeyPair() {
KeyPairGenerator keyPairGenerator = null;
KeyPair keyPair = null;
try {
keyPairGenerator = KeyPairGenerator.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
keyPairGenerator.initialize(1024);
keyPair = keyPairGenerator.generateKeyPair();
RSA.privateKey = keyPair.getPrivate();
RSA.publicKey = keyPair.getPublic();
}
public static String getEncodedPublicKey() {
return (new String(Base64.encode(RSA.getPublicKey().getEncoded())));
}
public static String encrypt(String string) {
byte[] encrypted = null;
try {
Cipher cipher = Cipher.getInstance("RSA");//174 bytes
cipher.init(Cipher.ENCRYPT_MODE, RSA.getPublicKey());
encrypted = cipher.doFinal(string.getBytes());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return (new String(Base64.encode(encrypted)));
}
public static String decrypt(String string) {
byte[] decrypted = null;
try {
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, RSA.getPrivateKey());
decrypted = cipher.doFinal(Base64.decode(string));
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (Base64DecodingException e) {
e.printStackTrace();
}
return (new String(decrypted));
}
我知道我的填充有一些东西 "wrong" 因为错误是这样说的,但我不明白是什么。
我从客户端得到的加密信息长度是174字节。我知道它太长了,但为什么它会从我的纯文本中创建这么大的加密消息。
private final String MESSAGE = "Hello from client side";
您似乎有两个问题需要回答:
a) public 密钥在客户端是否正确?
b) 服务器端的密文是否正确?
尝试分别回答问题。例如,您可以尝试:
在服务器上获取 public 密钥,并加密消息 "hello world"。然后在服务器上获取私钥,并解密消息。有用吗?那么...
从#1中取出密文并在客户端进行硬编码,这样无论服务器向客户端发送什么,客户端都会发送这个已知是正确的密文,回到服务器。现在,服务器是否再次解密?
如果服务器解密正常,那么你可以:
从服务器获取 public 密钥并加密一些数据(在客户端)。现在,在客户端使用私钥解密数据。它解密了吗?
好了,现在将密文发送到服务器并解密。
限制每一步的未知数。服务器能否真正解密正确的密文(也许由于某些错误而不能)?客户端真的能收到正确的 public 密钥吗?客户端能否发送正确的密文?
我在做一个小学校"project",就是一个聊天的小程序。您启动服务器,服务器向客户端发送一个 public 密钥,以便客户端可以发回加密数据。
问题是当我尝试在服务器端解密时收到错误消息。
javax.crypto.BadPaddingException: Decryption error
at sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:380)
at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:291)
我的服务器等待 socket.accept()
,当客户端连接时,它会向此套接字发送一个 public 密钥。
(这不是全部代码)
private Client client;
private JSONObject json;
//Connector is used as a listener for messages.
public Connector(Socket socket, ServerBroadCast SBC) throws IOException {
DIS = new DataInputStream(socket.getInputStream());
this.SBC = SBC;
this.client = SBC.AddClient(socket);
//Sending public RSA key to client to use to encrypt their message
this.client.sendPublicKey(RSA.getPublicKey()); //This is where I am sending RSA public key to client
}
我只是将一条消息发回服务器,看看它是否加密以及服务器是否可以解密。
使用这个class发送给客户
DataOutputStream DOS;
public Client(Socket s) throws IOException {
DOS = new DataOutputStream(s.getOutputStream());
}
public void sendPublicKey(PublicKey publicKey) throws IOException {
JSONObject json = new JSONObject();
json.put(JSONKeys.TYPE, JSONTypes.PUBLIC_KEY);
json.put(JSONKeys.MESSAGE, RSA.getEncodedPublicKey());
this.send(json);
}
public void send(JSONObject json) throws IOException{
this.DOS.writeUTF(json.toString());
System.out.println(json);
}
这是我的 RSA class 加密和解密
private static PrivateKey privateKey = null;
private static PublicKey publicKey = null;
public static void generateKeyPair() {
KeyPairGenerator keyPairGenerator = null;
KeyPair keyPair = null;
try {
keyPairGenerator = KeyPairGenerator.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
keyPairGenerator.initialize(1024);
keyPair = keyPairGenerator.generateKeyPair();
RSA.privateKey = keyPair.getPrivate();
RSA.publicKey = keyPair.getPublic();
}
public static String getEncodedPublicKey() {
return (new String(Base64.encode(RSA.getPublicKey().getEncoded())));
}
public static String encrypt(String string) {
byte[] encrypted = null;
try {
Cipher cipher = Cipher.getInstance("RSA");//174 bytes
cipher.init(Cipher.ENCRYPT_MODE, RSA.getPublicKey());
encrypted = cipher.doFinal(string.getBytes());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return (new String(Base64.encode(encrypted)));
}
public static String decrypt(String string) {
byte[] decrypted = null;
try {
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, RSA.getPrivateKey());
decrypted = cipher.doFinal(Base64.decode(string));
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (Base64DecodingException e) {
e.printStackTrace();
}
return (new String(decrypted));
}
我知道我的填充有一些东西 "wrong" 因为错误是这样说的,但我不明白是什么。
我从客户端得到的加密信息长度是174字节。我知道它太长了,但为什么它会从我的纯文本中创建这么大的加密消息。
private final String MESSAGE = "Hello from client side";
您似乎有两个问题需要回答:
a) public 密钥在客户端是否正确?
b) 服务器端的密文是否正确?
尝试分别回答问题。例如,您可以尝试:
在服务器上获取 public 密钥,并加密消息 "hello world"。然后在服务器上获取私钥,并解密消息。有用吗?那么...
从#1中取出密文并在客户端进行硬编码,这样无论服务器向客户端发送什么,客户端都会发送这个已知是正确的密文,回到服务器。现在,服务器是否再次解密?
如果服务器解密正常,那么你可以:
从服务器获取 public 密钥并加密一些数据(在客户端)。现在,在客户端使用私钥解密数据。它解密了吗?
好了,现在将密文发送到服务器并解密。
限制每一步的未知数。服务器能否真正解密正确的密文(也许由于某些错误而不能)?客户端真的能收到正确的 public 密钥吗?客户端能否发送正确的密文?