在套接字错误上接收Diffie-Hellman密钥

时间:2016-04-01 01:50:30

标签: java sockets encryption cryptography diffie-hellman

我一直在做很多研究,但找不到解决这个问题的方法。我已经花了好几个小时,我无法理解,所以我希望有人比我更有经验,可以提供帮助。这个程序可能不是最佳实践,但它适用于作业。

我正在使用RSA传输公钥,但更重要的是,我正在尝试将Bob(服务器)的Diffie Hellman参数传输到Alice(客户端)。运行程序时出现以下错误:

  

线程“main”中的异常java.security.spec.InvalidKeySpecException:   不恰当的密钥规范   com.sun.crypto.provider.DHKeyFactory.engineGeneratePublic(DHKeyFactory.java:85)     在java.security.KeyFactory.generatePublic(KeyFactory.java:334)at   client.Client.main(Client.java:114)引起:   java.security.InvalidKeyException:解析密钥编码时出错   com.sun.crypto.provider.DHPublicKey。(DHPublicKey.java:178)at at   com.sun.crypto.provider.DHKeyFactory.engineGeneratePublic(DHKeyFactory.java:78)     ... 2更多引起:java.io.IOException:   DerInputStream.getLength():lengthTag = 127,太大了。在   sun.security.util.DerInputStream.getLength(DerInputStream.java:561)     在sun.security.util.DerValue.init(DerValue.java:365)at   sun.security.util.DerValue。(DerValue.java:320)at   com.sun.crypto.provider.DHPublicKey。(DHPublicKey.java:125)...   还有3个

这是代码: Client.java:

package client;
import java.io.*;
import java.security.*;
import javax.crypto.*;
import java.util.*;
import java.net.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import javax.crypto.spec.DHParameterSpec;
import java.security.spec.*;


class Client{
    private static PublicKey publicKey = null;
    private static PrivateKey privateKey = null;
    private static PublicKey rsaBobPub = null;
    private static SecretKey SecretSharedKeyCipher = null;
    private static SecretKey SecretSharedKeyIntgSend = null;
    private static SecretKey SecretSharedKeyIntRecv = null; 
    private static KeyAgreement aKeyAgreement = null;


    public static void main(String args[]) throws ClassNotFoundException, `IOException, NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, InvalidParameterSpecException, InvalidKeySpecException{`
        Client client = new Client();
        KeyPairGenerator keyGen;
        byte[] alicePub;
        Cipher cipher2;
        byte[] encryptedDH = null;  
        byte[] bobEncryptedDH = null;
        OutputStream dh;
        InputStream bobDHConn;

            Socket connection = new Socket("localhost", 4129);

            //Generate Keys & then send to Bob
                keyGen = KeyPairGenerator.getInstance("RSA");
                keyGen.initialize(2048);
                KeyPair keyPair = keyGen.genKeyPair();
                publicKey = keyPair.getPublic();
                privateKey = keyPair.getPrivate();

           //Send Public Key to Bob
                ObjectOutputStream toBob = new ObjectOutputStream(connection.getOutputStream());
                toBob.writeObject(publicKey);

           //Receive Bob's Public Key
                ObjectInputStream fromBob;
                fromBob = new ObjectInputStream(connection.getInputStream());
                rsaBobPub = (PublicKey) fromBob.readObject();

  //SET UP DIFFIE HELLMAN PROTOCOL
  //For some reason, when receiving Bob's DH param, I am getting a lot of issues.
            //Exchange DH info
                DHParameterSpec paramSpec;
                AlgorithmParameterGenerator paramGen = AlgorithmParameterGenerator.getInstance("DH");
                paramGen.init(512);
                AlgorithmParameters parameters = paramGen.generateParameters();
                paramSpec = (DHParameterSpec) parameters.getParameterSpec(DHParameterSpec.class);

            //Generate Key Pair
                KeyPairGenerator aliceKpGen = KeyPairGenerator.getInstance("DH");
                aliceKpGen.initialize(paramSpec);
                KeyPair aliceKp = aliceKpGen.generateKeyPair();
                aKeyAgreement = KeyAgreement.getInstance("DH");
                aKeyAgreement.init(aliceKp.getPrivate());
                alicePub = aliceKp.getPublic().getEncoded();
                //System.out.println(aliceKp.getPublic())
                //System.out.println(aliceKp.getPublic().getEncoded())
                //Send Alice's encrypted DH byte info to Bob
               /*     cipher2 = Cipher.getInstance("RSA/ECB/PKCS1Padding");
                    cipher2.init(Cipher.ENCRYPT_MODE, rsaBobPub);
                    encryptedDH = cipher2.doFinal(alicePub);
                    System.out.print(encryptedDH);
                */
                    dh = connection.getOutputStream();
                    dh.write(alicePub);

             //Recieve Bob's DH Info
                bobDHConn = connection.getInputStream();
                int length;
                byte[] bobDH = null;


