If your Java stack currently uses Bouncy Castle for certificate tooling, moving CRL generation to wolfSSL’s JNI is straightforward once you map the flow correctly.
wolfSSL JNI/JSSE uses wolfSSL’s native C crypto/TLS library, so projects can share one crypto implementation across Java and non-Java components. In environments that require validated cryptography, wolfSSL has significant experience delivering FIPS 140-3 validated modules.
What changes in practice
- Bouncy Castle is builder-centric (X509v2CRLBuilder, X509v3CertificateBuilder).
- wolfssljni is JNI/native-call centric (WolfSSLCRL, WolfSSLCertificate) and uses return codes.
- For JNI-backed objects, explicit free() is part of the normal lifecycle.
Comparison table of CRL generation flow
| Step | Bouncy Castle (BC) | wolfSSL JNI (wolfssljni) |
|---|---|---|
| Initialize | Security.addProvider(new BouncyCastleProvider()) | WolfSSL.loadLibrary() (and optionally WolfSSL.CrlGenerationEnabled()) |
| Create CRL object | new X509v2CRLBuilder(issuer, thisUpdate) | new WolfSSLCRL() |
| Set issuer + times | Set issuer in builder constructor above, then setNextUpdate(…) | setIssuerName(…), setLastUpdate(…), setNextUpdate(…) |
| Add revoked entry | addCRLEntry(serial, date, reason) | addRevoked(serialBytes, date) |
| Sign CRL | build(ContentSigner) | sign(privateKey, “SHA256”) |
| Export CRL | DER: getEncoded(); PEM via PEM writer | getDer(), getPem(), writeToFile(…) |
| Add CRL DP extension (URI) to cert | addExtension(Extension.cRLDistributionPoints, …) | addCrlDistPoint(…) / addCRLDistributionPoint(…) -> native X509_CRL_add_dist_point |
| Add CRL DP extension (pre-encoded DER) to cert | addExtension(…, encodedValue) | setCrlDistPoints(…) / setCRLDistributionPoints(…) -> native X509_CRL_set_dist_points |
| Cleanup | Java GC | Explicit free() for JNI-backed objects |
Example 1: Bouncy Castle (CRL + CRL Distribution Point extension)
// imports trimmed for readability
public class BcCrlExample {
public static void main(String[] args) throws Exception {
Security.addProvider(new BouncyCastleProvider());
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(2048);
KeyPair caKeyPair = kpg.generateKeyPair();
Date now = new Date();
Date nextUpdate = new Date(now.getTime() + 7L * 24 * 60 * 60 * 1000);
// Basic CRL generation
X509v2CRLBuilder crlBuilder =
new X509v2CRLBuilder(new X500Name("CN=Example CA"), now);
crlBuilder.setNextUpdate(nextUpdate);
crlBuilder.addCRLEntry(new BigInteger("1001"), now, CRLReason.unspecified);
X509CRLHolder crlHolder = crlBuilder.build(
new JcaContentSignerBuilder("SHA256withRSA")
.build(caKeyPair.getPrivate())
);
byte[] crlDer = crlHolder.getEncoded();
// Certificate CRL Distribution Points extension (URI form)
GeneralName uri = new GeneralName(
GeneralName.uniformResourceIdentifier,
"http://example.com/example-ca.crl"
);
DistributionPointName dpName =
new DistributionPointName(new GeneralNames(uri));
DistributionPoint dp = new DistributionPoint(dpName, null, null);
CRLDistPoint crlDp = new CRLDistPoint(new DistributionPoint[] { dp });
certBuilder.addExtension(Extension.cRLDistributionPoints, false, crlDp);
System.out.println("BC CRL DER length: " + crlDer.length);
}
// Assume this comes from your cert-issuance flow
static X509v3CertificateBuilder certBuilder;
}
Example 2: wolfSSL JNI (CRL + both CRL DP functions)
// imports trimmed for readability
public class WolfSslCrlExample {
private static void check(String op, int ret) {
if (ret != WolfSSL.SSL_SUCCESS) {
throw new RuntimeException(op + " failed: " + ret);
}
}
public static void main(String[] args) throws Exception {
WolfSSL.loadLibrary();
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(2048);
KeyPair caKeyPair = kpg.generateKeyPair();
Date now = new Date();
Date nextUpdate = new Date(now.getTime() + 7L * 24 * 60 * 60 * 1000);
WolfSSLX509Name issuer = new WolfSSLX509Name();
WolfSSLCRL crl = new WolfSSLCRL();
WolfSSLCertificate cert = new WolfSSLCertificate();
try {
// Basic CRL generation
issuer.setCommonName("Example CA");
check("setIssuerName", crl.setIssuerName(issuer));
check("setLastUpdate", crl.setLastUpdate(now));
check("setNextUpdate", crl.setNextUpdate(nextUpdate));
check("addRevoked", crl.addRevoked(new byte[] { 0x03, (byte)0xE9 }, now));
check("sign", crl.sign(caKeyPair.getPrivate(), "SHA256"));
byte[] crlDer = crl.getDer();
// CRL DP from URI (native: X509_CRL_add_dist_point)
cert.addCrlDistPoint("http://example.com/example-ca.crl", false);
// or: cert.addCRLDistributionPoint("http://example.com/example-ca.crl", false);
// CRL DP from pre-encoded DER (native: X509_CRL_set_dist_points)
byte[] crlDpDer = buildOrLoadCrlDpDer();
cert.setCrlDistPoints(crlDpDer);
// or: cert.setCRLDistributionPoints(crlDpDer);
System.out.println("wolfSSL CRL DER length: " + crlDer.length);
} finally {
cert.free();
crl.free();
issuer.free();
}
}
static byte[] buildOrLoadCrlDpDer() {
throw new UnsupportedOperationException("Provide DER-encoded CRL DP value");
}
}
Migration checklist
- Port baseline CRL generation first (issuer, times, revoked serials, signing).
- Add CRL DP cert extension parity.
- URI path (add…dist_point)
- DER path (set…dist_points)
- Keep strict return-code checks in JNI calls.
- Add explicit native resource cleanup (free()).
- Compare DER outputs in tests to validate behavioral parity.
Question?
If you have questions about any of the above, please contact us at facts@wolfssl.com or call us at +1 425 245 8247.
Download wolfSSL Now

