熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java高級技術 >> 正文

Java加密技術(九)

2013-11-23 19:42:46  來源: Java高級技術 

  在Java加密技術(八)中我們模擬了一個基於RSA非對稱加密網絡的安全通信現在我們深度了解一下現有的安全網絡通信——SSL

  我們需要構建一個由CA機構簽發的有效證書這裡我們使用上文中生成的自簽名證書zlexcer

  這裡我們將證書導入到我們的密鑰庫

  Shell代碼

  keytool import alias file d/zlexcer keystore d/zlexkeystore

  其中

  import表示導入

  alias指定別名這裡是

  file指定算法這裡是d/zlexcer

  keystore指定存儲位置這裡是d/zlexkeystore

  在這裡我使用的密碼為

  控制台輸出

  Console代碼
 輸入keystore密碼
再次輸入新密碼:
所有者:CN= OU=zlex O=zlex L=BJ ST=BJ C=CN
簽發人:CN= OU=zlex O=zlex L=BJ ST=BJ C=CN
序列號:aedf
有效期: Thu May :: CST 至Wed Aug :: CST
證書指紋:
         MD::CA:E::E:DF:AD::::F:A:AD:FC::A
         SHA:::::::F::CA::A:D:A:CF::D:C:D:C:C
         簽名算法名稱:SHAwithRSA
         版本:
信任這個認證? [否]  y
認證已添加至keystore中

  OK最復雜的准備工作已經完成

  接下來我們將域名定位到本機上打開C\Windows\System\drivers\etc\hosts文件將綁定在本機上在文件末尾追加       現在通過地址欄訪問或者通過ping命令如果能夠定位到本機域名映射就搞定了

  現在配置tomcat先將zlexkeystore拷貝到tomcat的conf目錄下然後配置serverxml將如下內容加入配置文件

  Xml代碼
 <Connector
    SSLEnabled=true
    URIEncoding=UTF
    clientAuth=false
    keystoreFile=conf/zlexkeystore
    keystorePass=
    maxThreads=
    port=
    protocol=HTTP/
    scheme=https
    secure=true
    sslProtocol=TLS />

  注意clientAuth=false測試階段置為false正式使用時建議使用true現在啟動tomcat訪問

  

  顯然證書未能通過認證這個時候你可以選擇安裝證書(上文中的zlexcer文件就是證書)作為受信任的根證書頒發機構導入再次重啟浏覽器(IE其他浏覽器對於域名不支持本地方式訪問)訪問你會看到地址欄中會有個小鎖就說明安裝成功所有的浏覽器聯網操作已經在RSA加密解密系統的保護之下了但似乎我們感受不到

  這個時候很多人開始懷疑如果我們要手工做一個這樣的https的訪問是不是需要把浏覽器的這些個功能都實現呢?不需要!

  接著上篇內容給出如下代碼實現

  Java代碼

  import javaioFileInputStream;
import javasecurityKeyStore;
import javasecurityPrivateKey;
import javasecurityPublicKey;
import javasecuritySignature;
import javasecuritycertCertificate;
import javasecuritycertCertificateFactory;
import javasecuritycertXCertificate;
import javautilDate;

  import javaxcryptoCipher;
import sslHttpsURLConnection;
import sslKeyManagerFactory;
import sslSSLContext;
import sslSSLSocketFactory;
import sslTrustManagerFactory;

  /**
 * 證書組件
 *
 * @author 梁棟
 * @version
 * @since
 */
public abstract class CertificateCoder extends Coder {

  /**
     * Java密鑰庫(Java Key StoreJKS)KEY_STORE
     */
    public static final String KEY_STORE = JKS;

  public static final String X = X;
    public static final String SunX = SunX;
    public static final String SSL = SSL;

  /**
     * 由KeyStore獲得私鑰
     *
     * @param keyStorePath
     * @param alias
     * @param password
     * @return
     * @throws Exception
     */
    private static PrivateKey getPrivateKey(String keyStorePath String alias
            String password) throws Exception {
        KeyStore ks = getKeyStore(keyStorePath password);
        PrivateKey key = (PrivateKey) ksgetKey(alias passwordtoCharArray());
        return key;
    }

  /**
     * 由Certificate獲得公鑰
     *
     * @param certificatePath
     * @return
     * @throws Exception
     */
    private static PublicKey getPublicKey(String certificatePath)
            throws Exception {
        Certificate certificate = getCertificate(certificatePath);
        PublicKey key = certificategetPublicKey();
        return key;
    }