                while((length = bobDHConn.available()) == 0){
                    bobDH = new byte[length];
                    int i = 0;
                    while(i < length){
                        i+= bobDHConn.read(bobDH, i, length - i);
                    }
                } 
          //NOT WORKING
           KeyFactory clientKeyFac = KeyFactory.getInstance("DH");
           X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(bobDH);
           PublicKey bobsDHPubKey = clientKeyFac.generatePublic(x509KeySpec);
           aKeyAgreement.doPhase(bobsDHPubKey, true);


        //Generate AES Secret Keys
        SecretKey aesKeyGen = aKeyAgreement.generateSecret("AES");


    }
}

Server.java

package server;
import java.io.*;
import java.security.*;
import javax.crypto.*;
import java.util.*;
import java.net.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;

public class Server{
    private static int port = 4129;
    private static PublicKey publicKey = null;
    private static PrivateKey privateKey = null;
    private static PublicKey rsaAlicePub = null;
    private static ServerSocket server = null;
    private static SecretKey SecretSharedKeyCipher = null;
    private static SecretKey SecretSharedKeyIntgSend = null;
    private static SecretKey SecretSharedKeyIntRecv = null;

    public static void main(String args[]) throws ClassNotFoundException, NoSuchAlgorithmException, IOException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidKeySpecException, InvalidAlgorithmParameterException{
        //Declarations
            Server serv = new Server();
            server = new ServerSocket(4129);
            server.setReuseAddress(true);
            KeyPairGenerator keyGen;
            byte[] cipherText = null;
            InputStream input = null;
            byte[] data = null;
            byte[] decryptedDH;
            InputStream DH = null;
            byte[] DHinfo = null;
            int length;
            byte[] aliceEncryptedDH = null;    
            SecretKey keyGenDH= null;
            InputStream aliceDH = null;
            Cipher cipher;
            PublicKey bobDHPub = null;
            OutputStream sendDH;

            //String message = "bbbbbbbbbbbbbb";
            String message = "bbbbbbb";
            Socket client = server.accept();

            //Get Public Key froM Alice
                ObjectInputStream alicePK;
                alicePK = new ObjectInputStream(client.getInputStream());
                rsaAlicePub = (PublicKey)alicePK.readObject();

            //Generate Bob's keys
                keyGen = KeyPairGenerator.getInstance("RSA");
                keyGen.initialize(2048);
                KeyPair keyPair = keyGen.genKeyPair();
                privateKey = keyPair.getPrivate();
                publicKey = keyPair.getPublic();

            //Send Bob's public Key to Alice
                ObjectOutputStream bobPK;
                bobPK = new ObjectOutputStream(client.getOutputStream());
                bobPK.writeObject(publicKey);

            //Exchange information for DH
            //Decrypt received information using Bob PK
            //You can assume that Bob selects the public parameters of Diffie‐Hellman protocol, and send them to Alice

            DH = client.getInputStream();
            while((length = DH.available()) == 0);
            int i = 0;
            DHinfo = new byte[length];
            while (i < length) {
                i += DH.read(DHinfo, i, length - i);
            }
/*
            cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            decryptedDH = cipher.doFinal(DHinfo);
           */ 
            KeyFactory clientKeyFac = KeyFactory.getInstance("DH");
            X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(DHinfo);
            bobDHPub = clientKeyFac.generatePublic(x509KeySpec);

            DHParameterSpec dhParamSpec = ((DHPublicKey) bobDHPub).getParams();

            //Create Bob DH Keys
                KeyPairGenerator bobKpGen = KeyPairGenerator.getInstance("DH");
                bobKpGen.initialize(dhParamSpec);
                KeyPair bobsKeys = bobKpGen.generateKeyPair();

                KeyAgreement bobKeyAgreement = KeyAgreement.getInstance("DH");
                bobKeyAgreement.init(bobsKeys.getPrivate());
                bobKeyAgreement.doPhase(bobDHPub, true);

            //Send Bob's DH Parameters to Alice
            //send bobsKeys.getPublic().getEncoded()
                    sendDH = client.getOutputStream();
                    sendDH.write(bobsKeys.getPublic().getEncoded());

            //Encrypt message.getBytes();

    }

    private void Server() throws IOException{
        server = new ServerSocket(port);


    }



}

1 个答案:

答案 0 :(得分:2)

您从InputStream中读取的方式是错误的。首先,您不想使用可用的方法。它不会返回您认为它返回的内容,它返回的内容对您没有用。

当您将字节数组写入OutputStream并且希望另一方重建相同的字节数组时,您需要以某种方式告诉另一方字节数组的长度。最简单的方法是在前面添加长度。

在您的情况下,您已经有一个ObjectOutputStream和ObjectInputStream包裹着您的原始输出和输入流。只需使用它们。字节数组也是对象,因此您可以调用writeObjectreadObject来传输它们。

在客户端:

toBob.writeObject(alicePub);

在服务器中:

DHinfo = (byte[]) alicePK.readObject();

(注意:如果您将alicePk用于多种用途,则应将fromAlice重命名为{{1}}。