[
https://issues.apache.org/jira/browse/GEODE-10509?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Jinwoo Hwang updated GEODE-10509:
---------------------------------
Description:
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
> 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
> 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)