  /**
     * 獲得Certificate
     *
     * @param certificatePath
     * @return
     * @throws Exception
     */
    private static Certificate getCertificate(String certificatePath)
            throws Exception {
        CertificateFactory certificateFactory = CertificateFactory
                getInstance(X);
        FileInputStream in = new FileInputStream(certificatePath);

  Certificate certificate = certificateFactorygenerateCertificate(in);
        inclose();

  return certificate;
    }

  /**
     * 獲得Certificate
     *
     * @param keyStorePath
     * @param alias
     * @param password
     * @return
     * @throws Exception
     */
    private static Certificate getCertificate(String keyStorePath
            String alias String password) throws Exception {
        KeyStore ks = getKeyStore(keyStorePath password);
        Certificate certificate = ksgetCertificate(alias);

  return certificate;
    }

  /**
     * 獲得KeyStore
     *
     * @param keyStorePath
     * @param password
     * @return
     * @throws Exception
     */
    private static KeyStore getKeyStore(String keyStorePath String password)
            throws Exception {
        FileInputStream is = new FileInputStream(keyStorePath);
        KeyStore ks = KeyStoregetInstance(KEY_STORE);
        ksload(is passwordtoCharArray());
        isclose();
        return ks;
    }

  /**
     * 私鑰加密
     *
     * @param data
     * @param keyStorePath
     * @param alias
     * @param password
     * @return
     * @throws Exception
     */
    public static byte[] encryptByPrivateKey(byte[] data String keyStorePath
            String alias String password) throws Exception {
        // 取得私鑰
        PrivateKey privateKey = getPrivateKey(keyStorePath alias password);

  // 對數據加密
        Cipher cipher = CiphergetInstance(privateKeygetAlgorithm());
        cipherinit(CipherENCRYPT_MODE privateKey);

  return cipherdoFinal(data);

  }

  /**
     * 私鑰解密
     *
     * @param data
     * @param keyStorePath
     * @param alias
     * @param password
     * @return
     * @throws Exception
     */
    public static byte[] decryptByPrivateKey(byte[] data String keyStorePath
            String alias String password) throws Exception {
        // 取得私鑰
        PrivateKey privateKey = getPrivateKey(keyStorePath alias password);

  // 對數據加密
        Cipher cipher = CiphergetInstance(privateKeygetAlgorithm());
        cipherinit(CipherDECRYPT_MODE privateKey);

  return cipherdoFinal(data);

  }

  /**
     * 公鑰加密
     *
     * @param data
     * @param certificatePath
     * @return
     * @throws Exception
     */
    public static byte[] encryptByPublicKey(byte[] data String certificatePath)
            throws Exception {

  // 取得公鑰
        PublicKey publicKey = getPublicKey(certificatePath);
        // 對數據加密
        Cipher cipher = CiphergetInstance(publicKeygetAlgorithm());
        cipherinit(CipherENCRYPT_MODE publicKey);

  return cipherdoFinal(data);

  }

  /**
     * 公鑰解密
     *
     * @param data
     * @param certificatePath
     * @return
     * @throws Exception
     */
    public static byte[] decryptByPublicKey(byte[] data String certificatePath)
            throws Exception {
        // 取得公鑰
        PublicKey publicKey = getPublicKey(certificatePath);

  // 對數據加密
        Cipher cipher = CiphergetInstance(publicKeygetAlgorithm());
        cipherinit(CipherDECRYPT_MODE publicKey);

  return cipherdoFinal(data);

  }

  /**
     * 驗證Certificate
     *
     * @param certificatePath
     * @return
     */
    public static boolean verifyCertificate(String certificatePath) {
        return verifyCertificate(new Date() certificatePath);
    }

  /**
     * 驗證Certificate是否過期或無效
     *
     * @param date
     * @param certificatePath
     * @return
     */
    public static boolean verifyCertificate(Date date String certificatePath) {
        boolean status = true;
        try {
            // 取得證書
            Certificate certificate = getCertificate(certificatePath);
            // 驗證證書是否過期或無效
            status = verifyCertificate(date certificate);
        } catch (Exception e) {
            status = false;
        }
        return status;
    }

  /**
     * 驗證證書是否過期或無效
     *
     * @param date
     * @param certificate
     * @return
     */
    private static boolean verifyCertificate(Date date Certificate certificate) {
        boolean status = true;
        try {
            XCertificate xCertificate = (XCertificate) certificate;
            xCertificatecheckValidity(date);
        } catch (Exception e) {
            status = false;
        }
        return status;
    }

