Reputation: 133
I am developing an application i java which will implement a TLS protocol. As i have started implementing it recently. while developing a Record Protocol implementation of type handshake, i got strange cipher suites from google chrome and mozilla firefox. As this document says, in a handshake protocol there is type, handshake length, version , random , session id length , session id, cipher suite length , cipher suites .......
I am getting all the fields correct ( before cipher suites ) but on the cipher suites i am getting strange values from google chrome and firefox.
Here is my code that accepts the connection on port 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();
}
}
}
And here is the class that decodes the TLS packet.
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)
{
}
}
the output of my code is
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
as you can see, cipher suites length is 0 30 which means 15 cipher suites received. but i am sure there is no cipher suite id like 192 43 and so on. Please help me with this.
Upvotes: 0
Views: 840
Reputation: 133
And yes there is another problem, third cipher suit id is 192 192 but there no such cipher suite exists. that is because of br.readLine() statement. it will skip the character 10 and consider it as a line break but its actually information. using byte array to read data is the right way.
DataInputStream s = new DataInputStream(socket.getInputStream());
byte data[] = new byte[s.available()];
s.readFully(data);
This implementation will give the actual data.
Upvotes: 0
Reputation: 133
192 43 is the id for TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256.
Wireshark packet capture. TLS 1.2 client hello packet.
Here is the complete list of cipher suite ids.
Upvotes: 1
Reputation: 310903
You're parsing every packet as though it contains cipher suites. They don't.
You've also started off completely on the wrong foot. TLS records are binary, and String is not a container for binary data.
And you're really never going to get anywhere with code structured like this. Quit while you're ahead, or have a look at how real implementations are coded. Nothing like this whatsoever.
Upvotes: 1