2015-12-20 3 views
-1

Я разрабатываю приложение i java, которое будет реализовывать протокол TLS. Поскольку я начал внедрять его в последнее время. при разработке реализации протокола записи типа рукопожатия типа я получил странные шифровальные наборы от google chrome и mozilla firefox. Как this документ говорит, в протоколе рукопожатия есть тип, длина рукопожатия, версия, случайный, длина идентификатора сеанса, идентификатор сеанса, длина шифра, шифратовые номера .......tls 1.2 странные шифровальные наборы

Я получаю все поля правильно (до наборов шифров), но в наборах шифров я получаю странные значения от google chrome и firefox.

Вот мой код, который принимает соединение на порт 4040.

package server; 

import java.io.BufferedReader; 
import java.io.FileInputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.io.PrintWriter; 
import java.net.*; 
import java.security.KeyStore; 
import java.security.SecureRandom; 

import javax.net.ssl.KeyManagerFactory; 
import javax.net.ssl.SSLContext; 
import javax.net.ssl.SSLServerSocket; 
import javax.net.ssl.SSLServerSocketFactory; 
import javax.net.ssl.TrustManager; 
import javax.net.ssl.TrustManagerFactory; 
import javax.net.ssl.X509TrustManager; 

public class Server extends ServerSocket { 
    public Server() throws IOException { 
     super(); 
     // TODO Auto-generated constructor stub 
    } 
    public static void main(String args[]) 
    { 
     System.setProperty("java.net.ssl.trustStore", "mam.store"); 
     System.setProperty("java.net.ssl.keyStorePassword", "mamoon"); 
     try { 
      /*KeyStore ks = KeyStore.getInstance("JKS"); 
      InputStream in = new FileInputStream("/Users/Ahmed/Desktop/mam.store"); 
      ks.load(in, "mamoon".toCharArray()); 
      in.close(); 
      KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); 
      kmf.init(ks,"mamoon".toCharArray()); 
      TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); 
      tmf.init(ks); 
      SSLContext con = SSLContext.getInstance("TLSv1.2"); 
      con.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); 

      SSLServerSocket socket = (SSLServerSocket)con.getServerSocketFactory().createServerSocket(4040); 
      */ 
      ServerSocket socket = new ServerSocket(4040); 
      System.out.println("Server is up."); 

      Socket s = socket.accept(); 
      PrintWriter w = new PrintWriter(s.getOutputStream()); 
      BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream(),"ISO-8859-1")); 
      String line; 
      String packet = ""; 
      int l=0; 
      while((line = br.readLine()) != null) 
      { 
       packet += line; 
       System.out.println(line.length()); 
       if(packet.length() >= 100) 
       { 
       for(char c:packet.toCharArray()) 
        System.out.print((int)c + " "); 
       System.out.println(); 
       new TLS(packet); 
       break; 
       } 
      } 
      System.out.println(l); 
      //w.write("<html><body>hello world</body> </html>"); 
      //s.close(); 
      socket.close(); 

     } catch (Exception e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 
} 

А вот класс, который декодирует пакет TLS.

package server; 

import java.math.BigInteger; 
import java.nio.ByteBuffer; 

public class TLS { 
    String start = (char)22 + "" + (char)3; 
    float version; 
    int packetLength,handshakeLength,sessionIdLength; 
    String random = "",sessionId = ""; 
    String message; 
    String packetType,encryption; 
    int cipherSuitsLength; 
    int cipherSuitesId[]; 

    TLS(String packet) throws Exception 
    { 
     if(packet.startsWith(start)) 
     { 
      version = Float.parseFloat((int)packet.charAt(1) + "."+(int)packet.charAt(2)); 
      packetLength = new BigInteger(new byte[]{(byte)packet.charAt(3),(byte)packet.charAt(4)}).intValue(); 
      System.out.println(packetLength); 
        //(byte)packet.charAt(3) << 8 | ((byte)packet.charAt(4) & 0xFF); 
      if((int)packet.charAt(5) == 1) 
       packetType = "Client Hello"; 
      else if((int)packet.charAt(5) == 2) 
       packetType = "Server Hello"; 
      else if((int)packet.charAt(5) == 11) 
       packetType = "Certificate"; 
      else if((int)packet.charAt(5) == 12) 
       packetType = "Server Key Exchange"; 
      else if((int)packet.charAt(5) == 13) 
       packetType = "Certificate Request"; 
      else if((int)packet.charAt(5) == 14) 
       packetType = "Server Done"; 
      else if((int)packet.charAt(5) == 15) 
       packetType = "Certificate Verify"; 
      else if((int)packet.charAt(5) == 16) 
       packetType = "Client Key Exchange"; 
      else if((int)packet.charAt(5) == 20) 
       packetType = "Finished"; 
      handshakeLength = new BigInteger(new byte[] {(byte)packet.charAt(6) , (byte)packet.charAt(7), (byte)packet.charAt(8)}).intValue(); 
        //(byte)packet.charAt(7) << 16 | ((byte)packet.charAt(8) << 8 & 0xFF) | ((byte)); 
      System.out.println(handshakeLength); 
      version = Float.parseFloat((int)packet.charAt(9) + "."+(int)packet.charAt(10)); 
      System.out.println(version); 
      for(int a=11;a<11+32;a++) 
      { random += packet.charAt(a); 
      System.out.println((int)packet.charAt(a)); 
      } 
      System.out.println(random.length()); 
      sessionIdLength = (int)packet.charAt(43); 
      System.out.println(sessionIdLength); 
      int c = 44+sessionIdLength; 
      for(int a=44;a<44+sessionIdLength;a++) 
      { 
       sessionId += packet.charAt(a); 
      } 
      System.out.println(sessionId); 
      cipherSuitsLength = new BigInteger(new byte[] {(byte)packet.charAt(c),(byte) packet.charAt(c+1)}).intValue(); 
      System.out.println(cipherSuitsLength); 
      cipherSuitesId = new int[cipherSuitsLength/2]; 
      c+=2; 
      for(int a=0;a<cipherSuitesId.length;a++) 
      { 
       cipherSuitesId[a] = new BigInteger(new byte[]{(byte)packet.charAt(c),(byte)packet.charAt(c+1)}).intValue(); 
       c+=2; 
       System.out.println(cipherSuitesId[a]); 
      } 
     } 
     else 
      throw new Exception("Not a TLS packet."); 
    } 
    public void processTLS(String packet) 
    { 

    } 
} 

