用OpenSSL与JAVA(JSSE)通信

用OpenSSL与JAVA(JSSE)通信

概念
JAVA使用keystore文件来存储所有KEY,keystore文件可以存放多个KEY,访问它需要密码。
下面我介绍下如何将用OpenSSL做自签名的证书一文中介绍的OpenSSL产生的KEY与JAVA的KEY转换后使用,从而达到JAVA与OpenSSL通信的目的。


用OpenSSL生成CA根证书,即(P1,V1)
此步骤参见用OpenSSL做自签名的证书一文


在JAVA环境下生成自己的KEY,即(P2,V2)

keytool -genkey -alias clientapp -keystore mycerts

注意:这里会提示输入访问keystore的密码,以及组织、城市、省份,一定要与CA根证书的一致,否则不能被CA签名。


从keystore中导出public key,即P2

keytool -keystore mycerts -certreq -alias clientapp -file clientapp.crs


用CA根证书为这个public key进行签名,即用V1给P2加密

openssl ca -out clientapp.pem -config ./openssl.cnf -infiles clientapp.crs
 

转换PEM到DER格式

openssl x509 -in clientapp.pem -out clientapp.der -outform DER


导入CA证书,即P1

keytool -keystore mycerts -alias systemca -import -file cacert.pem


导入用户证书,即被V1加密过的P2

keytool -keystore mycerts -alias clientapp -import -file clientapp.der

注意:这里一定要先导入CA证书再导入用户证书,否则会报错。

现在我们就生成了JAVA服务器使用的所有KEY了,在程序中将mycerts这个keystore导入就可以了。
如果客户端是使用OpenSSL的程序,那么用CA证书cacert.pem就能正常通信了,如果也是JAVA程序,那么我们需要将CA证书也转换成keystore:

keytool -import -keystore clikeystore -import -trustcacerts -file cacert.pem

生成的clikeystore供JAVA客户端使用,就能通信。


