利用Java生成公私钥密钥对和根证书以及公钥证书文件

package com.yussion.sign;

import java.io.StringWriter;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.cert.CertStore;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.jcajce.JcaCertStore;
import org.bouncycastle.cms.CMSProcessable;
import org.bouncycastle.cms.CMSProcessableByteArray;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.CMSSignedDataGenerator;
import org.bouncycastle.cms.CMSTypedData;
import org.bouncycastle.cms.SignerInformation;
import org.bouncycastle.cms.SignerInformationStore;
import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
import org.bouncycastle.util.Store;
import org.bouncycastle.util.encoders.Base64;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemWriter;

/**
 * java生成openssl兼容的rsa 公私钥
 *
 * KeyPairGenerator生成的 私钥是pkcs8格式,需要先转为pkcs1格式,再由pkcs1转为pem格式(openssl生成的pem)
 * KeyPairGenerator生成的 公钥是x509格式,需要替换_为/,替换-为+,格式化后,加-----BEGIN PUBLIC KEY-----头,-----END PUBLIC KEY-----尾,
 * 就与openssl生成的公钥一致了
 *
 * 根据私钥生成公钥,公私钥是一对一 openssl rsa -pubout -in rsa_private_key.pem -out rsa_public_key.pem
 */
public class Test {

    public static void main(String[] args) throws Exception{
        KeyPairGenerator kpg =KeyPairGenerator.getInstance("RSA");
        kpg.initialize(1024);
        KeyPair keyPair = kpg.generateKeyPair();
        String  publicKey = Base64.toBase64String(keyPair.getPublic().getEncoded());
        String  privateKey = Base64.toBase64String(keyPair.getPrivate().getEncoded());

        System.out.println(privateKey);
        String pem = privatePem(privateKey);
        System.out.println("openssl 生成的私钥.pem:");
        System.out.println(pem);

        System.out.println(publicKey);
        System.out.println("openssl 生成的公钥.pem");
        System.out.println("-----BEGIN PUBLIC KEY-----");
        formatKey(publicKey.replace("_","/").replace("-","+"));
        System.out.println("-----END PUBLIC KEY-----");

       
        
        byte[] keyBytes = Base64.decode(privateKey);   
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);  
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");  
        PrivateKey signKP = keyFactory.generatePrivate(keySpec);  
        //keyFactory.generatePublic(keySpec);

        //为“Hello World”这一字符串生成 CMS 数字签名的过程。其中 certs 代表签名方的证书,signKP.getPrivate() 
        //代表签名方的私钥,SHA1withRSA 代表消息的哈希算法是 SHA1,生成公钥私钥的算法是 RSA
        X509CertificateHolder signCert = null;
        System.out.println(sign(signCert, signKP)); 
    }

    public static String publicPem(String publicKey) throws Exception{
        byte[] pubBytes = Base64.encode(publicKey.getBytes());

        SubjectPublicKeyInfo spkInfo = SubjectPublicKeyInfo.getInstance(pubBytes);
        ASN1Primitive primitive = spkInfo.parsePublicKey();
        byte[] publicKeyPKCS1 = primitive.getEncoded();

        PemObject pemObject = new PemObject("RSA PUBLIC KEY", publicKeyPKCS1);
        StringWriter stringWriter = new StringWriter();
        PemWriter pemWriter = new PemWriter(stringWriter);
        pemWriter.writeObject(pemObject);
        pemWriter.close();
        String pemString = stringWriter.toString();

        return pemString;
    }

    public static String privatePem(String privateKey) throws Exception{
        byte[] privBytes = Base64.decode(privateKey);

        PrivateKeyInfo pkInfo = PrivateKeyInfo.getInstance(privBytes);
        ASN1Encodable encodable = pkInfo.parsePrivateKey();
        ASN1Primitive primitive = encodable.toASN1Primitive();
        byte[] privateKeyPKCS1 = primitive.getEncoded();

        return pkcs1ToPem(privateKeyPKCS1,false);
    }

    public static String pkcs1ToPem(byte[] pcks1KeyBytes,boolean isPublic) throws Exception{
        String type;
        if(isPublic){
            type = "RSA PUBLIC KEY";
        }else{
            type = "RSA PRIVATE KEY";
        }

        PemObject pemObject = new PemObject(type, pcks1KeyBytes);
        StringWriter stringWriter = new StringWriter();
        PemWriter pemWriter = new PemWriter(stringWriter);
        pemWriter.writeObject(pemObject);
        pemWriter.close();
        String pemString = stringWriter.toString();

        return pemString;
    }

    /**
     * 格式化java生成的key,一行长的,不适合pem中的-----BEGIN PUBLIC KEY-----,pem已经有换行了
     * @param key
     */
    public static void formatKey(String key){
        if(key==null) return;

        key = key.replace("\n","");

        int count = (key.length()-1)/64+1;
        for(int i=0;i<count;i++){
            if(i+1==count){
                //循环的最后一次
                System.out.println(key.substring(i*64));
            }else{
                System.out.println(key.substring(i*64,i*64+64));
            }
        }
    }

    /**
     * 从pem格式(-----BEGIN PUBLIC KEY-----)的key获取一行key
     * @param pem
     * @return
     */
    public static String pemToKey(String pem){
        if(pem==null) return "";
        if(pem.indexOf("KEY-----")>0){
            pem = pem.substring(pem.indexOf("KEY-----")+"KEY-----".length());
        }
        if(pem.indexOf("-----END")>0){
            pem = pem.substring(0,pem.indexOf("-----END"));
        }
        return pem.replace("\n","");
    }
    
    /
    public static String sign(X509CertificateHolder signCert, PrivateKey priKey) throws Exception {
        List certList = new ArrayList();
        certList.add(signCert);
        Store certs = new JcaCertStore(certList);
        CMSTypedData msg = new CMSProcessableByteArray("Hello world!".getBytes());
        CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
        ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider("BC").build(priKey);
        gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(
        new JcaDigestCalculatorProviderBuilder().setProvider("BC").build()).build(sha1Signer, signCert));
        gen.addCertificates(certs);
        CMSSignedData sigData = gen.generate(msg, true);
        String signature = new String(sigData.getEncoded());
        return signature;
    }
    //https://blog.csdn.net/sharemyfree/article/details/44016925
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值