现在的位置: 首页 > 综合 > 正文

Java加密技术(九)

2013年11月28日 ⁄ 综合 ⁄ 共 15454字 ⁄ 字号 评论关闭

关键字: ssl

    在Java加密技术(八)中,我们模拟了一个基于RSA非对称加密网络的安全通信。现在我们深度了解一下现有的安全网络通信——SSL。
    我们需要构建一个由CA机构签发的有效证书,这里我们使用上文中生成的自签名证书zlex.cer
    这里,我们将证书导入到我们的密钥库。

Shell代码 复制代码
  1. 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

控制台输出:

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

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。将如下内容加入配置文件

Xml代码 复制代码
  1. <Connector  
  2.     SSLEnabled="true"  
  3.     URIEncoding="UTF-8"  
  4.     clientAuth="false"  
  5.     keystoreFile="conf/zlex.keystore"  
  6.     keystorePass="123456"  
  7.     maxThreads="150"  
  8.     port="443"  
  9.     protocol="HTTP/1.1"  
  10.     scheme="https"  
  11.     secure="true"  
  12.     sslProtocol="TLS" />  

注意clientAuth="false"测试阶段,置为false,正式使用时建议使用true。现在启动tomcat,访问https://www.zlex.org/
显然,证书未能通过认证,这个时候你可以选择安装证书(上文中的zlex.cer文件就是证书),作为受信任的根证书颁发机构导入,再次重启浏览器(IE,其他浏览器对于域名www.zlex.org不支持本地方式访问),访问https://www.zlex.org/,你会看到地址栏中会有个小锁,就说明安装成功。所有的浏览器联网操作已经在RSA加密解密系统的保护之下了。但似乎我们感受不到。
这个时候很多人开始怀疑,如果我们要手工做一个这样的https的访问是不是需要把浏览器的这些个功能都实现呢?不需要!

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

