kooyee ‘s blog

          開(kāi)源軟件, 眾人努力的結(jié)晶, 全人類的共同財(cái)富
          posts - 103, comments - 55, trackbacks - 0, articles - 66
             :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理
          概念 JAVA使用keystore文件來(lái)存儲(chǔ)所有KEY,keystore文件可以存放多個(gè)KEY,訪問(wèn)它需要密碼。下面我介紹下如何將用OpenSSL做自簽名的證書(shū)一文中介紹的OpenSSL產(chǎn)生的KEY與JAVA的KEY轉(zhuǎn)換后使用,從而達(dá)到JAVA與OpenSSL通信的目的。
          文章來(lái)源:http://blog.csdn.net/ky5566/archive/2007/05/10/1603531.aspx



          cnf -infiles clientapp.crs
           

          轉(zhuǎn)換PEM到DER格式

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


          導(dǎo)入CA證書(shū),即P1

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


          導(dǎo)入用戶證書(shū),即被V1加密過(guò)的P2

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

          注意:這里一定要先導(dǎo)入CA證書(shū)再導(dǎo)入用戶證書(shū),否則會(huì)報(bào)錯(cuò)。

          現(xiàn)在我們就生成了JAVA服務(wù)器使用的所有KEY了,在程序中將mycerts這個(gè)keystore導(dǎo)入就可以了。
          如果客戶端是使用OpenSSL的程序,那么用CA證書(shū)cacert.pem就能正常通信了,如果也是JAVA程序,那么我們需要將CA證書(shū)也轉(zhuǎn)換成keystore:

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

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


          再附上SVR和CLI的JAVA程序,我已經(jīng)用上面的KEY都測(cè)試通過(guò):
          SVR端:
          import  java.io. * ;
          import  java.net. * ;
          import  com.sun.net.ssl.KeyManagerFactory;
          import  com.sun.net.ssl.KeyManager;
          import  com.sun.net.ssl.TrustManagerFactory;
          import  com.sun.net.ssl.TrustManager;
          import  com.sun.net.ssl.SSLContext;
          import  javax.net.ServerSocketFactory;
          import  java.security.KeyStore;

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

            
          //  The new constants that are used during setup.
             public   static   final  String KEYSTORE_FILE  =   " mycerts " ; // "server_keystore";
             public   static   final  String ALGORITHM  =   " sunx509 " ;
            
          public   static   final  String PASSWORD  =   " churchillobjects " ;
            
            
          public   static   void  main(String[] args) {
              
          new  Thread( new  svr()).start();
            }

            
            
          public   void  run() {
              ServerSocket ss 
          =   null ;
              
          try   {

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

                
          //  Initialize the key manager factory with the keystore object,
                
          //  again using the same password for security since it is going to
                
          //  access the private key.
                kmf.init(ks, PASSWORD.toCharArray());
                
                
          //  Now we can get the key managers from the factory, since it knows
                
          //  what type we are using now.
                km  =  kmf.getKeyManagers();
                
                
          //  Next, create a trust manager factory using the same algorithm.
                
          //  This is to avoid using the certificates in cacerts that
                
          //  represent an authentication security risk.
                tmf  =  TrustManagerFactory.getInstance(ALGORITHM);
                
                
          //  then initialize it with the keystore object. This time we don't
                
          //  need the keystore password. This is because trusted certificates
                
          //  are not a sensitive element in the keystore, unlike the
                
          //  private keys.
                tmf.init(ks);
                
                
          //  Once that's initialized, get the trust managers from the factory.
                tm  =  tmf.getTrustManagers();
                
                
          //  Almost done, we need a context object that will get our
                
          //  server socket factory. We specify TLS to indicate that we will
                
          //  need a server socket factory that supports SSL.
                sslc  =  SSLContext.getInstance( " TLS " );
                
                
          //  Initialize the context object with the key managers and trust
                
          //  managers we got earlier. The third parameter is an optional
                
          //  SecureRandom object. By passing in null, we are letting the
                
          //  context object create its own.
                sslc.init(km, tm,  null );
                
                
          //  Finally, we get the ordinary-looking server socket factory
                
          //  from the context object.
                ServerSocketFactory ssf  =  sslc.getServerSocketFactory();
                
                
          //  From the factory, we simply ask for an ordinary-looking
                
          //  server socket on the port we wish.
                ss  =  ssf.createServerSocket(PORT);

                listen(ss);
              }

              
          catch (Exception e) {
                e.printStackTrace();
              }

              
          finally {
                
          if (ss != null ) {
                  
          try {
                    ss.close();
                  }

                  
          catch (IOException e) {
                    
          //  oh, well
                  }

                }

                System.exit(
          0 );
              }

            }

            
            
          static   void  listen(ServerSocket ss)  throws  Exception {
              System.out.println(
          " Ready for connections. " );
              
          while ( true ) {
                Socket s 
          =  ss.accept();
                BufferedWriter bw 
          =   new  BufferedWriter(
                  
          new  OutputStreamWriter(s.getOutputStream()));
                BufferedReader br 
          =   new  BufferedReader(
                  
          new  InputStreamReader(s.getInputStream()));
                String q 
          =  br.readLine();
                
          if ( ! QUESTION.equals(q)) {
                  
          throw   new  RuntimeException( " Wrong question: \ ""  + q +  " \ "" );
                }

                System.out.println(
          " Question: \ ""  + q +  " \ "" );
                bw.write(ANSWER
          + " \n " );
                bw.flush();
                s.close();
              }

            }

          }


          CLI端程序:

          import  java.io. * ;
          import  java.net. * ;
          import  com.sun.net.ssl.KeyManagerFactory;
          import  com.sun.net.ssl.TrustManagerFactory;
          import  com.sun.net.ssl.SSLContext;
          import  java.security.KeyStore;
          import  javax.net.SocketFactory;

          public   class  cli  implements  Runnable {
            
            
          public   static   final   int  PORT  =   5555 ;
            
          public   static   final  String HOST  =   " localhost " ;
            
          public   static   final  String KEYSTORE_FILE  =   " clikeystore " ; // "client_keystore";
             public   static   final  String ALGORITHM  =   " sunx509 " ;
            
          public   static   final  String PASSWORD  =   " churchillobjects " ;
            
          public   static   final  String QUESTION  =   " Knock, knock. " ;
            
          public   static   final  String ANSWER  =   " Who's there? " ;
            
            
          public   static   void  main(String[] args) {
              
          new  Thread( new  cli()).start();
            }

            
            
          public   void  run() {
              Socket socket 
          =   null ;
              
          try {
                KeyManagerFactory kmf;
                KeyStore ks;
                TrustManagerFactory tmf;
                SSLContext sslc;

                kmf 
          =  KeyManagerFactory.getInstance(ALGORITHM);
                ks 
          =  KeyStore.getInstance(  " JKS "  );
                ks.load(
          new  FileInputStream(KEYSTORE_FILE), PASSWORD.toCharArray());
                kmf.init(ks, PASSWORD.toCharArray());
                tmf 
          =  TrustManagerFactory.getInstance(ALGORITHM);
                tmf.init(ks);
                sslc 
          =  SSLContext.getInstance( " TLS " );
                sslc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), 
          null );

                
          //  The process is different from here on the client. Instead of
                
          //  getting a ServerSocketFactory, we ask for a SocketFactory from
                
          //  the SSL context.
                SocketFactory sf  =  sslc.getSocketFactory();

                
          //  Then we get the socket from the factory and treat it
                
          //  as if it were a standard (plain) socket.
                socket  =  sf.createSocket(HOST, PORT);
              
                doQuery(socket);
              }

              
          catch (Exception e) {
                e.printStackTrace();
              }

              
          finally {
                
          if (socket != null ) {
                  
          try {
                    socket.close();
                  }

                  
          catch (IOException e) {
                    
          //  oh, well
                  }

                }

                System.exit(
          0 );
              }

            }


            
          private   void  doQuery(Socket s)  throws  Exception {
              BufferedWriter bw 
          =   new  BufferedWriter( new  OutputStreamWriter(s.getOutputStream()));
              BufferedReader br 
          =   new  BufferedReader( new  InputStreamReader(s.getInputStream()));
              bw.write(QUESTION
          + " \n " );
              bw.flush();
              String response 
          =  br.readLine();
              
          if ( ! ANSWER.equals(response)) {
                
          throw   new  RuntimeException( " Wrong answer: \ ""  + response +  " \ "" );
              }

              System.out.println(
          " Got the right answer: \ ""  + response +  " \ "" );
            }

          }


          評(píng)論

          # re: [導(dǎo)入]用OpenSSL與JAVA(JSSE)通信   回復(fù)  更多評(píng)論   

          2008-05-27 16:59 by kooyee
          如果客戶端不使用keystore的話
          可以用:

          System.setProperty("javax.net.ssl.trustStore","trustedcerts");

          SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory
          .getDefault();
          SSLSocket client = (SSLSocket) factory.createSocket("127.0.0.1",8080);

          這樣就可以無(wú)條件的trust服務(wù)端的keystore
          (注 這里的trustedcerts是服務(wù)端keystore文件名)

          如果不用System.setProperty的話,也可以在啟動(dòng)客戶端時(shí)加入?yún)?shù)(與setProperty效果一樣)
          java -Djavax.net.ssl.trustStore=truststore clientApp

          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 汤阴县| 交城县| 应城市| 呼玛县| 沾益县| 荣昌县| 麻栗坡县| 武隆县| 满洲里市| 白朗县| 永清县| 婺源县| 江西省| 老河口市| 弥渡县| 五大连池市| 丰县| 五常市| 吴江市| 阳高县| 迁安市| 东乡族自治县| 昭通市| 安阳县| 汤原县| 山阴县| 府谷县| 驻马店市| 武宁县| 元江| 日照市| 宁河县| 新宁县| 北票市| 会同县| 墨玉县| 清丰县| 鹤庆县| 南皮县| 苏尼特右旗| 阿拉尔市|