📄 ssl_with_signature.java
字号:
**/
public static int send(Socket s,byte[] buf,int length)
{
try{
OutputStream out=s.getOutputStream();
int real_length = 0;
if ( buf.length < length){ //防止缓冲区溢出
real_length = buf.length;
}
else
{
real_length = length;
}
out.write(buf,0,real_length);
out.flush();
return real_length;
} catch (IOException e) {
System.err.println("通过Socket发送消息出错,原因: " +
e.getMessage());
e.printStackTrace();
return -1;
}
}
/**
* 通过SSL的socket接收数据,本方法也通用于TCP socket
* s:使用的socket
* but:缓冲区
* 返回实际接收字节长度
* 返回 -1 表示出错
**/
public static int recv(Socket s,byte[] buf)
{
try{
InputStream in=s.getInputStream();
return in.read(buf);
} catch (IOException e) {
System.err.println("通过Socket接收消息出错,原因: " +
e.getMessage());
e.printStackTrace();
return -1;
}
}
/**
* 创建与远程计算机的SSL连接
* host为要连接的主机
* port为端口
* 函数返回标准的TCP socket,应用程序可以直接使用这个socket通过SSL传输数据
**/
public Socket connect(String host,int port)
{
try{
Socket socket = sf.createSocket(host, port);
((SSLSocket)socket).startHandshake();
if(debug_mode)
((SSLSocket)socket).addHandshakeCompletedListener(
new HandshakeCompletedListener() {
public void handshakeCompleted(
HandshakeCompletedEvent event) {
System.err.println("SSL 握手过程完成!");
System.err.println(
"\t 使用的密码组合:" + event.getCipherSuite());
System.err.println(
"\t SessionId " + event.getSession());
System.err.println(
"\t 对方机器 " + event.getSession().getPeerHost());
}
}
);
return socket;
} catch (IOException e) {
System.err.println("无法连接获取服务器Socket,原因: " +
e.getMessage());
e.printStackTrace();
return null;
}
}
/**
* 创建SSLsignature_reply对象和启动SSLsignature_reply,使其开始接受签名请求
* reply_callback实现SSLsignature_reply_callback接口,定义接收到签名请求时的回调函数
* reply_callback == null 时使用缺省的回调函数
**/
public void begin_accept_signature_request(SSLsignature_reply_callback reply_callback) throws Exception
{
if( sslsignature_reply == null){
ServerSocket ss;
ss=listen(SSLsignature_listen_port);
//产生SSLsignature_reply对象专门用于在SSLsignature_listen_port端口监听签名请求
sslsignature_reply=new SSLsignature_reply(ss,my_privatekey,this,reply_callback);
sslsignature_reply.set_Log(Log_Object);
//sslsignature_reply.debug_mode=debug_mode;
}
else
{
if(sslsignature_reply.listening()==false) //检测是否在监听连接
{
ServerSocket ss;
ss=listen(SSLsignature_listen_port);
sslsignature_reply.begin_to_listen(ss);
}
}
}
/**
* 创建SSLsignature_reply对象和启动SSLsignature_reply,使用缺省的回调函数
* 等价于begin_accept_signature_request(null)
**/
public void begin_accept_signature_request() throws Exception
{
begin_accept_signature_request(null);
}
/**
* 命令所属的SSLsignature_reply对象停止接受签名请求
**/
public void stop_accept_signature_request()
{
if(sslsignature_reply == null)return;
sslsignature_reply.stop_to_listen();
}
/**
* 签名请求调用方法
* 参数说明:
* partner_host为签名响应方的主机
* signdata_desc为签名描述信息
* signdata为要签名的数据
* 成功时返回一个SSLsignature_record对象,这个对象包含这次签名过程有关的所有信息
* 失败时返回null
**/
public SSLsignature_record request_partner_signature(String partner_host,String signdata_desc,byte[] signdata)
{
Signature_reply S_reply=new Signature_reply();
Signature_request S_request=new Signature_request();
//SSLRandom sslrand=generate_SSLRandom(); //随机数
try{
SSLRandom sslrand=new SSLRandom(); //随机数
//填充Signature_request结构
S_request.random=sslrand;
S_request.signdata_desc=signdata_desc.getBytes(BYTE_ENCODING); //解决汉字问题
//S_request.signdata_desc=signdata_desc.getBytes();
S_request.signdata_desc_length=S_request.signdata_desc.length;
S_request.signdata_length=signdata.length;
S_request.signdata=signdata;
byte sign_algorithm=0;
if(my_privatekey.getAlgorithm().equals("RSA"))
sign_algorithm=SignatureAlgorithm.md5RSA;
else
if(my_privatekey.getAlgorithm().equals("DSA"))
sign_algorithm=SignatureAlgorithm.sha1DSA;
else
return null; //受限与SSL协议,暂时不支持其他的公钥的签名算法
byte request_sign_data[]=new byte[S_request.signdata_desc_length+S_request.signdata_length]; //签名请求的数据
for(int i=0;i<S_request.signdata_desc_length;++i)request_sign_data[i]=S_request.signdata_desc[i];
for(int i=0;i<S_request.signdata_length;++i)request_sign_data[i+S_request.signdata_desc_length]=S_request.signdata[i];
DSignature dsignature=new DSignature(request_sign_data,sign_algorithm,my_privatekey);
S_request.request_signature=dsignature;
} catch (Exception e){
System.err.println("无法组包,原因: " +
e.getMessage());
e.printStackTrace();
return null;
}
//连接
Socket s=connect(partner_host,SSLsignature_listen_port);
if (s == null){
Show_Debug_Message("无法连接对方的主机,可能对方没有监听签名请求!");
return null;
}
byte[] buffer=new byte[65536]; //定义缓冲区
buffer[0]=SSLSignatureType.signature_request;
buffer[1]=ProtocolVersion.major;
buffer[2]=ProtocolVersion.minor;
buffer[3]=0; //长度高字节
buffer[4]=0; //长度低字节
int p=5; //用于定位
//random字段
Show_Debug_Message("gmt_unix_time ="+Long.toString(S_request.random.gmt_unix_time));
//发现gmt_unix_time在Java中以5个字节表示
buffer[p++]=(byte)((S_request.random.gmt_unix_time>>32) % 256); //从UINT32 -> UINT40
buffer[p++]=(byte)((S_request.random.gmt_unix_time>>24) % 256);
buffer[p++]=(byte)((S_request.random.gmt_unix_time>>16) % 256);
buffer[p++]=(byte)((S_request.random.gmt_unix_time>>8) % 256);
buffer[p++]=(byte)(S_request.random.gmt_unix_time % 256);
for(int i=0;i<28;++i)buffer[p++]=S_request.random.random_bytes[i];
//signdata_desc_length字段
buffer[p++]=(byte)((S_request.signdata_desc_length>>8) % 256);
buffer[p++]=(byte)(S_request.signdata_desc_length % 256);
//signdata_desc字段
for(int i=0;i<S_request.signdata_desc_length;++i)buffer[p++]=S_request.signdata_desc[i];
//signdata_length字段
buffer[p++]=(byte)((S_request.signdata_length>>8) % 256);
buffer[p++]=(byte)(S_request.signdata_length % 256);
//signdata字段
for(int i=0;i<S_request.signdata_length;++i)buffer[p++]=S_request.signdata[i];
//request_signature字段
buffer[p++]=S_request.request_signature.signatureAlgorithm;
buffer[p++]=(byte)S_request.request_signature.signaturelength;
for(int i=0;i<S_request.request_signature.signaturelength;++i)buffer[p++]=S_request.request_signature.signatureValue[i];
buffer[3]=(byte)(((p-5)>>8) % 256); //长度不包括开头的5个字节
buffer[4]=(byte)((p-5) % 256);
Log_Object.Save_buffer_log("向"+partner_host+"发送Signature_request(len="+Integer.toString(p)+")",buffer,p);
Show_Buffer_Hex("向"+partner_host+"发送Signature_request(len="+Integer.toString(p)+")",buffer,p);
send(s,buffer,p); //向对方发送数据
Show_Message("向"+partner_host+"发送签名请求,内容如下:");
Show_Message(S_request.toString());
int recv_len=recv(s,buffer);
Log_Object.Save_buffer_log(partner_host+"返回(len="+Integer.toString(recv_len)+")",buffer,recv_len);
Show_Buffer_Hex(partner_host+"返回(len="+Integer.toString(recv_len)+")",buffer,recv_len);
//开始解包
//int pack_len=(new Byte(buffer[3])).intValue() * 256 +(new Byte(buffer[4])).intValue();
//以下逻辑用于解决当byte大于128时转换成int会变成负数的问题
int pack_len = 0;
if(buffer[3]>=0){
pack_len = buffer[3];
}
else
{
pack_len = buffer[3] & 127 + 128;
}
pack_len=pack_len <<8;
if(buffer[4]>=0){
pack_len += buffer[4];
}
else
{
pack_len += buffer[4] & 127 + 128;
}
Show_Debug_Message("pack_len="+Integer.toString(pack_len));
if(pack_len != recv_len-5){
Show_Message("接收到信息的长度不对!");
return null;
}
switch(buffer[0])
{
case SSLSignatureType.signature_alert:
p=38; //不解释随机数
p++; //不管Signature_Alert_type;
byte[] because=new byte[recv_len-p+1];
for(int i=0;p<recv_len;++i)because[i]=buffer[p++];
Show_Message("对方没有执行数字签名,因为:"+(new String(because)));
try{
s.close(); //关闭socket
} catch (IOException e)
{
System.err.println("关闭socket出错:" + e.getMessage());
e.printStackTrace();
}
return null;
case SSLSignatureType.signature_reply:
//解出随机数
long gmt_unix_time=0;
byte[] random_bytes=new byte[28];
//gmt_unix_time=((new Byte(buffer[5])).longValue() << 24)+((new Byte(buffer[6])).longValue() << 16)+((new Byte(buffer[7])).longValue() << 8)+(new Byte(buffer[8])).longValue();
//以下逻辑用于解决当byte大于128时转换成long会变成负数的问题
if(buffer[5] >= 0){
gmt_unix_time = buffer[5];
}
else
{
gmt_unix_time = buffer[5] & 127 + 128;
}
gmt_unix_time = gmt_unix_time <<8;
if(buffer[6] >= 0){
gmt_unix_time += buffer[6];
}
else
{
gmt_unix_time += buffer[6] & 127 + 128;
}
gmt_unix_time = gmt_unix_time <<8;
if(buffer[7] >= 0){
gmt_unix_time += buffer[7];
}
else
{
gmt_unix_time += buffer[7] & 127 + 128;
}
gmt_unix_time = gmt_unix_time <<8;
if(buffer[8] >= 0){
gmt_unix_time += buffer[8];
}
else
{
gmt_unix_time += buffer[8] & 127 + 128;
}
gmt_unix_time = gmt_unix_time <<8;
if(buffer[9] >= 0){
gmt_unix_time += buffer[9];
}
else
{
gmt_unix_time += buffer[9] & 127 + 128;
}
p=10; //用于定位
Show_Debug_Message("gmt_unix_time ="+Long.toString(gmt_unix_time));
for(int i=0;i<28;i++)random_bytes[i]=buffer[p++];
SSLRandom reply_sslrand=new SSLRandom(gmt_unix_time,random_bytes); //恢复随机数
if(reply_sslrand.equals(S_request.random)){
S_reply.random=reply_sslrand;
//S_reply.replydata_length=((new Byte(buffer[p++])).intValue() << 8) + (new Byte(buffer[p++])).intValue(); //返回数据的长度
//以下逻辑用于解决byte转换成int时高位为1变成负数的问题
int replydata_length=0;
if(buffer[p] >= 0){
replydata_length = buffer[p];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -