Skip to content

Commit 468b528

Browse files
abvaidyaevantorrie
andauthored
Use generateCertificates() of CertificateFactory to process certificates (#6579)
Signed-off-by: Abhijeet V <[email protected]> Co-authored-by: ET <[email protected]>
1 parent 685a378 commit 468b528

File tree

2 files changed

+61
-11
lines changed

2 files changed

+61
-11
lines changed

exporters/common/src/main/java/io/opentelemetry/exporter/internal/TlsUtil.java

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import java.security.cert.Certificate;
2121
import java.security.cert.CertificateException;
2222
import java.security.cert.CertificateFactory;
23-
import java.security.cert.X509Certificate;
2423
import java.security.spec.InvalidKeySpecException;
2524
import java.security.spec.PKCS8EncodedKeySpec;
2625
import java.util.ArrayList;
@@ -77,14 +76,11 @@ public static X509KeyManager keyManager(byte[] privateKeyPem, byte[] certificate
7776
PrivateKey key = generatePrivateKey(keySpec, SUPPORTED_KEY_FACTORIES);
7877

7978
CertificateFactory cf = CertificateFactory.getInstance("X.509");
80-
81-
List<Certificate> chain = new ArrayList<>();
82-
8379
ByteArrayInputStream is = new ByteArrayInputStream(certificatePem);
84-
while (is.available() > 0) {
85-
chain.add(cf.generateCertificate(is));
86-
}
87-
80+
// pass the input stream to generateCertificates to get a list of certificates
81+
// generateCertificates can handle multiple certificates in a single input stream
82+
// including PEM files with explanatory text
83+
List<? extends Certificate> chain = (List<? extends Certificate>) cf.generateCertificates(is);
8884
ks.setKeyEntry("trusted", key, "".toCharArray(), chain.toArray(new Certificate[] {}));
8985

9086
KeyManagerFactory kmf =
@@ -126,9 +122,13 @@ public static X509TrustManager trustManager(byte[] trustedCertificatesPem) throw
126122
ByteArrayInputStream is = new ByteArrayInputStream(trustedCertificatesPem);
127123
CertificateFactory factory = CertificateFactory.getInstance("X.509");
128124
int i = 0;
129-
while (is.available() > 0) {
130-
X509Certificate cert = (X509Certificate) factory.generateCertificate(is);
131-
ks.setCertificateEntry("cert_" + i, cert);
125+
// pass the input stream to generateCertificates to get a list of certificates
126+
// generateCertificates can handle multiple certificates in a single input stream
127+
// including PEM files with explanatory text
128+
List<? extends Certificate> certificates =
129+
(List<? extends Certificate>) factory.generateCertificates(is);
130+
for (Certificate certificate : certificates) {
131+
ks.setCertificateEntry("cert_" + i, certificate);
132132
i++;
133133
}
134134

exporters/common/src/test/java/io/opentelemetry/exporter/internal/TlsUtilTest.java

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,36 @@
88
import static org.assertj.core.api.Assertions.assertThatCode;
99

1010
import com.linecorp.armeria.internal.common.util.SelfSignedCertificate;
11+
import java.io.File;
12+
import java.io.IOException;
13+
import java.nio.charset.StandardCharsets;
14+
import java.nio.file.Files;
15+
import java.nio.file.Path;
16+
import java.nio.file.StandardOpenOption;
1117
import java.security.KeyFactory;
1218
import java.security.cert.CertificateException;
1319
import java.security.spec.PKCS8EncodedKeySpec;
1420
import java.time.Instant;
1521
import java.util.Collections;
1622
import java.util.Date;
23+
import java.util.stream.Stream;
1724
import javax.net.ssl.SSLException;
1825
import org.junit.jupiter.api.BeforeEach;
1926
import org.junit.jupiter.api.Test;
27+
import org.junit.jupiter.api.io.TempDir;
28+
import org.junit.jupiter.params.ParameterizedTest;
29+
import org.junit.jupiter.params.provider.Arguments;
30+
import org.junit.jupiter.params.provider.MethodSource;
2031

2132
class TlsUtilTest {
2233

34+
@TempDir private Path tempDir;
35+
36+
private static final String EXPLANATORY_TEXT =
37+
"Subject: CN=Foo\n"
38+
+ "Issuer: CN=Foo\n"
39+
+ "Validity: from 7/9/2012 3:10:38 AM UTC to 7/9/2013 3:10:37 AM UTC\n";
40+
2341
private SelfSignedCertificate rsaCertificate;
2442
private SelfSignedCertificate ecCertificate;
2543

@@ -60,4 +78,36 @@ void generatePrivateKey_Invalid() {
6078
.isInstanceOf(SSLException.class)
6179
.hasMessage("Unable to generate key from supported algorithms: [EC]");
6280
}
81+
82+
/**
83+
* Append <a href="https://datatracker.ietf.org/doc/html/rfc7468#section-5.2">explanatory text</a>
84+
* prefix and verify {@link TlsUtil#keyManager(byte[], byte[])} succeeds.
85+
*/
86+
@ParameterizedTest
87+
@MethodSource("keyManagerArgs")
88+
void keyManager_CertWithExplanatoryText(SelfSignedCertificate selfSignedCertificate)
89+
throws IOException {
90+
Path certificate = tempDir.resolve("certificate");
91+
Files.write(certificate, EXPLANATORY_TEXT.getBytes(StandardCharsets.UTF_8));
92+
Files.write(
93+
certificate,
94+
com.google.common.io.Files.toByteArray(selfSignedCertificate.certificate()),
95+
StandardOpenOption.APPEND);
96+
Files.write(certificate, "\n".getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);
97+
98+
assertThatCode(
99+
() ->
100+
TlsUtil.keyManager(
101+
com.google.common.io.Files.toByteArray(selfSignedCertificate.privateKey()),
102+
com.google.common.io.Files.toByteArray(new File(certificate.toString()))))
103+
.doesNotThrowAnyException();
104+
}
105+
106+
private static Stream<Arguments> keyManagerArgs() throws CertificateException {
107+
Instant now = Instant.now();
108+
return Stream.of(
109+
Arguments.of(
110+
new SelfSignedCertificate(Date.from(now), Date.from(now), "RSA", 2048),
111+
new SelfSignedCertificate(Date.from(now), Date.from(now), "EC", 256)));
112+
}
63113
}

0 commit comments

Comments
 (0)