原文地址

http://snowolf.iteye.com/blog/397693

 

  我们需要构建一个由CA机构签发的有效证书,这里我们使用上文中生成的自签名证书zlex.cer 
    这里,我们将证书导入到我们的密钥库。

keytool -import -alias www.zlex.org -file d:/zlex.cer -keystore d:/zlex.keystore  

其中 
-import表示导入 
-alias指定别名,这里是www.zlex.org 
-file指定算法,这里是d:/zlex.cer 
-keystore指定存储位置,这里是d:/zlex.keystore 
在这里我使用的密码为654321 

控制台输出: 

java-信息安全(十四)-初探SSL
输入keystore密码:  
再次输入新密码:  
所有者:CN=www.zlex.org, OU=zlex, O=zlex, L=BJ, ST=BJ, C=CN  
签发人:CN=www.zlex.org, OU=zlex, O=zlex, L=BJ, ST=BJ, C=CN  
序列号:4a1e48df  
有效期: Thu May 28 16:18:39 CST 2009 至Wed Aug 26 16:18:39 CST 2009  
证书指纹:  
         MD5:19:CA:E6:36:E2:DF:AD:96:31:97:2F:A9:AD:FC:37:6A  
         SHA1:49:88:30:59:29:45:F1:69:CA:97:A9:6D:8A:CF:08:D2:C3:D5:C0:C4  
         签名算法名称:SHA1withRSA  
         版本: 3  
信任这个认证? [否]:  y  
认证已添加至keystore中  
java-信息安全(十四)-初探SSL

OK,最复杂的准备工作已经完成。 
接下来我们将域名www.zlex.org定位到本机上。打开C:\Windows\System32\drivers\etc\hosts文件,将www.zlex.org绑定在本机上。在文件末尾追加127.0.0.1       www.zlex.org。现在通过地址栏访问http://www.zlex.org,或者通过ping命令,如果能够定位到本机,域名映射就搞定了。 
现在,配置tomcat。先将zlex.keystore拷贝到tomcat的conf目录下,然后配置server.xml。将如下内容加入配置文件:

java-信息安全(十四)-初探SSL
<Connector  
    SSLEnabled="true"  
    URIEncoding="UTF-8"  
    clientAuth="false"  
    keystoreFile="conf/zlex.keystore"  
    keystorePass="123456"  
    maxThreads="150"  
    port="443"  
    protocol="HTTP/1.1"  
    scheme="https"  
    secure="true"  
    sslProtocol="TLS" />  
java-信息安全(十四)-初探SSL

注意clientAuth="false"测试阶段,置为false,正式使用时建议使用true。现在启动tomcat,访问https://www.zlex.org/java-信息安全(十四)-初探SSL

显然,证书未能通过认证,这个时候你可以选择安装证书(上文中的zlex.cer文件就是证书),作为受信任的根证书颁发机构导入,再次重启浏览器(IE,其他浏览器对于域名www.zlex.org不支持本地方式访问),访问https://www.zlex.org/,你会看到地址栏中会有个小锁java-信息安全(十四)-初探SSL,就说明安装成功。所有的浏览器联网操作已经在RSA加密解密系统的保护之下了。但似乎我们感受不到。 

这个时候很多人开始怀疑,如果我们要手工做一个这样的https的访问是不是需要把浏览器的这些个功能都实现呢?不需要! 

接着上篇内容,给出如下代码实现: 

java-信息安全(十四)-初探SSL
import java.io.FileInputStream;  
import java.security.KeyStore;  
import java.security.PrivateKey;  
import java.security.PublicKey;  
import java.security.Signature;  
import java.security.cert.Certificate;  
import java.security.cert.CertificateFactory;  
import java.security.cert.X509Certificate;  
import java.util.Date;  
  
import javax.crypto.Cipher;  
import javax.net.ssl.HttpsURLConnection;  
import javax.net.ssl.KeyManagerFactory;  
import javax.net.ssl.SSLContext;  
import javax.net.ssl.SSLSocketFactory;  
import javax.net.ssl.TrustManagerFactory;  
  
/** 
 * 证书组件 
 *  
 * @author 梁栋 
 * @version 1.0 
 * @since 1.0 
 */  
public abstract class CertificateCoder extends Coder {  
  
    /** 
     * Java密钥库(Java Key Store,JKS)KEY_STORE 
     */  
    public static final String KEY_STORE = "JKS";  
  
