
com.jd.blockchain.ca.CertificateUtils Maven / Gradle / Ivy
The newest version!
package com.jd.blockchain.ca;
import com.jd.blockchain.crypto.*;
import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm;
import com.jd.blockchain.crypto.service.sm.SMAlgorithm;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.x500.RDN;
import org.bouncycastle.asn1.x500.style.BCStyle;
import org.bouncycastle.asn1.x500.style.IETFUtils;
import org.bouncycastle.asn1.x509.BasicConstraints;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
import org.bouncycastle.pkcs.PKCS10CertificationRequest;
import sun.security.x509.X509CertImpl;
import utils.io.FileUtils;
import java.io.*;
import java.security.*;
import java.security.cert.*;
import java.util.*;
/**
* @description: X509 证书工具
* @author: imuge
* @date: 2021/8/23
**/
public class CertificateUtils {
// EC 相关算法参数
static final String EC_ALGORITHM = "EC";
static final String SIGALG_SM3WITHSM2 = "SM3WITHSM2";
static final String SECP256R1 = "BggqhkjOPQMBBw==";
static final String SM2ECC = "BggqgRzPVQGCLQ==";
static final String BEGIN_PARAMS = "-----BEGIN EC PARAMETERS-----";
static final String END_PARAMS = "-----END EC PARAMETERS-----";
static Map identifierMap = new HashMap<>();
static JcaPEMKeyConverter converter;
static {
Security.addProvider(new BouncyCastleProvider());
converter = new JcaPEMKeyConverter();
identifierMap.put("1.2.840.10045.2.1" + "1.2.840.10045.3.1.7", "ECDSA");
identifierMap.put("1.3.101.112", "ED25519");
identifierMap.put("1.2.840.113549.1.1.1", "RSA");
identifierMap.put("1.2.840.10045.2.1" + "1.2.156.10197.1.301", "SM2");
}
public static String toPEMString(X509Certificate certificate) {
try {
final StringWriter writer = new StringWriter();
final JcaPEMWriter pemWriter = new JcaPEMWriter(writer);
pemWriter.writeObject(certificate);
pemWriter.flush();
pemWriter.close();
return writer.toString();
} catch (IOException e) {
throw new CryptoException(e.getMessage(), e);
}
}
/**
* PrivateKey to PEM String
*
* @param algorithm
* @param privateKey
* @return
*/
public static String toPEMString(String algorithm, PrivateKey privateKey) {
try {
StringWriter sw = new StringWriter();
if (algorithm.equals("SM2")) {
sw.append(BEGIN_PARAMS + "\n" +
SM2ECC + "\n" +
END_PARAMS + "\n");
} else if (algorithm.equals("ECDSA")) {
sw.append(BEGIN_PARAMS + "\n" +
SECP256R1 + "\n" +
END_PARAMS + "\n");
}
JcaPEMWriter writer = new JcaPEMWriter(sw);
writer.writeObject(privateKey);
writer.close();
return sw.getBuffer().toString();
} catch (Exception e) {
throw new IllegalStateException("private key to string error", e);
}
}
public static String toPEMString(PrivateKey privateKey) {
try {
String encodedString = "-----BEGIN PRIVATE KEY-----\n";
encodedString = encodedString + Base64.getEncoder().encodeToString(privateKey.getEncoded()) + "\n";
encodedString = encodedString + "-----END PRIVATE KEY-----\n";
return encodedString;
} catch (Exception e) {
throw new IllegalStateException("private key to string error", e);
}
}
/**
* Checks that the certificate is currently valid
*
* @param certificate
*/
public static void checkValidity(X509Certificate certificate) {
try {
certificate.checkValidity();
} catch (CertificateExpiredException | CertificateNotYetValidException e) {
throw new CryptoException(e.getMessage(), e);
}
}
/**
* Checks that any certificates is currently valid
*
* @param certificates
*/
public static void checkValidityAny(X509Certificate... certificates) {
boolean valid = false;
for (X509Certificate cert : certificates) {
try {
checkValidity(cert);
valid = true;
break;
} catch (Exception e) {
}
}
if (!valid) {
throw new CryptoException("Invalid CAs");
}
}
public static void checkCACertificate(X509Certificate certificate) {
if (certificate.getBasicConstraints() == -1) {
throw new CryptoException("not ca certificate!");
}
}
public static boolean checkCACertificateNoException(X509Certificate certificate) {
return BasicConstraints.getInstance(certificate.getExtensionValue(Extension.basicConstraints.getId())).isCA();
}
/**
* Checks that the type is valid
*
* @param certificate
* @param caType
*/
public static void checkCertificateRole(X509Certificate certificate, CertificateRole caType) {
if (!getSubject(certificate, BCStyle.OU).contains(caType.name())) {
throw new CryptoException(caType.name() + " ca invalid!");
}
}
/**
* Checks that the type is valid
*
* @param certificates
* @param caType
*/
public static void checkCertificateRole(X509Certificate[] certificates, CertificateRole caType) {
Arrays.stream(certificates).forEach(cert -> checkCertificateRole(cert, caType));
}
/**
* Checks that any type is valid
*
* @param certificate
* @param caTypes
*/
public static void checkCertificateRolesAny(X509Certificate certificate, CertificateRole... caTypes) {
Set ous = getSubject(certificate, BCStyle.OU);
boolean contains = false;
for (CertificateRole caType : caTypes) {
if (ous.contains(caType.name())) {
contains = true;
break;
}
}
if (!contains) {
throw new CryptoException(caTypes.toString() + " ca invalid!");
}
}
/**
* Checks that any type is valid
*
* @param certificate
* @param caTypes
*/
public static boolean checkCertificateRolesAnyNoException(X509Certificate certificate, CertificateRole... caTypes) {
Set ous = getSubject(certificate, BCStyle.OU);
boolean contains = false;
for (CertificateRole caType : caTypes) {
if (ous.contains(caType.name())) {
contains = true;
break;
}
}
return contains;
}
/**
* Checks that any type is valid
*
* @param csr
* @param caTypes
*/
public static boolean checkCertificateRolesAnyNoException(PKCS10CertificationRequest csr, CertificateRole... caTypes) {
Set ous = getSubject(csr, BCStyle.OU);
boolean contains = false;
for (CertificateRole caType : caTypes) {
if (ous.contains(caType.name())) {
contains = true;
break;
}
}
return contains;
}
/**
* Checks that all types are valid
*
* @param certificate
* @param caTypes
*/
public static void checkCertificateRolesAll(X509Certificate certificate, CertificateRole... caTypes) {
Set ous = getSubject(certificate, BCStyle.OU);
for (CertificateRole caType : caTypes) {
if (!ous.contains(caType.name())) {
throw new CryptoException(caTypes.toString() + " ca invalid!");
}
}
}
/**
* Verifies that this certificate was signed using the private key that corresponds to the specified public key.
*
* @param certificate
* @param publicKey
*/
public static void verify(X509Certificate certificate, PublicKey publicKey) {
try {
certificate.verify(publicKey);
} catch (CertificateException | NoSuchAlgorithmException | InvalidKeyException | NoSuchProviderException | SignatureException e) {
throw new CryptoException(e.getMessage(), e);
}
}
/**
* Verifies that this certificate was signed using the private key that corresponds to the specified public key.
*
* @param certificate
* @param parents
*/
public static void verifyAny(X509Certificate certificate, X509Certificate[] parents) {
boolean valid = false;
for (X509Certificate cert : parents) {
try {
verify(certificate, cert.getPublicKey());
valid = true;
break;
} catch (Exception e) {
}
}
if (!valid) {
throw new CryptoException("Invalid CA");
}
}
/**
* Get the specified subject item.
*
* @param certificate
* @param identifier
* @return
*/
public static Set getSubject(X509Certificate certificate, ASN1ObjectIdentifier identifier) {
try {
Set values = new HashSet<>();
RDN[] rdNs = new JcaX509CertificateHolder(certificate).getSubject().getRDNs(identifier);
Arrays.stream(rdNs).forEach(rdn -> values.add(IETFUtils.valueToString(rdn.getFirst().getValue())));
return values;
} catch (CertificateEncodingException e) {
throw new CryptoException(e.getMessage(), e);
}
}
/**
* Get the specified subject item.
*
* @param csr
* @param identifier
* @return
*/
public static Set getSubject(PKCS10CertificationRequest csr, ASN1ObjectIdentifier identifier) {
Set values = new HashSet<>();
RDN[] rdNs = csr.getSubject().getRDNs(identifier);
Arrays.stream(rdNs).forEach(rdn -> values.add(IETFUtils.valueToString(rdn.getFirst().getValue())));
return values;
}
/**
* Find issuers
*
* @param certificate
* @param parents
* @return
*/
public static X509Certificate[] findIssuers(X509Certificate certificate, X509Certificate[] parents) {
List certs = new ArrayList<>();
Arrays.stream(parents).forEach(cert -> {
try {
verify(certificate, cert.getPublicKey());
certs.add(cert);
} catch (Exception e) {
}
});
return certs.toArray(new X509Certificate[certs.size()]);
}
/**
* 解析 X509 证书
*
* @param certificate
* @return
*/
public static X509Certificate parseCertificate(String certificate) {
try {
CertificateFactory certificateFactory = CertificateFactory.getInstance(X509CertImpl.NAME, BouncyCastleProvider.PROVIDER_NAME);
return (X509Certificate) certificateFactory.generateCertificate(new ByteArrayInputStream(certificate.getBytes()));
} catch (CertificateException | NoSuchProviderException e) {
throw new CryptoException(e.getMessage(), e);
}
}
/**
* 解析 X509 证书
*
* @param certificates
* @return
*/
public static X509Certificate[] parseCertificates(String[] certificates) {
try {
CertificateFactory certificateFactory = CertificateFactory.getInstance(X509CertImpl.NAME, BouncyCastleProvider.PROVIDER_NAME);
X509Certificate[] certs = new X509Certificate[certificates.length];
for (int i = 0; i < certificates.length; i++) {
certs[i] = (X509Certificate) certificateFactory.generateCertificate(new ByteArrayInputStream(certificates[i].getBytes()));
}
return certs;
} catch (CertificateException | NoSuchProviderException e) {
throw new CryptoException(e.getMessage(), e);
}
}
/**
* 加载 X509 证书
*
* @param certificate
* @return
*/
public static X509Certificate parseCertificate(File certificate) {
try {
CertificateFactory certificateFactory = CertificateFactory.getInstance(X509CertImpl.NAME, BouncyCastleProvider.PROVIDER_NAME);
return (X509Certificate) certificateFactory.generateCertificate(new FileInputStream(certificate));
} catch (CertificateException | NoSuchProviderException | FileNotFoundException e) {
throw new CryptoException(e.getMessage(), e);
}
}
/**
* 解析 certification request
*
* @param csr
* @return
*/
public static PKCS10CertificationRequest parseCertificationRequest(String csr) {
try (PEMParser pemParser = new PEMParser(new StringReader(csr))) {
Object pemObj = pemParser.readObject();
return (PKCS10CertificationRequest) pemObj;
} catch (IOException e) {
throw new CryptoException(e.getMessage(), e);
}
}
/**
* Resolve PubKey from certification request
*
* @param csr
* @return
*/
public static PubKey resolvePubKey(PKCS10CertificationRequest csr) {
SubjectPublicKeyInfo pkInfo = csr.getSubjectPublicKeyInfo();
CryptoAlgorithm algorithm = Crypto.getAlgorithm(identifierMap.get(
pkInfo.getAlgorithm().getAlgorithm().getId() + (
null != pkInfo.getAlgorithm().getParameters() && !"NULL".equals(pkInfo.getAlgorithm().getParameters().toString())
? pkInfo.getAlgorithm().getParameters().toString()
: "")
));
return Crypto.getCASignatureFunction(algorithm).resolvePubKey(csr);
}
/**
* Get PubKey in JD Chain crypto framework.
*
* @param certificate
* @return
*/
public static PubKey resolvePubKey(X509Certificate certificate) {
PublicKey publicKey = certificate.getPublicKey();
String algorithmName = publicKey.getAlgorithm();
String sigAlgName = certificate.getSigAlgName();
CryptoAlgorithm algorithm = !algorithmName.equals(EC_ALGORITHM) ? Crypto.getAlgorithm(algorithmName.toUpperCase()) :
(sigAlgName.equals(SIGALG_SM3WITHSM2) ? SMAlgorithm.SM2 : ClassicAlgorithm.ECDSA);
return Crypto.getCASignatureFunction(algorithm).resolvePubKey(certificate);
}
public static PrivKey parsePrivKey(short algorithmId, String privkey) {
CryptoAlgorithm algorithm = null;
// EC 相关算法
if (privkey.startsWith(BEGIN_PARAMS)) {
// 解析具体算法
if (privkey.contains(SECP256R1)) {
algorithm = ClassicAlgorithm.ECDSA;
} else if (privkey.contains(SM2ECC)) {
algorithm = SMAlgorithm.SM2;
} else {
throw new CryptoException("Unsupported ec algorithm");
}
privkey = privkey.substring(privkey.indexOf(END_PARAMS) + END_PARAMS.length());
}
algorithm = null == algorithm ? Crypto.getAlgorithm(algorithmId) : algorithm;
return Crypto.getCASignatureFunction(algorithm).parsePrivKey(privkey);
}
/**
* Get PrivKey in JD Chain crypto framework.
*
* @param algorithmId
* @param privkey
* @param privkey
* @return
*/
public static PrivKey parsePrivKey(short algorithmId, String privkey, String password) {
CryptoAlgorithm algorithm = null;
// EC 相关算法
if (privkey.startsWith(BEGIN_PARAMS)) {
// 解析具体算法
if (privkey.contains(SECP256R1)) {
algorithm = ClassicAlgorithm.ECDSA;
} else if (privkey.contains(SM2ECC)) {
algorithm = SMAlgorithm.SM2;
} else {
throw new CryptoException("Unsupported ec algorithm");
}
privkey = privkey.substring(privkey.indexOf(END_PARAMS) + END_PARAMS.length());
}
algorithm = null == algorithm ? Crypto.getAlgorithm(algorithmId) : algorithm;
return Crypto.getCASignatureFunction(algorithm).parsePrivKey(privkey, password.toCharArray());
}
/**
* Load PrivKey in JD Chain crypto framework.
*
* @param algorithmId
* @param privkey
* @return
*/
public static PrivKey parsePrivKey(short algorithmId, File privkey) {
return parsePrivKey(algorithmId, FileUtils.readText(privkey));
}
/**
* Load PrivKey in JD Chain crypto framework.
*
* @param algorithmId
* @param privkey
* @param password
* @return
*/
public static PrivKey parsePrivKey(short algorithmId, File privkey, String password) {
return parsePrivKey(algorithmId, FileUtils.readText(privkey), password);
}
/**
* Resolve PrivateKey from JD Chain PrivKey
*
* @param privKey
* @return
*/
public static PrivateKey retrievePrivateKey(PrivKey privKey) {
return Crypto.getCASignatureFunction(privKey.getAlgorithm()).retrievePrivateKey(privKey);
}
public static PrivateKey retrievePrivateKey(PrivKey privKey, PubKey pubKey) {
return Crypto.getCASignatureFunction(privKey.getAlgorithm()).retrievePrivateKey(privKey, pubKey);
}
/**
* Resolve PublicKey from JD Chain PubKey
*
* @param pubKey
* @return
*/
public static PublicKey retrievePublicKey(PubKey pubKey) {
return Crypto.getCASignatureFunction(pubKey.getAlgorithm()).retrievePublicKey(pubKey);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy