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

  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();

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

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

posted @ 2012-01-29 13:58  秋日私语的博客  阅读(1783)  评论(0编辑  收藏  举报