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

📄 ssl_with_signature.java

📁 身份认证和数字签名在实际应用中是通过以数字证书为核心的公开密钥基础结构(PKI)来实现的
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
/****************************************************************
* 软件:Java签名协议扩展 (Java Signature Protocol Extension, JSPE)
* 版本:V1.0
* 软件功能:实现SSL签名协议
* 模块: 私有类ProtocolVersion
*       私有类SSLSignatureType
*       私有类Signature_Alert_type
*       公共类SSL_with_signature
*       私有类SSLsignature_reply
*-----------------------------------------------------------------
*                                 版权所有:中山大学软件研究所 2002
*                          Programmed by 佛山张峰岭 fszfl@21cn.com
*                                              2002.4 - 2002.5
*****************************************************************/
package com.zsusoft.zfl;
import java.util.*;
import java.security.*;
import java.security.KeyStore;
import java.net.*;
import javax.net.*;
import javax.net.ssl.*;   
//import com.sun.net.ssl.*;
import java.io.*;
import java.lang.*;
/**
*  SSL_with_signature类的私有类,定义SSL签名协议版本号。
**/
class ProtocolVersion{
   /**
   *  主版本号 
   **/
   public static final byte major=1;
   /**
   *  次版本号 
   **/
   public static final byte minor=0;
}
/**
* SSL_with_signature类的私有类,定义SSL签名协议中的消息类型。
**/
class SSLSignatureType{
   /**
   *   签名请求 
   **/
   public static final byte signature_request=1;
   /**
   *   签名响应 
   **/
   public static final byte signature_reply=2;
   /**
   *   签名警告 
   **/
   public static final byte signature_alert=3;
}
/**
* SSL_with_signature类的私有类,定义SSL签名协议中的警告类型。
**/
class Signature_Alert_type{
   /**
   *  签名值无法通过校验,可能是非法或损坏的签名值
   **/
   public static final byte Illegal_Signature=1;  
   /**
   * 签名响应方拒绝签名
   **/
   public static final byte Reject_To_Signature=2;  
   /**
   *  非法随机数
   **/
   public static final byte Illegal_random=3;    
   /**
   * 没有签名能力,签名响应方可能没有具备签名能力的私人数字证书
   **/
   public static final byte No_signature_ability=4;
   /**
   * 系统内部故障
   **/  
   public static final byte System_interal_error=5;
   /**
   *  用户自定义的警告类型
   **/ 
   public static final byte User_define_alert=6;  
   /**
   * 消息格式错误
   **/
   public static final byte Format_error=7;       
}
/**********
* 使用用户指定的私钥库和证书库初始化SSL会话;
* 实现了Unix Socket API格式的通信调用方法;
* 通过创建签名回应对象(SSLsignature_reply)启动对签名请求的监听;
* 提供签名请求功能调用方法;
* 提供一些如字符串输入,记日志文件之类的功能调用方法。
* 类中的main方法实现了SSL签名协议功能的演示和调试。
**********/
public class SSL_with_signature {
   //可以公共访问的成员
   /**
   *  自己的证书
   **/
   public java.security.cert.X509Certificate my_certificate;  
   //private javax.security.cert.Certificate my_certificate;  
   // 注:javax.security.cert.Certificate 是JSSE中,专用于SSL
   //    java.security.cert.Certificate  是Java自带的,不知为什么两者不兼容
   //    X509Certificate 是Certificate的子类
   /**
   *  用于创建服务器Socket
   **/
   public SSLServerSocketFactory ssf= null;
   /**
   * 用于创建客户机Socket
   **/   
   public SSLSocketFactory sf= null;
   /**
   * SSL版本,来自SSLContext.getProtocol()
   **/     
   public String SSL_version = null;
   //public static final String BYTE_ENCODING ="8859_1";    //传送信息时的编码方式
   /**
   * 传送信息时的编码方式
   **/
   public static final String BYTE_ENCODING ="GBK";    
   //public static final String BYTE_ENCODING ="ASCII7";    //传送信息时的编码方式
   /**
   * 本人证书中的Suject Distinguished Name
   **/
   public String my_SubjectDN = "";
   /**
   *  调用Message_Box.inputString()显示输入窗口并提示用户输入信息
   **/                  
   public static Message_Box message_box = new Message_Box();  
   