  /**
     * 簽名
     *
     * @param keyStorePath
     * @param alias
     * @param password
     *
     * @return
     * @throws Exception
     */
    public static String sign(byte[] sign String keyStorePath String alias
            String password) throws Exception {
        // 獲得證書
        XCertificate xCertificate = (XCertificate) getCertificate(
                keyStorePath alias password);
        // 獲取私鑰
        KeyStore ks = getKeyStore(keyStorePath password);
        // 取得私鑰
        PrivateKey privateKey = (PrivateKey) ksgetKey(alias password
                toCharArray());

  // 構建簽名
        Signature signature = SignaturegetInstance(xCertificate
                getSigAlgName());
        signatureinitSign(privateKey);
        signatureupdate(sign);
        return encryptBASE(signaturesign());
    }

  /**
     * 驗證簽名
     *
     * @param data
     * @param sign
     * @param certificatePath
     * @return
     * @throws Exception
     */
    public static boolean verify(byte[] data String sign
            String certificatePath) throws Exception {
        // 獲得證書
        XCertificate xCertificate = (XCertificate) getCertificate(certificatePath);
        // 獲得公鑰
        PublicKey publicKey = xCertificategetPublicKey();
        // 構建簽名
        Signature signature = SignaturegetInstance(xCertificate
                getSigAlgName());
        signatureinitVerify(publicKey);
        signatureupdate(data);

  return signatureverify(decryptBASE(sign));

  }

  /**
     * 驗證Certificate
     *
     * @param keyStorePath
     * @param alias
     * @param password
     * @return
     */
    public static boolean verifyCertificate(Date date String keyStorePath
            String alias String password) {
        boolean status = true;
        try {
            Certificate certificate = getCertificate(keyStorePath alias
                    password);
            status = verifyCertificate(date certificate);
        } catch (Exception e) {
            status = false;
        }
        return status;
    }

  /**
     * 驗證Certificate
     *
     * @param keyStorePath
     * @param alias
     * @param password
     * @return
     */
    public static boolean verifyCertificate(String keyStorePath String alias
            String password) {
        return verifyCertificate(new Date() keyStorePath alias password);
    }

  /**
     * 獲得SSLSocektFactory
     *
     * @param password
     *            密碼
     * @param keyStorePath
     *            密鑰庫路徑
     *
     * @param trustKeyStorePath
     *            信任庫路徑
     * @return
     * @throws Exception
     */
    private static SSLSocketFactory getSSLSocketFactory(String password
            String keyStorePath String trustKeyStorePath) throws Exception {
        // 初始化密鑰庫
        KeyManagerFactory keyManagerFactory = KeyManagerFactory
                getInstance(SunX);
        KeyStore keyStore = getKeyStore(keyStorePath password);
        keyManagerFactoryinit(keyStore passwordtoCharArray());

  // 初始化信任庫
        TrustManagerFactory trustManagerFactory = TrustManagerFactory
                getInstance(SunX);
        KeyStore trustkeyStore = getKeyStore(trustKeyStorePath password);
        trustManagerFactoryinit(trustkeyStore);

  // 初始化SSL上下文
        SSLContext ctx = SSLContextgetInstance(SSL);
        ctxinit(keyManagerFactorygetKeyManagers() trustManagerFactory
                getTrustManagers() null);
        SSLSocketFactory sf = ctxgetSocketFactory();

  return sf;
    }

  /**
     * 為HttpsURLConnection配置SSLSocketFactory
     *
     * @param conn
     *            HttpsURLConnection
     * @param password
     *            密碼
     * @param keyStorePath
     *            密鑰庫路徑
     *
     * @param trustKeyStorePath
     *            信任庫路徑
     * @throws Exception
     */
    public static void configSSLSocketFactory(HttpsURLConnection conn
            String password String keyStorePath String trustKeyStorePath)
            throws Exception {
        connsetSSLSocketFactory(getSSLSocketFactory(password keyStorePath
                trustKeyStorePath));
    }
}

  增加了configSSLSocketFactory方法供外界調用該方法為HttpsURLConnection配置了SSLSocketFactory當HttpsURLConnection配置了SSLSocketFactory後我們就可以通過HttpsURLConnection的getInputStreamgetOutputStream像往常使用HttpURLConnection做操作了尤其要說明一點未配置SSLSocketFactory前HttpsURLConnection的getContentLength()獲得值永遠都是

  給出相應測試類

  Java代碼

  import static orgjunitAssert*;

  import javaioDataInputStream;
