演示使用RSA公钥系统来交换实现机密性和完整性/认证的消息 [英] Demonstrate the use of RSA Public-key system to exchange messages that achieve confidentiality and integrity/authentication
问题描述
我试图演示使用RSA公钥系统来交换实现机密性和完整性/认证的消息。我试图加密在客户端的消息,并发送此信息到服务器端进行解密。我遇到的问题是我的代码不解密。它给我以下错误:
javax.crypto.BadPaddingException:数据必须以零开始
。 security.rsa.RSAPadding.unpadV15(RSAPadding.java:308)
at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:255)
at com.sun.crypto.provider.RSACipher。 a(DashoA13 * ..)
at com.sun.crypto.provider.RSACipher.engineDoFinal(DashoA13 * ..)
at javax.crypto.Cipher.doFinal(DashoA13 * ..)
在PKServer.decryptMessage(PKServer.java:36)
在PKServer.main(PKServer.java:69)
公钥客户端代码:
import java.io. *;
import java.net。*;
import java.security。*;
import javax.crypto。*;
public class PKClient
{
public static final int kBufferSize = 8192;
public static void main(String [] args)throws Exception
{
try {
//生成新密钥
KeyPair keyPair = KeyPairGenerator.getInstance(RSA)。generateKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
String message =快速的棕色狐狸跳过懒惰的狗。
//计算签名
签名实例= Signature.getInstance(SHA1withRSA);
instance.initSign(privateKey);
instance.update((message).getBytes());
byte [] signature = instance.sign();
//计算摘要
MessageDigest sha1 = MessageDigest.getInstance(SHA1);
byte [] digest = sha1.digest((message).getBytes());
//加密摘要
加密密码= Cipher.getInstance(RSA / ECB / PKCS1Padding);
cipher.init(Cipher.ENCRYPT_MODE,privateKey);
byte [] encryptedMsg = cipher.doFinal(digest);
//将密钥存储在文件中
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(KeyFile.xx));
out.writeObject(privateKey);
out.close();
System.out.println(Client - Message:+ message);
System.out.println(Client - Encrypted:+ PKServer.asHex(encryptedMsg));
String host =localhost;
int port = 7999;
Socket s = new Socket(host,port);
//打开流到密码服务器
DataOutputStream os = new DataOutputStream(s.getOutputStream());
os.writeInt(encryptedMsg.length);
os.write(encryptedMsg);
os.writeInt(digest.length);
os.write(digest);
os.writeInt(signature.length);
os.write(signature);
os.flush();
os.close();
//关闭套接字
s.close();
} catch(Exception e){
e.printStackTrace();
}
}
}
公用密钥服务器代码:
import java.io. *;
import java.net。*;
import java.security。*;
import javax.crypto。*;
public class PKServer
{
public void decryptMessage(InputStream inStream)throws IOException,NoSuchAlgorithmException
{
try {
//从套接字创建数据输入流
DataInputStream dis = new DataInputStream(inStream);
//获取密钥
ObjectInputStream in = new ObjectInputStream(new FileInputStream(KeyFile.xx));
// ObjectOutputStream outSocket = new ObjectOutputStream(s.getOutputStream());
PrivateKey privatekey =(PrivateKey)in.readObject();
System.out.println(Key Used:+ in.toString());
in.close();
//启动密码
Cipher cipher = Cipher.getInstance(RSA / ECB / PKCS1Padding);
cipher.init(Cipher.DECRYPT_MODE,privatekey);
int len = dis.readInt();
byte [] encryptedMsg = new byte [len];
dis.readFully(encryptedMsg);
System.out.println(Server - Msg Length:+ len);
System.out.println(Server - Encrypted:+ asHex(encryptedMsg));
// - 打印解密字符串以查看它是否与原始消息匹配。
byte [] plainText = cipher.doFinal(encryptedMsg);
System.out.println(Decrypted Message:+ new String(plainText,SHA));
} catch(Exception e){
e.printStackTrace();
}
}
//使字节可打印的函数(十六进制格式)
public static String asHex(byte buf []){
StringBuilder strbuf = new StringBuilder(buf.length * 2);
int i;
for(i = 0; i if((int)buf [i]& 0xff)<0x10){
strbuf.append (0);
}
strbuf.append(Long.toString((int)buf [i]& 0xff,16));
}
return strbuf.toString();
}
public static void main(String [] args)throws Exception
{
int port = 7999;
ServerSocket server = new ServerSocket(port);
Socket s = server.accept();
PKServer cs = new PKServer();
cs.decryptMessage(s.getInputStream());
server.close();
}
}
这是我在服务器端收到的输出:
使用的密钥:java.io.ObjectInputStream@fee4648
服务器 - 消息长度:128
服务器 - 加密:8c23b2cd96c07950f4901a670b025531b5f52be0730e4548c9a76090d7ae65a8ce82901c66acfb6bd79520cf8d86bf74bf3105fd638892a681a6905556cbadf394915fbdc09babb5b78b9dd06382e92604e9ca88901613520ccb45fcc376e813df059ebc649c52f233dc2632733d99212b42ce54e59ebd6d9dca98af36a20fc6
javax.crypto.BadPaddingException:数据必须开始与sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:308)
零
。在sun.security.rsa。 RSAPadding.unpad(RSAPadding.java:255)
at com.sun.crypto.provider.RSACipher.a(DashoA13 * ..)
at com.sun.crypto.provider.RSACipher.engineDoFinal(DashoA13 * ..)
at PKCS.m.m(PKServer.java:PKServer.java)上的
在PKServer.main(PKServer.java:36) 69)
我注意到如果我调整行:
Cipher cipher = Cipher.getInstance(RSA / ECB / PKCS1Padding);
到
Cipher cipher = Cipher.getInstance(RSA / ECB / NoPadding);
程序会解密,但不会解密到预期的字符串。它看起来像这样:
解密消息:E ???。1G?:*?$ ?? | α
pre>
VO)Zjap6 - △T * ?:?(?C?,??'??`(?2D?mC?OLc <7???????
请让我知道,如果你能看到我在这个代码错误。
解决方案您需要使用 PKClient 中的公钥对您的摘要进行加密:
KeyPair keyPair = KeyPairGenerator.getInstance(RSA)。generateKeyPair();
Key pubKey = keyPair.getPublic(); //添加这个
PrivateKey privateKey = keyPair.getPrivate();
//几行之后...
//启动密码
cipher.init(Cipher.ENCRYPT_MODE,pubKey); //将privateKey更改为pubKey
I'm trying to demonstrate the use of RSA Public-key system to exchange messages that achieve confidentiality and integrity/authentication. I am trying to encrypt a message on the client side and send this information to the server side to decrypt. The issue I am having is that my code is not decrypting. It is giving me the following error:
javax.crypto.BadPaddingException: Data must start with zero at sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:308) at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:255) at com.sun.crypto.provider.RSACipher.a(DashoA13*..) at com.sun.crypto.provider.RSACipher.engineDoFinal(DashoA13*..) at javax.crypto.Cipher.doFinal(DashoA13*..) at PKServer.decryptMessage(PKServer.java:36) at PKServer.main(PKServer.java:69)
Public-Key Client code:
import java.io.*; import java.net.*; import java.security.*; import javax.crypto.*; public class PKClient { public static final int kBufferSize = 8192; public static void main(String[] args) throws Exception { try { // Generate new key KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair(); PrivateKey privateKey = keyPair.getPrivate(); String message = "The quick brown fox jumps over the lazy dog."; // Compute signature Signature instance = Signature.getInstance("SHA1withRSA"); instance.initSign(privateKey); instance.update((message).getBytes()); byte[] signature = instance.sign(); // Compute digest MessageDigest sha1 = MessageDigest.getInstance("SHA1"); byte[] digest = sha1.digest((message).getBytes()); // Encrypt digest Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.ENCRYPT_MODE, privateKey); byte[] encryptedMsg = cipher.doFinal(digest); //Store the key in a file ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("KeyFile.xx")); out.writeObject(privateKey); out.close(); System.out.println("Client - Message: " + message); System.out.println("Client - Encrypted: " + PKServer.asHex(encryptedMsg)); String host = "localhost"; int port = 7999; Socket s = new Socket(host, port); //Open stream to cipher server DataOutputStream os = new DataOutputStream(s.getOutputStream()); os.writeInt(encryptedMsg.length); os.write(encryptedMsg); os.writeInt(digest.length); os.write(digest); os.writeInt(signature.length); os.write(signature); os.flush(); os.close(); //Close socket s.close(); }catch (Exception e) { e.printStackTrace(); } } }
Public-key Server code:
import java.io.*; import java.net.*; import java.security.*; import javax.crypto.*; public class PKServer { public void decryptMessage(InputStream inStream) throws IOException, NoSuchAlgorithmException { try { //Create the Data input stream from the socket DataInputStream dis = new DataInputStream(inStream); //Get the key ObjectInputStream in = new ObjectInputStream(new FileInputStream("KeyFile.xx")); //ObjectOutputStream outSocket = new ObjectOutputStream(s.getOutputStream()); PrivateKey privatekey = (PrivateKey) in.readObject(); System.out.println("Key Used: " + in.toString()); in.close(); //Initiate the cipher Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.DECRYPT_MODE,privatekey); int len = dis.readInt(); byte[] encryptedMsg = new byte[len]; dis.readFully(encryptedMsg); System.out.println("Server - Msg Length: " + len); System.out.println("Server - Encrypted: " + asHex(encryptedMsg)); // -Print out the decrypt String to see if it matches the original message. byte[] plainText = cipher.doFinal(encryptedMsg); System.out.println("Decrypted Message: " + new String(plainText, "SHA")); } catch (Exception e) { e.printStackTrace(); } } //Function to make the bytes printable (hex format) public static String asHex(byte buf[]) { StringBuilder strbuf = new StringBuilder(buf.length * 2); int i; for (i = 0; i < buf.length; i++) { if (((int) buf[i] & 0xff) < 0x10) { strbuf.append("0"); } strbuf.append(Long.toString((int) buf[i] & 0xff, 16)); } return strbuf.toString(); } public static void main(String[] args) throws Exception { int port = 7999; ServerSocket server = new ServerSocket(port); Socket s = server.accept(); PKServer cs = new PKServer(); cs.decryptMessage(s.getInputStream()); server.close(); } }
Here is the output I receive on the server side:
Key Used: java.io.ObjectInputStream@fee4648 Server - Msg Length: 128 Server - Encrypted: 8c23b2cd96c07950f4901a670b025531b5f52be0730e4548c9a76090d7ae65a8ce82901c66acfb6bd79520cf8d86bf74bf3105fd638892a681a6905556cbadf394915fbdc09babb5b78b9dd06382e92604e9ca88901613520ccb45fcc376e813df059ebc649c52f233dc2632733d99212b42ce54e59ebd6d9dca98af36a20fc6 javax.crypto.BadPaddingException: Data must start with zero at sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:308) at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:255) at com.sun.crypto.provider.RSACipher.a(DashoA13*..) at com.sun.crypto.provider.RSACipher.engineDoFinal(DashoA13*..) at javax.crypto.Cipher.doFinal(DashoA13*..) at PKServer.decryptMessage(PKServer.java:36) at PKServer.main(PKServer.java:69)
I have noticed that if I adjust the line:
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
to
Cipher cipher = Cipher.getInstance("RSA/ECB/NoPadding");
The program does decrypt but it does not decrypt to the intended string. It looks like this:
Decrypted Message: E???.1G?:*?$??|o\?"? V????????O)Z?j??a?!p)6??????_??T*?c?6O????????:?(??C?,??'??`??????(?2D?mC?OLc<7?'?S?R?
Please let me know if you can see where I am going wrong with this code.
解决方案You need to encrypt your digest with public key in PKClient:
KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair(); Key pubKey = keyPair.getPublic(); // add this PrivateKey privateKey = keyPair.getPrivate(); // several lines later... // Initiate the cipher cipher.init(Cipher.ENCRYPT_MODE, pubKey); // change privateKey to pubKey
这篇关于演示使用RSA公钥系统来交换实现机密性和完整性/认证的消息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!