All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.tdchain.tdmsp.util.PkiUtil Maven / Gradle / Ivy

There is a newer version: 3.0.1.TD1
Show newest version
/*
 * Copyright (c) 2017-2018 Beijing Tiande Technology Co., Ltd.
 * All Rights Reserved.
 */
package cn.tdchain.tdmsp.util;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.ECGenParameterSpec;
import java.util.Calendar;
import java.util.Date;

import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.DERGeneralString;
import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x500.X500NameBuilder;
import org.bouncycastle.asn1.x500.style.BCStyle;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.BasicConstraints;
import org.bouncycastle.asn1.x509.ExtendedKeyUsage;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.asn1.x509.KeyPurposeId;
import org.bouncycastle.asn1.x509.KeyUsage;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.X509ExtensionUtils;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECNamedCurveGenParameterSpec;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.DigestCalculator;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.bc.BcDigestCalculatorProvider;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.pkcs.PKCS10CertificationRequest;
import org.bouncycastle.pkcs.PKCS10CertificationRequestBuilder;
import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder;

import cn.tdchain.cipher.utils.CipherUtil;
import cn.tdchain.tdmsp.ca.config.SystemConfig;

/**
 * Utility.
 *
 * @version 2.0
 * @author Houmj 2018-09-18
 */
public final class PkiUtil {

