
net.dona.doip.util.tls.X509CertificateGenerator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of doip-sdk Show documentation
Show all versions of doip-sdk Show documentation
DOIP Software Development Kit that implements DOIP v2 Specification.
package net.dona.doip.util.tls;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.math.BigInteger;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.DERUTF8String;
import org.bouncycastle.asn1.x500.AttributeTypeAndValue;
import org.bouncycastle.asn1.x500.RDN;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x500.style.BCStyle;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
/**
* Utility methods to generate X509 certificates, and to read and write
* certificates from and to PEM files.
*/
public class X509CertificateGenerator {
private static SecureRandom random = new SecureRandom();
static {
random.setSeed(System.nanoTime());
}
public static X509Certificate generate(String handle, PublicKey pubKey, PrivateKey privKey) throws Exception {
if (handle == null) return generateWithUid(null, pubKey, privKey);
int colon = handle.indexOf(':');
if (colon < 0) return generateWithUid(handle, pubKey, privKey);
String maybeIndex = handle.substring(0, colon);
if (isDigits(maybeIndex)) return generateWithUid("0:" + handle, pubKey, privKey);
return generateWithUid(handle, pubKey, privKey);
}
public static X509Certificate generate(String handle, int index, PublicKey pubKey, PrivateKey privKey) throws Exception {
return generateWithUid("" + index + ":" + handle, pubKey, privKey);
}
private static final Date notBefore, notAfter;
static {
notBefore = Date.from(Instant.parse("2000-01-01T00:00:00Z"));
notAfter = Date.from(Instant.parse("9999-12-31T23:59:59Z"));
}
public static X509Certificate generateWithUid(String uid, PublicKey pubKey, PrivateKey privKey) throws Exception {
return generateWithCnAndUid(null, uid, pubKey, privKey);
}
public static X509Certificate generateWithCnAndUid(String cn, String uid, PublicKey pubKey, PrivateKey privKey) throws Exception {
X500Name name;
if (uid == null) {
if (cn == null) cn = "anonymous";
// String anon = Util.decodeHexString(Util.doSHA1Digest(pubKey.getEncoded()), false);
name = new X500Name(new RDN[] { new RDN(new AttributeTypeAndValue(BCStyle.CN, new DERUTF8String(cn))), });
} else if (cn == null) {
name = new X500Name(new RDN[] { new RDN(new AttributeTypeAndValue(BCStyle.UID, new DERUTF8String(uid))), });
} else {
name = new X500Name(new RDN[] { new RDN(new AttributeTypeAndValue(BCStyle.CN, new DERUTF8String(cn))), new RDN(new AttributeTypeAndValue(BCStyle.UID, new DERUTF8String(uid))), });
}
ASN1InputStream in = new ASN1InputStream(pubKey.getEncoded());
SubjectPublicKeyInfo pubKeyInfo;
try {
pubKeyInfo = SubjectPublicKeyInfo.getInstance(in.readObject());
} finally {
in.close();
}
byte[] serialBytes = new byte[20];
random.nextBytes(serialBytes);
serialBytes[0] = (byte) (serialBytes[0] & 0x7F);
X509v3CertificateBuilder builder = new X509v3CertificateBuilder(name, new BigInteger(serialBytes), notBefore, notAfter, name, pubKeyInfo);
ContentSigner signer = new JcaContentSignerBuilder("SHA256with" + privKey.getAlgorithm()).build(privKey);
X509CertificateHolder certHolder = builder.build(signer);
return new JcaX509CertificateConverter().getCertificate(certHolder);
}
public static void storeCertAndKey(KeyStore keyStore, Certificate cert, PrivateKey privKey, String alias, String keyPass) throws KeyStoreException {
keyStore.setKeyEntry(alias, privKey, keyPass.toCharArray(), new Certificate[] { cert });
}
private static void addBCProviderIfNeeded() {
if (Security.getProvider("BC") == null) {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
}
}
public static void writeCertAsPem(Writer writer, Certificate cert) throws IOException {
addBCProviderIfNeeded();
JcaPEMWriter pemWriter = new JcaPEMWriter(writer);
try {
pemWriter.writeObject(cert);
} finally {
pemWriter.close();
}
}
public static X509Certificate readCertAsPem(Reader reader) throws IOException {
addBCProviderIfNeeded();
PEMParser pemReader = new PEMParser(reader);
try {
Object obj = pemReader.readObject();
if (obj instanceof X509Certificate) return (X509Certificate) obj;
if (obj instanceof X509CertificateHolder) return new JcaX509CertificateConverter().getCertificate((X509CertificateHolder) obj);
return null;
} catch (CertificateException e) {
return null;
} finally {
pemReader.close();
reader.close();
}
}
public static X509Certificate[] readCertChainAsPem(Reader reader) throws IOException {
addBCProviderIfNeeded();
List certs = new ArrayList<>();
PEMParser pemReader = new PEMParser(reader);
try {
while (true) {
Object obj = pemReader.readObject();
if (obj == null) break;
else if (obj instanceof X509Certificate) certs.add((X509Certificate) obj);
else if (obj instanceof X509CertificateHolder) certs.add(new JcaX509CertificateConverter().getCertificate((X509CertificateHolder) obj));
}
} catch (CertificateException e) {
return null;
} finally {
pemReader.close();
reader.close();
}
return certs.toArray(new X509Certificate[certs.size()]);
}
private static boolean isDigits(String s) {
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
if (ch < '0' || ch > '9') return false;
}
return true;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy