签名研究

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);
    }
    
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值