   //私有成员,不能被公开访问
   /**
   * 签名响应方监听对方连接的端口常数定义
   **/            
   private static final int SSLsignature_listen_port=9008;  
   private static boolean debug_mode = false;           //调试模式
   /**
   *  这个对象用独立的线程监听请求签名的连接
   **/
   private SSLsignature_reply sslsignature_reply=null;  
   private PrivateKey my_privatekey;  //自己的私钥
   private SSLSignature_Log Log_Object=null;                //用于记录日志   
   /**************
   *   构造函数的作用:
   *   1 装置自己的私钥库和对方的信任证书库
   *   2 生成可以创建SSL socket的socket 工厂
   *   参数说明: 
   *   my_keystore存放自己的私钥
   *   alias:密钥证书库中的alias名,缺省为mykey(JKS的缺省)
   *   my_password为访问私钥的密码
   *   cert_keystore存放信任的证书
   *   LogFileName为保存记录日志的文件名
   **/
   public SSL_with_signature(KeyStore my_keystore,String alias,String my_password,KeyStore cert_keystore,String LogFileName)
    throws Exception
   {
    //final String ALIASNAME ="mykey";                //密钥证书库中的alias名,缺省为mykey(JKS的缺省)
        try {  
    	/*本段代码用于产生SSL socket工厂*/
    	// kmf 为SSL使用的本方私钥和证书
    	// tmf 为SSL使用对方证书 ,注意 tmf 中可以保存很多证书,也就是一个SSL_with_signature对象可以同时与许多其他机器联系
    	// sf 为 SSL client 的socket factory
    	// ssf 为  SSL server 的 serversocke factory
    		Security.addProvider(new com.sun.rsajca.Provider());
   		Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
   	        if(debug_mode){
   			Show_Debug_Message("以下是Java安全平台SSL提供商的资料:");
   			ListProviderInfo(new com.sun.rsajca.Provider());
   	        	ListProviderInfo(new com.sun.net.ssl.internal.ssl.Provider());
   		}	
		TrustManagerFactory tmf;
		KeyManagerFactory kmf;
		SSLContext sslContext = null;
		sslContext = SSLContext.getInstance("TLS");
		SSL_version = sslContext.getProtocol();
		tmf=TrustManagerFactory.getInstance("SunX509");
		kmf = KeyManagerFactory.getInstance("SunX509");
		kmf.init(my_keystore, my_password.toCharArray());
		tmf.init(cert_keystore);
		//使用随机数加强加密强度
		SecureRandom srand=SecureRandom.getInstance("SHA1PRNG","SUN");
		srand.setSeed((new Date()).getTime());
		sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), srand);
		sf = sslContext.getSocketFactory();
		ssf = sslContext.getServerSocketFactory();
		if(my_keystore.isKeyEntry(alias) == false)  //不是保存私钥 
		      throw new KeyStoreException(alias+" entry is not a key entry"); 		 
        /*取自己的私钥*/
     	        my_privatekey=(PrivateKey)my_keystore.getKey(alias,my_password.toCharArray());    //装入自己私钥
     	/*取自己的证书和Subject distinguished name*/
     	        my_certificate=(java.security.cert.X509Certificate)my_keystore.getCertificate(alias);
     	        my_certificate.checkValidity();  //检查证书是否仍然有效
     	        my_SubjectDN=my_certificate.getSubjectDN().getName();        
        /*设置日志对象*/
                if(LogFileName == null)
                {
                 int begin=my_SubjectDN.indexOf("CN=");    //定位CN域头
                 int end=my_SubjectDN.indexOf(",",begin);  //定位CN域尾
                 String my_SubjectDN_CN = null;
                 if(end<0){
                   my_SubjectDN_CN=my_SubjectDN.substring(begin+3);
                 }
                 else{
                   my_SubjectDN_CN=my_SubjectDN.substring(begin+3,end);
                 }
                 Log_Object=new SSLSignature_Log(my_SubjectDN_CN+"_signature.log");  //缺省使用Subject Distinguish name中的CN字段
                }
                else
                 Log_Object=new SSLSignature_Log(LogFileName);
	 } catch (Exception e) {
	 	System.err.println("无法创建SSL_with_signature对象: " +
	           e.getMessage());
	        e.printStackTrace();
	        throw e;
	        //System.exit(-1);
	 }     	
   }
   /*
   *    显示Java安全方案SSL提供商提供的Java安全类信息
   **/
   private static void ListProviderInfo(java.security.Provider p){
   	Show_Debug_Message("---------------Provider name:"+p.getName()+"-------------------");
   	Show_Debug_Message("Provider version:"+p.getVersion());
   	Show_Debug_Message("Provider information:"+p.getInfo());
   }
   /**
   *  显示我的证书信息
   **/
   public void Show_My_Certificate()
   {
   	Show_Message("个人证书信息:");
   	Show_Message(my_certificate.toString());
   }
   /**
   *  显示SSL的信息
   **/
   public void Show_SSL_information()
   {
   	Show_Message("SSL的信息:");
   	Show_Message("版本:"+SSL_version);
   	String[] supportedCipherSuites = sf.getSupportedCipherSuites();
   	Show_Message("支持的加密算法为:");
   	for(int i=0;i<supportedCipherSuites.length;++i)Show_Message(supportedCipherSuites[i]);
   	String[] defaultCipherSuites=sf.getDefaultCipherSuites();
   	Show_Message("缺省的加密算法为:");
   	for(int i=0;i<defaultCipherSuites.length;++i)Show_Message(defaultCipherSuites[i]);
   }
   /**
   *  获取SSL会话的信息
   *  socket: 使用的socket
   *  返回SSL会话的信息
   **/
   public static String getSSLsessionMessage(Socket socket)
   {
   	String SSLMessage = null;
		   try{
		        SSLSession sslsession = ((SSLSocket)socket).getSession();  //SSL会话
		        SSLMessage = "SSL Session id :" + sslsession.toString() + "\r\n";
		        SSLMessage += " 对方主机:" + sslsession.getPeerHost() + "\r\n";  //获取对方的主机名
	 		try{
	 		   javax.security.cert.Certificate partner_cert=(javax.security.cert.Certificate)(sslsession.getPeerCertificateChain()[0]);  //对方的证书
	 		   SSLMessage += " 对方证书:\r\n";
	 	           SSLMessage += partner_cert.toString()+"\r\n";
	 		} catch (Exception ie) {
	 			SSLMessage += " 对方没有证书!\r\n";
	 		}
	 		SSLMessage += "SSL会话使用的加密算法:"+ sslsession.getCipherSuite() + "\r\n";
	 		SSLMessage += "SSL会话创建的时间:"+ (new Date(sslsession.getCreationTime())).toString() +"\r\n";
	 		SSLMessage += "SSL会话最近使用的时间:"+ (new Date(sslsession.getLastAccessedTime())).toString() +"\r\n";
	 		SSLMessage += "SSL会话绑定的对象:";
	 		String ObjectName[] = sslsession.getValueNames();
	 		for(int i=0;i<ObjectName.length;i++)SSLMessage += ObjectName[0]+" ";
	 		SSLMessage += "\r\n";
		   } catch (Exception e){
			SSLMessage = "无法获取SSL信息,可能不是使用SSL连接\r\n";
			SSLMessage += "出错原因:"+e.getMessage()+"\r\n";
		   }
		   return SSLMessage;
   }
   /**
    *   创建ServerSocket,在指定端口监听SSL连接
    *   参数说明:
    *   listen_port为监听连接的端口
    *   调用返回服务器Socket
    **/
   public ServerSocket listen(int listen_port)
   {
   	try {
   	    //通讯使用SSL加密
   	  ServerSocket ss = ssf.createServerSocket(listen_port);
	  ((SSLServerSocket)ss).setNeedClientAuth(true);    //需要认证对方
	  return ss;
	} catch (IOException e) {
	    System.err.println("无法创建服务器Socket,原因: " +
			       e.getMessage());
	    e.printStackTrace();
	  return null;   
	}
   }
   /**
   *   通过SSL的socket发送数据,本方法也通用于TCP socket
   *   参数说明:
   *   s:使用的socket
   *   but:缓冲区
   *   length:发送字节长度
   *   返回实际发送长度
   *   -1 表示出错

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -