随便写的一段代码

public enum HandshakeType {

	HELLO_REQUEST(0), 
	
	CLIENT_HELLO(1), 
	
	SERVER_HELLO(2), 
	
	// certificate
	CERTIFICATE(3), 
	
	// server_key_exchange (12)
	SERVER_KEY_EXCHANGE(12), 
	
	// certificate_request(13)
	CERTIFICATE_REQUEST(13), 
	
	// server_hello_done(14)
	SERVER_HELLO_DONE(14), 
	
	// certificate_verify(15)
	CERTIFICATE_VERIFY(15), 
	
	// client_key_exchange(16)
	CLIENT_KEY_EXCHANGE(16), 
	
	// finished(20)
	FINISHED(20);
	
	private int value;
	
	private HandshakeType(int value) {
		this.value = value;
	}
	
	public int value() {
		return value;
	}
}
public abstract class Handshake {

	public abstract ByteArrayOutputStream body() throws IOException;
}
public enum ContentType {

	CHANGE_CIPHER_SPEC(20), 
	
	ALERT(21), 
	
	HANDSHAKE(22), 
	
	APPLICATION_DATA(23);
	
	private int value;
	
	private ContentType(int value) {
		this.value = value;
	}
	
	public int value() {
		return value;
	}
}
public enum CipherSuite {

	TLS_NULL_WITH_NULL_NULL((byte) 0x00, (byte) 0x00), 
	
	TLS_RSA_WITH_NULL_MD5((byte) 0x00, (byte) 0x01), 
	TLS_RSA_WITH_NULL_SHA((byte) 0x00, (byte) 0x02), 
	TLS_RSA_EXPORT_WITH_RC4_40_MD5((byte) 0x00, (byte) 0x03), 
	TLS_RSA_WITH_RC4_128_MD5((byte) 0x00, (byte) 0x04), 
	TLS_RSA_WITH_RC4_128_SHA((byte) 0x00, (byte) 0x05), 
	TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5((byte) 0x00, (byte) 0x06), 
	TLS_RSA_WITH_IDEA_CBC_SHA((byte) 0x00, (byte) 0x07), 
	TLS_RSA_EXPORT_WITH_DES40_CBC_SHA((byte) 0x00, (byte) 0x08), 
	TLS_RSA_WITH_DES_CBC_SHA((byte) 0x00, (byte) 0x09),
	TLS_RSA_WITH_3DES_EDE_CBC_SHA((byte) 0x00, (byte) 0x0A), 
	
	TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA((byte) 0x00, (byte) 0x0B),
	TLS_DH_DSS_WITH_DES_CBC_SHA((byte) 0x00, (byte) 0x0C), 
	TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA((byte) 0x00, (byte) 0x0D), 
	TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA((byte) 0x00, (byte) 0x0E), 
	TLS_DH_RSA_WITH_DES_CBC_SHA((byte) 0x00, (byte) 0x0F), 
	TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA((byte) 0x00, (byte) 0x10), 
	TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA((byte) 0x00, (byte) 0x11), 
	TLS_DHE_DSS_WITH_DES_CBC_SHA((byte) 0x00, (byte) 0x12), 
	TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA((byte) 0x00, (byte) 0x13), 
	TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA((byte) 0x00, (byte) 0x14), 
	TLS_DHE_RSA_WITH_DES_CBC_SHA((byte) 0x00, (byte) 0x15), 
	TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA((byte) 0x00, (byte) 0x16), 
	
	TLS_DH_anon_EXPORT_WITH_RC4_40_MD5((byte) 0x00, (byte) 0x17), 
	TLS_DH_anon_WITH_RC4_128_MD5((byte) 0x00, (byte) 0x18), 
	TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA((byte) 0x00, (byte) 0x19), 
	TLS_DH_anon_WITH_DES_CBC_SHA((byte) 0x00, (byte) 0x1A), 
	TLS_DH_anon_WITH_3DES_EDE_CBC_SHA((byte) 0x00, (byte) 0x1B);
	
	private byte hb;
	
	private byte lb;
	
	private CipherSuite(byte high, byte low) {
		this.hb = high;
		this.lb = low;
	}
	
	public byte high() {
		return hb;
	}
	
	public byte low() {
		return lb;
	}
}
public class ClientHello extends Handshake {

	// 23 * 16 + 3
	public ByteArrayOutputStream body() throws IOException {
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		bos.write(Test.MAJOR);
		bos.write(Test.MINOR);
		
		long ms = System.currentTimeMillis();
		ms = ms / 1000;
		
		bos.write((int) ((ms << 32) >> 56));
		bos.write((int) ((ms << 40) >> 56));
		bos.write((int) ((ms << 48) >> 56));
		bos.write((int) ((ms << 56) >> 56));
		
		Random random = new Random(ms);
		
		byte[] random_bytes = new byte[28];
		random.nextBytes(random_bytes);
		bos.write(random_bytes);
		
//		bos.write(0); // the length of session id, this value indicates the bytes of length
//		// if session id is empty, then the length of session id is zero
//		// and so here do not write session id
		
		byte[] sessionId = new byte[32];
		Random sessionIdGenerator = new Random(System.currentTimeMillis());
		sessionIdGenerator.nextBytes(sessionId);
		bos.write(sessionId.length);
		bos.write(sessionId);
		
//		// the length of cipher suite, this value indicates the bytes of cipher suite
//		bos.write(0);
//		bos.write(0);
//		// if doe's contains cipher suite, do not write cipher suites
		
		// the length of cipher suite, this value indicates the bytes of cipher suite
		bos.write(0);
		bos.write(2);
		bos.write(CipherSuite.TLS_DH_RSA_WITH_DES_CBC_SHA.high());
		bos.write(CipherSuite.TLS_DH_RSA_WITH_DES_CBC_SHA.low());
		
		bos.write(1);
		bos.write(0);
		return bos;
	}

}
public class ClientHello extends Handshake {

