TLS 1.2 набор странных шифров

Я разрабатываю приложение i java, которое будет реализовывать протокол TLS. Поскольку я начал внедрять это недавно. при разработке реализации протокола записи рукопожатия я получил странные наборы шифров от Google Chrome и Mozilla Firefox. Как этот документ говорит, что в протоколе рукопожатия есть тип, длина рукопожатия, версия, случайная, длина идентификатора сеанса, идентификатор сеанса, длина набора шифров, наборы шифров .......

Я получаю все поля правильно (до наборов шифров), но в наборах шифров я получаю странные значения от 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 и так далее. Пожалуйста, помогите мне с этим.


person Mamoon Ahmed    schedule 20.12.2015    source источник
comment
Это для академических целей или вы действительно планируете использовать эту реализацию?   -  person Robert    schedule 21.12.2015
comment
@Robert, я буду использовать эту реализацию. Я знаю, что эта реализация сейчас жалкая, но я сделаю ее лучше и отдельно для каждого протокола TLS. Но я застрял с наборами шифров.   -  person Mamoon Ahmed    schedule 21.12.2015
comment
Это начало реализации, и я одновременно занимаюсь фазой тестирования.   -  person Mamoon Ahmed    schedule 21.12.2015


Ответы (3)


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

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

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

person user207421    schedule 20.12.2015
comment
это реализация только для пакета приветствия клиента. и я беру каждый байт как целое число без знака. я знаю, что реализация сейчас действительно жалкая. Я сделаю это лучше. - person Mamoon Ahmed; 22.12.2015
comment
в любом случае спасибо за ваш ответ, я понял, в чем проблема. 192 43 - это идентификатор TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256. - person Mamoon Ahmed; 22.12.2015
comment
Неважно, что вы делаете с символами в String, он по-прежнему не является контейнером для двоичных данных, и его символы не обязательно сопоставляют 1 :: 1 с исходными байтами. Работа двусторонней связи между _1 _- ›_ 2 _-› _ 3_ не гарантируется, и это также совершенно бессмысленно. Просто используйте byte[]. - person user207421; 22.12.2015
comment
да. использование байтового массива - правильный путь. У меня есть еще один вопрос. как правильно идентифицировать пакет tls? - person Mamoon Ahmed; 22.12.2015

192 43 - это идентификатор TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256.

Захват пакетов Wireshark. Пакет приветствия клиента TLS 1.2.

Здесь полный список идентификаторов шифров.

person Mamoon Ahmed    schedule 21.12.2015
comment
Похоже, что ссылка на список идентификаторов наборов шифров теперь перенаправляет на средний блог / профиль пользователя. Поэтому, возможно, для этого потребуется использовать веб-архив: https://web.archive.org/web/20151219054439/http://www.thesprawl.org/research/tls-and-ssl-cipher-suites/ - person David; 07.12.2019

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

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

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

person Mamoon Ahmed    schedule 21.12.2015
comment
Но использовать available() - неправильный путь. См. Javadoc. - person user207421; 22.12.2015
comment
available () метод дает доступное количество байтов (count). Прочитав javadoc, я не вижу проблем с этой функцией. Если вы знаете или знаете о какой-либо проблеме, пожалуйста, сообщите мне. Ваша помощь будет оценена по достоинству. - person Mamoon Ahmed; 22.12.2015