背景:
需求,生成P10时用的私钥不能暴露出来,为了安全起见,将需要用户自己用私钥进行签名后,将私钥签名当参数传入生成P10的接口中。
1.生成P10的工具类
①该方法是需要使用者传入用户公钥,签名算法,私钥签名,才能生成P10

   /*** 生成 P10* @param pubKey  用户公钥* @param signAlg   签名算法* @param signer   私钥签名 对象* @return  p10*/public static String makeCertificate(String pubKey, String signAlg,ContentSigner signer) {try {byte[] publicKey = Base64.decodeBase64(pubKey);//  byte[] privateKey = Base64.decodeBase64(signedPriKey);PublicKey pubkey = null;//  PrivateKey prikey = null;if(signAlg.equalsIgnoreCase(SignAlg.SIGN_ALGO_SM3WITHSM2)){pubkey = BCECUtil.convertX509ToECPublicKey(publicKey);//  prikey = BCECUtil.convertPKCS8ToECPrivateKey(privateKey);}if(signAlg.equalsIgnoreCase(SignAlg.SIGN_ALGO_SHA1WITHRSA) || signAlg.equalsIgnoreCase(SignAlg.SIGN_ALGO_SHA256WITHRSA) || signAlg.equalsIgnoreCase(SignAlg.SIGN_ALGO_SHA384WITHRSA)|| signAlg.equalsIgnoreCase(SignAlg.SIGN_ALGO_SHA512WITHRSA)){KeyFactory keyFactory = KeyFactory.getInstance("RSA");X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKey);//转公钥pubkey = keyFactory.generatePublic(x509EncodedKeySpec);//转私钥// PKCS8EncodedKeySpec x509EncodedKeySpec1 = new PKCS8EncodedKeySpec(privateKey);// prikey = keyFactory.generatePrivate(x509EncodedKeySpec1);}X500NameBuilder localX500NameBuilder = new X500NameBuilder(BCStyle.INSTANCE);localX500NameBuilder.addRDN(BCStyle.CN, "userName or CompName"); //个人,企业用户名localX500NameBuilder.addRDN(BCStyle.C, "CN");  //国家localX500NameBuilder.addRDN(BCStyle.O, "39dian blog"); //机构名称localX500NameBuilder.addRDN(BCStyle.ST, "shanghai");  //省localX500NameBuilder.addRDN(BCStyle.L, "shanghai");  //市localX500NameBuilder.addRDN(BCStyle.E, "admin@39dian.com"); //邮箱org.bouncycastle.asn1.x500.X500Name localX500Name = localX500NameBuilder.build();JcaPKCS10CertificationRequestBuilder p10Builder = new JcaPKCS10CertificationRequestBuilder(localX500Name, pubkey);JcaContentSignerBuilder csBuilder = new JcaContentSignerBuilder(signAlg);// 签名算法/*  ContentSigner signer = null;if(signAlg.equalsIgnoreCase(SignAlg.SIGN_ALGO_SM3WITHSM2)){signer = csBuilder.setProvider("BC").build(prikey);}*/// signer = csBuilder.build(prikey);    //  私钥签名    localKeyPair.getPrivate()PKCS10CertificationRequest csr = p10Builder.build(signer);// PKCS10的请求return Base64.encodeBase64String(csr.getEncoded());  //P10 Base64 CSR} catch (Exception ex) {ex.printStackTrace();}return null;}

②该方法需要使用者传入签名算法就可以生成P10,因为里面需要的公私钥都用随机数进行了计算生成,不需要再手动收入

/*** 生成证书请求和公私玥。* @param subject  基本信息* @param signAlg  签名算法* @return* @throws NoSuchAlgorithmException* @throws InvalidKeyException* @throws OperatorCreationException* @throws IOException* @throws NoSuchProviderException* @throws InvalidAlgorithmParameterException*/public static byte[] genUserReq(CertSubject subject, String signAlg) throws NoSuchAlgorithmException, InvalidKeyException, OperatorCreationException, IOException, NoSuchProviderException, InvalidAlgorithmParameterException {//主题信息org.bouncycastle.asn1.x500.X500Name userDN = subject.buildDN();if (signAlg.equalsIgnoreCase(SignAlg.SIGN_ALGO_SM3WITHSM2)) {//公私钥对KeyPair userKP = SM2Util.generateKeyPair();SM2PublicKey userPub = new SM2PublicKey(userKP.getPublic().getAlgorithm(),(BCECPublicKey) userKP.getPublic());//生成证书请求byte[] userCSR = CommonUtil.createCSR(userDN, userPub, userKP.getPrivate(),signAlg).getEncoded();//保存byte[] x = ((BCECPublicKey) userKP.getPublic()).getQ().getAffineXCoord().getEncoded();byte[] y = ((BCECPublicKey) userKP.getPublic()).getQ().getAffineYCoord().getEncoded();byte[] sk = ((BCECPrivateKey) userKP.getPrivate()).getD().toByteArray();GenReqResult genReqResult = new GenReqResult(userCSR, x, y, sk);return userCSR;} else if (signAlg.equalsIgnoreCase(SignAlg.SIGN_ALGO_SHA256WITHRSA)) {CertAndKeyGen gen = new CertAndKeyGen("RSA", SignAlg.SIGN_ALGO_SHA256WITHRSA);gen.generate(1024);//生成1024位密钥//生成证书请求byte[] userCSR = CommonUtil.createCSR(userDN, gen.getPublicKey(), gen.getPrivateKey(),signAlg).getEncoded();return userCSR;} else if (signAlg.equalsIgnoreCase(SignAlg.SIGN_ALGO_SHA384WITHRSA)) {CertAndKeyGen gen = new CertAndKeyGen("RSA", SignAlg.SIGN_ALGO_SHA384WITHRSA);gen.generate(1024);//生成1024位密钥//生成证书请求byte[] userCSR = CommonUtil.createCSR(userDN, gen.getPublicKey(), gen.getPrivateKey(),signAlg).getEncoded();return userCSR;} else if (signAlg.equalsIgnoreCase(SignAlg.SIGN_ALGO_SHA512WITHRSA)) {CertAndKeyGen gen = new CertAndKeyGen("RSA", SignAlg.SIGN_ALGO_SHA512WITHRSA);gen.generate(1024);//生成1024位密钥//生成证书请求byte[] userCSR = CommonUtil.createCSR(userDN, gen.getPublicKey(), gen.getPrivateKey(),signAlg).getEncoded();return userCSR;} else if (signAlg.equalsIgnoreCase(SignAlg.SIGN_ALGO_SHA1WITHRSA)) {CertAndKeyGen gen = new CertAndKeyGen("RSA", SignAlg.SIGN_ALGO_SHA1WITHRSA);gen.generate(1024);//生成1024位密钥//生成证书请求byte[] userCSR = CommonUtil.createCSR(userDN, gen.getPublicKey(), gen.getPrivateKey(),signAlg).getEncoded();return userCSR;}return null;}

注:补充②中用到的CertSubject实体类

import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x500.X500NameBuilder;
import org.bouncycastle.asn1.x500.style.BCStyle;public class CertSubject {public  String country;public  String province;public String locality;public String orgName;public String orgUnit;public String commonName;public String email;public X500Name buildDN( ){X500NameBuilder builder = new X500NameBuilder(BCStyle.INSTANCE);if (country !=null) {builder.addRDN(BCStyle.C, country);}if (province !=null) {builder.addRDN(BCStyle.ST, province);}if (locality !=null) {builder.addRDN(BCStyle.L, locality);}if (orgName !=null) {builder.addRDN(BCStyle.O, orgName);}if (orgUnit !=null) {builder.addRDN(BCStyle.OU, orgUnit);}if (commonName !=null) {builder.addRDN(BCStyle.CN, commonName);}if (email !=null) {builder.addRDN(BCStyle.E, email);}return builder.build();}public String getCountry() {return country;}public void setCountry(String country) {this.country = country;}public String getProvince() {return province;}public void setProvince(String province) {this.province = province;}public String getLocality() {return locality;}public void setLocality(String locality) {this.locality = locality;}public String getOrgName() {return orgName;}public void setOrgName(String orgName) {this.orgName = orgName;}public String getCommonName() {return commonName;}public void setCommonName(String commonName) {this.commonName = commonName;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}public String getOrgUnit() {return orgUnit;}public void setOrgUnit(String orgUnit) {this.orgUnit = orgUnit;}@Overridepublic String toString() {return "CertSubject{" +"country='" + country + '\'' +", province='" + province + '\'' +", locality='" + locality + '\'' +", orgName='" + orgName + '\'' +", orgUnit='" + orgUnit + '\'' +", commonName='" + commonName + '\'' +", email='" + email + '\'' +'}';}

2.上面工具类已成,下面开始调用,以第一种为例
直接上干货:

public void testP10(){  //生成P10String signAlg = "SHA256WithRSA";Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());KeyPairGenerator localKeyPairGenerator = null;String pubKey  = null;ContentSigner signer = null;PrivateKey prikey1 = null;KeyPair localKeyPair = null;try {if(signAlg.equalsIgnoreCase(SignAlg.SIGN_ALGO_SHA1WITHRSA) || signAlg.equalsIgnoreCase(SignAlg.SIGN_ALGO_SHA256WITHRSA) || signAlg.equalsIgnoreCase(SignAlg.SIGN_ALGO_SHA384WITHRSA)|| signAlg.equalsIgnoreCase(SignAlg.SIGN_ALGO_SHA512WITHRSA)){localKeyPairGenerator = KeyPairGenerator.getInstance("RSA",new BouncyCastleProvider());localKeyPairGenerator.initialize(1024);KeyFactory keyFactory = KeyFactory.getInstance("RSA");localKeyPair = localKeyPairGenerator.genKeyPair();// X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(localKeyPair.getPublic().getEncoded());//转公钥// pubkey1 = keyFactory.generatePublic(x509EncodedKeySpec);//转私钥PKCS8EncodedKeySpec x509EncodedKeySpec1 = new PKCS8EncodedKeySpec(localKeyPair.getPrivate().getEncoded());// prikey1 = keyFactory.generatePrivate(x509EncodedKeySpec1);} else if (signAlg.equalsIgnoreCase(SignAlg.SIGN_ALGO_SM3WITHSM2)) {localKeyPairGenerator = KeyPairGenerator.getInstance("EC", new BouncyCastleProvider());localKeyPairGenerator.initialize(new ECGenParameterSpec("sm2p256v1"));localKeyPair = localKeyPairGenerator.genKeyPair();//   pubkey1 = BCECUtil.convertX509ToECPublicKey(localKeyPair.getPublic().getEncoded());//  prikey1 = BCECUtil.convertPKCS8ToECPrivateKey(localKeyPair.getPrivate().getEncoded());}pubKey = Base64.encodeBase64String(localKeyPair.getPublic().getEncoded()); //转Base64//为了私钥的安全性,私钥签名过程需要用户自己来完成JcaContentSignerBuilder csBuilder = new JcaContentSignerBuilder(signAlg);// 签名算法if(signAlg.equalsIgnoreCase(SignAlg.SIGN_ALGO_SM3WITHSM2)){signer = csBuilder.setProvider("BC").build(localKeyPair.getPrivate());}signer = csBuilder.build(localKeyPair.getPrivate());    //  私钥签名    localKeyPair.getPrivate()} catch (Exception ex) {ex.printStackTrace();Assert.fail();}String P10 = makeCertificate(pubKey,signAlg,signer);Log4jBean.logger.info("生成的P10为:"+P10);}

结果图示:

补上:BCECUtil .java

import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1Encoding;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.DERNull;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.asn1.x9.X962Parameters;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.asn1.x9.X9ECPoint;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
import org.bouncycastle.crypto.params.ECKeyParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util;
import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECNamedCurveSpec;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.math.ec.FixedPointCombMultiplier;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemReader;
import org.bouncycastle.util.io.pem.PemWriter;import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;/*** 这个工具类的方法,也适用于其他基于BC库的ECC算法*/
public class BCECUtil {private static final String ALGO_NAME_EC = "EC";private static final String PEM_STRING_PUBLIC = "PUBLIC KEY";private static final String PEM_STRING_ECPRIVATEKEY = "EC PRIVATE KEY";/*** 生成ECC密钥对** @return ECC密钥对*/public static AsymmetricCipherKeyPair generateKeyPairParameter(ECDomainParameters domainParameters, SecureRandom random) {ECKeyGenerationParameters keyGenerationParams = new ECKeyGenerationParameters(domainParameters,random);ECKeyPairGenerator keyGen = new ECKeyPairGenerator();keyGen.init(keyGenerationParams);return keyGen.generateKeyPair();}public static KeyPair generateKeyPair(ECDomainParameters domainParameters, SecureRandom random)throws NoSuchProviderException, NoSuchAlgorithmException,InvalidAlgorithmParameterException {KeyPairGenerator kpg = KeyPairGenerator.getInstance(ALGO_NAME_EC, BouncyCastleProvider.PROVIDER_NAME);ECParameterSpec parameterSpec = new ECParameterSpec(domainParameters.getCurve(), domainParameters.getG(),domainParameters.getN(), domainParameters.getH());kpg.initialize(parameterSpec, random);return kpg.generateKeyPair();}public static int getCurveLength(ECKeyParameters ecKey) {return getCurveLength(ecKey.getParameters());}public static int getCurveLength(ECDomainParameters domainParams) {return (domainParams.getCurve().getFieldSize() + 7) / 8;}public static byte[] fixToCurveLengthBytes(int curveLength, byte[] src) {if (src.length == curveLength) {return src;}byte[] result = new byte[curveLength];if (src.length > curveLength) {System.arraycopy(src, src.length - result.length, result, 0, result.length);} else {System.arraycopy(src, 0, result, result.length - src.length, src.length);}return result;}/*** @param dHex             十六进制字符串形式的私钥d值,如果是SM2算法,Hex字符串长度应该是64(即32字节)* @param domainParameters EC Domain参数,一般是固定的,如果是SM2算法的可参考{@link SM2Util#DOMAIN_PARAMS}* @return*/public static ECPrivateKeyParameters createECPrivateKeyParameters(String dHex, ECDomainParameters domainParameters) {return createECPrivateKeyParameters(ByteUtils.fromHexString(dHex), domainParameters);}/*** @param dBytes           字节数组形式的私钥d值,如果是SM2算法,应该是32字节* @param domainParameters EC Domain参数,一般是固定的,如果是SM2算法的可参考{@link SM2Util#DOMAIN_PARAMS}* @return*/public static ECPrivateKeyParameters createECPrivateKeyParameters(byte[] dBytes, ECDomainParameters domainParameters) {return createECPrivateKeyParameters(new BigInteger(1, dBytes), domainParameters);}/*** @param d                大数形式的私钥d值* @param domainParameters EC Domain参数,一般是固定的,如果是SM2算法的可参考{@link SM2Util#DOMAIN_PARAMS}* @return*/public static ECPrivateKeyParameters createECPrivateKeyParameters(BigInteger d, ECDomainParameters domainParameters) {return new ECPrivateKeyParameters(d, domainParameters);}/*** 根据EC私钥构造EC公钥** @param priKey ECC私钥参数对象* @return*/public static ECPublicKeyParameters buildECPublicKeyByPrivateKey(ECPrivateKeyParameters priKey) {ECDomainParameters domainParameters = priKey.getParameters();ECPoint q = new FixedPointCombMultiplier().multiply(domainParameters.getG(), priKey.getD());return new ECPublicKeyParameters(q, domainParameters);}/*** @param x                大数形式的公钥x分量* @param y                大数形式的公钥y分量* @param curve            EC曲线参数,一般是固定的,如果是SM2算法的可参考{@link SM2Util#CURVE}* @param domainParameters EC Domain参数,一般是固定的,如果是SM2算法的可参考{@link SM2Util#DOMAIN_PARAMS}* @return*/public static ECPublicKeyParameters createECPublicKeyParameters(BigInteger x, BigInteger y, ECCurve curve, ECDomainParameters domainParameters) {return createECPublicKeyParameters(x.toByteArray(), y.toByteArray(), curve, domainParameters);}/*** @param xHex             十六进制形式的公钥x分量,如果是SM2算法,Hex字符串长度应该是64(即32字节)* @param yHex             十六进制形式的公钥y分量,如果是SM2算法,Hex字符串长度应该是64(即32字节)* @param curve            EC曲线参数,一般是固定的,如果是SM2算法的可参考{@link SM2Util#CURVE}* @param domainParameters EC Domain参数,一般是固定的,如果是SM2算法的可参考{@link SM2Util#DOMAIN_PARAMS}* @return*/public static ECPublicKeyParameters createECPublicKeyParameters(String xHex, String yHex, ECCurve curve, ECDomainParameters domainParameters) {return createECPublicKeyParameters(ByteUtils.fromHexString(xHex), ByteUtils.fromHexString(yHex),curve, domainParameters);}/*** @param xBytes           十六进制形式的公钥x分量,如果是SM2算法,应该是32字节* @param yBytes           十六进制形式的公钥y分量,如果是SM2算法,应该是32字节* @param curve            EC曲线参数,一般是固定的,如果是SM2算法的可参考{@link SM2Util#CURVE}* @param domainParameters EC Domain参数,一般是固定的,如果是SM2算法的可参考{@link SM2Util#DOMAIN_PARAMS}* @return*/public static ECPublicKeyParameters createECPublicKeyParameters(byte[] xBytes, byte[] yBytes, ECCurve curve, ECDomainParameters domainParameters) {final byte uncompressedFlag = 0x04;int curveLength = getCurveLength(domainParameters);xBytes = fixToCurveLengthBytes(curveLength, xBytes);yBytes = fixToCurveLengthBytes(curveLength, yBytes);byte[] encodedPubKey = new byte[1 + xBytes.length + yBytes.length];encodedPubKey[0] = uncompressedFlag;System.arraycopy(xBytes, 0, encodedPubKey, 1, xBytes.length);System.arraycopy(yBytes, 0, encodedPubKey, 1 + xBytes.length, yBytes.length);return new ECPublicKeyParameters(curve.decodePoint(encodedPubKey), domainParameters);}public static ECPrivateKeyParameters convertPrivateKeyToParameters(BCECPrivateKey ecPriKey) {ECParameterSpec parameterSpec = ecPriKey.getParameters();ECDomainParameters domainParameters = new ECDomainParameters(parameterSpec.getCurve(), parameterSpec.getG(),parameterSpec.getN(), parameterSpec.getH());return new ECPrivateKeyParameters(ecPriKey.getD(), domainParameters);}public static ECPublicKeyParameters convertPublicKeyToParameters(BCECPublicKey ecPubKey) {ECParameterSpec parameterSpec = ecPubKey.getParameters();ECDomainParameters domainParameters = new ECDomainParameters(parameterSpec.getCurve(), parameterSpec.getG(),parameterSpec.getN(), parameterSpec.getH());return new ECPublicKeyParameters(ecPubKey.getQ(), domainParameters);}public static BCECPublicKey createPublicKeyFromSubjectPublicKeyInfo(SubjectPublicKeyInfo subPubInfo)throws NoSuchProviderException,NoSuchAlgorithmException, InvalidKeySpecException, IOException {return BCECUtil.convertX509ToECPublicKey(subPubInfo.toASN1Primitive().getEncoded(ASN1Encoding.DER));}/*** 将ECC私钥转换为PKCS8标准的字节流** @param priKey* @param pubKey 可以为空,但是如果为空的话得到的结果OpenSSL可能解析不了* @return*/public static byte[] convertECPrivateKeyToPKCS8(ECPrivateKeyParameters priKey, ECPublicKeyParameters pubKey) {ECDomainParameters domainParams = priKey.getParameters();ECParameterSpec spec = new ECParameterSpec(domainParams.getCurve(), domainParams.getG(),domainParams.getN(), domainParams.getH());BCECPublicKey publicKey = null;if (pubKey != null) {publicKey = new BCECPublicKey(ALGO_NAME_EC, pubKey, spec,BouncyCastleProvider.CONFIGURATION);}BCECPrivateKey privateKey = new BCECPrivateKey(ALGO_NAME_EC, priKey, publicKey,spec, BouncyCastleProvider.CONFIGURATION);return privateKey.getEncoded();}/*** 将PKCS8标准的私钥字节流转换为私钥对象** @param pkcs8Key* @return* @throws NoSuchAlgorithmException* @throws NoSuchProviderException* @throws InvalidKeySpecException*/public static BCECPrivateKey convertPKCS8ToECPrivateKey(byte[] pkcs8Key)throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException {PKCS8EncodedKeySpec peks = new PKCS8EncodedKeySpec(pkcs8Key);KeyFactory kf = KeyFactory.getInstance(ALGO_NAME_EC, BouncyCastleProvider.PROVIDER_NAME);return (BCECPrivateKey) kf.generatePrivate(peks);}/*** 将PKCS8标准的私钥字节流转换为PEM** @param encodedKey* @return* @throws IOException*/public static String convertECPrivateKeyPKCS8ToPEM(byte[] encodedKey) throws IOException {return convertEncodedDataToPEM(PEM_STRING_ECPRIVATEKEY, encodedKey);}/*** 将PEM格式的私钥转换为PKCS8标准字节流** @param pemString* @return* @throws IOException*/public static byte[] convertECPrivateKeyPEMToPKCS8(String pemString) throws IOException {return convertPEMToEncodedData(pemString);}/*** 将ECC私钥转换为SEC1标准的字节流* openssl d2i_ECPrivateKey函数要求的DER编码的私钥也是SEC1标准的,* 这个工具函数的主要目的就是为了能生成一个openssl可以直接“识别”的ECC私钥.* 相对new NetworkConnPub().getProtocolHostPort()私钥的PKCS1标准,ECC私钥的标准为SEC1** @param priKey* @param pubKey* @return* @throws IOException*/public static byte[] convertECPrivateKeyToSEC1(ECPrivateKeyParameters priKey, ECPublicKeyParameters pubKey) throws IOException {byte[] pkcs8Bytes = convertECPrivateKeyToPKCS8(priKey, pubKey);PrivateKeyInfo pki = PrivateKeyInfo.getInstance(pkcs8Bytes);ASN1Encodable encodable = pki.parsePrivateKey();ASN1Primitive primitive = encodable.toASN1Primitive();byte[] sec1Bytes = primitive.getEncoded();return sec1Bytes;}/*** 将SEC1标准的私钥字节流恢复为PKCS8标准的字节流** @param sec1Key* @return* @throws IOException*/public static byte[] convertECPrivateKeySEC1ToPKCS8(byte[] sec1Key) throws IOException {/*** 参考org.bouncycastle.asn1.pkcs.PrivateKeyInfo和* org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey,逆向拼装*/X962Parameters params = getDomainParametersFromName(SM2Util.JDK_EC_SPEC, false);ASN1OctetString privKey = new DEROctetString(sec1Key);ASN1EncodableVector v = new ASN1EncodableVector();v.add(new ASN1Integer(0)); //版本号v.add(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params)); //算法标识v.add(privKey);DERSequence ds = new DERSequence(v);return ds.getEncoded(ASN1Encoding.DER);}/*** 将SEC1标准的私钥字节流转为BCECPrivateKey对象** @param sec1Key* @return* @throws NoSuchAlgorithmException* @throws NoSuchProviderException* @throws InvalidKeySpecException* @throws IOException*/public static BCECPrivateKey convertSEC1ToBCECPrivateKey(byte[] sec1Key)throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException, IOException {PKCS8EncodedKeySpec peks = new PKCS8EncodedKeySpec(convertECPrivateKeySEC1ToPKCS8(sec1Key));KeyFactory kf = KeyFactory.getInstance(ALGO_NAME_EC, BouncyCastleProvider.PROVIDER_NAME);return (BCECPrivateKey) kf.generatePrivate(peks);}/*** 将SEC1标准的私钥字节流转为ECPrivateKeyParameters对象* openssl i2d_ECPrivateKey函数生成的DER编码的ecc私钥是:SEC1标准的、带有EC_GROUP、带有公钥的,* 这个工具函数的主要目的就是为了使Java程序能够“识别”openssl生成的ECC私钥** @param sec1Key* @return* @throws NoSuchAlgorithmException* @throws NoSuchProviderException* @throws InvalidKeySpecException*/public static ECPrivateKeyParameters convertSEC1ToECPrivateKey(byte[] sec1Key)throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException, IOException {BCECPrivateKey privateKey = convertSEC1ToBCECPrivateKey(sec1Key);return convertPrivateKeyToParameters(privateKey);}/*** 将ECC公钥对象转换为X509标准的字节流** @param pubKey* @return*/public static byte[] convertECPublicKeyToX509(ECPublicKeyParameters pubKey) {ECDomainParameters domainParams = pubKey.getParameters();ECParameterSpec spec = new ECParameterSpec(domainParams.getCurve(), domainParams.getG(),domainParams.getN(), domainParams.getH());BCECPublicKey publicKey = new BCECPublicKey(ALGO_NAME_EC, pubKey, spec,BouncyCastleProvider.CONFIGURATION);return publicKey.getEncoded();}/*** 将X509标准的公钥字节流转为公钥对象** @param x509Bytes* @return* @throws NoSuchProviderException* @throws NoSuchAlgorithmException* @throws InvalidKeySpecException*/public static BCECPublicKey convertX509ToECPublicKey(byte[] x509Bytes) throws NoSuchProviderException,NoSuchAlgorithmException, InvalidKeySpecException {X509EncodedKeySpec eks = new X509EncodedKeySpec(x509Bytes);KeyFactory kf = KeyFactory.getInstance("EC", BouncyCastleProvider.PROVIDER_NAME);return (BCECPublicKey) kf.generatePublic(eks);}/*** 将X509标准的公钥字节流转为PEM** @param encodedKey* @return* @throws IOException*/public static String convertECPublicKeyX509ToPEM(byte[] encodedKey) throws IOException {return convertEncodedDataToPEM(PEM_STRING_PUBLIC, encodedKey);}/*** 将PEM格式的公钥转为X509标准的字节流** @param pemString* @return* @throws IOException*/public static byte[] convertECPublicKeyPEMToX509(String pemString) throws IOException {return convertPEMToEncodedData(pemString);}/*** copy from BC** @param genSpec* @return*/public static X9ECParameters getDomainParametersFromGenSpec(ECGenParameterSpec genSpec) {return getDomainParametersFromName(genSpec.getName());}/*** copy from BC** @param curveName* @return*/public static X9ECParameters getDomainParametersFromName(String curveName) {X9ECParameters domainParameters;try {if (curveName.charAt(0) >= '0' && curveName.charAt(0) <= '2') {ASN1ObjectIdentifier oidID = new ASN1ObjectIdentifier(curveName);domainParameters = ECUtil.getNamedCurveByOid(oidID);} else {if (curveName.indexOf(' ') > 0) {curveName = curveName.substring(curveName.indexOf(' ') + 1);domainParameters = ECUtil.getNamedCurveByName(curveName);} else {domainParameters = ECUtil.getNamedCurveByName(curveName);}}} catch (IllegalArgumentException ex) {domainParameters = ECUtil.getNamedCurveByName(curveName);}return domainParameters;}/*** copy from BC** @param ecSpec* @param withCompression* @return*/public static X962Parameters getDomainParametersFromName(java.security.spec.ECParameterSpec ecSpec, boolean withCompression) {X962Parameters params;if (ecSpec instanceof ECNamedCurveSpec) {ASN1ObjectIdentifier curveOid = ECUtil.getNamedCurveOid(((ECNamedCurveSpec) ecSpec).getName());if (curveOid == null) {curveOid = new ASN1ObjectIdentifier(((ECNamedCurveSpec) ecSpec).getName());}params = new X962Parameters(curveOid);} else if (ecSpec == null) {params = new X962Parameters(DERNull.INSTANCE);} else {ECCurve curve = EC5Util.convertCurve(ecSpec.getCurve());X9ECParameters ecP = new X9ECParameters(curve,new X9ECPoint(EC5Util.convertPoint(curve, ecSpec.getGenerator()), withCompression),ecSpec.getOrder(),BigInteger.valueOf(ecSpec.getCofactor()),ecSpec.getCurve().getSeed()); 如果是1.62或更低版本的bcprov-jdk15on应该使用以下这段代码,因为高版本的EC5Util.convertPoint没有向下兼容/*X9ECParameters ecP = new X9ECParameters(curve,EC5Util.convertPoint(curve, ecSpec.getGenerator(), withCompression),ecSpec.getOrder(),BigInteger.valueOf(ecSpec.getCofactor()),ecSpec.getCurve().getSeed());*/params = new X962Parameters(ecP);}return params;}private static String convertEncodedDataToPEM(String type, byte[] encodedData) throws IOException {ByteArrayOutputStream bOut = new ByteArrayOutputStream();PemWriter pWrt = new PemWriter(new OutputStreamWriter(bOut));try {PemObject pemObj = new PemObject(type, encodedData);pWrt.writeObject(pemObj);} finally {pWrt.close();}return new String(bOut.toByteArray());}private static byte[] convertPEMToEncodedData(String pemString) throws IOException {ByteArrayInputStream bIn = new ByteArrayInputStream(pemString.getBytes());PemReader pRdr = new PemReader(new InputStreamReader(bIn));try {PemObject pemObject = pRdr.readPemObject();return pemObject.getContent();} finally {pRdr.close();}}
}

Java环境下用SM2或者RSA格式生成P10相关推荐

  1. java 安卓客户端开发_《安卓网络编程》之第一篇 java环境下模拟客户端、服务器端...

    1.Socket简介 在网络上的两个程序通过一个双向的通信连接实现数据的交换,这个双向链路的一端称为一个Socket.Socket通常用来实现客户方和服务方的连接.Socket是TCP/IP协议的一个 ...

  2. Java环境下GDAL / OGR环境配置与入门

    Java环境下GDAL / OGR环境配置与入门 0.概述 1.环境配置 1.1 开发环境下载 1.2 环境变量配置 1.3java工程配置 1.3.1新建Java工程 1.3.2添加GDAL的jar ...

  3. Java微服务开发指南 -- Java环境下的微服务

    Java环境下的微服务 本文涉及的内容,能让你学到什么? 本书适用于开发微服务的Java开发人员和架构师.我们在开始介绍微服务架构前,先讲述一些抽象的基本概念.不幸的是,使用新技术并不能神奇地解决分布 ...

  4. Java练习-----2.对Windows和Linux环境下输入的文件路径格式进行校验

    1.需求 Windows环境下路径格式只能为 D:\Desktop\source Linux环境下路径格式只能为 /data/source 2.结果展示 Linux环境下运行成功,懒得开虚拟机,就不展 ...

  5. sqlcipher java_纯java环境下sqlsqlcipher解密sqlite数据库文件

    由于工作需要,最近一周以来研究sqlite数据库文件的解密方法.最终采用sqlcipher工具进行解密.由于sqlcipher的实现大多是支持android的,修改为纯java平台下的代码有难度,因此 ...

  6. JAVA调用 keras,在TensorFlow(Python, Java)环境下使用Keras模型

    Keras 是一个用 Python 编写的高级神经网络 API,它能够以 TensorFlow, CNTK, 或者 Theano 作为后端运行.Keras 的开发重点是支持快速的实验.有时候我们在使用 ...

  7. Java环境下运行fastqc_在Ubuntu上安装FastQC

    一. 什么是FastQC. FastQC是一款基于Java的软件,一般都是在linux环境下使用命令行运行,它可以快速多线程地对测序数据进行质量评估.因为是一个Java软件,下载后可以直接使用,但是需 ...

  8. 基于Java环境下的高校跳蚤市场商城系统

    目 录 摘 要 I Abstract II 1绪论 1 1.1 课题背景 1 1.2 目的和意义 1 1.3 研究现状 2 1.4 研究主要内容 3 2开发平台与技术的介绍 4 2.1 Eclipse ...

  9. Java微服务开发指南-Java环境下的微服务

    本文涉及的内容,能让你学到什么? 本书适用于开发微服务的Java开发人员和架构师.我们在开始介绍微服务架构前,先讲述一些抽象的基本概念.不幸的是,使用新技术并不能神奇地解决分布式系统问题.但是我们通过 ...

最新文章

  1. 鲸鱼优化算法_Java 代码优化细节之比比谁更细
  2. ScrollView 内嵌 ListView 只能看到第一个Item
  3. 四年C++老炮,转攻Python实践分享
  4. Python Redis
  5. Docker容器原理及相关知识
  6. 文本编辑器中替换对话框的设计与实现
  7. Java 洛谷 P1909 买铅笔讲解
  8. IBASE header change - read access sequence
  9. Python使用本地代理 proxy
  10. oracle 连接字符串备份
  11. Oracle修改字段长度
  12. 学习笔记:FW内容安全概述
  13. Windows无法访问指定设备,路径或文件.您可能没有合适的权限访问这个项目
  14. ViewPager标签栏滑条
  15. log buffer及日志管理深入分析及性能调整(七)
  16. 新一代iPhone后盖或将采用超级合金
  17. SpriteAtlas
  18. Junit单元测试工具
  19. bootstrap table添加合计行
  20. C语言编写扫雷游戏,超简单

热门文章

  1. 决定显卡性能的比较重要的几个参数是什么?
  2. 20190308搜索考试(水货)
  3. 截胡华为鸿蒙,截胡华为鸿蒙,安卓12登场!迎来3大升级,10家国产手机优先升级...
  4. 读取eml格式文件,并解析
  5. html标签手册 360doc,360doc网文摘手
  6. 【美国原装进口健身补充剂 乳清蛋白 绝对正品】
  7. 重磅直播|视觉惯性SLAM之多约束扩展卡尔曼滤波
  8. thinking-in-java-version2
  9. 校招宣讲会|行业前景,职业秘籍,学长学姐来分享
  10. centos7.4同步系统时间和网络时间