	// 23 * 16 + 3
	public ByteArrayOutputStream body() throws IOException {
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		bos.write(Test.MAJOR);
		bos.write(Test.MINOR);
		
		long ms = System.currentTimeMillis();
		ms = ms / 1000;
		
		bos.write((int) ((ms << 32) >> 56));
		bos.write((int) ((ms << 40) >> 56));
		bos.write((int) ((ms << 48) >> 56));
		bos.write((int) ((ms << 56) >> 56));
		
		Random random = new Random(ms);
		
		byte[] random_bytes = new byte[28];
		random.nextBytes(random_bytes);
		bos.write(random_bytes);
		
//		bos.write(0); // the length of session id, this value indicates the bytes of length
//		// if session id is empty, then the length of session id is zero
//		// and so here do not write session id
		
		byte[] sessionId = new byte[32];
		Random sessionIdGenerator = new Random(System.currentTimeMillis());
		sessionIdGenerator.nextBytes(sessionId);
		bos.write(sessionId.length);
		bos.write(sessionId);
		
//		// the length of cipher suite, this value indicates the bytes of cipher suite
//		bos.write(0);
//		bos.write(0);
//		// if doe's contains cipher suite, do not write cipher suites
		
//		// the length of cipher suite, this value indicates the bytes of cipher suite
//		bos.write(0);
//		bos.write(2);
//		bos.write(CipherSuite.TLS_DH_RSA_WITH_DES_CBC_SHA.high());
//		bos.write(CipherSuite.TLS_DH_RSA_WITH_DES_CBC_SHA.low());
		
		// the length of cipher suite, this value indicates the bytes of cipher suite
		bos.write(0x00);
		bos.write(0x38);
		byte[] cipherSuites = new byte[] {(byte)0xc0, (byte)0x14, (byte)0x00, (byte)0x88, 
				(byte)0x00, (byte)0x87, (byte)0x00, (byte)0x39, (byte)0x00, (byte)0x38, (byte)0xc0, (byte)0x0f, 
				(byte)0x00, (byte)0x84, (byte)0x00, (byte)0x35, (byte)0xc0, (byte)0x11, (byte)0xc0, (byte)0x13, 
				(byte)0x00, (byte)0x45, (byte)0x00, (byte)0x44, (byte)0x00, (byte)0x66, (byte)0x00, (byte)0x33, 
				(byte)0x00, (byte)0x32, (byte)0xc0, (byte)0x0c, (byte)0xc0, (byte)0x0e, (byte)0x00, (byte)0x96, 
				(byte)0x00, (byte)0x41, (byte)0x00, (byte)0x05, (byte)0x00, (byte)0x04, (byte)0x00, (byte)0x2f, 
				(byte)0xc0, (byte)0x12, (byte)0x00, (byte)0x16, (byte)0x00, (byte)0x13, (byte)0xc0, (byte)0x0d, 
				(byte)0xfe, (byte)0xff, (byte)0x00, (byte)0x0a};
		bos.write(cipherSuites);
		
		bos.write(1);
		bos.write(0);
		return bos;
	}

}
public class Test {
	
	// 版本由主版本和小版本组成:major.minor,如3.2,3表示主版本,2表示小版本
	// 目前版本包括3.1, 3.2
	
	// 主版本,3表示版本3.x, 3.0以上的版本。
	public static final int MAJOR = 0x03;
	
	// 小版本
	public static final int MINOR = 0x02;

	public static final int DEFAULT_PORT = 443;
	
	private Socket socket;
	
	public Test(String host) throws IOException {
		this(host, DEFAULT_PORT);
	}
	
	public Test(String host, int port) throws IOException {
		socket = new Socket(host, port);
	}
	
	public void handshake() throws IOException {
		OutputStream os = socket.getOutputStream();
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		bos.write(ContentType.HANDSHAKE.value());
		
		bos.write(MAJOR);
		bos.write(MINOR);
		
		ByteArrayOutputStream bbos = hello();
		int length = bbos.size();
		bos.write((int) ((length << 16) >> 24));
		bos.write((int) ((length << 24) >> 24));
		
		bos.write(bbos.toByteArray());
		
		os.write(bos.toByteArray());
		
		InputStream is = socket.getInputStream();
	}
	
	public ByteArrayOutputStream hello() throws IOException {
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		bos.write(HandshakeType.CLIENT_HELLO.value());
		
		ClientHello client_hello = new ClientHello();
		ByteArrayOutputStream bbos = client_hello.body();
		int length = bbos.size();
		bos.write((int) ((length << 8) >> 24));
		bos.write((int) ((length << 16) >> 24));
		bos.write((int) ((length << 24) >> 24));
		
		bos.write(bbos.toByteArray());
		return bos;
	}
}
public class TestTest {

	private static final String DEFAULT_HOST = "112.65.203.33";
	
	private static com.chos.tls.Test test;
	
	@BeforeClass
	public static void initialize() throws IOException {
		test = new com.chos.tls.Test(DEFAULT_HOST);
	}
	
	@Test
	public void handshake() throws IOException {
		test.handshake();
	}
}

猜你喜欢

转载自lobin.iteye.com/blog/2376814