再附上SVR和CLI的JAVA程序,我已经用上面的KEY都测试通过:
SVR端:


  1.  import  java.io. * ;
  2.  import  java.net. * ;
  3.  import  com.sun.net.ssl.KeyManagerFactory;
  4.  import  com.sun.net.ssl.KeyManager;
  5.  import  com.sun.net.ssl.TrustManagerFactory;
  6.  import  com.sun.net.ssl.TrustManager;
  7.  import  com.sun.net.ssl.SSLContext;
  8.  import  javax.net.ServerSocketFactory;
  9.  import  java.security.KeyStore;

  10.  public   class  svr  implements  Runnable  {
  11.   
  12.    public   static   final   int  PORT  =   5555 ;
  13.    public   static   final  String HOST  =   " localhost " ;
  14.    public   static   final  String QUESTION  =   " Knock, knock. " ;
  15.    public   static   final  String ANSWER  =   " Who's there? " ;

  16.    //  The new constants that are used during setup. 
  17.     public   static   final  String KEYSTORE_FILE  =   " mycerts " ; // "server_keystore"; 
  18.     public   static   final  String ALGORITHM  =   " sunx509 " ;
  19.    public   static   final  String PASSWORD  =   " churchillobjects " ;
  20.   
  21.    public   static   void  main(String[] args)  {
  22.      new  Thread( new  svr()).start();
  23.   } 
  24.   
  25.    public   void  run()  {
  26.     ServerSocket ss  =   null ;
  27.      try    {

  28.        //  Local references used for clarity. Their presence
  29.        //  here is part of the reason we need to import
  30.        //  so many classes. 
  31.        KeyManagerFactory kmf;
  32.       KeyManager[] km;
  33.       KeyStore ks;
  34.       TrustManagerFactory tmf;
  35.       TrustManager[] tm;
  36.       SSLContext sslc;
  37.       
  38.        //  Create a keystore that will read the JKS (Java KeyStore)
  39.        //  file format which was created by the keytool utility. 
  40.        ks  =  KeyStore.getInstance( " JKS " );
  41.       
  42.        //  Load the keystore object with the binary keystore file and
  43.        //  a byte array representing its password. 
  44.        ks.load( new  FileInputStream(KEYSTORE_FILE), PASSWORD.toCharArray());
  45.       
  46.        //  Gives us a factory for key managers that will let
  47.        //  us handle the asymetric keys we created earlier. 
  48.        kmf  =  KeyManagerFactory.getInstance(ALGORITHM);

  49.        //  Initialize the key manager factory with the keystore object,
  50.        //  again using the same password for security since it is going to
  51.        //  access the private key. 
  52.        kmf.init(ks, PASSWORD.toCharArray());
  53.       
  54.        //  Now we can get the key managers from the factory, since it knows
  55.        //  what type we are using now. 
  56.        km  =  kmf.getKeyManagers();
  57.       
  58.        //  Next, create a trust manager factory using the same algorithm.
  59.        //  This is to avoid using the certificates in cacerts that
  60.        //  represent an authentication security risk. 
  61.        tmf  =  TrustManagerFactory.getInstance(ALGORITHM);
  62.       
  63.        //  then initialize it with the keystore object. This time we don't
  64.        //  need the keystore password. This is because trusted certificates
  65.        //  are not a sensitive element in the keystore, unlike the
  66.        //  private keys. 
  67.        tmf.init(ks);
  68.       
  69.        //  Once that's initialized, get the trust managers from the factory. 
  70.        tm  =  tmf.getTrustManagers();
  71.       
  72.        //  Almost done, we need a context object that will get our
  73.        //  server socket factory. We specify TLS to indicate that we will
  74.        //  need a server socket factory that supports SSL. 
  75.        sslc  =  SSLContext.getInstance( " TLS " );
  76.       
  77.        //  Initialize the context object with the key managers and trust
  78.        //  managers we got earlier. The third parameter is an optional
  79.        //  SecureRandom object. By passing in null, we are letting the
  80.        //  context object create its own. 
  81.        sslc.init(km, tm,  null );
  82.       
  83.        //  Finally, we get the ordinary-looking server socket factory
  84.        //  from the context object. 
  85.        ServerSocketFactory ssf  =  sslc.getServerSocketFactory();
  86.       
  87.        //  From the factory, we simply ask for an ordinary-looking
  88.        //  server socket on the port we wish. 
  89.        ss  =  ssf.createServerSocket(PORT);

  90.       listen(ss);
  91.     } 
  92.       catch (Exception e)  {
  93.       e.printStackTrace();
  94.     } 
  95.       finally  {
  96.        if (ss != null )  {
  97.          try  {
  98.           ss.close();
  99.         } 
  100.           catch (IOException e)  {
  101.            //  oh, well 
  102.          } 
  103.       } 
  104.       System.exit( 0 );
  105.     } 
  106.   } 
  107.   
  108.    static   void  listen(ServerSocket ss)  throws  Exception  {
  109.     System.out.println( " Ready for connections. " );
  110.      while ( true )  {
  111.       Socket s  =  ss.accept();
  112.       BufferedWriter bw  =   new  BufferedWriter(
  113.          new  OutputStreamWriter(s.getOutputStream()));
  114.       BufferedReader br  =   new  BufferedReader(
  115.          new  InputStreamReader(s.getInputStream()));
  116.       String q  =  br.readLine();
  117.        if ( ! QUESTION.equals(q))  {
  118.          throw   new  RuntimeException( " Wrong question: / ""  + q +  " / "" );
  119.       } 
  120.       System.out.println( " Question: / ""  + q +  " / "" );
  121.       bw.write(ANSWER + " /n " );
  122.       bw.flush();
  123.       s.close();
  124.     } 
  125.   } 
CLI端程序:

  1.  import  java.io. * ;
  2.  import  java.net. * ;
  3.  import  com.sun.net.ssl.KeyManagerFactory;
  4.  import  com.sun.net.ssl.TrustManagerFactory;
  5.  import  com.sun.net.ssl.SSLContext;
  6.  import  java.security.KeyStore;
  7.  import  javax.net.SocketFactory;
  8.  public   class  cli  implements  Runnable  {
  9.   
  10.    public   static   final   int  PORT  =   5555 ;
  11.    public   static   final  String HOST  =   " localhost " ;
  12.    public   static   final  String KEYSTORE_FILE  =   " clikeystore " ; // "client_keystore"; 
  13.     public   static   final  String ALGORITHM  =   " sunx509 " ;
  14.    public   static   final  String PASSWORD  =   " churchillobjects " ;
  15.    public   static   final  String QUESTION  =   " Knock, knock. " ;
  16.    public   static   final  String ANSWER  =   " Who's there? " ;
  17.   
  18.    public   static   void  main(String[] args)  {
  19.      new  Thread( new  cli()).start();
  20.   } 
  21.   
  22.    public   void  run()  {
  23.     Socket socket  =   null ;
  24.      try  {
  25.       KeyManagerFactory kmf;
  26.       KeyStore ks;
  27.       TrustManagerFactory tmf;
  28.       SSLContext sslc;
  29.       kmf  =  KeyManagerFactory.getInstance(ALGORITHM);
  30.       ks  =  KeyStore.getInstance(  " JKS "  );
  31.       ks.load( new  FileInputStream(KEYSTORE_FILE), PASSWORD.toCharArray());
  32.       kmf.init(ks, PASSWORD.toCharArray());
  33.       tmf  =  TrustManagerFactory.getInstance(ALGORITHM);
  34.       tmf.init(ks);
  35.       sslc  =  SSLContext.getInstance( " TLS " );
  36.       sslc.init(kmf.getKeyManagers(), tmf.getTrustManagers(),  null );
  37.        //  The process is different from here on the client. Instead of
  38.        //  getting a ServerSocketFactory, we ask for a SocketFactory from
  39.        //  the SSL context. 
  40.        SocketFactory sf  =  sslc.getSocketFactory();
  41.        //  Then we get the socket from the factory and treat it
  42.        //  as if it were a standard (plain) socket. 
  43.        socket  =  sf.createSocket(HOST, PORT);
  44.     
  45.       doQuery(socket);
  46.     } 
  47.       catch (Exception e)  {
  48.       e.printStackTrace();
  49.     } 
  50.       finally  {
  51.        if (socket != null )  {
  52.          try  {
  53.           socket.close();
  54.         } 
  55.           catch (IOException e)  {
  56.            //  oh, well 
  57.          } 
  58.       } 
  59.       System.exit( 0 );
  60.     } 
  61.   } 
  62.  
  63.     private   void  doQuery(Socket s)  throws  Exception  {
  64.     BufferedWriter bw  =   new  BufferedWriter( new  OutputStreamWriter(s.getOutputStream()));
  65.     BufferedReader br  =   new  BufferedReader( new  InputStreamReader(s.getInputStream()));
  66.     bw.write(QUESTION + " /n " );
  67.     bw.flush();
  68.     String response  =  br.readLine();
  69.      if ( ! ANSWER.equals(response))  {
  70.        throw   new  RuntimeException( " Wrong answer: / ""  + response +  " / "" );
  71.     } 
  72.     System.out.println( " Got the right answer: / ""  + response +  " / "" );
  73.   } 


以上方法主要参考了如下两个网页:

http://www.churchillobjects.com/c/11201g.html

http://mark.foster.cc/kb/openssl-keytool.html


原文:http://www.blogjava.net/alwayscy/archive/2008/11/22/85161.html


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值