签名研究
程序员文章站
2024-03-19 13:35:40
...
package com.yussion.sign2;
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.PublicKey;
import java.security.Security;
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.cert.X509CertificateHolder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
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 = "D:/cert/ca.crt";
private static final String PRIVATE_KEY_PASSWORD="123456";
public static final String PUBLIC_KEY_PATH="D:/cert/client.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);
X509Certificate publicCert = getX509Certificate(PUBLIC_KEY_PATH);
PublicKey publicKey = publicCert.getPublicKey();
publicCert.getSignature();
X509Certificate privateCert = getX509Certificate(PRIVATE_KEY_PATH);
PublicKey publicKeyFromPrivateCert = privateCert.getPublicKey();
privateCert.getSignature();
PEMParser pemParser = new PEMParser(new FileReader(PRIVATE_KEY_PATH));
Object object = pemParser.readObject();
pemParser.close();
PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder().build(PRIVATE_KEY_PASSWORD.toCharArray());
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);
}
X509CertificateHolder holder = (X509CertificateHolder)object;
new JcaX509CertificateConverter().getCertificate(holder).verify(publicKey);
byte[] deData = Base64.getDecoder().decode(rsaPubEncrypt);
CMSEnvelopedDataParser cmsEnvelopedDataParser = new CMSEnvelopedDataParser(deData);
Collection<RecipientInformation> recInfos = cmsEnvelopedDataParser.getRecipientInfos().getRecipients();
Iterator<RecipientInformation> recipientIterator = recInfos.iterator();
if (recipientIterator.hasNext()) {
RecipientInformation recipientInformation = (RecipientInformation) recipientIterator.next();
JceKeyTransEnvelopedRecipient jceKeyTransEnvelopedRecipient = new JceKeyTransEnvelopedRecipient(kp.getPrivate());
byte[] contentBytes = recipientInformation.getContent(jceKeyTransEnvelopedRecipient);
String decryptContent = new String(contentBytes);
System.out.println(decryptContent);
}
//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 (Exception 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);
}
}
上一篇: 消息摘要算法之MD5
下一篇: payload模块使用(四)