    public static final String X509 = "X.509";  
    public static final String SunX509 = "SunX509";  
    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) ks.getKey(alias, password.toCharArray());  
        return key;  
    }  
  
    /** 
     * 由Certificate获得公钥 
     *  
     * @param certificatePath 
     * @return 
     * @throws Exception 
     */  
    private static PublicKey getPublicKey(String certificatePath)  
            throws Exception {  
        Certificate certificate = getCertificate(certificatePath);  
        PublicKey key = certificate.getPublicKey();  
        return key;  
    }  
  
    /** 
     * 获得Certificate 
     *  
     * @param certificatePath 
     * @return 
     * @throws Exception 
     */  
    private static Certificate getCertificate(String certificatePath)  
            throws Exception {  
        CertificateFactory certificateFactory = CertificateFactory  
                .getInstance(X509);  
        FileInputStream in = new FileInputStream(certificatePath);  
  
        Certificate certificate = certificateFactory.generateCertificate(in);  
        in.close();  
  
        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 = ks.getCertificate(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 = KeyStore.getInstance(KEY_STORE);  
        ks.load(is, password.toCharArray());  
        is.close();  
        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 = Cipher.getInstance(privateKey.getAlgorithm());  
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);  
  
        return cipher.doFinal(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 = Cipher.getInstance(privateKey.getAlgorithm());  
        cipher.init(Cipher.DECRYPT_MODE, privateKey);  
  
        return cipher.doFinal(data);  
  
    }  
  
    /** 
     * 公钥加密 
     *  
     * @param data 
     * @param certificatePath 
     * @return 
     * @throws Exception 
     */  
    public static byte[] encryptByPublicKey(byte[] data, String certificatePath)  
            throws Exception {  
  
        // 取得公钥  
        PublicKey publicKey = getPublicKey(certificatePath);  
        // 对数据加密  
        Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());  
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);  
  
        return cipher.doFinal(data);  
  
    }  
  
    /** 
     * 公钥解密 
     *  
     * @param data 
     * @param certificatePath 
     * @return 
     * @throws Exception 
     */  
    public static byte[] decryptByPublicKey(byte[] data, String certificatePath)  
            throws Exception {  
        // 取得公钥  
        PublicKey publicKey = getPublicKey(certificatePath);  
  
        // 对数据加密  
        Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());  
        cipher.init(Cipher.DECRYPT_MODE, publicKey);  
  
        return cipher.doFinal(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 {  
            X509Certificate x509Certificate = (X509Certificate) certificate;  
            x509Certificate.checkValidity(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 {  
        // 获得证书  
        X509Certificate x509Certificate = (X509Certificate) getCertificate(  
                keyStorePath, alias, password);  
        // 获取私钥  
        KeyStore ks = getKeyStore(keyStorePath, password);  
        // 取得私钥  
        PrivateKey privateKey = (PrivateKey) ks.getKey(alias, password  
                .toCharArray());  
  
        // 构建签名  
        Signature signature = Signature.getInstance(x509Certificate  
                .getSigAlgName());  
        signature.initSign(privateKey);  
        signature.update(sign);  
        return encryptBASE64(signature.sign());  
    }  
  
    /** 
     * 验证签名 
     *  
     * @param data 
     * @param sign 
     * @param certificatePath 
     * @return 
     * @throws Exception 
     */  
    public static boolean verify(byte[] data, String sign,  
            String certificatePath) throws Exception {  
        // 获得证书  
        X509Certificate x509Certificate = (X509Certificate) getCertificate(certificatePath);  
        // 获得公钥  
        PublicKey publicKey = x509Certificate.getPublicKey();  
        // 构建签名  
        Signature signature = Signature.getInstance(x509Certificate  
                .getSigAlgName());  
        signature.initVerify(publicKey);  
        signature.update(data);  
  
        return signature.verify(decryptBASE64(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(SunX509);  
        KeyStore keyStore = getKeyStore(keyStorePath, password);  
        keyManagerFactory.init(keyStore, password.toCharArray());  
  
        // 初始化信任库  
        TrustManagerFactory trustManagerFactory = TrustManagerFactory  
                .getInstance(SunX509);  
        KeyStore trustkeyStore = getKeyStore(trustKeyStorePath, password);  
        trustManagerFactory.init(trustkeyStore);  
  
        // 初始化SSL上下文  
        SSLContext ctx = SSLContext.getInstance(SSL);  
        ctx.init(keyManagerFactory.getKeyManagers(), trustManagerFactory  
                .getTrustManagers(), null);  
        SSLSocketFactory sf = ctx.getSocketFactory();  
  
        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 {  
        conn.setSSLSocketFactory(getSSLSocketFactory(password, keyStorePath,  
                trustKeyStorePath));  
    }  
}  
java-信息安全(十四)-初探SSL

相关文章: