第三方使用公钥.crt加密后返回的内容,需要使用私钥解密.pem
返回内容格式如下
MIME-Version: 1.0 Content-Disposition: attachment; filename="smime.p7m" Content-Type: application/pkcs7-mime; smime-type=enveloped-data; name="smime.p7m" Content-Transfer-Encoding: base64 MIICEQYJKoZIhvcNAQcDoIICAjCCAf4CAQAxggFAMIIBPAIBADAkMBYxFDASBgNV BAMTC1NpbmFwdElRIENBAgoeg+bBAAAAAAAMMA0GCSqGSIb3DQEBAQUABIIBACGx OPGANR0bAlwPxlYt6DBTEPinPc2eiduiYLXEOftEmDA3vLNyeQ+Q1sxfYj1U5K2o 26qKr937yNwrtZ1VTird4NXHiR60Gtm0VJ+sd88XylHe2VxJrrNWHFPwoT+q7nfy IT6cfMgfOMzA1YO3/efWKEFJgmiUoeo+PZgrcRr4PIMYIFnnxQNKz+iwutfd+O44 H5wIviHsqGjiSqoVzEg5/pWh07aZ9hr/2CNGbDwBH4f+hucJTzt98tvMhrjFvbDy uiegAgxN/nolzRQv7lUlLvUrNJSOiFM5/1BWUfoiTLRgoseHjt9RxPKb8WRpul7f Om0hWxXl0mWus9GLBCIwgbQGCSqGSIb3DQEHATAUBggqhkiG9w0DBwQIBcIBRSKJ WEuAgZCcvoeat07ncIZI6owiP7WMSC9RXfuRQ//FKuBx+cpJdHnGkYuPTA3gJJca kTis/5rpDiE7bmiCiDlMBdoM1h+A0jSpR78nOCsJuJI08clAJQmj82ACbPmwRUwg OCrkTLUqbJ7brsYJeMYZWyBZIAL3bKtgqi2VRqOPerzaxOcjqv873wed/2kRUrhV gMw9bSc=
解密开始,你需要提取内容部分,并去掉换行,让内容部分保持在一行
比如:MIICEQYJKoZIhvcNAQcDoIICAjCCAf4CAQAxggFAMIIBPAIBADAkMBYxFDASBgNVBAMTC......
maven pom.xml需要引用
<dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcpkix-jdk15on</artifactId> <version>1.60</version> </dependency>
<dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.60</version> </dependency>
JAVA解密加密工具类
package com.perfect.all.core.util.pay.toc2p; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.security.KeyPair; import java.security.NoSuchProviderException; import java.security.PrivateKey; import java.security.Security; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.security.interfaces.RSAPublicKey; import java.util.Base64; import java.util.Collection; import java.util.Iterator; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.cms.CMSEnvelopedData; import org.bouncycastle.cms.CMSEnvelopedDataGenerator; import org.bouncycastle.cms.CMSEnvelopedDataParser; import org.bouncycastle.cms.CMSException; import org.bouncycastle.cms.CMSProcessableByteArray; import org.bouncycastle.cms.CMSTypedData; import org.bouncycastle.cms.RecipientInformation; import org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder; import org.bouncycastle.cms.jcajce.JceKeyTransEnvelopedRecipient; import org.bouncycastle.cms.jcajce.JceKeyTransRecipientInfoGenerator; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.openssl.PEMDecryptorProvider; import org.bouncycastle.openssl.PEMEncryptedKeyPair; import org.bouncycastle.openssl.PEMKeyPair; import org.bouncycastle.openssl.PEMParser; import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder; public class Pcks7EncryptOrDecryptUtil { private static final String PRIVATE_KEY_PATH = "/xxxx.pem"; private static final String PRIVATE_KEY_PASSWORD="xxxx"; public static final String PUBLIC_KEY_PATH="/xxx.crt"; private static PrivateKey PRIVATE_KEY = null; private static RSAPublicKey PUBLIC_KEY = null; private static final char[] HEX_CHAR = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; static { Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); } public static void main(String[] args) throws Exception { String sendConent="<PaymentProcessRequest><version>3.0</version><timeStamp>161018173004</timeStamp><merchantID>764764000001350</merchantID><processType>R</processType><invoiceNo>THBPOps180808153209</invoiceNo><actionAmount>0.01</actionAmount><hashValue>E8CCDCDBDBB7428CF0CC9F06AB30B595067F4C89</hashValue></PaymentProcessRequest>"; String rsaPubEncrypt = encryptByRsaPub(PUBLIC_KEY_PATH,sendConent,"utf-8");//加密数据 System.out.println(rsaPubEncrypt); System.out.println(decryptByContent(rsaPubEncrypt, PRIVATE_KEY_PATH, PRIVATE_KEY_PASSWORD)); //解密数据 //第三方返回的数据 String encryptContent = "MIICcgYJKoZIhvcNAQcDoIICYzCCAl8CAQA......"; System.out.println(decryptByContent(encryptContent, PRIVATE_KEY_PATH, PRIVATE_KEY_PASSWORD)); } /** * 使用私钥加密 */ public static String encryptByRsaPub(String content) { return encryptByRsaPub( PUBLIC_KEY_PATH,content,"utf-8"); } /** * 使用私钥加密 */ public static String encryptByRsaPub(String publicKeyPath , String content,String charSet) { try { X509Certificate cert = getX509Certificate(publicKeyPath); //添加数字信封 CMSTypedData msg = new CMSProcessableByteArray(content.getBytes(charSet)); CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator( cert).setProvider("BC")); CMSEnvelopedData ed = edGen.generate(msg, new JceCMSContentEncryptorBuilder(PKCSObjectIdentifiers.rc4) .setProvider("BC").build()); String rslt = new String(Base64.getEncoder().encode(ed.getEncoded())); System.out.println(rslt); return rslt; } catch (CertificateEncodingException | CMSException | IOException e) { e.printStackTrace(); } return null; } /** * 使用公钥解密 * @param encryptContent 比如:MIICEQYJKoZIhvcNAQcDoIICAjCCAf4CAQAxggFAMIIBPAIBADAkMBYxFDASBgNVBAMTC...... * @param privatePemKeyPath xxxx.pem * @param privatePemKeyPassword * @return */ public static String decryptByContent(String encryptContent,String privatePemKeyPath,String privatePemKeyPassword) { return decryptByContent(encryptContent,getPrivateKey(privatePemKeyPath, privatePemKeyPassword)); } public static String decryptByContent(String encryptContent,PrivateKey privateKey) { return decryptByContent(Base64.getDecoder().decode(encryptContent),privateKey); } public static String decryptByContent(String encryptContent) { return decryptByContent(Base64.getDecoder().decode(encryptContent),getPrivateKey(PRIVATE_KEY_PATH, PRIVATE_KEY_PASSWORD)); } public static String decryptByContent(byte[] encryptContent,PrivateKey privateKey) { try { CMSEnvelopedDataParser cmsEnvelopedDataParser = new CMSEnvelopedDataParser(encryptContent); Collection<RecipientInformation> recInfos = cmsEnvelopedDataParser.getRecipientInfos().getRecipients(); Iterator<RecipientInformation> recipientIterator = recInfos.iterator(); if (recipientIterator.hasNext()) { RecipientInformation recipientInformation = (RecipientInformation) recipientIterator.next(); JceKeyTransEnvelopedRecipient jceKeyTransEnvelopedRecipient = new JceKeyTransEnvelopedRecipient(privateKey); byte[] contentBytes = recipientInformation.getContent(jceKeyTransEnvelopedRecipient); String decryptContent = new String(contentBytes); return decryptContent; } } catch (CMSException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } System.out.println("decrypt error"); return null; } public static PrivateKey getPrivateKey(String pemFilePath, String password){ if(PRIVATE_KEY != null) { return PRIVATE_KEY; } Security.addProvider(new BouncyCastleProvider()); KeyPair kp; try{ kp = (KeyPair)initKeyPair(new File(pemFilePath), password.toCharArray()); PrivateKey privateKey = kp.getPrivate(); return (PRIVATE_KEY = privateKey); }catch(Exception e){ e.printStackTrace(); } return null; } public static KeyPair initKeyPair(File pemFile, char[] password) throws Exception{ PEMParser pemParser = new PEMParser(new FileReader(pemFile)); Object object = pemParser.readObject(); pemParser.close(); PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder().build(password); JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC"); //获得密钥对 KeyPair kp = null; if(object instanceof PEMEncryptedKeyPair){ kp = converter.getKeyPair(((PEMEncryptedKeyPair)object).decryptKeyPair(decProv)); }else{ kp = converter.getKeyPair((PEMKeyPair)object); } return kp; } public static RSAPublicKey getRSAPublicKey(String crtFileName) { if(PUBLIC_KEY != null) { return PUBLIC_KEY; } return (PUBLIC_KEY = (RSAPublicKey) getX509Certificate(crtFileName).getPublicKey()); } /** * 获取公钥 */ public static X509Certificate getX509Certificate(String crtFileName) { try { CertificateFactory certificatefactory; X509Certificate cert; // 使用公钥对对称密钥进行加密 //若此处不加参数 "BC" 会报异常:CertificateException - certificatefactory = CertificateFactory.getInstance("X.509", "BC"); // 读取.crt文件;你可以读取绝对路径文件下的crt,返回一个InputStream(或其子类)即可。 InputStream bais = new FileInputStream(crtFileName); cert = (X509Certificate) certificatefactory.generateCertificate(bais); return cert; } catch (FileNotFoundException e) { e.printStackTrace(); } catch (CertificateException e) { e.printStackTrace(); } catch (NoSuchProviderException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } public static String byteArrayToString(byte[] data) { StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < data.length; i++) { // 取出字节的高四位 作为索引得到相应的十六进制标识符 注意无符号右移 stringBuilder.append(HEX_CHAR[(data[i] & 0xf0) >>> 4]); // 取出字节的低四位 作为索引得到相应的十六进制标识符 stringBuilder.append(HEX_CHAR[(data[i] & 0x0f)]); if (i < data.length - 1) { stringBuilder.append(' '); } } return stringBuilder.toString(); } public static byte[] hexStringToBytes(String hexString) { if (hexString == null || hexString.equals("")) { return null; } hexString = hexString.toUpperCase(); int length = hexString.length() / 2; char[] hexChars = hexString.toCharArray(); byte[] d = new byte[length]; for (int i = 0; i < length; i++) { int pos = i * 2; d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1])); } return d; } /** * Convert char to byte * @param c char * @return byte */ private static byte charToByte(char c) { return (byte) "0123456789ABCDEF".indexOf(c); } }