Nucleus
Performance & native

Native SSL — trust roots from the OS, not the JRE

An X509TrustManager that merges the JVM defaults with the OS keychain / cert store, so corporate roots and MDM-installed CAs Just Work.

A JVM app shipped with a bundled JRE only trusts the cacerts baked into that JRE. Custom root CAs installed by an enterprise IT policy, an MDM, or an SSL-inspection proxy are invisible — every HTTPS handshake to those hosts fails. native-ssl reads trusted certificates directly from the OS store on all three platforms and merges them with the JVM defaults into a single X509ExtendedTrustManager.

TL;DR

  • One singleton: NativeTrustManager. Lazy, thread-safe.
  • macOS: Security framework via JNI — system anchors + user/admin domain with full trust-settings evaluation.
  • Windows: Crypt32 via JNI — ROOT and CA stores across user, machine, group policy, enterprise scopes.
  • Linux: pure-JVM — reads the PEM bundles crypto/x509 reads.
  • HTTPS to corporate, MDM, or proxy-inspected hosts works without any manual trust store wiring.

Install

dependencies {
    implementation("dev.nucleusframework:nucleus.native-ssl:<version>")
}

Quickstart

import dev.nucleusframework.nativessl.NativeTrustManager
import javax.net.ssl.SSLContext
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.X509TrustManager

val trustManager: X509TrustManager = NativeTrustManager.trustManager
val sslContext: SSLContext = NativeTrustManager.sslContext
val sslSocketFactory: SSLSocketFactory = NativeTrustManager.sslSocketFactory

Pass these to your HTTP client of choice. If that client is java.net.http, OkHttp, or Ktor, use the Native HTTP adapters instead — they handle the wiring for you.

How it works

macOS

Security framework via libnucleus_ssl.dylib (bundled in the JAR for arm64 and x86_64). Two passes:

  1. System anchorsSecTrustCopyAnchorCertificates() returns every Apple-shipped root.
  2. User & admin domainsSecTrustSettingsCopyCertificates() enumerates everything with explicit trust settings. Each candidate is evaluated through logic mirroring JetBrains jvm-native-trusted-roots:
    • User trust settings first, then admin.
    • No trust settings → live evaluation via SecTrustEvaluateWithError.
    • Empty trust settings array → trusted (per Apple docs).
    • kSecTrustSettingsResult must be TrustRoot; the cert must be self-signed (DN equality and signature verified against its own key).
    • kSecTrustSettingsPolicy, if present, must be kSecPolicyAppleSSL.
    • Unknown constraint keys reject the certificate — better to fail closed than silently relax rules.

Windows

Crypt32 via nucleus_ssl.dll (bundled for x64 and ARM64). Scans five store locations across two store types:

Store typeInclusion rule
ROOTTrusted root CAs — included unconditionally
CAIntermediate CAs — validated via CertGetCertificateChain + CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_BASE) with cache-only revocation

Locations: CURRENT_USER, LOCAL_MACHINE, CURRENT_USER_GROUP_POLICY, LOCAL_MACHINE_GROUP_POLICY, LOCAL_MACHINE_ENTERPRISE. Group Policy and Active Directory–distributed certs land in stores that SunMSCAPI does not reach.

Deduplication is by SHA-1 thumbprint (CERT_HASH_PROP_ID), the standard Windows identity. If the JNI library fails to load, the module falls back to SunMSCAPI's Windows-ROOT, Windows-CA, Windows-MY keystores.

Linux

Pure-JVM — no shared library. Reads the same paths Go's crypto/x509 does:

PathDistribution
/etc/ssl/certs/ca-certificates.crtDebian, Ubuntu, Gentoo
/etc/pki/tls/certs/ca-bundle.crtFedora, RHEL 6
/etc/ssl/ca-bundle.pemopenSUSE
/etc/pki/tls/cacert.pemOpenELEC
/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pemCentOS, RHEL 7
/etc/ssl/cert.pemAlpine
/etc/ssl/certs/ (dir)SLES10/SLES11
/etc/pki/tls/certs/ (dir)Fedora, RHEL
/system/etc/security/cacerts/ (dir)Android

Deduplicated by DER content across all sources.

Reference

APIDescription
NativeTrustManager.trustManager: X509ExtendedTrustManagerCombined trust manager (JVM defaults + OS native)
NativeTrustManager.sslContext: SSLContextTLS context initialized with the trust manager
NativeTrustManager.sslSocketFactory: SSLSocketFactoryDerived from sslContext
NativeTrustManager.isAvailable(): Booleanfalse only if the JNI bridge failed to load on macOS/Windows
interface NativeCertificateProviderSPI if you need to plug in a custom certificate source

Use cases

  • Enterprise networks with internal root CAs deployed via Group Policy or MDM.
  • SSL inspection proxies (Zscaler, Netskope, Blue Coat, …) that re-sign every cert with a custom root.
  • Self-hosted PKI for staging environments where the user installed the dev root locally.
  • Anything keytool -import was historically the answer to.

Notes

ProGuard

JNI bridge classes must be preserved on macOS and Windows. The Nucleus Gradle plugin adds the rules automatically; if you maintain ProGuard config manually:

-keep class dev.nucleusframework.nativessl.mac.NativeSslBridge {
    native <methods>;
}
-keep class dev.nucleusframework.nativessl.windows.WindowsSslBridge {
    native <methods>;
}

Logging

Debug logs are tagged NativeCertificateProvider, NativeSslBridge, WindowsCertificateProvider, LinuxCertificateProvider, etc. Off by default. Turn them on with:

import dev.nucleusframework.core.runtime.tools.allowNucleusRuntimeLogging

allowNucleusRuntimeLogging = true