Java代码 复制代码
  1. import java.io.FileInputStream;   
  2. import java.security.KeyStore;   
  3. import java.security.PrivateKey;   
  4. import java.security.PublicKey;   
  5. import java.security.Signature;   
  6. import java.security.cert.Certificate;   
  7. import java.security.cert.CertificateFactory;   
  8. import java.security.cert.X509Certificate;   
  9. import java.util.Date;   
  10.   
  11. import javax.crypto.Cipher;   
  12. import javax.net.ssl.HttpsURLConnection;   
  13. import javax.net.ssl.KeyManagerFactory;   
  14. import javax.net.ssl.SSLContext;   
  15. import javax.net.ssl.SSLSocketFactory;   
  16. import javax.net.ssl.TrustManagerFactory;   
  17.   
  18. /**  
  19.  * 证书组件  
  20.  *   
  21.  * @author 梁栋  
  22.  * @version 1.0  
  23.  * @since 1.0  
  24.  */  
  25. public abstract class CertificateCoder extends Coder {   
  26.   
  27.     /**  
  28.      * Java密钥库(Java Key Store,JKS)KEY_STORE  
  29.      */  
  30.     public static final String KEY_STORE = "JKS";   
  31.   
  32.     public static final String X509 = "X.509";   
  33.     public static final String SunX509 = "SunX509";   
  34.     public static final String SSL = "SSL";   
  35.   
  36.     /**  
  37.      * 由KeyStore获得私钥  
  38.      *   
  39.      * @param keyStorePath  
  40.      * @param alias  
  41.      * @param password  
  42.      * @return  
  43.      * @throws Exception  
  44.      */  
  45.     private static PrivateKey getPrivateKey(String keyStorePath, String alias,   
  46.             String password) throws Exception {   
  47.         KeyStore ks = getKeyStore(keyStorePath, password);   
  48.         PrivateKey key = (PrivateKey) ks.getKey(alias, password.toCharArray());   
  49.         return key;   
  50.     }   
  51.   
  52.     /**  
  53.      * 由Certificate获得公钥  
  54.      *   
  55.      * @param certificatePath  
  56.      * @return  
  57.      * @throws Exception  
  58.      */  
  59.     private static PublicKey getPublicKey(String certificatePath)   
  60.             throws Exception {   
  61.         Certificate certificate = getCertificate(certificatePath);   
  62.         PublicKey key = certificate.getPublicKey();   
  63.         return key;   
  64.     }   
  65.   
  66.     /**  
  67.      * 获得Certificate  
  68.      *   
  69.      * @param certificatePath  
  70.      * @return  
  71.      * @throws Exception  
  72.      */  
  73.     private static Certificate getCertificate(String certificatePath)   
  74.             throws Exception {   
  75.         CertificateFactory certificateFactory = CertificateFactory   
  76.                 .getInstance(X509);   
  77.         FileInputStream in = new FileInputStream(certificatePath);   
  78.   
  79.         Certificate certificate = certificateFactory.generateCertificate(in);   
  80.         in.close();   
  81.   
  82.         return certificate;   
  83.     }   
  84.   
  85.     /**  
  86.      * 获得Certificate  
  87.      *   
  88.      * @param keyStorePath  
  89.      * @param alias  
  90.      * @param password  
  91.      * @return  
  92.      * @throws Exception  
  93.      */  
  94.     private static Certificate getCertificate(String keyStorePath,   
  95.             String alias, String password) throws Exception {   
  96.         KeyStore ks = getKeyStore(keyStorePath, password);   
  97.         Certificate certificate = ks.getCertificate(alias);   
  98.   
  99.         return certificate;   
  100.     }   
  101.   
  102.     /**  
  103.      * 获得KeyStore  
  104.      *   
  105.      * @param keyStorePath  
  106.      * @param password  
  107.      * @return  
  108.      * @throws Exception  
  109.      */  
  110.     private static KeyStore getKeyStore(String keyStorePath, String password)   
  111.             throws Exception {   
  112.         FileInputStream is = new FileInputStream(keyStorePath);   
  113.         KeyStore ks = KeyStore.getInstance(KEY_STORE);   
  114.         ks.load(is, password.toCharArray());   
  115.         is.close();   
  116.         return ks;   
  117.     }   
  118.   
  119.     /**  
  120.      * 私钥加密  
  121.      *   
  122.      * @param data  
  123.      * @param keyStorePath  
  124.      * @param alias  
  125.      * @param password  
  126.      * @return  
  127.      * @throws Exception  
  128.      */  
  129.     public static byte[] encryptByPrivateKey(byte[] data, String keyStorePath,   
  130.             String alias, String password) throws Exception {   
  131.         // 取得私钥   
  132.         PrivateKey privateKey = getPrivateKey(keyStorePath, alias, password);   
  133.   
  134.         // 对数据加密   
  135.         Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());   
  136.         cipher.init(Cipher.ENCRYPT_MODE, privateKey);   
  137.   
  138.         return cipher.doFinal(data);   
  139.   
  140.     }   
  141.   
  142.     /**  
  143.      * 私钥解密  
  144.      *   
  145.      * @param data  
  146.      * @param keyStorePath  
  147.      * @param alias  
  148.      * @param password  
  149.      * @return  
  150.      * @throws Exception  
  151.      */  
  152.     public static byte[] decryptByPrivateKey(byte[] data, String keyStorePath,   
  153.             String alias, String password) throws Exception {   
  154.         // 取得私钥   
  155.         PrivateKey privateKey = getPrivateKey(keyStorePath, alias, password);   
  156.   
  157.         // 对数据加密   
  158.         Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());   
  159.         cipher.init(Cipher.DECRYPT_MODE, privateKey);   
  160.   
  161.         return cipher.doFinal(data);   
  162.   
  163.     }   
  164.   
  165.     /**  
  166.      * 公钥加密  
  167.      *   
  168.      * @param data  
  169.      * @param certificatePath  
  170.      * @return  
  171.      * @throws Exception  
  172.      */  
  173.     public static byte[] encryptByPublicKey(byte[] data, String certificatePath)   
  174.             throws Exception {   
  175.   
  176.         // 取得公钥   
  177.         PublicKey publicKey = getPublicKey(certificatePath);   
  178.         // 对数据加密   
  179.         Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());   
  180.         cipher.init(Cipher.ENCRYPT_MODE, publicKey);   
  181.   
  182.         return cipher.doFinal(data);   
  183.   
  184.     }   
  185.   
  186.     /**  
  187.      * 公钥解密  
  188.      *   
  189.      * @param data  
  190.      * @param certificatePath  
  191.      * @return  
  192.      * @throws Exception  
  193.      */  
  194.     public static byte[] decryptByPublicKey(byte[] data, String certificatePath)   
  195.             throws Exception {   
  196.         // 取得公钥   
  197.         PublicKey publicKey = getPublicKey(certificatePath);   
  198.   
  199.         // 对数据加密   
  200.         Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());   
  201.         cipher.init(Cipher.DECRYPT_MODE, publicKey);   
  202.   
  203.         return cipher.doFinal(data);   
  204.   
  205.     }   
  206.   
  207.     /**  
  208.      * 验证Certificate  
  209.      *   
  210.      * @param certificatePath  
  211.      * @return  
  212.      */  
  213.     public static boolean verifyCertificate(String certificatePath) {   
  214.         return verifyCertificate(new Date(), certificatePath);   
  215.     }   
  216.   
  217.     /**  
  218.      * 验证Certificate是否过期或无效  
  219.      *   
  220.      * @param date  
  221.      * @param certificatePath  
  222.      * @return  
  223.      */  
  224.     public static boolean verifyCertificate(Date date, String certificatePath) {   
  225.         boolean status = true;   
  226.         try {   
  227.             // 取得证书   
  228.             Certificate certificate = getCertificate(certificatePath);   
  229.             // 验证证书是否过期或无效   
  230.             status = verifyCertificate(date, certificate);   
  231.         } catch (Exception e) {   
  232.             status = false;   
  233.         }   
  234.         return status;   
  235.     }   
  236.   
  237.     /**  
  238.      * 验证证书是否过期或无效  
  239.      *   
  240.      * @param date  
  241.      * @param certificate  
  242.      * @return  
  243.      */  
  244.     private static boolean verifyCertificate(Date date, Certificate certificate) {   
  245.         boolean status = true;   
  246.         try {   
  247.             X509Certificate x509Certificate = (X509Certificate) certificate;   
  248.             x509Certificate.checkValidity(date);   
  249.         } catch (Exception e) {   
  250.             status = false;   
  251.         }   
  252.         return status;   
  253.     }   
  254.   
  255.     /**  
  256.      * 签名  
  257.      *   
  258.      * @param keyStorePath  
  259.      * @param alias  
  260.      * @param password  
  261.      *   
  262.      * @return  
  263.      * @throws Exception  
  264.      */  
  265.     public static String sign(byte[] sign, String keyStorePath, String alias,   
  266.             String password) throws Exception {   
  267.         // 获得证书   
  268.         X509Certificate x509Certificate = (X509Certificate) getCertificate(   
  269.                 keyStorePath, alias, password);   
  270.         // 获取私钥   
  271.         KeyStore ks = getKeyStore(keyStorePath, password);   
  272.         // 取得私钥   
  273.         PrivateKey privateKey = (PrivateKey) ks.getKey(alias, password   
  274.                 .toCharArray());   
  275.   
  276.         // 构建签名   
  277.         Signature signature = Signature.getInstance(x509Certificate   
  278.                 .getSigAlgName());   
  279.         signature.initSign(privateKey);   
  280.         signature.update(sign);   
  281.         return encryptBASE64(signature.sign());   
  282.     }   
  283.   
  284.     /**  
  285.      * 验证签名  
  286.      *   
  287.      * @param data  
  288.      * @param sign  
  289.      * @param certificatePath  
  290.      * @return  
  291.      * @throws Exception  
  292.      */  
  293.     public static boolean verify(byte[] data, String sign,   
  294.             String certificatePath) throws Exception {   
  295.         // 获得证书   
  296.         X509Certificate x509Certificate = (X509Certificate) getCertificate(certificatePath);   
  297.         // 获得公钥   
  298.         PublicKey publicKey = x509Certificate.getPublicKey();   
  299.         // 构建签名   
  300.         Signature signature = Signature.getInstance(x509Certificate   
  301.                 .getSigAlgName());   
  302.         signature.initVerify(publicKey);   
  303.         signature.update(data);   
  304.   
  305.         return signature.verify(decryptBASE64(sign));   
  306.   
  307.     }   
  308.   
  309.     /**  
  310.      * 验证Certificate  
  311.      *   
  312.      * @param keyStorePath  
  313.      * @param alias  
  314.      * @param password  
  315.      * @return  
  316.      */  
  317.     public static boolean verifyCertificate(Date date, String keyStorePath,   
  318.             String alias, String password) {   
  319.         boolean status = true;   
  320.         try {   
  321.             Certificate certificate = getCertificate(keyStorePath, alias,   
  322.                     password);   
  323.             status = verifyCertificate(date, certificate);   
  324.         } catch (Exception e) {   
  325.             status = false;   
  326.         }   
  327.         return status;   
  328.     }   
  329.   
  330.     /**  
  331.      * 验证Certificate  
  332.      *   
  333.      * @param keyStorePath  
  334.      * @param alias  
  335.      * @param password  
  336.      * @return  
  337.      */  
  338.     public static boolean verifyCertificate(String keyStorePath, String alias,   
  339.             String password) {   
  340.         return verifyCertificate(new Date(), keyStorePath, alias, password);   
  341.     }   
  342.   
  343.     /**  
  344.      * 获得SSLSocektFactory  
  345.      *   
  346.      * @param password  
  347.      *            密码  
  348.      * @param keyStorePath  
  349.      *            密钥库路径  
  350.      *   
  351.      * @param trustKeyStorePath  
  352.      *            信任库路径  
  353.      * @return  
  354.      * @throws Exception  
  355.      */  
  356.     private static SSLSocketFactory getSSLSocketFactory(String password,   
  357.             String keyStorePath, String trustKeyStorePath) throws Exception {   
  358.         // 初始化密钥库   
  359.         KeyManagerFactory keyManagerFactory = KeyManagerFactory   
  360.                 .getInstance(SunX509);   
  361.         KeyStore keyStore = getKeyStore(keyStorePath, password);   
  362.         keyManagerFactory.init(keyStore, password.toCharArray());   
  363.   
  364.         // 初始化信任库   
  365.         TrustManagerFactory trustManagerFactory = TrustManagerFactory   
  366.                 .getInstance(SunX509);   
  367.         KeyStore trustkeyStore = getKeyStore(trustKeyStorePath, password);   
  368.         trustManagerFactory.init(trustkeyStore);   
  369.   
  370.         // 初始化SSL上下文   
  371.         SSLContext ctx = SSLContext.getInstance(SSL);   
  372.         ctx.init(keyManagerFactory.getKeyManagers(), trustManagerFactory   
  373.                 .getTrustManagers(), null);   
  374.         SSLSocketFactory sf = ctx.getSocketFactory();   
  375.   
  376.         return sf;   
  377.     }   
  378.   
  379.     /**  
  380.      * 为HttpsURLConnection配置SSLSocketFactory  
  381.      *   
  382.      * @param conn  
  383.      *            HttpsURLConnection  
  384.      * @param password  
  385.      *            密码  
  386.      * @param keyStorePath  
  387.      *            密钥库路径  
  388.      *   
  389.      * @param trustKeyStorePath  
  390.      *            信任库路径  
  391.      * @throws Exception  
  392.      */  
  393.     public static void configSSLSocketFactory(HttpsURLConnection conn,   
  394.             String password, String keyStorePath, String trustKeyStorePath)   
  395.             throws Exception {   
  396.         conn.setSSLSocketFactory(getSSLSocketFactory(password, keyStorePath,   
  397.                 trustKeyStorePath));   
  398.     }   
  399. }  

抱歉!评论已关闭.