выход моего кода

Server is up. 
51 
19 
14 
61 
22 3 1 0 168 1 0 0 164 3 3 57 220 109 126 106 16 106 75 232 65 206 177 89 90 5 241 76 167 135 150 97 51 67 213 33 60 209 73 137 119 119 80 0 0 30 192 43 192 47 192 192 9 192 19 192 20 192 7 192 17 0 51 0 57 0 47 0 53 0 0 5 0 4 1 0 0 93 255 1 0 1 0 0 0 8 0 6 0 23 0 24 0 25 0 11 0 2 1 0 0 35 0 0 51 116 0 0 0 16 0 23 0 21 2 104 50 8 115 112 100 121 47 51 46 49 8 104 116 116 112 47 49 46 49 0 5 0 5 1 0 0 0 0 0 
168 
164 
3.3 
57 
220 
109 
126 
106 
16 
106 
75 
232 
65 
206 
177 
89 
90 
5 
241 
76 
167 
135 
150 
97 
51 
67 
213 
33 
60 
209 
73 
137 
119 
119 
80 
32 
0 

30 
-16341 
-16337 
-16192 
2496 
5056 
5312 
1984 
4352 
13056 
14592 
12032 
13568 
5 
4 
256 
0 

, как вы можете видеть, длина шифров составляет 0 30, что означает получил 15 шифров. но я уверен, что нет идентификатора шифрованного набора, такого как 192 43 и так далее. Пожалуйста, помогите мне с этим.

+0

Это для академических целей или вы действительно планируете использовать эту реализацию? – Robert

+0

@ Robert, я буду использовать эту реализацию. Я знаю, что эта реализация сейчас жалкая, но я сделаю ее лучше и раздельно для каждого протокола TLS. Но я застрял с наборами шифров. –

+0

Его начало реализации, и я выполняю этап тестирования одновременно. –

ответ

2

Вы анализируете каждый пакет так, как будто он содержит шифрованные сюиты. Они этого не делают.

Вы также полностью исправились на неправильной ноге. Записи TLS являются двоичными, а String не является контейнером для двоичных данных.

И вы действительно никуда не денутся с кодом, структурированным таким образом. Выйдите, пока вы впереди, или посмотрите, как кодируются реальные реализации. Ничего подобного.

+0

Это реализация только для клиентского пакета приветствия. и i m принимает каждый байт как целое без знака. Я знаю, что реализация сейчас очень жалкая. Я сделаю это лучше. –

+0

в любом случае спасибо за ваш ответ, я понял, в чем проблема. 192 43 - идентификатор для TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256. –

+0

Не имеет значения, что вы делаете с символами в String, оно по-прежнему не является контейнером для двоичных данных, и его символы не обязательно отображают 1 :: 1 на исходные байты.Не гарантируется, что работа туда и обратно между 'byte []' -> 'String'->' byte [] 'и это также совершенно бессмысленно. Просто используйте 'byte []'. – EJP

0

И еще есть проблема, третий идентификатор кодированного идентификатора - 192 192, но такого набора шифров нет. это из-за инструкции br.readLine(). он пропустит символ 10 и рассмотрит его как разрыв строки, но его фактическую информацию. использование байтового массива для чтения данных является правильным способом.

DataInputStream s = new DataInputStream(socket.getInputStream()); 
byte data[] = new byte[s.available()]; 
s.readFully(data); 

Эта реализация даст фактические данные.

+0

Но использование 'available()' неверно. См. Javadoc. – EJP

+0

Доступный() метод дает доступное количество байтов (количество). После чтения javadoc я не вижу проблем с этой функцией. Если вы знаете или знаете о какой-либо проблеме plz, скажите мне. вы поможете будете оценены. –

Смежные вопросы