2016-04-01 20 views
1

Çok fazla araştırma yapıyorum ve bu sorun için bir çözüm bulamıyorum. Saatlerimi harcadım ve anlayamıyorum, bu yüzden burada birinden daha tecrübeli olan birinin yardım edebileceğini umuyorum. Bu program en iyi uygulama olmayabilir, ancak bir ödev için.Diffie-Hellman Anahtar Üstü Yuvaları Alma Hatası

Genel anahtarları RSA kullanarak iletiyorum, ancak daha önemlisi, Diffie Hellman parametrelerini Bob'dan (sunucu) Alice'e (istemci) iletmeye çalışıyorum. dizisindeki

İstisna "ana" java.security.spec.InvalidKeySpecException: com.sun.crypto.provider.DHKeyFactory.engineGeneratePublic de uygunsuz anahtar şartname (DHKeyFactory programını çalıştırırken aşağıdaki hatayı alıyorum .java: 85) client.Client.main (Client.java:114) 'da java.security.KeyFactory.generatePublic (KeyFactory.java:334) adresinde neden: java.security.InvalidKeyException: Anahtar kodlamayı ayrıştırma hatası com.sun.crypto.provider.DHPublicKey. (DHPublicKey.java:178) at com.sun.crypto.provider.DHKeyFactory.engineGeneratePublic (DHKeyFactory.java:78) ... 2 daha fazla Neden: java.io.IOException: DerInputStream.getLength(): lengthTag = 127, çok büyük. sun.security.util.DerInputStream.getLength (DerInputStream.java:561) at sun.security.util.DerValue.init (DerValue.java:365) at sun.security.util.DerValue. (DerValue.java : com.sun.crypto.provider.DHPublicKey 320) (DHPublicKey.java:125) ... İşte 3 daha

kodudur. 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"); 


    } 
} 

Sunucu.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); 


    } 



} 
+0

Does istemcisi olarak

denklemin dışına sokarsan işe yarar mı? Diğer bir deyişle, her iki DH anahtar kümesini oluşturan tek bir program yazarsanız ve bu değişim kendi içinde çalışırsa, çalışır mı? – QuantumMechanic

cevap

2

Bir InputStream'den okuma biçiminiz yanlış. İlk olarak, kullanılabilir yöntemini kullanmak istemezsiniz. Geri döndüğünü düşündüğünüz şeyi geri getirmez ve ne döndüğü sizin için yararlı değildir.

Bir OutputStream'e bayt dizileri yazdığınızda ve diğer tarafın aynı bayt dizisini yeniden oluşturmasını istiyorsanız, diğer tarafa bayt dizisinin ne kadar uzun olduğunu bildirmeniz gerekir. En kolay yol, uzunluğu ile ön eklemektir.

Sizin durumunuzda, zaten ham çıktı ve girdi akışlarınızın etrafına bir ObjectOutputStream ve ObjectInputStream sarılmış var. Sadece onları kullan. Bayt dizileri de nesnelerdir, bu yüzden bunları aktarmak için writeObject ve readObject'u arayabilirsiniz.

toBob.writeObject(alicePub); 

Ve sunucuda:

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

(Not: Birden amaçlar için kullanmak eğer fromAlice gibi bir şey için alicePk adlandırmak gerekir)