生成私鑰 openssl genrsa -out rsa\_private\_key.pem 1024 導出公鑰 openssl rsa -in rsa\_private\_key.pem -out rsa\_public\_key.pem -pubout 私鑰轉PKCS#8編碼 openssl pkcs8 -topk8 -in rsa\_private\_key.pem -out pkcs8\_rsa\_private_key.pem -nocrypt
1. 初始化公私鑰 實例化RSA: RSA rsa = new RSA() 加載公私鑰文件: basepath + privateKeyFilePKCS1 私鑰文件路徑 basepath + publicKeyFile 公鑰文件路徑 rsa.loadPrivateKeyPKCS1(new FileInputStream(new File(basepath + privateKeyFilePKCS1))); rsa.loadPublicKey(new FileInputStream(new File(basepath + publicKeyFile))); 2. 簽名 構造待籤原文數據 String content = "qwertyuiop1234567890"; 原文數據使用base64編碼 String contentBase64 = Base64.encodeBase64String(content.getBytes()); 簽名方法,返回簽名結果使用base64編碼 String signBase64 = rsa.signBase64(rsa.getPrivateKey(), contentBase64); 3. 驗證簽名 contentBase64 : 簽名原文base64編碼 signBase64 : 簽名結果base64編碼 返回簽名結果 boolean rs = rsa.verifyBase64(rsa.getPublicKey(), contentBase64, signBase64);
源代碼java
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.Signature; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.RSAPrivateKeySpec; import java.security.spec.X509EncodedKeySpec; import javax.crypto.Cipher; import javax.crypto.NoSuchPaddingException; import org.apache.commons.codec.binary.Base64; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.pkcs.RSAPrivateKeyStructure; /** * @author * @date 2014-11-1 * @time 下午12:02:35 * */ public class RSA { public static final String DEFAULT_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQChDzcjw/rWgFwnxunbKp7/4e8w" + "\r" + "/UmXx2jk6qEEn69t6N2R1i/LmcyDT1xr/T2AHGOiXNQ5V8W4iCaaeNawi7aJaRht" + "\r" + "Vx1uOH/2U378fscEESEG8XDqll0GCfB1/TjKI2aitVSzXOtRs8kYgGU78f7VmDNg" + "\r" + "XIlk3gdhnzh+uoEQywIDAQAB" + "\r"; public static final String DEFAULT_PRIVATE_KEY = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAKEPNyPD+taAXCfG" + "\r" + "6dsqnv/h7zD9SZfHaOTqoQSfr23o3ZHWL8uZzINPXGv9PYAcY6Jc1DlXxbiIJpp4" + "\r" + "1rCLtolpGG1XHW44f/ZTfvx+xwQRIQbxcOqWXQYJ8HX9OMojZqK1VLNc61GzyRiA" + "\r" + "ZTvx/tWYM2BciWTeB2GfOH66gRDLAgMBAAECgYBp4qTvoJKynuT3SbDJY/XwaEtm" + "\r" + "u768SF9P0GlXrtwYuDWjAVue0VhBI9WxMWZTaVafkcP8hxX4QZqPh84td0zjcq3j" + "\r" + "DLOegAFJkIorGzq5FyK7ydBoU1TLjFV459c8dTZMTu+LgsOTD11/V/Jr4NJxIudo" + "\r" + "MBQ3c4cHmOoYv4uzkQJBANR+7Fc3e6oZgqTOesqPSPqljbsdF9E4x4eDFuOecCkJ" + "\r" + "DvVLOOoAzvtHfAiUp+H3fk4hXRpALiNBEHiIdhIuX2UCQQDCCHiPHFd4gC58yyCM" + "\r" + "6Leqkmoa+6YpfRb3oxykLBXcWx7DtbX+ayKy5OQmnkEG+MW8XB8wAdiUl0/tb6cQ" + "\r" + "FaRvAkBhvP94Hk0DMDinFVHlWYJ3xy4pongSA8vCyMj+aSGtvjzjFnZXK4gIjBjA" + "\r" + "2Z9ekDfIOBBawqp2DLdGuX2VXz8BAkByMuIh+KBSv76cnEDwLhfLQJlKgEnvqTvX" + "\r" + "TB0TUw8avlaBAXW34/5sI+NUB1hmbgyTK/T/IFcEPXpBWLGO+e3pAkAGWLpnH0Zh" + "\r" + "Fae7oAqkMAd3xCNY6ec180tAe57hZ6kS+SYLKwb4gGzYaCxc22vMtYksXHtUeamo" + "\r" + "1NMLzI2ZfUoX" + "\r"; /** * 私鑰 */ private RSAPrivateKey privateKey; /** * 公鑰 */ private RSAPublicKey publicKey; public RSAPrivateKey getPrivateKey() { return privateKey; } public RSAPublicKey getPublicKey() { return publicKey; } /** * 隨機生成密鑰對 */ public void genKeyPair() { KeyPairGenerator keyPairGen = null; try { keyPairGen = KeyPairGenerator.getInstance("RSA"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } keyPairGen.initialize(1024, new SecureRandom()); KeyPair keyPair = keyPairGen.generateKeyPair(); this.privateKey = (RSAPrivateKey) keyPair.getPrivate(); this.publicKey = (RSAPublicKey) keyPair.getPublic(); } /** * 從文件中輸入流中加載公鑰 * * @param in * 公鑰輸入流 * @throws Exception * 加載公鑰時產生的異常 */ public void loadPublicKey(InputStream in) throws Exception { try { BufferedReader br = new BufferedReader(new InputStreamReader(in)); String readLine = null; StringBuilder sb = new StringBuilder(); while ((readLine = br.readLine()) != null) { if (readLine.charAt(0) == '-') { continue; } else { sb.append(readLine); sb.append('\r'); } } loadPublicKey(sb.toString()); } catch (IOException e) { throw new Exception("公鑰數據流讀取錯誤"); } catch (NullPointerException e) { throw new Exception("公鑰輸入流爲空"); } } /** * 從字符串中加載公鑰 * * @param publicKeyStr * 公鑰數據字符串 * @throws Exception * 加載公鑰時產生的異常 */ public void loadPublicKey(String publicKeyStr) throws Exception { byte[] buffer = Base64.decodeBase64(publicKeyStr); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer); this.publicKey = (RSAPublicKey) keyFactory.generatePublic(keySpec); } public void loadPrivateKeyPKCS1(InputStream in) throws Exception{ try { BufferedReader br = new BufferedReader(new InputStreamReader(in)); String readLine = null; StringBuilder sb = new StringBuilder(); while ((readLine = br.readLine()) != null) { if (readLine.charAt(0) == '-') { continue; } else { sb.append(readLine); sb.append('\r'); } } loadPrivateKeyPKCS1(sb.toString()); } catch (IOException e) { throw new Exception("私鑰數據讀取錯誤"); } catch (NullPointerException e) { throw new Exception("私鑰輸入流爲空"); } } public void loadPrivateKeyPKCS1(String privateKeyStr) throws Exception{ System.out.println("load-privateKey-PKCS#1"); byte[] buffer = Base64.decodeBase64(privateKeyStr); RSAPrivateKeyStructure asn1PrivKey = new RSAPrivateKeyStructure((ASN1Sequence) ASN1Sequence.fromByteArray(buffer)); RSAPrivateKeySpec rsaPrivKeySpec = new RSAPrivateKeySpec(asn1PrivKey.getModulus(), asn1PrivKey.getPrivateExponent()); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); this.privateKey = (RSAPrivateKey) keyFactory.generatePrivate(rsaPrivKeySpec); } /** * 從文件中加載私鑰 * * @param keyFileName * 私鑰文件名 * @return 是否成功 * @throws Exception */ public void loadPrivateKey(InputStream in) throws Exception { try { BufferedReader br = new BufferedReader(new InputStreamReader(in)); String readLine = null; StringBuilder sb = new StringBuilder(); while ((readLine = br.readLine()) != null) { if (readLine.charAt(0) == '-') { continue; } else { sb.append(readLine); sb.append('\r'); } } loadPrivateKey(sb.toString()); } catch (IOException e) { throw new Exception("私鑰數據讀取錯誤"); } catch (NullPointerException e) { throw new Exception("私鑰輸入流爲空"); } } public void loadPrivateKey(String privateKeyStr) throws Exception { System.out.println("load-privateKey-PKCS#8"); byte[] buffer = Base64.decodeBase64(privateKeyStr); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); this.privateKey = (RSAPrivateKey) keyFactory.generatePrivate(keySpec); } /** * @Description: RAS-publicKey-加密 * @author * @date 2014-11-1 * @time 下午12:00:34 * @param publicKey * @param plainTextData * @return 返回字節數組 * @throws Exception */ public byte[] encrypt(RSAPublicKey publicKey, byte[] plainTextData) throws Exception { try { Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] enBytes = cipher.doFinal(plainTextData); return enBytes; } catch (NoSuchAlgorithmException e) { throw new Exception("RSA-publicKey-加密異常"); } catch (NoSuchPaddingException e) { throw new Exception("RSA-publicKey-加密異常"); } } /** * @Description: RAS-publicKey-加密 * @author * @date 2014-11-1 * @time 下午12:00:55 * @param publicKey * @param plainTextDataBase64 * 【明文數據-base64編碼字符串】 * @return 返回base64編碼字符串 * @throws Exception */ public String encryptBase64(RSAPublicKey publicKey, String plainTextDataBase64) throws Exception { byte[] plainTextData = Base64.decodeBase64(plainTextDataBase64); byte[] enBytes = this.encrypt(publicKey, plainTextData); return Base64.encodeBase64String(enBytes); } /** * @Description: RSA-privateKey-解密 * @author * @date 2014-11-1 * @time 下午12:01:31 * @param privateKey * @param cipherTextData * @return 返回字節數組 * @throws Exception */ public byte[] decrypt(RSAPrivateKey privateKey, byte[] cipherTextData) throws Exception { try { Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.DECRYPT_MODE, privateKey); byte[] deBytes = cipher.doFinal(cipherTextData); return deBytes; } catch (NoSuchAlgorithmException e) { throw new Exception("RSA-privateKey-解密異常"); } catch (NoSuchPaddingException e) { throw new Exception("RSA-privateKey-解密異常"); } } /** * @Description: RSA-privateKey-解密 * @author * @date 2014-11-1 * @time 下午12:01:57 * @param privateKey * @param cipherTextDataBase64 * @return 返回base64字符串 * @throws Exception */ public String decryptBase64(RSAPrivateKey privateKey, String cipherTextDataBase64) throws Exception { byte[] cipherTextData = Base64.decodeBase64(cipherTextDataBase64); byte[] deBytes = this.decrypt(privateKey, cipherTextData); return Base64.encodeBase64String(deBytes); } /** * @Description: RSA-privateKey-簽名 * @author * @date 2014-11-1 * @time 下午12:07:39 * @param privateKey * @param content * @return 返回字節數組 * @throws Exception */ public byte[] sign(RSAPrivateKey privateKey, byte[] content) throws Exception { try { Signature signature = Signature.getInstance("SHA1WithRSA"); signature.initSign(privateKey); signature.update(content); byte[] signResult = signature.sign(); return signResult; } catch (NoSuchAlgorithmException e) { throw new Exception("RSA-privateKey-簽名異常"); } } /** * @Description: RSA-privateKey-簽名 * @author * @date 2014-11-1 * @time 下午12:09:12 * @param privateKey * @param contentBase64 * 【驗證簽名原文-base64編碼字符串】 * @return 返回base64字符串 * @throws Exception */ public String signBase64(RSAPrivateKey privateKey, String contentBase64) throws Exception { byte[] content = Base64.decodeBase64(contentBase64); byte[] signResult = this.sign(privateKey, content); return Base64.encodeBase64String(signResult); } /** * @Description: RSA-publicKey-驗證簽名 * @author * @date 2014-11-1 * @time 下午12:15:52 * @param publicKey * @param content * 【簽名原文-字節數組】 * @param sign * 【待驗證簽名-字節數組】 * @return 簽名結果 * @throws Exception */ public boolean verify(RSAPublicKey publicKey, byte[] content, byte[] sign) throws Exception { try { Signature signature = Signature.getInstance("SHA1WithRSA"); signature.initVerify(publicKey); signature.update(content); return signature.verify(sign); } catch (NoSuchAlgorithmException e) { throw new Exception("RSA-publicKey-驗證簽名異常"); } } /** * @Description: RSA-publicKey-驗證簽名 * @author * @date 2014-11-1 * @time 下午12:18:52 * @param publicKey * @param contentBase64 * 【簽名原文-base64編碼字符串】 * @param signBase64 * 【待驗證簽名-base64編碼字符串】 * @return 簽名結果 * @throws Exception */ public boolean verifyBase64(RSAPublicKey publicKey, String contentBase64, String signBase64) throws Exception { byte[] content = Base64.decodeBase64(contentBase64); byte[] sign = Base64.decodeBase64(signBase64); return this.verify(publicKey, content, sign); } }
參考文獻apache