Certificado auto firmado X509 con Bouncy Castle en Java

Necesito crear un Certificado X509 autofirmado con Bouncy Castle en Java, pero todas las clases que bash incluir están en desuso. ¿Como puedo resolver esto? ¿Hay alguna otra clase para incluir? Gracias

Usando la última versión de Bouncycastle – 1.55

Actualización a la respuesta por @Bewusstsein. Las clases de bouncycastle están en desuso en la última versión a partir de esta respuesta (5/11/2017). Si está utilizando la última versión (1.55) o una versión relativamente reciente:

public static Certificate selfSign(KeyPair keyPair, String subjectDN) throws OperatorCreationException, CertificateException, IOException { Provider bcProvider = new BouncyCastleProvider(); Security.addProvider(bcProvider); long now = System.currentTimeMillis(); Date startDate = new Date(now); X500Name dnName = new X500Name(subjectDN); BigInteger certSerialNumber = new BigInteger(Long.toString(now)); // <-- Using the current timestamp as the certificate serial number Calendar calendar = Calendar.getInstance(); calendar.setTime(startDate); calendar.add(Calendar.YEAR, 1); // <-- 1 Yr validity Date endDate = calendar.getTime(); String signatureAlgorithm = "SHA256WithRSA"; // <-- Use appropriate signature algorithm based on your keyPair algorithm. ContentSigner contentSigner = new JcaContentSignerBuilder(signatureAlgorithm).build(keyPair.getPrivate()); JcaX509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder(dnName, certSerialNumber, startDate, endDate, dnName, keyPair.getPublic()); // Extensions -------------------------- // Basic Constraints BasicConstraints basicConstraints = new BasicConstraints(true); // <-- true for CA, false for EndEntity certBuilder.addExtension(new ASN1ObjectIdentifier("2.5.29.19"), true, basicConstraints); // Basic Constraints is usually marked as critical. // ------------------------------------- return new JcaX509CertificateConverter().setProvider(bcProvider).getCertificate(certBuilder.build(contentSigner)); } 

ATENCIÓN: esta respuesta utiliza una versión anterior de la biblioteca con 11 CVE .

Esto es lo que estoy usando (con BouncyCastle v1.38):

 import java.math.BigInteger; import java.security.InvalidKeyException; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.SecureRandom; import java.security.Security; import java.security.SignatureException; import java.util.Date; import javax.security.auth.x500.X500Principal; import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; import org.bouncycastle.asn1.x509.ExtendedKeyUsage; import org.bouncycastle.asn1.x509.KeyPurposeId; import org.bouncycastle.asn1.x509.X509Extensions; import org.bouncycastle.asn1.x509.X509Name; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.x509.X509V3CertificateGenerator; public class BouncyCastle { public static void main(String[] args) throws CertificateEncodingException, InvalidKeyException, IllegalStateException, NoSuchProviderException, NoSuchAlgorithmException, SignatureException { X509Certificate selfSignedX509Certificate = new BouncyCastle().generateSelfSignedX509Certificate(); System.out.println(selfSignedX509Certificate); } public X509Certificate generateSelfSignedX509Certificate() throws CertificateEncodingException, InvalidKeyException, IllegalStateException, NoSuchProviderException, NoSuchAlgorithmException, SignatureException { addBouncyCastleAsSecurityProvider(); // generate a key pair KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", "BC"); keyPairGenerator.initialize(4096, new SecureRandom()); KeyPair keyPair = keyPairGenerator.generateKeyPair(); // build a certificate generator X509V3CertificateGenerator certGen = new X509V3CertificateGenerator(); X500Principal dnName = new X500Principal("cn=example"); // add some options certGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis())); certGen.setSubjectDN(new X509Name("dc=name")); certGen.setIssuerDN(dnName); // use the same // yesterday certGen.setNotBefore(new Date(System.currentTimeMillis() - 24 * 60 * 60 * 1000)); // in 2 years certGen.setNotAfter(new Date(System.currentTimeMillis() + 2 * 365 * 24 * 60 * 60 * 1000)); certGen.setPublicKey(keyPair.getPublic()); certGen.setSignatureAlgorithm("SHA256WithRSAEncryption"); certGen.addExtension(X509Extensions.ExtendedKeyUsage, true, new ExtendedKeyUsage(KeyPurposeId.id_kp_timeStamping)); // finally, sign the certificate with the private key of the same KeyPair X509Certificate cert = certGen.generate(keyPair.getPrivate(), "BC"); return cert; } public void addBouncyCastleAsSecurityProvider() { Security.addProvider(new BouncyCastleProvider()); } } 

Para certGen.generate(keyPair.getPrivate(), "BC"); para trabajar, se debe agregar BouncyCastle como proveedor de seguridad.

Confirmé que funciona con esta dependencia maven:

  org.bouncycastle bcprov-jdk16 1.38  

Aquí hay un generador de certificados ECDSA completo y autofirmado que crea certificados utilizables en conexiones TLS tanto en el lado del cliente como del servidor. Fue probado con BouncyCastle 1.57. Se puede utilizar un código similar para crear certificados RSA.

 SecureRandom random = new SecureRandom(); // create keypair KeyPairGenerator keypairGen = KeyPairGenerator.getInstance("EC"); keypairGen.initialize(256, random); KeyPair keypair = keypairGen.generateKeyPair(); // fill in certificate fields X500Name subject = new X500NameBuilder(BCStyle.INSTANCE) .addRDN(BCStyle.CN, "stackoverflow.com") .build(); byte[] id = new byte[20]; random.nextBytes(id); BigInteger serial = new BigInteger(160, random); X509v3CertificateBuilder certificate = new JcaX509v3CertificateBuilder( subject, serial, Date.from(LocalDate.of(2000, 1, 1).atStartOfDay(ZoneOffset.UTC).toInstant()), Date.from(LocalDate.of(2035, 1, 1).atStartOfDay(ZoneOffset.UTC).toInstant()), subject, keypair.getPublic()); certificate.addExtension(Extension.subjectKeyIdentifier, false, id); certificate.addExtension(Extension.authorityKeyIdentifier, false, id); BasicConstraints constraints = new BasicConstraints(true); certificate.addExtension( Extension.basicConstraints, true, constraints.getEncoded()); KeyUsage usage = new KeyUsage(KeyUsage.keyCertSign | KeyUsage.digitalSignature); certificate.addExtension(Extension.keyUsage, false, usage.getEncoded()); ExtendedKeyUsage usageEx = new ExtendedKeyUsage(new KeyPurposeId[] { KeyPurposeId.id_kp_serverAuth, KeyPurposeId.id_kp_clientAuth }); certificate.addExtension( Extension.extendedKeyUsage, false, usageEx.getEncoded()); // build BouncyCastle certificate ContentSigner signer = new JcaContentSignerBuilder("SHA256withECDSA") .build(keypair.getPrivate()); X509CertificateHolder holder = certificate.build(signer); // convert to JRE certificate JcaX509CertificateConverter converter = new JcaX509CertificateConverter(); converter.setProvider(new BouncyCastleProvider()); X509Certificate x509 = converter.getCertificate(holder); // serialize in DER format byte[] serialized = x509.getEncoded();