• 基於數字證書的數據加密算法


      1 package com.ice.webos.util.security;
    2
    3 import java.io.DataInputStream;
    4 import java.io.FileInputStream;
    5 import java.io.InputStream;
    6 import java.net.URL;
    7 import java.security.KeyStore;
    8 import java.security.PrivateKey;
    9 import java.security.PublicKey;
    10 import java.security.Signature;
    11 import java.security.cert.Certificate;
    12 import java.security.cert.CertificateFactory;
    13 import java.security.cert.X509Certificate;
    14 import java.util.Date;
    15
    16 import javax.crypto.Cipher;
    17 import javax.net.ssl.HttpsURLConnection;
    18 import javax.net.ssl.KeyManagerFactory;
    19 import javax.net.ssl.SSLContext;
    20 import javax.net.ssl.SSLSocketFactory;
    21 import javax.net.ssl.TrustManagerFactory;
    22
    23 /**
    24 * 证书的制作,导入,删除
    25 * <ul>
    26 * <li>生成keyStroe文件</li>
    27 * <ul>
    28 * <li>keytool -genkey -validity 36000 -alias 192.168.20.230 -keyalg RSA
    29 * -keystore d:\zlex.keystore</li>
    30 * <ul>
    31 * 参数说明
    32 * <li>-genkey表示生成密钥</li>
    33 * <li>-validity指定证书有效期,这里是36000天</li>
    34 * <li>-alias指定别名,这里是192.168.20.230</li>
    35 * <li>-keyalg指定算法,这里是RSA</li>
    36 * <li>-keystore指定存储位置,这里是d:\zlex.keystore</li>
    37 * </ul>
    38 * </ul>
    39 * <li>生成自签名证书</li>
    40 * <ul>
    41 * <li>keytool -export -keystore d:\zlex.keystore -alias 192.168.20.230 -file
    42 * d:\zlex.cer -rfc</li>
    43 * <ul>
    44 * 参数说明
    45 * <li>-export指定为导出操作</li>
    46 * <li>-keystore指定keystore文件</li>
    47 * <li>-alias指定导出keystore文件中的别名</li>
    48 * <li>-file指向导出路径</li>
    49 * <li>-rfc以文本格式输出,也就是以BASE64编码输出 </li>
    50 * </ul>
    51 * </ul>
    52 * <li>证书导入到密钥库</li>
    53 * <ul>
    54 * <li>keytool -import -alias 192.168.20.230 -file d:/zlex.cer -keystore
    55 * d:/zlex.keystore</li>
    56 * <ul>
    57 * 参数说明
    58 * <li>-import表示导入</li>
    59 * <li>-alias指定别名,这里是192.168.20.230</li>
    60 * <li>-file指定算法,这里是d:/zlex.cer</li>
    61 * <li>-keystore指定存储位置,这里是d:/zlex.keystore </li>
    62 * </ul>
    63 * </ul>
    64 * <li>配置tomcat</li>
    65 * <ul>
    66 * <li>将zlex.keystore拷贝到tomcat的conf目录下</li>
    67 * <li>配置server.xml。将如下内容加入配置文件<br>
    68 * &lt;Connector SSLEnabled="true" URIEncoding="UTF-8" clientAuth="false"
    69 * keystoreFile="conf/zlex.keystore" keystorePass="654321" maxThreads="150"
    70 * port="443" protocol="HTTP/1.1" scheme="https" secure="true" sslProtocol="TLS" />
    71 * </li>
    72 * <li>clientAuth="false"测试阶段,置为false,正式使用时建议使用true</li>
    73 * <li>启动tomcat,访问https://192.168.20.230</li>
    74 * <li></li>
    75 * </ul>
    76 * <li>证书的删除</li>
    77 * <ul>
    78 * <li>命令行中输入 certmgr.msc</li>
    79 * <li>找到安装的证书,删除即可</li>
    80 * </ul>
    81 * </ul>
    82 *
    83 * @author Ice_Liu
    84 *
    85 */
    86 public class Certificateutil {
    87 /**
    88 * Java密钥库(Java Key Store,JKS)KEY_STORE
    89 */
    90 public static final String KEY_STORE = "JKS";
    91
    92 public static final String X509 = "X.509";
    93 public static final String SunX509 = "SunX509";
    94 public static final String SSL = "SSL";
    95
    96 /**
    97 * 由 KeyStore获得私钥
    98 *
    99 * @param keyStorePath
    100 * @param alias
    101 * @param password
    102 * @return
    103 * @throws Exception
    104 */
    105 private static PrivateKey getPrivateKey(String keyStorePath, String alias, String password)
    106 throws Exception {
    107 KeyStore ks = getKeyStore(keyStorePath, password);
    108 PrivateKey key = (PrivateKey) ks.getKey(alias, password.toCharArray());
    109 return key;
    110 }
    111
    112 /**
    113 * 由 Certificate获得公钥
    114 *
    115 * @param certificatePath
    116 * @return
    117 * @throws Exception
    118 */
    119 private static PublicKey getPublicKey(String certificatePath) throws Exception {
    120 Certificate certificate = getCertificate(certificatePath);
    121 PublicKey key = certificate.getPublicKey();
    122 return key;
    123 }
    124
    125 /**
    126 * 获得Certificate
    127 *
    128 * @param certificatePath
    129 * @return
    130 * @throws Exception
    131 */
    132 private static Certificate getCertificate(String certificatePath) throws Exception {
    133 CertificateFactory certificateFactory = CertificateFactory.getInstance(X509);
    134 FileInputStream in = new FileInputStream(certificatePath);
    135
    136 Certificate certificate = certificateFactory.generateCertificate(in);
    137 in.close();
    138
    139 return certificate;
    140 }
    141
    142 /**
    143 * 获得Certificate
    144 *
    145 * @param keyStorePath
    146 * @param alias
    147 * @param password
    148 * @return
    149 * @throws Exception
    150 */
    151 private static Certificate getCertificate(String keyStorePath, String alias, String password)
    152 throws Exception {
    153 KeyStore ks = getKeyStore(keyStorePath, password);
    154 Certificate certificate = ks.getCertificate(alias);
    155
    156 return certificate;
    157 }
    158
    159 /**
    160 * 获得KeyStore
    161 *
    162 * @param keyStorePath
    163 * @param password
    164 * @return
    165 * @throws Exception
    166 */
    167 private static KeyStore getKeyStore(String keyStorePath, String password) throws Exception {
    168 FileInputStream is = new FileInputStream(keyStorePath);
    169 KeyStore ks = KeyStore.getInstance(KEY_STORE);
    170 ks.load(is, password.toCharArray());
    171 is.close();
    172 return ks;
    173 }
    174
    175 /**
    176 * 私钥加密
    177 *
    178 * @param data
    179 * @param keyStorePath
    180 * @param alias
    181 * @param password
    182 * @return
    183 * @throws Exception
    184 */
    185 public static byte[] encryptByPrivateKey(byte[] data, String keyStorePath, String alias,
    186 String password) throws Exception {
    187 // 取得私钥
    188 PrivateKey privateKey = getPrivateKey(keyStorePath, alias, password);
    189
    190 // 对数据加密
    191 Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
    192 cipher.init(Cipher.ENCRYPT_MODE, privateKey);
    193
    194 return cipher.doFinal(data);
    195
    196 }
    197
    198 /**
    199 * 私钥解密
    200 *
    201 * @param data
    202 * @param keyStorePath
    203 * @param alias
    204 * @param password
    205 * @return
    206 * @throws Exception
    207 */
    208 public static byte[] decryptByPrivateKey(byte[] data, String keyStorePath, String alias,
    209 String password) throws Exception {
    210 // 取得私钥
    211 PrivateKey privateKey = getPrivateKey(keyStorePath, alias, password);
    212
    213 // 对数据加密
    214 Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
    215 cipher.init(Cipher.DECRYPT_MODE, privateKey);
    216
    217 return cipher.doFinal(data);
    218
    219 }
    220
    221 /**
    222 * 公钥加密
    223 *
    224 * @param data
    225 * @param certificatePath
    226 * @return
    227 * @throws Exception
    228 */
    229 public static byte[] encryptByPublicKey(byte[] data, String certificatePath) throws Exception {
    230
    231 // 取得公钥
    232 PublicKey publicKey = getPublicKey(certificatePath);
    233 // 对数据加密
    234 Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());
    235 cipher.init(Cipher.ENCRYPT_MODE, publicKey);
    236
    237 return cipher.doFinal(data);
    238
    239 }
    240
    241 /**
    242 * 公钥解密
    243 *
    244 * @param data
    245 * @param certificatePath
    246 * @return
    247 * @throws Exception
    248 */
    249 public static byte[] decryptByPublicKey(byte[] data, String certificatePath) throws Exception {
    250 // 取得公钥
    251 PublicKey publicKey = getPublicKey(certificatePath);
    252
    253 // 对数据加密
    254 Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());
    255 cipher.init(Cipher.DECRYPT_MODE, publicKey);
    256
    257 return cipher.doFinal(data);
    258
    259 }
    260
    261 /**
    262 * 验证Certificate
    263 *
    264 * @param certificatePath
    265 * @return
    266 */
    267 public static boolean verifyCertificate(String certificatePath) {
    268 return verifyCertificate(new Date(), certificatePath);
    269 }
    270
    271 /**
    272 * 验证Certificate是否过期或无效
    273 *
    274 * @param date
    275 * @param certificatePath
    276 * @return
    277 */
    278 public static boolean verifyCertificate(Date date, String certificatePath) {
    279 boolean status = true;
    280 try {
    281 // 取得证书
    282 Certificate certificate = getCertificate(certificatePath);
    283 // 验证证书是否过期或无效
    284 status = verifyCertificate(date, certificate);
    285 } catch (Exception e) {
    286 status = false;
    287 }
    288 return status;
    289 }
    290
    291 /**
    292 * 验证证书是否过期或无效
    293 *
    294 * @param date
    295 * @param certificate
    296 * @return
    297 */
    298 private static boolean verifyCertificate(Date date, Certificate certificate) {
    299 boolean status = true;
    300 try {
    301 X509Certificate x509Certificate = (X509Certificate) certificate;
    302 x509Certificate.checkValidity(date);
    303 } catch (Exception e) {
    304 status = false;
    305 }
    306 return status;
    307 }
    308
    309 /**
    310 * 签名
    311 *
    312 * @param keyStorePath
    313 * @param alias
    314 * @param password
    315 *
    316 * @return
    317 * @throws Exception
    318 */
    319 public static String sign(byte[] sign, String keyStorePath, String alias, String password)
    320 throws Exception {
    321 // 获得证书
    322 X509Certificate x509Certificate = (X509Certificate) getCertificate(keyStorePath, alias,
    323 password);
    324 // 获取私钥
    325 KeyStore ks = getKeyStore(keyStorePath, password);
    326 // 取得私钥
    327 PrivateKey privateKey = (PrivateKey) ks.getKey(alias, password.toCharArray());
    328
    329 // 构建签名
    330 Signature signature = Signature.getInstance(x509Certificate.getSigAlgName());
    331 signature.initSign(privateKey);
    332 signature.update(sign);
    333 return CryptUtil.encryptBASE64(signature.sign());
    334 }
    335
    336 /**
    337 * 验证签名
    338 *
    339 * @param data
    340 * @param sign
    341 * @param certificatePath
    342 * @return
    343 * @throws Exception
    344 */
    345 public static boolean verify(byte[] data, String sign, String certificatePath) throws Exception {
    346 // 获得证书
    347 X509Certificate x509Certificate = (X509Certificate) getCertificate(certificatePath);
    348 // 获得公钥
    349 PublicKey publicKey = x509Certificate.getPublicKey();
    350 // 构建签名
    351 Signature signature = Signature.getInstance(x509Certificate.getSigAlgName());
    352 signature.initVerify(publicKey);
    353 signature.update(data);
    354
    355 return signature.verify(CryptUtil.decryptBASE64(sign));
    356
    357 }
    358
    359 /**
    360 * 验证Certificate
    361 *
    362 * @param keyStorePath
    363 * @param alias
    364 * @param password
    365 * @return
    366 */
    367 public static boolean verifyCertificate(Date date, String keyStorePath, String alias,
    368 String password) {
    369 boolean status = true;
    370 try {
    371 Certificate certificate = getCertificate(keyStorePath, alias, password);
    372 status = verifyCertificate(date, certificate);
    373 } catch (Exception e) {
    374 status = false;
    375 }
    376 return status;
    377 }
    378
    379 /**
    380 * 验证Certificate
    381 *
    382 * @param keyStorePath
    383 * @param alias
    384 * @param password
    385 * @return
    386 */
    387 public static boolean verifyCertificate(String keyStorePath, String alias, String password) {
    388 return verifyCertificate(new Date(), keyStorePath, alias, password);
    389 }
    390
    391 /**
    392 * 获得SSLSocektFactory
    393 *
    394 * @param password
    395 * 密码
    396 * @param keyStorePath
    397 * 密钥库路径
    398 *
    399 * @param trustKeyStorePath
    400 * 信任库路径
    401 * @return
    402 * @throws Exception
    403 */
    404 private static SSLSocketFactory getSSLSocketFactory(String password, String keyStorePath,
    405 String trustKeyStorePath) throws Exception {
    406 // 初始化密钥库
    407 KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(SunX509);
    408 KeyStore keyStore = getKeyStore(keyStorePath, password);
    409 keyManagerFactory.init(keyStore, password.toCharArray());
    410
    411 // 初始化信任库
    412 TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(SunX509);
    413 KeyStore trustkeyStore = getKeyStore(trustKeyStorePath, password);
    414 trustManagerFactory.init(trustkeyStore);
    415
    416 // 初始化SSL上下文
    417 SSLContext ctx = SSLContext.getInstance(SSL);
    418 ctx.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
    419 SSLSocketFactory sf = ctx.getSocketFactory();
    420
    421 return sf;
    422 }
    423
    424 /**
    425 * 为 HttpsURLConnection配置SSLSocketFactory
    426 *
    427 * @param conn
    428 * HttpsURLConnection
    429 * @param password
    430 * 密码
    431 * @param keyStorePath
    432 * 密钥库路径
    433 *
    434 * @param trustKeyStorePath
    435 * 信任库路径
    436 * @throws Exception
    437 */
    438 public static void configSSLSocketFactory(HttpsURLConnection conn, String password,
    439 String keyStorePath, String trustKeyStorePath) throws Exception {
    440 conn.setSSLSocketFactory(getSSLSocketFactory(password, keyStorePath, trustKeyStorePath));
    441 }
    442
    443 /**
    444 * @param args
    445 * @throws Exception
    446 */
    447 public static void main(String[] args) throws Exception {
    448 String password = "123456";
    449 String alias = "192.168.20.230";
    450 String certificatePath = "d:/zlex.cer";
    451 String keyStorePath = "d:/zlex.keystore";
    452 String clientKeyStorePath = keyStorePath;//"d:/zlex-client.keystore";
    453 String clientPassword = "123456";
    454
    455 System.err.println("公钥加密——私钥解密");
    456 String inputStr = "Ceritifcate";
    457 byte[] data = inputStr.getBytes();
    458
    459 byte[] encrypt = Certificateutil.encryptByPublicKey(data, certificatePath);
    460
    461 byte[] decrypt = Certificateutil
    462 .decryptByPrivateKey(encrypt, keyStorePath, alias, password);
    463 String outputStr = new String(decrypt);
    464
    465 System.err.println("加密前: " + inputStr + "\n\r" + "解密后: " + outputStr);
    466 // 验证证书有效
    467 System.out.println("验证证书有效:" + Certificateutil.verifyCertificate(certificatePath));
    468
    469 System.out.println("**********************************************");
    470 System.err.println("私钥加密——公钥解密");
    471
    472 inputStr = "sign";
    473 data = inputStr.getBytes();
    474
    475 byte[] encodedData = Certificateutil.encryptByPrivateKey(data, keyStorePath, alias,
    476 password);
    477
    478 byte[] decodedData = Certificateutil.decryptByPublicKey(encodedData, certificatePath);
    479
    480 outputStr = new String(decodedData);
    481 System.err.println("加密前: " + inputStr + "\n\r" + "解密后: " + outputStr);
    482
    483 System.err.println("私钥签名——公钥验证签名");
    484 // 产生签名
    485 String sign = Certificateutil.sign(encodedData, keyStorePath, alias, password);
    486 System.err.println("签名:\r" + sign);
    487
    488 // 验证签名
    489 boolean status = Certificateutil.verify(encodedData, sign, certificatePath);
    490 System.err.println("状态:\r" + status);
    491
    492 System.out.println("*****************************************************");
    493 URL url = new URL("https://" + alias + ":18433/webos");
    494 HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
    495
    496 conn.setDoInput(true);
    497 conn.setDoOutput(true);
    498
    499 Certificateutil.configSSLSocketFactory(conn, clientPassword, clientKeyStorePath,
    500 clientKeyStorePath);
    501
    502 InputStream is = conn.getInputStream();
    503
    504 int length = conn.getContentLength();
    505
    506 DataInputStream dis = new DataInputStream(is);
    507 data = new byte[length];
    508 dis.readFully(data);
    509
    510 dis.close();
    511 System.err.println(new String(data));
    512 conn.disconnect();
    513
    514 }
    515 }

     取得私匙和公匙的方法:

            KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry) ks.getEntry("client", new KeyStore.PasswordProtection(password.toCharArray()));
            privateKey = pkEntry.getPrivateKey();
       publicKey = certificate.getPublicKey();

    這種取法 私匙和公匙一定是成對的。

    上邊代碼裏的取法,私匙和公匙 如果使用 特殊證書的情況下會不成對。

  • 相关阅读:
    Restful API
    事件冒泡
    DOM性能
    获取dom节点的所有子节点
    获取dom节点的父节点
    深拷贝
    Dropdown下拉菜单
    Breadcrumb面包屑
    【vue】----生产环境去除cosole.*
    刷leetcode时,重新认识LinkedList实现栈、队列或者双端队列
  • 原文地址:https://www.cnblogs.com/liubin0509/p/2331080.html
Copyright © 2020-2023  润新知