keytool的使用
keytool程式由JDK提供,可以產生、查看認證和key.而keystore是key的容器,可以容納多個key及相關資訊。
每一條key由一個別名alias引用。可以把keystore中的key匯出為認證檔案.cer。顯然,用keytool產生的.cer
是未經CA簽名的認證。
添加一個Key
keytool -genkey -alias acosta -keyalg RSA -keysize 1024 -keystore acosta.keystore
查看keystore中所有的Key
keytool -list -keystore acosta.keystore
查看keystore中指定的一條記錄
keytool -list -v -alias acosta -keystore acosta.keystore
將keystore中的key匯出成認證檔案
keytool -list -v -alias acosta -keystore acosta.keystore -export -file acosta.cer
使用java代碼驗證
代碼如下
RSAUtil.java
package com.cn.costa.testdemo.RSA;import java.io.ByteArrayOutputStream;import java.io.FileInputStream;import java.io.IOException;import java.security.Key;import java.security.KeyFactory;import java.security.KeyPair;import java.security.KeyPairGenerator;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.interfaces.RSAPrivateKey;import java.security.interfaces.RSAPublicKey;import java.security.spec.PKCS8EncodedKeySpec;import java.security.spec.X509EncodedKeySpec;import java.util.HashMap;import java.util.Map;import javax.crypto.Cipher;/** * <p> * RSA公開金鑰/私密金鑰/簽名工具包 * </p> * <p> * * </p> * <p> * 字串格式的密鑰在未在特殊說明情況下都為BASE64編碼格式<br/> * 由於非對稱式加密速度極其緩慢,一般檔案不使用它來加密而是使用對稱式加密,<br/> * 非對稱式加密演算法可以用來對對稱式加密的祕密金鑰加密,這樣保證密鑰的安全也就保證了資料的安全 * </p> * * @author wechart * @date 2016-4-26 * @version 1.0 */public class RSAUtils { public static final String KEY_ALGORITHM = "RSA"; //密碼編譯演算法RSA public static final String SIGNATURE_ALGORITHM = "MD5withRSA"; //簽名演算法 private static final String PUBLIC_KEY = "RSAPublicKey"; //擷取公開金鑰的KEY private static final String PRIVATE_KEY = "RSAPrivateKey"; //擷取私密金鑰的KEY private static final int MAX_ENCRYPT_BLOCK = 117; //RSA最大加密明文大小 private static final int MAX_DECRYPT_BLOCK = 128; //RSA最大解密密文大小 /** * <p> * 產生金鑰組(公開金鑰和私密金鑰) * </p> * * @return * @throws Exception */ public static Map<String, Object> genKeyPair() throws Exception { KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM); keyPairGen.initialize(1024); KeyPair keyPair = keyPairGen.generateKeyPair(); RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); Map<String, Object> keyMap = new HashMap<String, Object>(2); keyMap.put(PUBLIC_KEY, publicKey); keyMap.put(PRIVATE_KEY, privateKey); return keyMap; } /** * <p> * 用私密金鑰對資訊產生數位簽章 * </p> * * @param data 已加密資料 * @param privateKey 私密金鑰(BASE64編碼) * * @return * @throws Exception */ public static String sign(byte[] data, String privateKey) throws Exception { byte[] keyBytes = Base64Utils.decode(privateKey); PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec); Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initSign(privateK); signature.update(data); return Base64Utils.encode(signature.sign()); } /** * <p> * 校正數位簽章 * </p> * * @param data 已加密資料 * @param publicKey 公開金鑰(BASE64編碼) * @param sign 數位簽章 * * @return * @throws Exception * */ public static boolean verify(byte[] data, String publicKey, String sign) throws Exception { byte[] keyBytes = Base64Utils.decode(publicKey); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); PublicKey publicK = keyFactory.generatePublic(keySpec); Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initVerify(publicK); signature.update(data); return signature.verify(Base64Utils.decode(sign)); } /** *//** * <P> * 私密金鑰解密 * </p> * * @param encryptedData 已加密資料 * @param privateKey 私密金鑰(BASE64編碼) * @return * @throws Exception */ public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey) throws Exception { byte[] keyBytes = Base64Utils.decode(privateKey); PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key privateK = keyFactory.generatePrivate(pkcs8KeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, privateK); int inputLen = encryptedData.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 對資料分段解密 while (inputLen - offSet > 0) { if (inputLen - offSet > MAX_DECRYPT_BLOCK) { cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK); } else { cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * MAX_DECRYPT_BLOCK; } byte[] decryptedData = out.toByteArray(); out.close(); return decryptedData; } /** *//** * <p> * 公開金鑰解密 * </p> * * @param encryptedData 已加密資料 * @param publicKey 公開金鑰(BASE64編碼) * @return * @throws Exception */ public static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey) throws Exception { byte[] keyBytes = Base64Utils.decode(publicKey); X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key publicK = keyFactory.generatePublic(x509KeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, publicK); int inputLen = encryptedData.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 對資料分段解密 while (inputLen - offSet > 0) { if (inputLen - offSet > MAX_DECRYPT_BLOCK) { cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK); } else { cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * MAX_DECRYPT_BLOCK; } byte[] decryptedData = out.toByteArray(); out.close(); return decryptedData; } /** *//** * <p> * 公開金鑰加密 * </p> * * @param data 來源資料 * @param publicKey 公開金鑰(BASE64編碼) * @return * @throws Exception */ public static byte[] encryptByPublicKey(byte[] data, String publicKey) throws Exception { byte[] keyBytes = Base64Utils.decode(publicKey); X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key publicK = keyFactory.generatePublic(x509KeySpec); // 對資料加密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, publicK); int inputLen = data.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 對資料分段加密 while (inputLen - offSet > 0) { if (inputLen - offSet > MAX_ENCRYPT_BLOCK) { cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK); } else { cache = cipher.doFinal(data, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * MAX_ENCRYPT_BLOCK; } byte[] encryptedData = out.toByteArray(); out.close(); return encryptedData; } /** * <p> * 私密金鑰加密 * </p> * * @param data 來源資料 * @param privateKey 私密金鑰(BASE64編碼) * @return * @throws Exception */ public static byte[] encryptByPrivateKey(byte[] data, String privateKey) throws Exception { byte[] keyBytes = Base64Utils.decode(privateKey); PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key privateK = keyFactory.generatePrivate(pkcs8KeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, privateK); int inputLen = data.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 對資料分段加密 while (inputLen - offSet > 0) { if (inputLen - offSet > MAX_ENCRYPT_BLOCK) { cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK); } else { cache = cipher.doFinal(data, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * MAX_ENCRYPT_BLOCK; } byte[] encryptedData = out.toByteArray(); out.close(); return encryptedData; } /** * <p> * 擷取私密金鑰 * </p> * * @param keyMap 金鑰組 * @return * @throws Exception */ public static String getPrivateKey(Map<String, Object> keyMap) throws Exception { Key key = (Key) keyMap.get(PRIVATE_KEY); return Base64Utils.encode(key.getEncoded()); } /** * <p> * 擷取公開金鑰 * </p> * * @param keyMap 金鑰組 * @return * @throws Exception */ public static String getPublicKey(Map<String, Object> keyMap) throws Exception { Key key = (Key) keyMap.get(PUBLIC_KEY); return Base64Utils.encode(key.getEncoded()); } public static PublicKey loadPublicKeyByFile(String filepath) throws Exception { try { //通過認證,擷取公開金鑰 CertificateFactory cf = CertificateFactory.getInstance("X.509"); Certificate c = cf.generateCertificate(new FileInputStream(filepath)); PublicKey publicKey = c.getPublicKey(); return publicKey; } catch (IOException e) { throw new Exception("公開金鑰資料流讀取錯誤"); } catch (NullPointerException e) { throw new Exception("公開金鑰輸入資料流為空白"); } } public static PrivateKey loadPrivateKeyByFile(String filepath, String alias, String password) throws Exception { try { KeyStore ks= KeyStore.getInstance("JKS"); ks.load(new FileInputStream(filepath), password.toCharArray()); PrivateKey privateKey = (PrivateKey)ks.getKey(alias, password.toCharArray()); return privateKey; } catch (IOException e) { throw new Exception("私密金鑰資料讀取錯誤"); } catch (NullPointerException e) { throw new Exception("私密金鑰輸入資料流為空白"); } } public static void main(String[] args){ String serverAlias = ""; String clientAlias = "acosta"; String serverPassword = ""; String clientPassword = "acosta";// String serverPrivateKey = "d:\\server.keystore";// String serverPublicKey = "d:\\server.cer"; String clientPrivateKey = "E:\\TestCER\\RSATest04\\acosta.keystore"; String clientPublicKey = "E:\\TestCER\\RSATest04\\acosta.cer"; // // String serverPublicString = "";// String serverPrivateString = ""; String clientPublicString = ""; String clientPrivateString = ""; String orgString = "{\"ret\":\"0\",\"ExpireTime\":\"2015/10/28 23:59:59\",\"rettxt\":\"OK\",\"Token\":\"69296128A59798E2D423D3B1A9F766F4\"}'"; String encryptString = ""; String decryptString = "";// RSAPublicKey srvPubKey = null; RSAPublicKey cltPubKey = null;// RSAPrivateKey srvPriKey = null; RSAPrivateKey cltPriKey = null; try{ //1- 用戶端公開金鑰 cltPubKey = (RSAPublicKey) RSAUtils.loadPublicKeyByFile(clientPublicKey); //2- 用戶端私密金鑰 cltPriKey = (RSAPrivateKey) RSAUtils.loadPrivateKeyByFile(clientPrivateKey, clientAlias, clientPassword);// //3- 服務端公開金鑰// srvPubKey = (RSAPublicKey) RSAUtils.loadPublicKeyByFile(serverPublicKey);// // //4- 服務端私密金鑰// srvPriKey = (RSAPrivateKey) RSAUtils.loadPrivateKeyByFile(serverPrivateKey, serverAlias, serverPassword); System.out.println("\nclientPublicString:\n"+Base64Utils.encode(cltPubKey.getEncoded())+"\n"); System.out.println("\nclientPrivateString:\n"+Base64Utils.encode(cltPriKey.getEncoded())+"\n");// System.out.println("\nserverPublicString:\n"+Base64Utils.encode(srvPubKey.getEncoded())+"\n");// System.out.println("\nserverPrivateString:\n"+Base64Utils.encode(srvPriKey.getEncoded())+"\n"); }catch(Exception e){ e.printStackTrace(); }// System.out.println("\n=============================== Step-1:用戶端私密金鑰加密-服務端公開金鑰解密\n");// //用戶端私密金鑰加密-服務端公開金鑰解密// try{ // byte[] data = orgString.getBytes();// // byte[] encodedData = RSAUtils.encryptByPrivateKey(data, Base64Utils.encode(cltPriKey.getEncoded())); // encryptString = new String(encodedData); // // byte[] decodedData = RSAUtils.decryptByPublicKey(encodedData, Base64Utils.encode(srvPubKey.getEncoded()));// decryptString = new String(decodedData);// // System.out.println("orginalString:"+orgString);// System.out.println("encrypString:"+encryptString);// System.out.println("decryptString:"+decryptString); // }catch(Exception e){// System.err.println("Step-1 解密失敗!");// }// // System.out.println("\n=============================== Step-2:服務端私密金鑰加密-用戶端公開金鑰解密\n");// //服務端私密金鑰加密-用戶端公開金鑰解密// try{// // // byte[] data = orgString.getBytes();// // byte[] encodedData = RSAUtils.encryptByPrivateKey(data, Base64Utils.encode(srvPriKey.getEncoded())); // encryptString = new String(encodedData); // // byte[] decodedData = RSAUtils.decryptByPublicKey(encodedData, Base64Utils.encode(cltPubKey.getEncoded()));// decryptString = new String(decodedData);// // System.out.println("orginalString:"+orgString);// System.out.println("encrypString:"+encryptString);// System.out.println("decryptString:"+decryptString); // }catch(Exception e){// System.err.println("Step-2 解密失敗!");// } System.out.println("\n=============================== Step-3:用戶端私密金鑰加密-用戶端公開金鑰解密\n"); String orgString2 = ""; //用戶端私密金鑰加密-用戶端公開金鑰解密 try{ byte[] data = orgString.getBytes(); byte[] encodedData = RSAUtils.encryptByPrivateKey(data, Base64Utils.encode(cltPriKey.getEncoded())); encryptString = new String(encodedData); byte[] decodedData = RSAUtils.decryptByPublicKey(encodedData, Base64Utils.encode(cltPubKey.getEncoded())); decryptString = new String(decodedData); System.out.println("orginalString:"+orgString); System.out.println("encrypString:"+encryptString); System.out.println("decryptString:"+decryptString); }catch(Exception e){ System.err.println("Step-3 解密失敗!"); }// // System.out.println("\n=============================== Step-4:服務端私密金鑰加密-服務端公開金鑰解密\n");// //服務端私密金鑰加密-服務端公開金鑰解密// try{ // // byte[] data = orgString.getBytes();// // byte[] encodedData = RSAUtils.encryptByPrivateKey(data, Base64Utils.encode(srvPriKey.getEncoded())); // encryptString = new String(encodedData); // // byte[] decodedData = RSAUtils.decryptByPublicKey(encodedData, Base64Utils.encode(srvPubKey.getEncoded()));// decryptString = new String(decodedData);// // System.out.println("orginalString:"+orgString);// System.out.println("encrypString:"+encryptString);// System.out.println("decryptString:"+decryptString); // }catch(Exception e){// System.err.println("Step-4 解密失敗!");// }// }}
Base64Utils
package com.cn.costa.testdemo.RSA;import java.