⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ssl_with_signature.java

📁 身份认证和数字签名在实际应用中是通过以数字证书为核心的公开密钥基础结构(PKI)来实现的
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
   **/
   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 + -