Skip to content

Commit 8e7cb5f

Browse files
Use only public APIs to read PKCS#1 keys (helidon-io#5240)
Co-authored-by: Weijun Wang <[email protected]> Signed-off-by: Tomas Langer <[email protected]>
1 parent 78db0f7 commit 8e7cb5f

File tree

9 files changed

+141
-115
lines changed

9 files changed

+141
-115
lines changed

common/key-util/pom.xml

+5-43
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@
5656
<artifactId>junit-jupiter-api</artifactId>
5757
<scope>test</scope>
5858
</dependency>
59+
<dependency>
60+
<groupId>org.junit.jupiter</groupId>
61+
<artifactId>junit-jupiter-params</artifactId>
62+
<scope>test</scope>
63+
</dependency>
5964
<dependency>
6065
<groupId>org.hamcrest</groupId>
6166
<artifactId>hamcrest-core</artifactId>
@@ -68,47 +73,4 @@
6873
</dependency>
6974
</dependencies>
7075

71-
<build>
72-
<plugins>
73-
<plugin>
74-
<groupId>org.apache.maven.plugins</groupId>
75-
<artifactId>maven-compiler-plugin</artifactId>
76-
<configuration>
77-
<!-- needed to enable use of com.sun packages that we need to parse PKCS#1 keys -->
78-
<release combine.self="override"/>
79-
<compilerArgs>
80-
<compilerArg>--add-exports=java.base/sun.security.util=io.helidon.common.pki</compilerArg>
81-
</compilerArgs>
82-
</configuration>
83-
</plugin>
84-
</plugins>
85-
</build>
86-
87-
<profiles>
88-
<profile>
89-
<id>javadoc</id>
90-
<build>
91-
<plugins>
92-
<plugin>
93-
<groupId>org.apache.maven.plugins</groupId>
94-
<artifactId>maven-javadoc-plugin</artifactId>
95-
<configuration>
96-
<release combine.self="override"/>
97-
<additionalJOptions combine.children="append">
98-
<additionalJOption>--add-exports=java.base/sun.security.util=io.helidon.common.pki
99-
</additionalJOption>
100-
</additionalJOptions>
101-
</configuration>
102-
<executions>
103-
<execution>
104-
<goals>
105-
<goal>jar</goal>
106-
</goals>
107-
</execution>
108-
</executions>
109-
</plugin>
110-
</plugins>
111-
</build>
112-
</profile>
113-
</profiles>
11476
</project>

common/key-util/src/main/java/io/helidon/common/pki/DerUtils.java

-61
This file was deleted.

common/key-util/src/main/java/io/helidon/common/pki/PemReader.java