import javaioInputStream;
import URL;

  import sslHttpsURLConnection;

  import orgjunitTest;

  /**
 *
 * @author 梁棟
 * @version
 * @since
 */
public class CertificateCoderTest {
    private String password = ;
    private String alias = ;
    private String certificatePath = d:/zlexcer;
    private String keyStorePath = d:/zlexkeystore;
    private String clientKeyStorePath = d:/zlexclientkeystore;
    private String clientPassword = ;

  @Test
    public void test() throws Exception {
        Systemerrprintln(公鑰加密——私鑰解密);
        String inputStr = Ceritifcate;
        byte[] data = inputStrgetBytes();

  byte[] encrypt = CertificateCoderencryptByPublicKey(data
                certificatePath);

  byte[] decrypt = CertificateCoderdecryptByPrivateKey(encrypt
                keyStorePath alias password);
        String outputStr = new String(decrypt);

  Systemerrprintln(加密前: + inputStr + \n\r + 解密後: + outputStr);

  // 驗證數據一致
        assertArrayEquals(data decrypt);

  // 驗證證書有效
        assertTrue(CertificateCoderverifyCertificate(certificatePath));

  }

  @Test
    public void testSign() throws Exception {
        Systemerrprintln(私鑰加密——公鑰解密);

  String inputStr = sign;
        byte[] data = inputStrgetBytes();

  byte[] encodedData = CertificateCoderencryptByPrivateKey(data
                keyStorePath alias password);

  byte[] decodedData = CertificateCoderdecryptByPublicKey(encodedData
                certificatePath);

  String outputStr = new String(decodedData);
        Systemerrprintln(加密前: + inputStr + \n\r + 解密後: + outputStr);
        assertEquals(inputStr outputStr);

  Systemerrprintln(私鑰簽名——公鑰驗證簽名);
        // 產生簽名
        String sign = CertificateCodersign(encodedData keyStorePath alias
                password);
        Systemerrprintln(簽名:\r + sign);

  // 驗證簽名
        boolean status = CertificateCoderverify(encodedData sign
                certificatePath);
        Systemerrprintln(狀態:\r + status);
        assertTrue(status);

  }

  @Test
    public void testHttps() throws Exception {
        URL url = new URL();
        HttpsURLConnection conn = (HttpsURLConnection) urlopenConnection();

  connsetDoInput(true);
        connsetDoOutput(true);

  nfigSSLSocketFactory(conn clientPassword
                clientKeyStorePath clientKeyStorePath);

  InputStream is = conngetInputStream();

  int length = conngetContentLength();

  DataInputStream dis = new DataInputStream(is);
        byte[] data = new byte[length];
        disreadFully(data);

  disclose();
        Systemerrprintln(new String(data));
        conndisconnect();
    }
}

  注意testHttps方法幾乎和我們往常做HTTP訪問沒有差別我們來看控制台輸出

  Console代碼

  <!
  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership
  The ASF licenses this file to You under the Apache License Version
  (the License); you may not use this file except in compliance with
  the License  You may obtain a copy of the License at

  

  Unless required by applicable law or agreed to in writing software
  distributed under the License is distributed on an AS IS BASIS
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied
  See the License for the specific language governing permissions and
  limitations under the License
>
<!DOCTYPE HTML PUBLIC //WC//DTD HTML Transitional//EN>
<HTML><HEAD><TITLE>Apache Tomcat Examples</TITLE>
<META httpequiv=ContentType content=text/html>
</HEAD>
<BODY>
<P>
<H>Apache Tomcat Examples</H>
<P></P>
<ul>
<li><a >Servlets examples</a></li>
<li><a >JSP Examples</a></li>
</ul>
</BODY></HTML>

    通過浏覽器直接訪問你也會獲得上述內容也就是說應用甲方作為服務器構建tomcat服務乙方可以通過上述方式訪問甲方受保護的SSL應用並且不需要考慮具體的加密解密問題甲乙雙方可以經過相應配置通過雙方的tomcat配置有效的SSL服務簡化上述代碼實現完全通過證書配置完成SSL雙向認證!


From:http://tw.wingwit.com/Article/program/Java/gj/201311/27353.html
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.