Skip to content

Commit 6ce85f4

Browse files
author
gefeili
committed
Add HOWTO.md
1 parent 0b48ab0 commit 6ce85f4

File tree

1 file changed

+129
-0
lines changed

1 file changed

+129
-0
lines changed

HOWTO.md

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
# Bouncy Castle Java API How To
2+
## Using Bouncy Castle with GraalVM Native Image
3+
### Problem: Provider Not Registered at Build Time with `UnsupportedFeatureError` Exception
4+
#### Error message
5+
```text
6+
Trying to verify a provider that was not registered at build time: BC version...
7+
```
8+
#### Cause:
9+
Bouncy Castle security provider isn't properly registered during GraalVM native image build process.
10+
11+
### Solution 1: Static Initializer Approach (No GraalVM SDK)
12+
#### Step 1. Create Initializer Class
13+
```java
14+
package com.yourpackage.crypto; // ← Replace with your actual package
15+
16+
import org.bouncycastle.jce.provider.BouncyCastleProvider;
17+
import java.security.Security;
18+
19+
public class BCInitializer {
20+
static {
21+
// Force provider registration during image build
22+
Security.addProvider(new BouncyCastleProvider());
23+
}
24+
}
25+
```
26+
27+
#### Step 2. And then in the native-image build configuration
28+
For Maven (`pom.xml`)
29+
```xml
30+
<plugin>
31+
<groupId>org.graalvm.buildtools</groupId>
32+
<artifactId>native-maven-plugin</artifactId>
33+
<version>0.9.28</version>
34+
<configuration>
35+
<buildArgs>
36+
<!-- Initialize Bouncy Castle and our initializer -->
37+
<arg>--initialize-at-build-time=org.bouncycastle,com.yourpackage.crypto.BCInitializer</arg>
38+
<!-- Required for SecureRandom components -->
39+
<arg>--initialize-at-run-time=org.bouncycastle.jcajce.provider.drbg.DRBG$Default,org.bouncycastle.jcajce.provider.drbg.DRBG$NonceAndIV</arg>
40+
</buildArgs>
41+
</configuration>
42+
</plugin>
43+
```
44+
45+
For Gradle (`build.gradle`),
46+
```gradle
47+
buildArgs.add('--initialize-at-build-time=com.yourpackage.crypto.BCInitializer')
48+
buildArgs.add("--initialize-at-run-time=org.bouncycastle.jcajce.provider.drbg.DRBG\$Default,org.bouncycastle.jcajce.provider.drbg.DRBG\$NonceAndIV")
49+
```
50+
# Key Configuration
51+
52+
| Argument | Purpose |
53+
| ------------------------------- |-----------------------------------------------------------------|
54+
| `--initialize-at-build-time` | Forces inclusion of BC classes and triggers static initializer. |
55+
| `--initialize-at-run-time` | Solves stateful SecureRandom initialization issues. |
56+
|`--enable-all-security-services` | (optional) Enables JCE security infrastructure |
57+
58+
59+
### Solution 2: GraalVM Feature Approach (With SDK)
60+
61+
#### Step 1: Create a Native Image Feature
62+
```java
63+
package com.yourpackage.crypto; // ← Replace with your actual package
64+
65+
import org.bouncycastle.jce.provider.BouncyCastleProvider;
66+
import org.graalvm.nativeimage.hosted.Feature;
67+
68+
import java.security.Security;
69+
70+
/**
71+
* A GraalVM Feature that registers the Bouncy Castle provider.
72+
* This is required so that native image builds verify and include the provider.
73+
*/
74+
public class BouncyCastleFeature implements Feature {
75+
76+
@Override
77+
public void afterRegistration(AfterRegistrationAccess access) {
78+
// Register the Bouncy Castle provider
79+
Security.addProvider(new BouncyCastleProvider());
80+
}
81+
}
82+
```
83+
84+
#### Step 2: Configure Dependencies and Build
85+
##### 2.1 add dependency
86+
```xml
87+
<dependency>
88+
<groupId>org.graalvm.sdk</groupId>
89+
<artifactId>graal-sdk</artifactId>
90+
<version>21.0.0</version> <!-- Match your GraalVM version -->
91+
<scope>provided</scope>
92+
</dependency>
93+
```
94+
##### 2.2 add plugin
95+
```xml
96+
<plugin>
97+
<groupId>org.graalvm.buildtools</groupId>
98+
<artifactId>native-maven-plugin</artifactId>
99+
<version>0.9.28</version>
100+
<configuration>
101+
<buildArgs>
102+
<arg>--features=com.yourpackage.crypto.BouncyCastleFeature</arg> <!-- replace with correct package path -->
103+
<arg>--initialize-at-build-time=org.bouncycastle</arg>
104+
<arg>--initialize-at-run-time=org.bouncycastle.jcajce.provider.drbg.DRBG$Default,org.bouncycastle.jcajce.provider.drbg.DRBG$NonceAndIV</arg>
105+
</buildArgs>
106+
</configuration>
107+
</plugin>
108+
```
109+
Key Configuration Explanations:
110+
`--features=...`
111+
- Registers custom feature class that adds BouncyCastle provider at build time
112+
- Required for JCE security provider verification
113+
114+
### Troubleshooting
115+
#### Common Issues
116+
##### Classpath Conflicts:
117+
118+
```text
119+
Error: Class-path entry contains class from image builder
120+
```
121+
Fix: Add `-H:+AllowDeprecatedBuilderClassesOnImageClasspath` (temporary) or ensure graal-sdk has provided scope
122+
123+
##### Missing Algorithms:
124+
Example of the error message:
125+
```text
126+
No such algorithm: AES/CBC/PKCS5Padding
127+
```
128+
129+
Fix: Verify `--initialize-at-build-time` includes `org.bouncycastle`

0 commit comments

Comments
 (0)