<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-124  評論-194  文章-0  trackbacks-0

    概念
    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端:

    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?+? " \ "" );
    ??}

    }




    以上方法主要參考了如下兩個網頁:

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

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

    posted on 2006-12-03 12:36 我愛佳娃 閱讀(11850) 評論(7)  編輯  收藏 所屬分類: SSL

    評論:
    # re: 用OpenSSL與JAVA(JSSE)通信 2008-05-15 21:03 | 不不
    你好,你在另一片文章里這樣寫的:

    公私鑰:公鑰可以唯一解密私鑰加密過的數據,反之亦然。
    SSL過程:需要兩對公私鑰(P1,V1),(P2,V2),假設通信雙方是A和B,B是服務器,A要確認和它通信的是B:
    A->B: hello
    B->A: 用V2加密過的P1(即用戶證書,A就用P2解密出P1)
    A->B: ok
    B->A: 用V1加密的一段信息
    A->B: 用P1加密一個自動生成的K(用之前的P1解密成功這段信息則認為B是可信的了)
    B->A: 用K加密的數據(之后兩對密鑰功能結束,由K來加解密數據)
    這里,P2就是第3方的CA證書,由于非對稱加密很慢,所以公私鑰只是用來保證K的傳送安全,之后通信是用K的對稱加密算法來保證。

    為什么這里是P2是CA證書,而上面的例子里變成了P1是CA證書?我剛接觸SSL不太久,所以不是很懂。抱歉把你06年的東西都搬出來了!  回復  更多評論
      
    # re: 用OpenSSL與JAVA(JSSE)通信 2008-05-16 18:02 | 我愛佳娃
    上文描述的是:
    用OpenSSL生成CA根證書,即(P1,V1)
    在JAVA環境下生成自己的KEY,即(P2,V2)

    這里,P1,V1指代的是CA根證書,所以P1是CA證書,V1是簽名公司需要保密,專門用來給別人簽字的私鑰。

    而,我的另一篇文章提到:
    B->A: 用V2加密過的P1(即用戶證書,A就用P2解密出P1)

    這里,V2相當于CA公司的私鑰,相當于上邊的V1,P2自然就是CA證書了。也即,這兩篇文章在變量指代上正好反了,但內容應該都沒有問題。

      回復  更多評論
      
    # re: 用OpenSSL與JAVA(JSSE)通信 2008-11-20 11:15 | llp20_2000
    @我愛佳娃
    我愛娃娃,按照上文,用OPENSSL的私鑰 ./private/cakey.pem 為javatool的公鑰簽名請求"clientapp.crs"做簽名的時候,也就是執行語句:
    openssl ca -out clientapp.pem -config ./openssl.cnf -infiles clientapp.crs
    結果如下:
    **************************************************
    [~~~~ CA]$ openssl ca -out clientapp.pem -config ./openssl.cnf -infiles clientapp.crs
    Using configuration from ./openssl.cnf
    Enter pass phrase for ./private/cakey.pem:
    Check that the request matches the signature
    Signature ok
    The Subject's Distinguished Name is as follows
    commonName :ASN.1 12:'liangleping'
    organizationName :ASN.1 12:'HuaWei'
    organizationalUnitName:ASN.1 12:'Develop'
    localityName :ASN.1 12:'Cheng Du'
    stateOrProvinceName :ASN.1 12:'Si Chuan'
    countryName :ASN.1 12:'ch'
    The countryName field needed to be the same in the
    CA certificate (ch) and the request (ch)
    ************************************************
    最后出現:The countryName field needed to be the same in the
      回復  更多評論
      
    # re: 用OpenSSL與JAVA(JSSE)通信 2008-11-20 11:18 | llp20_2000
    接樓上,剛才少發了:
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    最后出現:The countryName field needed to be the same in the
    ....CA certificate (ch) and the request (ch)
    并且生成的clientapp.pem大小為0(零)k,因此不能由pem生成dem.不知是何原因?
    我反復對比過兩次輸入的countryName ,并且在javatool中都和Openssl生成時候都輸入全部一樣的公司,組織,城市,國家等,都是一樣的結果.而博主的另一文章,openssl做自簽名,用V1給 P2簽名是可以的.并且此時-infiles為 req.pem.
    新人,不熟悉openssl.請博主幫助
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  回復  更多評論
      
    # re: 用OpenSSL與JAVA(JSSE)通信 2008-11-22 08:24 | 我愛佳娃
    俺也不知為什么了。
    國名好像可以為空的,你試下為空的情況。
    另外,你的提示符為什么會多ASNXXX:commonName :ASN.1 12:
    如果解決了,請貼上來。  回復  更多評論
      
    # re: 用OpenSSL與JAVA(JSSE)通信 2009-02-03 11:25 | Jamie
    那是因為他的openssl.conf里對于CN的設定是match, 而非optional.
    countryName = match

    如下:
    [ policy_match ]
    countryName = match
    stateOrProvinceName = match
    organizationName = match
    organizationalUnitName = optional
    commonName = supplied
    emailAddress = optional

    所以, 必須是匹配的才行.
    你可以改為optional來解決這個問題.  回復  更多評論
      
    # 7867 2009-11-25 05:32 | 周永松
    757  回復  更多評論
      
    主站蜘蛛池模板: 亚洲国产成人久久一区二区三区| 岛国岛国免费V片在线观看| 四虎永久在线精品免费观看地址| 一级日本高清视频免费观看| 亚洲ⅴ国产v天堂a无码二区| 永久免费的网站在线观看| 精品亚洲av无码一区二区柚蜜| 亚洲中久无码永久在线观看同| 无码AV片在线观看免费| 精品亚洲视频在线| 亚洲五月六月丁香激情| 亚洲av高清在线观看一区二区| 67pao强力打造高清免费| 污视频网站免费观看| 久久精品国产亚洲AV电影| 免费一级毛片在线播放不收费| 999任你躁在线精品免费不卡| www亚洲精品久久久乳| 色拍自拍亚洲综合图区| 亚洲国产精品无码久久青草| 亚洲精品视频在线观看免费| 日日摸夜夜添夜夜免费视频 | 亚洲国产成人九九综合| 亚洲成a人片在线观看日本麻豆| www视频在线观看免费| jizz18免费视频| 亚洲精品无码专区在线播放| 亚洲国产综合精品中文第一区| 夜色阁亚洲一区二区三区| 国内精品乱码卡1卡2卡3免费| 女同免费毛片在线播放| 老外毛片免费视频播放| 亚洲AV无码乱码麻豆精品国产| 亚洲熟妇无码AV在线播放| 日韩一区二区三区免费体验| 国产国产人免费视频成69堂| 中文字幕在线免费看线人| 看免费毛片天天看| 亚洲色大成WWW亚洲女子| 亚洲欧洲日产国码二区首页| 亚洲国产精品VA在线观看麻豆 |