package com.ctrip.arch.cscmws.cscmws2.util; import java.util.List; import com.google.common.base.Joiner; import com.google.common.base.Splitter; import com.google.common.base.Strings; import com.google.common.collect.Lists; /** * Extract valid key content * * Raw Input Sample: -----BEGIN RSA PRIVATE KEY-----\r\nabc\r\ndef\r\n-----END RSA PRIVATE KEY-----\r\n ==> abcdef */ public class RsaKeyExtractor { private static final String COMMENT_BEGIN_FLAG = "-----"; private static final String RETURN_FLAG_R = "\r"; private static final String RETURN_FLAG_N = "\n"; //extract valid content from rawKey(PEM format) public static String extractFromPem(String rawKey){ String result = null; try { if(!Strings.isNullOrEmpty(rawKey)){ String tmp = rawKey.replaceAll(RETURN_FLAG_R, ""); List<String> validItemList = Lists.newArrayList(); Iterable<String> splitIter = Splitter.on(RETURN_FLAG_N).trimResults().omitEmptyStrings().split(tmp); for(String str : splitIter) { if(str != null && !str.startsWith(COMMENT_BEGIN_FLAG)){ validItemList.add(str); } } Joiner joiner = Joiner.on("").skipNulls(); result = joiner.join(validItemList); } } catch (Exception e) { e.printStackTrace(); } return result; } //=== Testing === public static void main(String[] args) { String rawKey = "-----BEGIN RSA PRIVATE KEY-----\r\nabc\r\ndef\r\n-----END RSA PRIVATE KEY-----\r\n"; String validKey = RsaKeyExtractor.extractFromPem(rawKey); System.out.println(validKey); //expect: abcdef } }
package com.ctrip.arch.cscmws.cscmws2.util; import java.io.ByteArrayOutputStream; import java.security.Key; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; 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; import org.apache.commons.codec.binary.Base64; /** * RSA cipher util * */ public class RsaCipherUtil { /** * 加密算法RSA */ public static final String KEY_ALGORITHM = "RSA"; /** * 簽名算法 */ // public static final String SIGNATURE_ALGORITHM_MD5 = "MD5withRSA"; public static final String SIGNATURE_ALGORITHM_SHA1 = "SHA1withRSA"; /** * 獲取公鑰的key */ private static final String PUBLIC_KEY = "RSAPublicKey"; /** * 獲取私鑰的key */ private static final String PRIVATE_KEY = "RSAPrivateKey"; /** * RSA最大加密明文大小 */ private static final int MAX_ENCRYPT_BLOCK = 117; /** * RSA最大解密密文大小 * 注意:這個和密鑰長度有關係, 公式= 密鑰長度 / 8 */ private static final int MAX_DECRYPT_BLOCK = 128; /** * <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 = Base64.decodeBase64(privateKey); PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec); Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM_SHA1); //SIGNATURE_ALGORITHM signature.initSign(privateK); signature.update(data); return Base64.encodeBase64String(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 = Base64.decodeBase64(publicKey); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); PublicKey publicK = keyFactory.generatePublic(keySpec); Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM_SHA1); //SIGNATURE_ALGORITHM signature.initVerify(publicK); signature.update(data); return signature.verify(Base64.decodeBase64(sign)); } /** * <P> * 私鑰解密 * </p> * * @param encryptedData 已加密數據 * @param privateKey 私鑰(BASE64編碼) * @return * @throws Exception */ public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey) throws Exception { byte[] keyBytes = Base64.decodeBase64(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 = Base64.decodeBase64(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 = Base64.decodeBase64(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 = Base64.decodeBase64(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 Base64.encodeBase64String(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 Base64.encodeBase64String(key.getEncoded()); } //=== Testing === public static void main(String[] args) { try { String input = "abc"; String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnOi3RwVTiB0LTCV0nPfigVqyROPbBA/Qkz21DExN3rnlziQ7vjwc1EJ9n+xH/o/BNc/j6yslYMdVPDLBOZqBUiaHH2w0+DWStAZVN51ZsYdceLYh1xc9WwNgwFk7Y1ME0uVjgOiKq1nhnPOPe3GvDvsS3E+2SqNN8+NfcaCeY8QIDAQAB"; String privateKey = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAKc6LdHBVOIHQtMJXSc9+KBWrJE49sED9CTPbUMTE3eueXOJDu+PBzUQn2f7Ef+j8E1z+PrKyVgx1U8MsE5moFSJocfbDT4NZK0BlU3nVmxh1x4tiHXFz1bA2DAWTtjUwTS5WOA6IqrWeGc8497ca8O+xLcT7ZKo03z419xoJ5jxAgMBAAECgYAIMPjDmIiNSQIqwjLc7dOUgj2SIEv99ZdrVWAqjYmoYbrmc0ujy/0nY6wOdNiGp11PyryvoQIVBUPhZMnrqgOnOOxPlWMDHMd6aFMfmDPqSQL5IEK982x56OCl8Z8fRe3wRZn3sT2DR1FvEJvlAFatLOzoQsLOz/ot26bjJyD8vQJBANyyjb0MZqHfuSKUT2t5VxHPsf5Xs7DleMmERqz5X4Iaj5HBUGl9Rv051Ta3oiADUM45MYkvDiOeyjhY9X6m6AcCQQDB+gxJl7qFU2pjnFhpPf/RqLzF0yri6SeXVUgcrUxj08f5+WsZdB0UaCa2+PW6R9Ln1IWl7ptD2MvekHIZYwlHAkBN0Dq/VBb/rgT1lzslVqQHaKaGWd/GWDItQxE0PbyZ/8ltB67VctFLyU9OupJUHTcpburzRn8CuiLsmRj9rdWTAkAgEov9jwzUBprMpYkovYuSyueLfgLVSd+18e/ebfj3eIjUGB1RNBWqzh24mylmB4IjusvuR6l8algrEI8NC4b5AkAlvT4xJhAASeFVxLEMWUm4uDkif9g1ruUs0J7EUHsFxffXIdAR8WXK9Nf3DdLsRLVvYka4z7VtOcucddiu1Xy/"; byte[] cipherBytes = encryptByPublicKey(input.getBytes(), publicKey); String cipherText = Base64.encodeBase64String(cipherBytes); System.out.println("cipherText=" + cipherText); System.out.println("---------------------"); byte[] rawBytes = decryptByPrivateKey(cipherBytes, privateKey); String rawText = new String(rawBytes, "UTF-8"); System.out.println("rawText=" + rawText); System.out.println("---------------------"); System.out.println("match ? " + (input.equals(rawText))); } catch (Exception e) { e.printStackTrace(); } } }
注:若是是密鑰長度是2048,修改MAX_DECRYPT_BLOCK=256java
測試類:算法
package com.ctrip.arch.cscmws.cscmws2.lzyan; import java.nio.charset.StandardCharsets; import org.apache.commons.codec.binary.Base64; import com.ctrip.arch.cscmws.cscmws2.util.CscmUtil; import com.ctrip.arch.cscmws.cscmws2.util.RsaCipherUtil; import com.ctrip.arch.cscmws.cscmws2.util.RsaKeyExtractor; /** * Notice: * AX00000000001436 - 公鑰 * SO00000000001437 - 私鑰(pkcs#1) [bad] * LP00000000003504 - 私鑰(pkcs#8) [ok] * * publicKey privateKey Length GenByJava * ------------------ ------------------ ------------------ ------------------ * OH00000000000119 JY00000000000120 1024 No * AX00000000001436 LP00000000003504 1024 No * KI00000000001530 UL00000000001531 1024 Yes * UE00000000001532 ZT00000000001533 2048 Yes * */ public class lzyanTester { public static final String rsaPublicKeySslCode = "OH00000000000119"; //OH00000000000119 AX00000000001436 KI00000000001530 public static final String rsaPrivateKeySslCode = "JY00000000000120"; //JY00000000000120 LP00000000003504 UL00000000001531 public static void main(String[] args) throws Exception { String inputString = "abc"; // String rasPublicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCm6TT29R9r2XF7gJu70wsKcnnRJvJTrptipOrfdQj3h3HKMPfi88iobaHWxigKC/1GsM2hMp1W4l4eEabSDn5D6KL5dUUlAWoDNIKudGHX853HQBFl0lwNE45V20zwNCj7ePI0WXyiVCycj1ojVreYG9BISA+EcELbLEmNUth+LwIDAQAB"; // String rasPrivateKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKbpNPb1H2vZcXuAm7vTCwpyedEm8lOum2Kk6t91CPeHccow9+LzyKhtodbGKAoL/UawzaEynVbiXh4RptIOfkPoovl1RSUBagM0gq50YdfzncdAEWXSXA0TjlXbTPA0KPt48jRZfKJULJyPWiNWt5gb0EhID4RwQtssSY1S2H4vAgMBAAECgYA7x2pgyInoZohuYzFjo8Jgi391mS1RK0gbnFVCkvgTLz9h2wftEMLdD+bWtUHB12lu2APNqAMSCyEKQ+grc2Vk+K2dul3f1kmpLLUJQB3UgfxX/X2Iz93wrG3gCFjN1TVLvlJ6QRk0ooD5uEluzd1J/s6+XqcfKF/KwN7B0UlRAQJBANrZ+2r44kNh2G3tPbEEZxzAo/xjBJJyAvwpoba6hygRFhORVBQ+AhXuUlSJSj6Jnhw3WVVXjs5+oDwosABXETcCQQDDPjC7/iU0l53hTXqnXenyxoSIBvXITdnQj1JaDH87LQA6/i/OXlLPMkpNoMgWeiZdj4p2D8KB1+pPIVvWqNbJAkBXKtFX9w9v1S32ArM6qU1Eh3oJUYsFpUGJHC/b7wlcLQoE+zJo6ZW9FHJYV2Jp7Dg8dtMvCbPIjWjW7UHEsOkbAkAgwiqDIF01ucqvpsRRmJxMM6rA+An9FbLaH3H90eL3FtHXFBcJVSInyZRV+ggYXV5ajF76+CH2jzetFzfFiIahAkEAioiQL7ancrccQYL1SNpRzx/mZWyXieQexpj7nW1ORNoOwPtxWyD0pVQdLihwkAed1wURQg3sHIZmK18S8/O2jw=="; System.out.println("\n------- Phase[1] get raw key -------"); CscmUtil cscmUtilInstance = CscmUtil.getInstance(); String rasPublicKey = cscmUtilInstance.getSignature(rsaPublicKeySslCode); String rasPrivateKey = cscmUtilInstance.getSignature(rsaPrivateKeySslCode); System.out.println("rasPublicKey=" + rasPublicKey); System.out.println("rasPrivateKey=" + rasPrivateKey); System.out.println("\n------- Phase[2] extract key -------"); rasPublicKey = RsaKeyExtractor.extractFromPem(rasPublicKey); rasPrivateKey = RsaKeyExtractor.extractFromPem(rasPrivateKey); System.out.println("rasPublicKey=" + rasPublicKey); System.out.println("rasPrivateKey=" + rasPrivateKey); System.out.println("\n------- Phase[3] encrypt -------"); byte[] cipherBytes = RsaCipherUtil.encryptByPublicKey(inputString.getBytes(), rasPublicKey); String cipherText = Base64.encodeBase64String(cipherBytes); System.out.println("cipherText=" + cipherText); System.out.println("\n------- Phase[4] decrypt -------"); byte[] rawBytes = RsaCipherUtil.decryptByPrivateKey(cipherBytes, rasPrivateKey); String decryptText = new String(rawBytes, StandardCharsets.UTF_8); //"UTF-8" System.out.println("inputString=" + inputString + ", decryptText=" + decryptText); System.out.println("\n------- Phase[5] sign -------"); String sign = RsaCipherUtil.sign(inputString.getBytes(), rasPrivateKey); System.out.println("sign=" + sign); System.out.println("\n------- Phase[6] verify -------"); boolean verifyResult = RsaCipherUtil.verify(inputString.getBytes(), rasPublicKey, sign); System.out.println("verifyResult=" + verifyResult); System.out.println("========================== over =========================="); } }