    static {
        if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
            Security.addProvider(new BouncyCastleProvider());
        }
    }

    private PkiUtil() {
    }

    /**
     * Create a random 1024 bit RSA key pair.
     * 
     * @throws NoSuchProviderException exception
     * @throws NoSuchAlgorithmException exception
     * @return keypair
     */
    public static KeyPair generateRsaKeyPair()
        throws NoSuchAlgorithmException, NoSuchProviderException {
        KeyPairGenerator kpGen = KeyPairGenerator.getInstance(PkiConstant.RSA,
                BouncyCastleProvider.PROVIDER_NAME);
        kpGen.initialize(1024, new SecureRandom());

        return kpGen.generateKeyPair();
    }

    /**
     * Generate SM2 keys.
     * 
     * @return KeyPair
     * @throws Exception NoSuchAlgorithmException, NoSuchProviderException,
     *             InvalidAlgorithmParameterException
     */
    public static KeyPair generateSm2KeyPair() throws Exception {
        KeyPairGenerator g = KeyPairGenerator.getInstance(PkiConstant.EC,
                BouncyCastleProvider.PROVIDER_NAME);
        g.initialize(new ECNamedCurveGenParameterSpec(PkiConstant.SM2P256V1),
                new SecureRandom());
        return g.generateKeyPair();
    }

    /**
     * Generate ECC key pair.
     * 

* Private keypairs are encoded using PKCS8 Private keys are encoded using X.509 *

* * @return ECC KeyPair * @throws InvalidAlgorithmParameterException This is the exception for invalid or inappropriate * algorithm parameters. * @throws NoSuchAlgorithmException This exception is thrown when a particular cryptographic * algorithm is requested but is not available in the environment. * @throws NoSuchProviderException This exception is thrown when a particular security provider * is requested but is not available in the environment. */ public static KeyPair generateEccKeyPair() throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchProviderException { KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance( PkiConstant.ECDSA, BouncyCastleProvider.PROVIDER_NAME); ECGenParameterSpec ecGenParameterSpec = new ECGenParameterSpec( PkiConstant.SECP256K1); keyPairGenerator.initialize(ecGenParameterSpec, SecureRandomUtils.secureRandom()); return keyPairGenerator.generateKeyPair(); } /** * Create encryption key pair. * @return KeyPair * @throws NoSuchAlgorithmException * @throws NoSuchProviderException * @throws InvalidAlgorithmParameterException */ public static KeyPair generateEcEncryptKeyPair() throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException { KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance( PkiConstant.EC, BouncyCastleProvider.PROVIDER_NAME); keyPairGenerator.initialize( ECNamedCurveTable.getParameterSpec(PkiConstant.SECP256K1)); return keyPairGenerator.generateKeyPair(); } /** * Get X500Name. * * @param name user full name * @param company String * @param country String * @return X500Name */ public static X500Name getNameBuilder(String name, String company, String country) { X500NameBuilder nameBuilder = new X500NameBuilder(BCStyle.INSTANCE); nameBuilder.addRDN(BCStyle.CN, name); nameBuilder.addRDN(BCStyle.O, company); nameBuilder.addRDN(BCStyle.C, country); return nameBuilder.build(); } public static X500Name getOuNameBuilder(String name, String company, String country) { X500NameBuilder nameBuilder = new X500NameBuilder(BCStyle.INSTANCE); nameBuilder.addRDN(BCStyle.CN, name); nameBuilder.addRDN(BCStyle.OU, company); nameBuilder.addRDN(BCStyle.C, country); return nameBuilder.build(); } public static byte[] getRootEncodedHolder(SubjectPublicKeyInfo subPubKeyInfo, X500Name x500Name, int validTime, X500Name subject, PrivateKey privateKey, String algorithm) throws Exception { BigInteger serialNumber = BigInteger .valueOf(System.currentTimeMillis()); Calendar c = Calendar.getInstance(); Date startDate = c.getTime(); c.add(Calendar.YEAR, validTime); Date endDate = c.getTime(); X509v3CertificateBuilder x509v3CertBuilder = new X509v3CertificateBuilder( x500Name, serialNumber, startDate, endDate, subject, subPubKeyInfo); // Basic constraints is a CA BasicConstraints constraints = new BasicConstraints(true); x509v3CertBuilder.addExtension( Extension.basicConstraints, true, constraints.getEncoded()); // Key usage KeyUsage usage = new KeyUsage(KeyUsage.keyEncipherment | KeyUsage.digitalSignature | KeyUsage.keyCertSign | KeyUsage.cRLSign); x509v3CertBuilder.addExtension(Extension.keyUsage, true, usage.getEncoded()); // Extended key usage x509v3CertBuilder.addExtension(Extension.extendedKeyUsage, false, new ExtendedKeyUsage(KeyPurposeId.anyExtendedKeyUsage)); // AuthorityKeyIdentifier,subjectKeyIdentifier 便于证书链的匹配查找 DigestCalculator calculator = new BcDigestCalculatorProvider().get(new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1)); X509ExtensionUtils extensionUtils = new X509ExtensionUtils(calculator); x509v3CertBuilder.addExtension(Extension.subjectKeyIdentifier, false, extensionUtils.createSubjectKeyIdentifier(subPubKeyInfo)); X509CertificateHolder holder = x509v3CertBuilder.build(getSigner(privateKey, algorithm)); return holder.getEncoded(); } /** * Get encoded X509CertificateHolder. * * @param subPubKeyInfo * @param x500Name * @param validTime * @param subject * @param privateKey * @param algorithm * @param rootPublickey * @return byte[] * @throws Exception */ public static byte[] getEncodedHolder(SubjectPublicKeyInfo subPubKeyInfo, X500Name x500Name, int validTime, X500Name subject, PrivateKey privateKey, String algorithm, PublicKey rootPublickey) throws Exception { BigInteger serialNumber = BigInteger .valueOf(System.currentTimeMillis()); Calendar c = Calendar.getInstance(); Date startDate = c.getTime(); c.add(Calendar.YEAR, validTime); Date endDate = c.getTime(); X509v3CertificateBuilder x509v3CertBuilder = new X509v3CertificateBuilder( x500Name, serialNumber, startDate, endDate, subject, subPubKeyInfo); // Basic constraints not a CA,just one end cert BasicConstraints constraints = new BasicConstraints(false); x509v3CertBuilder.addExtension( Extension.basicConstraints, true, constraints.getEncoded()); // Key usage KeyUsage usage = new KeyUsage(KeyUsage.dataEncipherment | KeyUsage.digitalSignature ); x509v3CertBuilder.addExtension(Extension.keyUsage, true, usage.getEncoded()); // AuthorityKeyIdentifier 颁发者密钥标识,subjectKeyIdentifier 使用者密钥标识 便于证书链的匹配查找 DigestCalculator calculator = new BcDigestCalculatorProvider().get(new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1)); X509ExtensionUtils extensionUtils = new X509ExtensionUtils(calculator); SubjectPublicKeyInfo rootPubKeyInfo = SubjectPublicKeyInfo .getInstance(rootPublickey.getEncoded()); x509v3CertBuilder.addExtension(Extension.authorityKeyIdentifier, false, extensionUtils.createAuthorityKeyIdentifier(rootPubKeyInfo)); X509CertificateHolder holder = x509v3CertBuilder .build(getSigner(privateKey, algorithm)); return holder.getEncoded(); } /** * Create E-cert request. * * @param keyPair KeyPair * @param algorithm SHA256withRSA/SHA256withECDSA/SM3withSM2 * @param name user full name * @param company user company * @param country user country * @return PKCS10CertificationRequest * @throws Exception exception */ public static PKCS10CertificationRequest generateEnrollRequest(KeyPair keyPair, String algorithm, String name, String company, String country) throws Exception { PKCS10CertificationRequestBuilder p10Builder = new JcaPKCS10CertificationRequestBuilder( getNameBuilder(name, company, country), keyPair.getPublic()); return p10Builder.build(getSigner(keyPair.getPrivate(), algorithm)); } public static PKCS10CertificationRequest generateEccEncryptEnrollCARequest(KeyPair keyPair, String country, String company, String name) throws Exception { PKCS10CertificationRequest csr = null; X500NameBuilder nameBuilder = new X500NameBuilder(BCStyle.INSTANCE); nameBuilder.addRDN(BCStyle.CN, country); nameBuilder.addRDN(BCStyle.O, company); nameBuilder.addRDN(BCStyle.C, name); X500Name x500Name = nameBuilder.build(); PKCS10CertificationRequestBuilder p10Builder = new JcaPKCS10CertificationRequestBuilder( x500Name, keyPair.getPublic()); p10Builder.addAttribute(new ASN1ObjectIdentifier("1.2.840.10045.2.1"), new DERGeneralString("EC") ); JcaContentSignerBuilder csBuilder = new JcaContentSignerBuilder(PkiConstant.ALGORITHM_ECC); ContentSigner signer = csBuilder.build(keyPair.getPrivate()); csr = p10Builder.build(signer); return csr; } /** * Create signer. * * @param privateKey PrivateKey * @param algorithm SHA256withRSA/SHA256withECDSA/SM3withSM2 * @return ContentSigner * @throws OperatorCreationException OperatorCreationException */ public static ContentSigner getSigner(PrivateKey privateKey, String algorithm) throws OperatorCreationException { JcaContentSignerBuilder csBuilder = new JcaContentSignerBuilder( algorithm).setProvider(BouncyCastleProvider.PROVIDER_NAME); ContentSigner signer = csBuilder.build(privateKey); return signer; } /** * Verify cert. * * @param certResult CertResult * @param localKey Public Key * @return cert chain * @throws Exception verify exception */ // public static X509Certificate[] verify(CertResult1 certResult, // PublicKey localKey) // throws Exception { // // check the cert // byte[] byteEnd = Base64Utils.decode(certResult.getEndCert()); // byte[] byteInter = Base64Utils.decode(certResult.getInterCert()); // byte[] byteRoot = Base64Utils.decode(certResult.getRootCert()); // // try (InputStream inStream1 = new ByteArrayInputStream(byteEnd); // InputStream inStream2 = new ByteArrayInputStream(byteInter); // InputStream inStream3 = new ByteArrayInputStream(byteRoot)) { // // X509Certificate endCert = (X509Certificate) CertificateFactory // .getInstance(PkiConstant.X509, // BouncyCastleProvider.PROVIDER_NAME) // .generateCertificate(inStream1); // X509Certificate interCert = (X509Certificate) CertificateFactory // .getInstance(PkiConstant.X509, // BouncyCastleProvider.PROVIDER_NAME) // .generateCertificate(inStream2); // X509Certificate rootCert = (X509Certificate) CertificateFactory // .getInstance(PkiConstant.X509, // BouncyCastleProvider.PROVIDER_NAME) // .generateCertificate(inStream3); // // endCert.verify(interCert.getPublicKey()); // 检查 终端证书是否由中级CA签发。 // interCert.verify(rootCert.getPublicKey()); // 检查 中级证书是否由根级CA签发。 // // 根级证书也可以直接从LDAP获取。 // if (!localKey.equals(endCert.getPublicKey())) { // throw new CertificateException("Public key not match."); // } // return new X509Certificate[] { endCert, interCert, rootCert }; // } // // } /** * Save cert to key store. * * @param param KeyStoreParam * @param privateKey private key * @param keyStoreType key store type: JCELS, PKCS12 * @throws Exception exception */ public static void saveRootToKeystore(SystemConfig param, PrivateKey privateKey, String keyStoreType) throws Exception { KeyStore store = null; if (PkiConstant.PKCS12.equals(keyStoreType)) { store = KeyStore.getInstance(PkiConstant.PKCS12, BouncyCastleProvider.PROVIDER_NAME); } else { store = KeyStore.getInstance(PkiConstant.JCEKS); } store.load(null, null); X509Certificate[] chain = param.getChain(); store.setCertificateEntry(param.getCertAlias(), chain[0]); // 保存证书 if (chain.length > 1 && null != param.getRootAlias()) { //保存根证书 store.setCertificateEntry(param.getRootAlias(), chain[1]); } store.setKeyEntry(param.getRootAlias(), privateKey, param.getRootPassword().toCharArray(), chain); // 保存私钥 File storeDir = new File(param.getRootKsPath()); if (!storeDir.exists()) { storeDir.mkdirs(); } File storeFile = new File(param.getRootKsPath() + File.separator + param.getRootKsFileName()); if (!storeFile.exists()) { storeFile.createNewFile(); //不存在则创建 try (FileOutputStream fos = new FileOutputStream(storeFile)) { store.store(fos, param.getRootPassword().toCharArray()); // Keystore } //保证证书到文件中,以cer格式 if(chain.length == 1) { //根证书 String rootKsName = param.getRootKsFileName().substring(0, param.getRootKsFileName().lastIndexOf(".")); saveCertToFile(param.getRootKsPath() + rootKsName + "_Cert.cer", chain[0]); } if(chain.length > 1) { //OU证书 String certKsName = param.getCertKsFileName().substring(0, param.getCertKsFileName().lastIndexOf(".")); saveCertToFile(param.getCertKsPath() + certKsName + "_Cert.cer", chain[0]); //根证书 // saveCertToFile(param.getRootKsPath()+"rootCert.cer",chain[1]); } }else { // key store文件已经存在,什么都不干! } } public static void saveCertToKeystore(SystemConfig param, PrivateKey privateKey, String keyStoreType) throws Exception { KeyStore store = null; if (PkiConstant.PKCS12.equals(keyStoreType)) { store = KeyStore.getInstance(PkiConstant.PKCS12, BouncyCastleProvider.PROVIDER_NAME); } else { store = KeyStore.getInstance(PkiConstant.JCEKS); } store.load(null, null); X509Certificate[] chain = param.getChain(); store.setCertificateEntry(param.getCertAlias(), chain[0]); // 保存证书 if (chain.length > 1 && null != param.getCertAlias()) { //保存根证书 store.setCertificateEntry(param.getCertAlias(), chain[1]); } store.setKeyEntry(param.getCertAlias(), privateKey, param.getCertPassword().toCharArray(), chain); // 保存私钥 File storeDir = new File(param.getCertKsPath()); if (!storeDir.exists()) { storeDir.mkdirs(); } File storeFile = new File(param.getCertKsPath() + File.separator + param.getCertKsFileName()); if (!storeFile.exists()) { storeFile.createNewFile(); //不存在则创建 try (FileOutputStream fos = new FileOutputStream(storeFile)) { store.store(fos, param.getCertPassword().toCharArray()); // Keystore } //保证证书到文件中,以cer格式 if (chain.length == 1) { //根证书 String rootKsName = param.getRootKsFileName().substring(0, param.getRootKsFileName().lastIndexOf(".")); saveCertToFile(param.getRootKsPath() + rootKsName + "_Cert.cer", chain[0]); } if (chain.length > 1) { //OU证书 String certKsName = param.getCertKsFileName().substring(0, param.getCertKsFileName().lastIndexOf(".")); saveCertToFile(param.getCertKsPath() + certKsName + "_Cert.cer", chain[0]); //根证书 // saveCertToFile(param.getCertKsPath() + "rootCert.cer", chain[1]); } } else { // key store文件已经存在,什么都不干! } } /** * Get enroll keystore. * * @param filePath * @param ksPassword * @param keyStoreType * @return KeyStore * @throws Exception */ public static KeyStore getKeyStore(String filePath, String ksPassword, String keyStoreType) throws Exception { ksPassword = CipherUtil.zeroSuffix(ksPassword); KeyStore store = null; File storeFile = new File(filePath); if (!storeFile.exists()) { return null; } try (FileInputStream fileInputStream = new FileInputStream(filePath)) { if (PkiConstant.JCEKS.equals(keyStoreType)) { store = KeyStore.getInstance(keyStoreType); } else { store = KeyStore.getInstance(keyStoreType, BouncyCastleProvider.PROVIDER_NAME); } store.load(fileInputStream, ksPassword.toCharArray()); return store; } } public static void saveCertToFile(String fileName,X509Certificate cert) { try { File file = new File(fileName); FileOutputStream fos = new FileOutputStream(file); fos.write(cert.getEncoded()); fos.flush(); fos.close(); } catch (Exception e) { e.printStackTrace(); } } public static X509Certificate getCertFromCer(String filePath) { X509Certificate cert = null; byte[] certByte = IOUtils.getBytes(filePath); ByteArrayInputStream inStream = new ByteArrayInputStream(certByte); try { cert = (X509Certificate) CertificateFactory .getInstance(PkiConstant.X509, BouncyCastleProvider.PROVIDER_NAME) .generateCertificate(inStream); } catch (Exception e) { e.printStackTrace(); } return cert; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy