public static X509Certificate generateCertificate(String dn, KeyPair pair, int days, String algorithm,
      Optional<GeneralNames> subjectAltNames)
      throws CertificateException {
    try {
      Security.addProvider(new BouncyCastleProvider());

      SubjectPublicKeyInfo subPubKeyInfo = SubjectPublicKeyInfo.getInstance(pair.getPublic().getEncoded());
      X500Name name = new X500Name(dn);
      Date from = new Date();
      Date to = new Date(from.getTime() + days * 86400000L);
      BigInteger sn = new BigInteger(64, new SecureRandom());
      X509v3CertificateBuilder v3CertGen = new X509v3CertificateBuilder(name, sn, from, to, name, subPubKeyInfo);
      if (subjectAltNames.isPresent()) {
        v3CertGen.addExtension(Extension.subjectAlternativeName, true, subjectAltNames.get());
      }

      AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find(algorithm);
      AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId);
      AsymmetricKeyParameter privateKeyAsymKeyParam = PrivateKeyFactory.createKey(pair.getPrivate().getEncoded());
      ContentSigner sigGen = new BcRSAContentSignerBuilder(sigAlgId, digAlgId).build(privateKeyAsymKeyParam);
      X509CertificateHolder certificateHolder = v3CertGen.build(sigGen);

      return new JcaX509CertificateConverter().setProvider("BC").getCertificate(certificateHolder);
    } catch (CertificateException ce) {
      throw ce;
    } catch (Exception e) {
      throw new CertificateException(e);
    }
  }
Create a self-signed X.509 Certificate.
From http://bfo.com/blog/2011/03/08/odds_and_ends_creating_a_new_x_509_certificate.html.

@param dn the X.509 Distinguished Name, eg "CN(commonName)=Test, O(organizationName)=Org"
@param pair the KeyPair
@param days how many days from now the Certificate is valid for
@param algorithm the signing algorithm, eg "SHA1withRSA"
@param subjectAltNames the subject alternative names for which the Certificate is valid for
@return the self-signed certificate
@throws java.security.cert.CertificateException thrown if a security error or an IO error ocurred.
ambry-test-utils/src/main/java/com/github/ambry/commons/TestSSLUtils.java