Reputation: 599
I have an application that uses BouncyCastle to generate an RSA key pair. I want to store that key pair in a java.security.Keystore. For that I need a certificate (the only reason I need one!).
I'm using bouncycastle version 1.51.
All the examples I have found on this are either using a *CertificateGenerator (deprecated in 1.51) or very complex and without any meaningful explanations.
Whats the easiest way to generate a basically meaningless self-signed certificate for this purpose?
Or is there an alternative to using a keystore?
To be clear: input is a KeyPair holding an RSAPrivateKey and an RSAPublicKey, output should be a java.security.cert.Certificate.
Upvotes: 3
Views: 2797
Reputation: 599
The solution I ended up using looks mostly like the following code (not pretty but it works):
import java.io.IOException;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPublicKey;
import java.sql.Date;
import javax.security.auth.x500.X500Principal;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.X509v1CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.crypto.util.SubjectPublicKeyInfoFactory;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
public class SelfSignedCertificateGenerator {
private static final JcaX509CertificateConverter CONVERTER = new JcaX509CertificateConverter()
.setProvider(new BouncyCastleProvider());
private static final String SIGNATURE_ALGORITHM = "SHA1withRSA";
private static final X500Name ISSUER = new X500Name(new X500Principal("CN=Stupid CA Certificate").getName());
private static final X500Name SUBJECT = ISSUER;
private static final Date NOT_AFTER = Date.valueOf("3000-01-01");
private static final Date NOT_BEFORE = Date.valueOf("2000-01-01");
private static final BigInteger SERIAL = new BigInteger("1");
public static Certificate[] getCerts(KeyPair keys) {
return new Certificate[] { getCertificate(keys) };
}
private static X509Certificate getCertificate(KeyPair keys) {
try {
X509v1CertificateBuilder certificateBuilder = getCertificateBuilder(keys.getPublic());
X509CertificateHolder certificateHolder = certificateBuilder.build(getSigner(keys));
return CONVERTER.getCertificate(certificateHolder);
} catch (CertificateException e) {
throw new RuntimeException(e);
}
}
private static X509v1CertificateBuilder getCertificateBuilder(PublicKey publicKey) {
return new X509v1CertificateBuilder(ISSUER, SERIAL, NOT_BEFORE, NOT_AFTER, SUBJECT, getPublicKeyInfo(publicKey));
}
private static SubjectPublicKeyInfo getPublicKeyInfo(PublicKey publicKey) {
if (!(publicKey instanceof RSAPublicKey))
throw new RuntimeException("publicKey is not an RSAPublicKey");
RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey;
try {
return SubjectPublicKeyInfoFactory.createSubjectPublicKeyInfo(new RSAKeyParameters(false, rsaPublicKey
.getModulus(), rsaPublicKey.getPublicExponent()));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private static ContentSigner getSigner(KeyPair keys) {
try {
return new JcaContentSignerBuilder(SIGNATURE_ALGORITHM).setProvider(new BouncyCastleProvider()).build(
keys.getPrivate());
} catch (OperatorCreationException e) {
throw new RuntimeException(e);
}
}
}
Upvotes: 4