【发布时间】:2015-12-20 21:42:59
【问题描述】:
我正在开发一个将实现 TLS 协议的 java 应用程序。因为我最近开始实施它。在开发握手类型的记录协议实现时,我从 google chrome 和 mozilla firefox 得到了奇怪的密码套件。正如this 文档所说,在握手协议中有类型、握手长度、版本、随机、会话 ID 长度、会话 ID、密码套件长度、密码套件......
我得到了正确的所有字段(在密码套件之前),但在密码套件上,我从 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 这样的密码套件 ID 等等。请帮我解决这个问题。
【问题讨论】:
-
这是出于学术目的还是您真的打算使用该实现?
-
@Robert 我将使用该实现。我知道这个实现现在很可悲,但我会为每个 TLS 协议做得更好和分开。但我坚持使用密码套件。
-
这是实施的开始,我正在同时进行测试阶段。