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 *
26 * - 生成keyStroe文件
27 * 28 * - keytool -genkey -validity 36000 -alias 192.168.20.230 -keyalg RSA 29 * -keystore d:\zlex.keystore
30 * 31 * 参数说明 32 * - -genkey表示生成密钥
33 * - -validity指定证书有效期,这里是36000天
34 * - -alias指定别名,这里是192.168.20.230
35 * - -keyalg指定算法,这里是RSA
36 * - -keystore指定存储位置,这里是d:\zlex.keystore
37 *
38 *
39 * - 生成自签名证书
40 * 41 * - keytool -export -keystore d:\zlex.keystore -alias 192.168.20.230 -file 42 * d:\zlex.cer -rfc
43 * 44 * 参数说明 45 * - -export指定为导出操作
46 * - -keystore指定keystore文件
47 * - -alias指定导出keystore文件中的别名
48 * - -file指向导出路径
49 * - -rfc以文本格式输出,也就是以BASE64编码输出
50 *
51 *
52 * - 证书导入到密钥库
53 * 54 * - keytool -import -alias 192.168.20.230 -file d:/zlex.cer -keystore 55 * d:/zlex.keystore
56 * 57 * 参数说明 58 * - -import表示导入
59 * - -alias指定别名,这里是192.168.20.230
60 * - -file指定算法,这里是d:/zlex.cer
61 * - -keystore指定存储位置,这里是d:/zlex.keystore
62 *
63 *
64 * - 配置tomcat
65 * 66 * - 将zlex.keystore拷贝到tomcat的conf目录下
67 * - 配置server.xml。将如下内容加入配置文件 68 * <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 *
72 * - clientAuth="false"测试阶段,置为false,正式使用时建议使用true
73 * - 启动tomcat,访问https://192.168.20.230
74 * 75 *
76 * - 证书的删除
77 * 78 * - 命令行中输入 certmgr.msc
79 * - 找到安装的证书,删除即可
80 *
81 *
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()));