+2-7
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ static PrivateKey readPrivateKey(InputStream input, char[] password) {
9696

9797
switch (pkInfo.type) {
9898
case "PKCS1-RSA":
99-
return rsaPrivateKey(pkcs1RsaKeySpec(pkInfo.bytes));
99+
return rsaPrivateKey(Pkcs1Util.pkcs1RsaKeySpec(pkInfo.bytes));
100100
case "PKCS1-DSA":
101101
throw new UnsupportedOperationException("PKCS#1 DSA private key is not supported");
102102
case "PKCS1-EC":
@@ -107,11 +107,6 @@ static PrivateKey readPrivateKey(InputStream input, char[] password) {
107107
}
108108
}
109109

110-
private static KeySpec pkcs1RsaKeySpec(byte[] bytes) {
111-
DerUtils.checkEnabled();
112-
return DerUtils.pkcs1RsaKeySpec(bytes);
113-
}
114-
115110
private static PrivateKey pkcs8(KeySpec keySpec) {
116111
try {
117112
return rsaPrivateKey(keySpec);
@@ -223,7 +218,7 @@ private static X509EncodedKeySpec generatePublicKeySpec(byte[] bytes) {
223218
return new X509EncodedKeySpec(bytes);
224219
}
225220

226-
private static PrivateKeyInfo readPrivateKeyBytes(InputStream in) {
221+
static PrivateKeyInfo readPrivateKeyBytes(InputStream in) {
227222
String content;
228223
try {
229224
content = readContent(in);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
* Copyright (c) 2021, 2022 Oracle and/or its affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.helidon.common.pki;
18+
19+
import java.security.spec.KeySpec;
20+
import java.security.spec.PKCS8EncodedKeySpec;
21+
import java.util.HexFormat;
22+
23+
final class Pkcs1Util {
24+
// this is a constant for RSA (and we only support RSA)
25+
private static final byte[] RSA_ALG = HexFormat.of().parseHex("020100300D06092A864886F70D0101010500");
26+
27+
private Pkcs1Util() {
28+
}
29+
30+
static KeySpec pkcs1RsaKeySpec(byte[] bytes) {
31+
return new PKCS8EncodedKeySpec(pkcs1ToPkcs8(bytes));
32+
}
33+
34+
// Code provided by Weijun Wang
35+
private static byte[] pkcs1ToPkcs8(byte[] pkcs1Bytes) {
36+
37+
// PKCS #8 key will look like
38+
// 30 len1
39+
// 02 01 00 30 0D 06 09 2A 86 48 86 F7 0D 01 01 01 05 00
40+
// 04 len2
41+
// p1
42+
43+
byte[] len2 = encodeLen(pkcs1Bytes.length);
44+
int p8len = pkcs1Bytes.length + len2.length + 1 + RSA_ALG.length;
45+
byte[] len1 = encodeLen(p8len);
46+
byte[] pkcs8bytes = new byte[1 + len1.length + p8len];
47+
48+
pkcs8bytes[0] = 0x30;
49+
System.arraycopy(len1, 0, pkcs8bytes, 1, len1.length);
50+
System.arraycopy(RSA_ALG, 0, pkcs8bytes, 1 + len1.length, RSA_ALG.length);
51+
pkcs8bytes[1 + len1.length + RSA_ALG.length] = 0x04;
52+
System.arraycopy(len2, 0, pkcs8bytes, 1 + len1.length + RSA_ALG.length + 1, len2.length);
53+
System.arraycopy(pkcs1Bytes, 0, pkcs8bytes, 1 + len1.length + RSA_ALG.length + 1 + len2.length, pkcs1Bytes.length);
54+
55+
return pkcs8bytes;
56+
}
57+
58+
private static byte[] encodeLen(int len) {
59+
if (len < 128) {
60+
return new byte[] {(byte) len};
61+
} else if (len < (1 << 8)) {
62+
return new byte[] {(byte) 0x081, (byte) len};
63+
} else if (len < (1 << 16)) {
64+
return new byte[] {(byte) 0x082, (byte) (len >> 8), (byte) len};
65+
} else {
66+
throw new PkiException("PKCS#1 key of unexpected size: " + len);
67+
}
68+
}
69+
}

common/key-util/src/test/java/io/helidon/common/pki/KeyConfigTest.java

+14-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2020 Oracle and/or its affiliates.
2+
* Copyright (c) 2017, 2022 Oracle and/or its affiliates.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
1616

1717
package io.helidon.common.pki;
1818

19+
import java.security.PrivateKey;
1920
import java.security.cert.X509Certificate;
2021
import java.security.interfaces.RSAPrivateKey;
2122
import java.security.interfaces.RSAPublicKey;
@@ -27,10 +28,13 @@
2728

2829
import org.junit.jupiter.api.BeforeAll;
2930
import org.junit.jupiter.api.Test;
31+
import org.junit.jupiter.params.ParameterizedTest;
32+
import org.junit.jupiter.params.provider.CsvSource;
3033

3134
import static org.hamcrest.CoreMatchers.instanceOf;
3235
import static org.hamcrest.CoreMatchers.is;
3336
import static org.hamcrest.CoreMatchers.not;
37+
import static org.hamcrest.CoreMatchers.notNullValue;
3438
import static org.hamcrest.MatcherAssert.assertThat;
3539
import static org.junit.jupiter.api.Assertions.assertThrows;
3640

@@ -55,6 +59,15 @@ void testConfigPublicKey() {
5559
assertThat(publicKey.publicKey().isPresent(), is(true));
5660
}
5761

62+
@ParameterizedTest
63+
@CsvSource({"512", "1024","2048"})
64+
void testPkcs1(String length) {
65+
PrivateKey privateKey = PemReader.readPrivateKey(KeyConfigTest.class.getResourceAsStream("/keystore/pkcs1-" + length +
66+
".pem"), null);
67+
assertThat(privateKey, notNullValue());
68+
assertThat(privateKey.getAlgorithm(), is("RSA"));
69+
}
70+
5871
@Test
5972
void testOldPublicKey() {
6073
KeyConfig publicKey = KeyConfig.create(config.get("unit-2"));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
-----BEGIN RSA PRIVATE KEY-----
2+
MIICXAIBAAKBgQCvkRPTPbnOGP3r+AJieU4HKocaDAGP3AyASrCfhAC3DJB5RL7Y
3+
3yhUqzwILbvE6wcbngZZkHka7Fzh7ZMtNdTsMI8UfsXtVtn0hNN1a/s9yt5J38xR
4+
LJAedA2XJQNJ5Cay4YkJbntegtO07sPu8JPBoiODn1/GMWez3URp6JJW1wIDAQAB
5+
AoGAbsL2YPS2PkIiIDatOncRNRAtf89HRP0snduBJoHe+ZzhoMAwLx5KkXAeRYKk
6+
zY0BRPkjRGoTHVs1FgwOKB2oH/aTyuEJ3nupFgvW2eLH3MQAL8yLc2YCufogBRMT
7+
3L1OskTk6XeaHLK2RWv1IilkY6WKERZf0/2FtipSC+adTcECQQDd3HjV/rX4yyHR
8+
wJ/zIZ4lzko1uzT4dSndDf9dWD/fzq6w8hnsyxJDTVS5m00FqVIhjzoKMrvJUJGC
9+
FPmPmMjRAkEAypT6aUJ1NmjDyMakIHwCN3oM70ghKQJTOuqL1e2J4TQYU9zAGaJm
10+
5FQJb7px9C/8cw73BUBkvAOLto91Je+PJwJAXTeVTdSHgNFYlFjq26z0Vc4nQAw4
11+
ZWxU+pw2/3Fk5RRiMdaHLgbk1YJYZuPpqMdLyu3y5PYMELnZaV6GvN7lAQJALkVS
12+
4OHuFcxeE6jTahwJAZTeCXVnJY/DZOyXnfhQiuC0QctlETXX3IUZVqy2RHkFZ15e
13+
q5Nmrs78hWlE77JE9wJBAJC2MaObm6grGEuWfe8NoBg8QC6sI0i6lOVpXUDvYV2e
14+
mixgnByUBbgu5MG0OEP95OpVxQTd7OubX9qwVemTRhU=
15+
-----END RSA PRIVATE KEY-----
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
-----BEGIN RSA PRIVATE KEY-----
2+
MIIEpAIBAAKCAQEArznMqI0bdj8vXaEKoLhrG/NT8eo5aIlRPQnM3819iSjgrS+0
3+
/3iRZg0LghTgUSm6czeFzeuKzDvOlV83n+NZUPWWZH3LlMmxJMN523IAJpT54ORC
4+
wjyo6bSoTxHEjYTWO5yMtdJfR+uozd8aAX876R7Shq9YlBKoNKyzFSEvgPVEuA8V
5+
sSpekeksEMw2HR4Izh2GSBCto2WOXe9lJFWMtjRBGbOiD62Z0qpJ6i+lCEr9wnwl
6+
ToT4f3P0hfpmmjZX0X8N4h+dAm/N1WRTeQw6VSbTztNtYNaJdX6p3T2PViagd9xF
7+
gUAf7cmyx7SnAc3GOiRNko6Yt5INekOvkMyPrwIDAQABAoIBAANgesg4x/G0cAY+
8+
50SHqVDFlLWRzP9tvgoOGUuq2yN8jS/pPnS57xtnXvRn0Jbf1f8Ib+SzCF69PFL2
9+
nczQBdWglgBjyDua03Yg6kVHYidcMaCa5Yp2vs6aM7AqaH5NtA88Ch4q6rkpGny1
10+
MvwaZp4sgOQllvBrl6BEP8NFe3PhvgJDCABfQXvnDA7q2HiK9MahBcNkQaOHwXgK
11+
L9Ssvn6UF9Z0LSvt+0SWvqckPSbncTJN1FIGGnHv+jHZVeMjSe6/aX/rjwjp1qGu
12+
gGbB3vNLUUj71LlF1rCsPj3Na2NA4TZxXS3lNGjHiP19UHav7RDa7f9ELftIEaKP
13+
ndElMDkCgYEA1q1kYXu0h5g0G/Cal+Kz3YKNDHsFQ9sRmfqQ6Isk6QEeEVR4hrZi
14+
lJBAXDRRKcLIwVMAATSHRF/1liF2mYfTITg/IrDLhTNE2adHPWw+yx6PuI/uQpOd
15+
jxiuVK024rl6DzSg7casORrwhnN6qgS7zf5men/KH33pbRABp+3LCyUCgYEA0PRc
16+
0RyuA7z+pewfGCuIGlpm2CvmhGDgA9WN8WCFvF7Szvm5qZ35f5Hd0cMQ5HCPy8pJ
17+
I4XwouLNmDHv461pR54LXxCu6Hx+wgKCAooCzTqW/S+rdZLvnGmY0AJ9NeaaOw2a
18+
rz08esrAfc5jWM7HBg+OOMjzpojmqtPPOsNvgUMCgYEAxWUYKP7bh9avC4XYUJK2
19+
+pZBZdl0hOlZrPEV742KOem6IQs/6/amfJ6LX30HqFOfzwuntHP9cSSfKBXK/O9E
20+
doZGn3pbGTaEN3I18kenEZQfaQCHf5ZGST7Tha7kCeOsVXD6DMkisTuRML/caZsC
21+
qS4kQr1gOEbJrWwLacMgcTUCgYA5i+L4ED74dpdnGMVjgbGlGFqUlFqTAJ8RT0Id
22+
ROjv/Olv6SSxyvkIoiKF/4PqdfmUNWy5JM0l/vKCRNZ9TKfe+m7FSrHxA0BhrBEk
23+
I+Arp0QoDHXbFpF48TgNqXHUY2L8en2sX2AFrUsgGrQPpDr5t1UC3I0Fw1RLnbPH
24+
ykUuQwKBgQDVIkquG3SybEHEdruwf7qOa3yFNO3G+8A7DrsyMJWltlaoeAfp+aUY
25+
jXPBisQEyPaXT/wWuk9WqPotw0UKEDxcmXbkbsZvcc2G+CnUpOsdhTJAX28ggUJN
26+
d1ix5Xm4Px0Djcsoq7C7NYwvAepQfK6RfucFdE6XvJpZ/dUY1cBs8w==
27+
-----END RSA PRIVATE KEY-----
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
-----BEGIN RSA PRIVATE KEY-----
2+
MIIBPAIBAAJBAMqJuM6TvqUEb0UlQDSQF2aXgD4JH7hojJ01m/1f3q91lnOpMzab
3+
+kBre1u3vtoGnl2+FqDKr/tthys8vkenyTMCAwEAAQJBAK78mkzwXTBZSoFlE7nW
4+
HEGo90WhwGQlAAf7f1BD+jOAS4XM5bBui4m77Qr0e3GaRd7EeYnW5yAZoKy+nrmb
5+
dwECIQD4nxUsEf4B6DWwdzctWKdx0iCxrIomR9Oe1aHI+5tKQQIhANCMhGxJGiiq
6+
f6N0YNrUeRCZfk4cjVuiizXKQ8hYne5zAiEAlKjyzPY5LsS9jbXLHWc8QDfH6tVj
7+
ib47EGdnJLklwsECIDXHRo61+yzpaqi35hIIIIALVOrHqhwrOkLQudH8KB3JAiEA
8+
w4vdFCrQlE3C+RfkK/TVn+r7kZ/hIqb99rTsbI6cnZ8=
9+
-----END RSA PRIVATE KEY-----

pom.xml

-3
Original file line numberDiff line numberDiff line change
@@ -383,9 +383,6 @@
383383
</offlineLinks>
384384
<additionalJOptions combine.children="append">
385385
<additionalJOption>-J-Dhttp.agent=maven-javadoc-plugin</additionalJOption>
386-
<additionalJOption>--add-exports=java.base/sun.security.util=io.helidon.common.pki
387-
</additionalJOption>
388-
<!--<additionalJOption>- -frames</additionalJOption>-->
389386
</additionalJOptions>
390387
<additionalOptions>
391388
<!--<additionalOption> - -add-stylesheet ${top.parent.basedir}/etc/helidon-javadoc.css</additionalOption>-->

0 commit comments

Comments
 (0)