如果java環境搭建好,注釋中內容可以新建一個bat來執行,或者直接粘貼到黑屏執行,即可生成私鑰和公鑰的證書
REM # create keystore file
keytool -genkey -dname "CN=Test Bank, OU=Test, O=Test, L=BeiJing, ST=BeiJing, C=CN" -alias testAlias -keyalg RSA -keysize 1024 -keystore TestPrivate.jks -keypass 12345678 -storepass 12345678 -validity 365
REM # export cert file
keytool -export -alias testAlias -file TestPublic.cer -keystore TestPrivate.jks -storepass 12345678
package com.develop.util; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.security.InvalidKeyException; import java.security.Key; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import java.security.SignatureException; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.Enumeration; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; public class SignUtil { /** 如果java環境搭建好,注釋中內容可以新建一個bat來執行,或者直接粘貼到黑屏執行,即可生成私鑰和公鑰的證書 REM # create keystore file keytool -genkey -dname "CN=Test Bank, OU=Test, O=Test, L=BeiJing, ST=BeiJing, C=CN" -alias testAlias -keyalg RSA -keysize 2048 -keystore TestPrivate.jks -keypass 12345678 -storepass 12345678 -validity 365 REM # export cert file keytool -export -alias testAlias -file TestPublic.cer -keystore TestPrivate.jks -storepass 12345678 **/ /** * RSA最大加密明文大小 */ private static final int MAX_ENCRYPT_BLOCK = 117; /** * RSA最大解密密文大小 */ private static final int MAX_DECRYPT_BLOCK = 128; /** * 簽名方法 * @param srcByte 待簽名數據(byte) * @param keystorePath 密鑰庫文件路徑 * @param keystorePwd 密鑰庫密碼 * @param keystoreType 密鑰庫類型 無設置默認JKS * @param algorithm 算法 無設置默認取證書算法 * @param alias 私鑰別名 無設置默認自動查找 * @return */ public static byte[] sign(byte[] srcByte,String keystorePath,String keystorePwd,String keystoreType,String algorithm,String alias){ if(srcByte==null){ System.out.println("待簽名數據為空!"); return null; } if(keystorePath==null||"".equals(keystorePath)){ System.out.println("密鑰庫路徑為空!"); return null; } if(keystorePwd==null){ System.out.println("密鑰庫密碼為空!"); return null; } KeyStore keyStore = getKeyStore(keystorePath, keystorePwd, keystoreType); if(keyStore==null){ System.out.println("獲取密鑰庫對象失敗!"); return null; } if(alias==null||"".equals(alias)){ alias = getAlias(keyStore); } PrivateKey privateKey = getPrivateKey(keyStore, keystorePwd, alias); if(privateKey==null){ System.out.println("獲取私鑰對象失敗!"); return null; } X509Certificate x509Certificate = getX509Certificate(keyStore, alias); if(algorithm==null||"".equals(algorithm)){ algorithm = x509Certificate.getSigAlgName(); } return doSign(srcByte, privateKey, algorithm); } /** * 簽名方法 * @param srcData 待簽名數據(String) * @param keystorePath 密鑰庫文件路徑 * @param keystorePwd 密鑰庫密碼 * @param keystoreType 密鑰庫類型 無設置默認JKS * @param algorithm 簽名算法 無設置默認取證書算法 * @return */ public static String sign(String srcData,String keystorePath,String keystorePwd,String keystoreType,String algorithm){ String signedData = ""; System.out.println("待簽名參數:"+srcData); if(srcData==null||"".equals(srcData)){ System.out.println("待簽名數據為空!"); return ""; } byte[] srcByte = srcData.getBytes();//待簽名數據String轉成byte byte[] rsByte = sign(srcByte, keystorePath, keystorePwd, keystoreType, algorithm, null); if(rsByte==null){ System.out.println("簽名失敗!"); return ""; } signedData = new BASE64Encoder().encodeBuffer(rsByte); System.out.println("簽名串:"+signedData); return signedData; } /** * 驗簽方法 * @param srcByte 待簽名數據(byte) * @param signedByte 簽名串(byte) * @param certificatePath 證書文件路徑 * @param algorithm 驗簽算法 無設置默認取證書算法 * @return */ public static boolean verify(byte[] srcByte,byte[] signedByte,String certificatePath,String algorithm){ if(srcByte==null){ System.out.println("傳入的原數據參數為空!"); return false; } if(signedByte==null){ System.out.println("傳入的簽名串參數為空!"); return false; } if(certificatePath==null||"".equals(certificatePath)){ System.out.println("公鑰證書路徑參數為空!"); return false; } X509Certificate x509Certificate = getX509Certificate(certificatePath); if(x509Certificate==null){ System.out.println("獲取X509證書對象失敗!"); return false; } PublicKey publicKey = getPublicKey(x509Certificate); if(publicKey==null){ System.out.println("公鑰對象獲取失敗!"); return false; } if(algorithm==null||"".equals(algorithm)){ algorithm = x509Certificate.getSigAlgName(); } return doVerify(srcByte, signedByte, publicKey, algorithm); } /** * 驗簽方法 * @param srcData 待簽名數據(String) * @param signedData 簽名串(String) * @param certificatePath 證書文件路徑 * @param algorithm 驗簽算法 無設置默認取證書算法 * @return */ public static boolean verify(String srcData,String signedData,String certificatePath,String algorithm){ boolean result = false; System.out.println("驗簽參數(待簽名數據):"+srcData); System.out.println("驗簽參數(簽名串):"+signedData); if(srcData==null||"".equals(srcData)){ System.out.println("傳入待簽名數據為空!"); return false; } if(signedData==null||"".equals(signedData)){ System.out.println("傳入簽名串為空!"); return false; } byte[] srcByte = srcData.getBytes(); byte[] signedByte = null; try { signedByte = new BASE64Decoder().decodeBuffer(signedData); } catch (IOException e) { e.printStackTrace(); } result = verify(srcByte, signedByte, certificatePath, algorithm); System.out.println("驗簽結果:"+result); return result; } /** * 創建簽名對象進行簽名 * @param srcByte 待簽名數據(byte) * @param privateKey 私鑰 * @param algorithm 簽名算法 無設置默認取證書算法 * @return */ private static byte[] doSign(byte[] srcByte,PrivateKey privateKey,String algorithm){ System.out.println("簽名算法:"+algorithm); try { Signature signature=Signature.getInstance(algorithm); signature.initSign(privateKey); signature.update(srcByte); return signature.sign(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (SignatureException e) { e.printStackTrace(); } return null; } /** * 創建簽名對象進行驗簽 * @param srcByte 原待簽名數據(byte) * @param signedByte 簽名串(byte) * @param publicKey 公鑰 * @param algorithm 驗簽算法 無設置默認取證書算法 * @return */ private static boolean doVerify(byte[] srcByte,byte[] signedByte,PublicKey publicKey,String algorithm){ System.out.println("驗簽算法:"+algorithm); try { Signature signature=Signature.getInstance(algorithm); signature.initVerify(publicKey); signature.update(srcByte); return signature.verify(signedByte); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (SignatureException e) { e.printStackTrace(); } return false; } /** * 找到路徑下的密鑰庫文件,獲取密鑰庫對象 * @param keystorePath 密鑰庫文件路徑 * @param keystorePwd 密鑰庫密碼 * @param keystoreType 密鑰庫類型 無設置默認JKS * @return */ private static KeyStore getKeyStore(String keystorePath,String keystorePwd,String keystoreType){ System.out.println("密鑰庫文件路徑:"+keystorePath); if(keystoreType==null||"".equals(keystoreType)){ keystoreType = KeyStore.getDefaultType(); } System.out.println("創建密鑰庫對象使用的密鑰庫類型:"+keystoreType); FileInputStream stream = null; KeyStore keyStore = null; try { stream = new FileInputStream(keystorePath); keyStore = KeyStore.getInstance(keystoreType); keyStore.load(stream, keystorePwd.toCharArray()); System.out.println("讀取文件密鑰庫對象成功!"); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (KeyStoreException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (CertificateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally{ if(stream!=null){ try { stream.close(); } catch (IOException e) { e.printStackTrace(); } stream = null; } } return keyStore; } /** * 查找密鑰庫中私鑰別名,找到名稱就停止查找 * @param keyStore 密鑰庫 * @return */ private static String getAlias(KeyStore keyStore){ String alias = null; try { Enumeration<String> aliases = keyStore.aliases(); while(aliases.hasMoreElements()){ String element = aliases.nextElement(); if(keyStore.isKeyEntry(element)){ alias = element; break; } } } catch (KeyStoreException e) { e.printStackTrace(); } return alias; } /** * 獲取密鑰庫中的私鑰 * @param keyStore 密鑰庫對象 * @param keystorePwd 密鑰庫密碼 * @param alias 私鑰的別名 * @return */ private static PrivateKey getPrivateKey(KeyStore keyStore,String keystorePwd,String alias){ System.out.println("私鑰別名:"+alias); try { return (PrivateKey)keyStore.getKey(alias, keystorePwd.toCharArray()); } catch (UnrecoverableKeyException e) { e.printStackTrace(); } catch (KeyStoreException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return null; } /** * 找到路徑下的證書文件,獲取證書對象 * @param certificatePath 證書文件路徑 * @return */ private static X509Certificate getX509Certificate(String certificatePath){ System.out.println("證書文件路徑:"+certificatePath); FileInputStream stream = null; X509Certificate x509Certificate = null; try { stream = new FileInputStream(certificatePath); CertificateFactory certificateFactory = CertificateFactory.getInstance("x.509");//1.6版本只支持x.509標准證書 x509Certificate = (X509Certificate)certificateFactory.generateCertificate(stream); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (CertificateException e) { e.printStackTrace(); } finally{ if(stream!=null){ try { stream.close(); } catch (IOException e) { e.printStackTrace(); } stream = null; } } return x509Certificate; } /** * 獲取證書的公鑰 * @param x509Certificate 證書對象 * @return */ private static PublicKey getPublicKey(X509Certificate x509Certificate){ return x509Certificate.getPublicKey(); } /** * 通過密鑰庫獲取證書對象 * @param keyStore 密鑰庫 * @param alias 私鑰別名 * @return */ private static X509Certificate getX509Certificate(KeyStore keyStore,String alias){ try { return (X509Certificate)keyStore.getCertificate(alias); } catch (KeyStoreException e) { e.printStackTrace(); } return null; } /** * 明文加密 * @param plainText 明文 * @param key 公鑰或私鑰 * @return */ public static byte[] encrypt(byte[] plainText, Key key){ System.out.println("加密方法encrypt開始!"); ByteArrayOutputStream out = null; try { Cipher cipher = Cipher.getInstance(key.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, key); int inputLen = plainText.length; out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 對數據分段加密 while (inputLen - offSet > 0) { if (inputLen - offSet > MAX_ENCRYPT_BLOCK) { cache = cipher.doFinal(plainText, offSet, MAX_ENCRYPT_BLOCK); } else { cache = cipher.doFinal(plainText, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * MAX_ENCRYPT_BLOCK; } byte[] encryptedData = out.toByteArray(); return encryptedData; } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } finally{ if(out!=null){ try { out.close(); } catch (IOException e) { e.printStackTrace(); } out = null; } System.out.println("加密方法encrypt結束!"); } return null; } /** * 密文解密 * @param ciphertext 密文 * @param key 公鑰或私鑰 * @return */ public static byte[] decrypt(byte[] ciphertext, Key key){ System.out.println("解密方法decrypt開始!"); ByteArrayOutputStream out = null; try { Cipher cipher = Cipher.getInstance(key.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, key); int inputLen = ciphertext.length; out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 對數據分段解密 while (inputLen - offSet > 0) { if (inputLen - offSet > MAX_DECRYPT_BLOCK) { cache = cipher.doFinal(ciphertext, offSet, MAX_DECRYPT_BLOCK); } else { cache = cipher.doFinal(ciphertext, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * MAX_DECRYPT_BLOCK; } byte[] decryptedData = out.toByteArray(); return decryptedData; } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } finally{ if(out!=null){ try { out.close(); } catch (IOException e) { e.printStackTrace(); } out = null; } System.out.println("解密方法decrypt結束!"); } return null; } public static void main(String[] args) { String srcData = "test測試數據"; //簽名驗簽測試 String rsData = sign(srcData, "D:\\test\\TestPrivate.jks", "12345678" , null, null); boolean result = verify(srcData, rsData, "D:\\test\\TestPublic.cer", null); //加密解密測試 KeyPairGenerator keyPairGenerator = null; try { keyPairGenerator = KeyPairGenerator.getInstance("RSA"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } keyPairGenerator.initialize(1024); KeyPair key = keyPairGenerator.genKeyPair(); PrivateKey privateKey = key.getPrivate(); PublicKey publicKey = key.getPublic(); byte[] a = encrypt(srcData.getBytes(), privateKey); byte[] b = decrypt(a, publicKey); System.out.println(new String(b)); } }
keytool:
Keytool 選項 | 描述 |
---|---|
-genkey |
產生一個鍵值對(公鑰和私鑰) |
-v |
允許動作輸出 |
-alias<alias_name> |
鍵的別名。只有前八位字符有效。 |
-keyalg |
產生鍵的加密算法。支持DSA和RSA。 |
-keysize |
產生鍵的長度。如果不支持,keytool用默認值1024 bits.通常我們用2048 bits 或更長的key。 |
-dname |
專有名稱,描述誰創建的密鑰。該值被用作自簽名證書的頒發者和主題字段。注意你可以不在命令行指定。如果沒有指定keytool會提示你(CN, OU, and so on)。 |
-keypass |
鍵的密碼。 主要為了安全起見,如果沒提供,keytool會提示你輸入。 |
-validity |
鍵的有效期,單位:天 Note: A value of 10000 or greater is recommended. |
-keystore.keystore |
用於存儲私鑰的文件。 |
-storepass |
私鑰存儲文件的密碼。 主要為了安全起見,如果沒提供,keytool會提示你輸入。這個密碼不會存儲在你的shell歷史記錄中。
|