[
https://issues.apache.org/jira/browse/GEODE-10509?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Jinwoo Hwang reassigned GEODE-10509:
------------------------------------
Assignee: Jinwoo Hwang
> Replace Internal JDK APIs in CertificateBuilder with Public Alternatives
> ------------------------------------------------------------------------
>
> Key: GEODE-10509
> URL: https://issues.apache.org/jira/browse/GEODE-10509
> Project: Geode
> Issue Type: Improvement
> Reporter: Jinwoo Hwang
> Assignee: Jinwoo Hwang
> Priority: Major
>
> h2. Summary
> Replace usage of internal proprietary {{sun.security.x509.*}} APIs in
> {{CertificateBuilder.java}} with public, supported alternatives to ensure
> compatibility with future JDK versions and eliminate compilation warnings.
> h2. Problem Statement
> h3. Current Behavior
> During compilation, the Java compiler produces warnings about usage of
> internal proprietary APIs in
> {{{}geode-junit/src/main/java/org/apache/geode/cache/ssl/CertificateBuilder.java{}}}:
> {noformat}
> warning: [class] is internal proprietary API and may be removed in a future
> release
> {noformat}
> h3. Affected Internal APIs
> The following {{sun.security.x509.*}} classes are currently being used:
> # {{AlgorithmId}}
> # {{BasicConstraintsExtension}}
> # {{CertificateAlgorithmId}}
> # {{CertificateExtensions}}
> # {{CertificateSerialNumber}}
> # {{CertificateValidity}}
> # {{CertificateVersion}}
> # {{CertificateX509Key}}
> # {{DNSName}}
> # {{GeneralName}}
> # {{GeneralNames}}
> # {{IPAddressName}}
> # {{KeyIdentifier}}
> # {{KeyUsageExtension}}
> # {{SubjectAlternativeNameExtension}}
> # {{SubjectKeyIdentifierExtension}}
> # {{X500Name}}
> # {{X509CertImpl}}
> # {{X509CertInfo}}
> h3. Root Cause
> {{CertificateBuilder}} is a test utility class that generates X.509
> certificates for SSL/TLS testing. It currently relies on internal JDK APIs
> from the {{sun.security.x509}} package, which are:
> * Not part of the public Java API
> * Not guaranteed to remain stable across JDK versions
> * May be removed or restricted in future JDK releases (especially with
> module system restrictions)
> * Generate compiler warnings that clutter build output
> h3. Risk Assessment
> *Severity:* Medium-High
> * *Immediate Impact:* Compilation warnings (non-blocking)
> * *Future Impact:* Code may break in future JDK versions when these APIs are
> removed
> * *JDK Module System:* APIs may become inaccessible due to strong
> encapsulation
> * *Maintenance:* Makes upgrading to newer JDK versions risky
> h2. Proposed Solution
> h3. Option 1: Use Bouncycastle Library (Recommended)
> Replace internal JDK APIs with the Bouncycastle cryptography library, which
> provides comprehensive X.509 certificate building capabilities through public
> APIs.
> *Advantages:*
> * Well-maintained, industry-standard library
> * Public, stable API with long-term support
> * Rich feature set for certificate manipulation
> * Cross-JDK compatibility
> * Already used in many Apache projects
> * Extensive documentation and examples
> *Disadvantages:*
> * Adds external dependency
> * Slightly larger footprint (library size)
> *Implementation:*
> {code:java}
> // Add dependency
> dependencies {
> implementation 'org.bouncycastle:bcpkix-jdk15on:1.70'
> }
> // Replace sun.security.x509.* imports with Bouncycastle equivalents
> import org.bouncycastle.asn1.x500.X500Name;
> import org.bouncycastle.asn1.x509.BasicConstraints;
> import org.bouncycastle.asn1.x509.Extension;
> import org.bouncycastle.asn1.x509.GeneralName;
> import org.bouncycastle.asn1.x509.GeneralNames;
> import org.bouncycastle.cert.X509CertificateHolder;
> import org.bouncycastle.cert.X509v3CertificateBuilder;
> import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
> import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
> import org.bouncycastle.operator.ContentSigner;
> import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
> {code}
> h3. Option 2: Use Java Standard APIs with Limited Functionality
> Use only public Java APIs like {{java.security.cert.X509Certificate}} and
> {{{}javax.security.auth.x500.X500Principal{}}}.
> *Advantages:*
> * No external dependencies
> * Uses only standard JDK APIs
> *Disadvantages:*
> * Limited certificate building capabilities
> * May require workarounds for advanced features (extensions, constraints)
> * Less flexible than current implementation
> * May not support all current test scenarios
> h3. Option 3: Use JDK 21+ Certificate API Enhancements
> If upgrading to JDK 21+, leverage newer certificate APIs (if available).
> *Advantages:*
> * Native JDK support
> * No external dependencies
> *Disadvantages:*
> * Requires JDK version upgrade
> * Limited compared to Bouncycastle
> * Still may not cover all use cases
> h2. Recommended Approach
> *Use Option 1 (Bouncycastle)* because:
> # Most comprehensive solution with full feature parity
> # Widely adopted in enterprise and Apache projects
> # Stable, public API with long-term support
> # Works across all supported JDK versions
> # Better than maintaining fragile code dependent on internal APIs
> h2. Implementation Plan
> h3. Phase 1: Analysis
> # Audit all usages of {{sun.security.x509.*}} APIs in {{CertificateBuilder}}
> # Map each internal API to Bouncycastle equivalent
> # Identify any unique features that need special handling
> # Document the mapping for review
> h3. Phase 2: Dependency Addition
> # Add Bouncycastle dependency to {{geode-junit}} module
> # Update dependency management configuration
> # Verify license compatibility (Bouncycastle uses MIT-like license)
> # Document dependency rationale in build files
> h3. Phase 3: Code Migration
> # Create new implementation using Bouncycastle APIs
> # Maintain method signatures for backward compatibility
> # Add comprehensive inline documentation
> # Ensure feature parity with current implementation
> h3. Phase 4: Testing
> # Run existing SSL/TLS test suite
> # Verify generated certificates match expected structure
> # Test certificate validation and chain building
> # Performance comparison (if applicable)
> # Cross-JDK testing (JDK 11, 17, 21)
> h3. Phase 5: Cleanup
> # Remove all {{sun.security.x509.*}} imports
> # Verify no compilation warnings
> # Update any related documentation
> # Add comments explaining why Bouncycastle was chosen
> h2. Expected Outcomes
> h3. Success Criteria
> (/) Zero compiler warnings about internal APIs
> (/) All existing SSL/TLS tests pass
> (/) Generated certificates are functionally equivalent
> (/) Code works on all supported JDK versions
> (/) No breaking changes to test utilities API
> h3. Impact Assessment
> ||Category||Impact||
> |*Risk Level*|Low - Changes isolated to test utilities|
> |*Scope*|geode-junit module only|
> |*Dependencies*|Adds Bouncycastle library|
> |*Compatibility*|Improved - works across all JDK versions|
> |*Maintenance*|Improved - uses stable public API|
> h2. Files to be Modified
> # {{geode-junit/build.gradle}} - Add Bouncycastle dependency
> #
> {{geode-junit/src/main/java/org/apache/geode/cache/ssl/CertificateBuilder.java}}
> - Replace internal APIs
> # Potentially: Any other files using {{sun.security.*}} packages (TBD from
> analysis)
> h2. Migration Mapping Examples
> h3. X509Certificate Creation
> {code:java}
> // Before (Internal API):
> X509CertInfo info = new X509CertInfo();
> info.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3));
> // ... more configuration
> X509CertImpl cert = new X509CertImpl(info);
> // After (Bouncycastle):
> X509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder(
> issuer, serialNumber, notBefore, notAfter, subject, publicKey);
> // ... add extensions
> X509CertificateHolder certHolder = certBuilder.build(signer);
> X509Certificate cert = new
> JcaX509CertificateConverter().getCertificate(certHolder);
> {code}
> h3. Subject Alternative Names
> {code:java}
> // Before (Internal API):
> GeneralNames generalNames = new GeneralNames();
> generalNames.add(new GeneralName(new DNSName(hostname)));
> SubjectAlternativeNameExtension san = new
> SubjectAlternativeNameExtension(generalNames);
> // After (Bouncycastle):
> GeneralName[] generalNames = new GeneralName[] {
> new GeneralName(GeneralName.dNSName, hostname)
> };
> GeneralNames subjectAltNames = new GeneralNames(generalNames);
> certBuilder.addExtension(Extension.subjectAlternativeName, false,
> subjectAltNames);
> {code}
> h3. Basic Constraints
> {code:java}
> // Before (Internal API):
> BasicConstraintsExtension bce = new BasicConstraintsExtension(true, true, 0);
> extensions.set(BasicConstraintsExtension.NAME, bce);
> // After (Bouncycastle):
> BasicConstraints basicConstraints = new BasicConstraints(true);
> certBuilder.addExtension(Extension.basicConstraints, true, basicConstraints);
> {code}
> h2. Alternative Libraries (For Consideration)
> If Bouncycastle is not acceptable:
> # *Apache Commons Crypto* - Limited cert building support
> # *Conscrypt* - Google's Java crypto provider (primarily for performance)
> # *JCA/JCE providers* - May still have limitations
> h2. Dependencies
> * *License:* Bouncycastle uses MIT-like license (compatible with Apache 2.0)
> * *Version:* Recommend bcpkix-jdk15on:1.70 or later
> * *Maven Coordinates:* {{org.bouncycastle:bcpkix-jdk15on:1.70}}
> h2. References
> * [JEP 260: Encapsulate Most Internal APIs|https://openjdk.org/jeps/260]
> * [Bouncycastle
> Documentation|https://www.bouncycastle.org/documentation.html]
> * [Java X.509 Certificate
> API|https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/security/cert/X509Certificate.html]
> * [Bouncycastle PKIX
> Examples|https://github.com/bcgit/bc-java/tree/main/pkix/src/test/java/org/bouncycastle/cert/test]
> h2. Testing Strategy
> h3. Unit Tests
> * Verify certificate generation with various parameters
> * Test all extension types (SAN, key usage, basic constraints)
> * Validate certificate chain building
> * Test self-signed and CA-signed certificates
> h3. Integration Tests
> * Run full SSL/TLS test suite
> * Test with different JDK versions (11, 17, 21)
> * Verify interoperability with existing certificates
> * Performance regression testing
> h3. Validation Criteria
> * All existing tests pass without modification
> * No new compiler warnings
> * Generated certificates validate with standard tools (openssl, keytool)
> * Certificate format matches previous implementation
--
This message was sent by Atlassian Jira
(v8.20.10#820010)