Zademonstruj wykorzystanie systemu RSA Public-key do wymiany wiadomości, które zapewniają poufność i integralność / uwierzytelnianie

Próbuję zademonstrować wykorzystanie systemu RSA Public-key do wymiany wiadomości, które zapewniają poufność i integralność / uwierzytelnianie. Próbuję zaszyfrować wiadomość po stronie klienta i wysłać te informacje po stronie serwera, aby je odszyfrować. Problem polega na tym, że mój kod nie odszyfrowuje. Daje mi następujący błąd:

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)

Kod klienta klucza publicznego:

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();
        }
    }
}

Kod klucza publicznego:

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();
    }
}

Oto dane wyjściowe, które otrzymuję po stronie serwera:

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)

Zauważyłem, że jeśli dostosuję linię:

Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");

do

Cipher cipher = Cipher.getInstance("RSA/ECB/NoPadding");

Program odszyfrowuje, ale nie odszyfrowuje do zamierzonego ciągu. To wygląda tak:

Decrypted Message: E???.1G?:*?$??|o\?"?
V????????O)Z?j??a?!p)6??????_??T*?c?6O????????:?(??C?,??'??`??????(?2D?mC?OLc<7?'?S?R?

Daj mi znać, jeśli możesz zobaczyć, gdzie się mylę z tym kodem.

questionAnswers(2)

yourAnswerToTheQuestion