Skip to content

Commit a24bf23

Browse files
committed
test: Cover weak EC and unsupported-algorithm paths in PemSslContext
Reorders the strength check before the signature check so a sub-spec EC key fails fast on bit count (192 < 256) instead of tripping the matching-signature probe. Adds P-192 EC and DSA fixtures, plus tests covering the weak EC throw, the "Unsupported TLS private key algorithm" branch (DSA key with RSA cert), and the "Unsupported TLS public key algorithm" branch (DSA cert with RSA key). Simplifies the algorithm switch in verifyKeyMatchesCert now that decodePrivateKey guarantees RSA or EC keys. Lifts PemSslContext line coverage from ~77% to 86%. Remaining uncovered lines are defensive GeneralSecurityException / IOException catches around JDK crypto APIs that do not throw for valid inputs.
1 parent 4145ced commit a24bf23

6 files changed

Lines changed: 85 additions & 9 deletions

File tree

src/main/java/com/retailsvc/http/internal/PemSslContext.java

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,8 @@ private static PrivateKey decodePrivateKey(String pem, Path source) {
123123
}
124124

125125
private static SSLContext buildSslContext(Certificate[] chain, PrivateKey key) {
126-
verifyKeyMatchesCert(key, chain[0]);
127126
requireMinimumStrength(chain[0]);
127+
verifyKeyMatchesCert(key, chain[0]);
128128
try {
129129
KeyStore ks = KeyStore.getInstance("PKCS12");
130130
ks.load(null, null);
@@ -171,14 +171,8 @@ private static void requireMinimumStrength(Certificate cert) {
171171
}
172172

173173
private static void verifyKeyMatchesCert(PrivateKey key, Certificate cert) {
174-
String algorithm =
175-
switch (key.getAlgorithm()) {
176-
case "RSA" -> "SHA256withRSA";
177-
case "EC" -> "SHA256withECDSA";
178-
default ->
179-
throw new IllegalStateException(
180-
"Unsupported TLS private key algorithm: " + key.getAlgorithm());
181-
};
174+
// decodePrivateKey only returns RSA or EC keys, so this switch is total without a default.
175+
String algorithm = "RSA".equals(key.getAlgorithm()) ? "SHA256withRSA" : "SHA256withECDSA";
182176
byte[] signature;
183177
try {
184178
Signature signer = Signature.getInstance(algorithm);

src/test/java/com/retailsvc/http/internal/PemSslContextTest.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ class PemSslContextTest {
1919
private static final Path MISSING = Path.of("src/test/resources/tls/does-not-exist.pem");
2020
private static final Path WEAK_RSA_CERT = Path.of("src/test/resources/tls/weak-rsa-cert.pem");
2121
private static final Path WEAK_RSA_KEY = Path.of("src/test/resources/tls/weak-rsa-key.pem");
22+
private static final Path WEAK_EC_CERT = Path.of("src/test/resources/tls/weak-ec-cert.pem");
23+
private static final Path WEAK_EC_KEY = Path.of("src/test/resources/tls/weak-ec-key.pem");
24+
private static final Path DSA_CERT = Path.of("src/test/resources/tls/dsa-cert.pem");
25+
private static final Path DSA_KEY = Path.of("src/test/resources/tls/dsa-key.pem");
2226

2327
@Test
2428
void loadsRsaPemPair() {
@@ -101,4 +105,26 @@ void rejectsWeakRsaKey() {
101105
.hasMessageContaining("TLS RSA key below minimum strength")
102106
.hasMessageContaining("1024 bits");
103107
}
108+
109+
@Test
110+
void rejectsWeakEcKey() {
111+
assertThatThrownBy(() -> PemSslContext.load(WEAK_EC_CERT, WEAK_EC_KEY))
112+
.isInstanceOf(IllegalStateException.class)
113+
.hasMessageContaining("TLS EC key below minimum strength")
114+
.hasMessageContaining("192 bits");
115+
}
116+
117+
@Test
118+
void rejectsUnsupportedKeyAlgorithm() {
119+
assertThatThrownBy(() -> PemSslContext.load(RSA_CERT, DSA_KEY))
120+
.isInstanceOf(IllegalStateException.class)
121+
.hasMessageContaining("Unsupported TLS private key algorithm");
122+
}
123+
124+
@Test
125+
void rejectsUnsupportedCertAlgorithm() {
126+
assertThatThrownBy(() -> PemSslContext.load(DSA_CERT, RSA_KEY))
127+
.isInstanceOf(IllegalStateException.class)
128+
.hasMessageContaining("Unsupported TLS public key algorithm");
129+
}
104130
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIEazCCBBmgAwIBAgIUNDFdkKEWyHLwpeKHQvzzAgY78UMwCwYJYIZIAWUDBAMC
3+
MBgxFjAUBgNVBAMMDWRzYS1sb2NhbGhvc3QwIBcNMjYwNTIxMTE1ODA1WhgPMjEy
4+
NjA0MjcxMTU4MDVaMBgxFjAUBgNVBAMMDWRzYS1sb2NhbGhvc3QwggNCMIICNQYH
5+
KoZIzjgEATCCAigCggEBAMc/wejLRCRVLn8zzCO0kIqkRhDtRu+PqQNbV+l+Muom
6+
K8dJ6m6ZLdcla7nLYa8cDTA8GurBDFGXv6PFPHlFV8+xJVC9jK9p4hcZZ1aS1ykN
7+
GKV3ha3pVFYVeGRzx2UAlQHR0/bw7LnnwNHAhQ7u1OqRdWKTx4PNiG60j99nb2Sh
8+
Sa+3Im90c2Yt+4PIuQQw5for7wY5iQRfNmlRi7i7F8aeO2rBVIVdainW42IEBC0W
9+
ldSqkx7IyF7Ym/+7HdRowMJ1yh36Zj67p5pkwuxs6h4GiucddYO3i2EomWygA/Xm
10+
PhzBuHMKUdI9aH5j0P6dtrXN8TiwJupFCiPzMGsK49sCHQDdN2HZKEIr1JmcnnIo
11+
8hbgufDqqOMAOhGiKAkVAoIBABGihRZdRmOtvWpgdF/ttaaM0Ds+gffpdQn3zXHe
12+
su8iRQFQqXbF4R31VKiqVmz36HHRLH55CJZc4SXKpW+5loDEfZYtECrwQggvwoYj
13+
f5Ko7Gd/p/iKnTVn+bnsehdqI9csWrjkiqWxDdpq8LYcH2uUQLbJWCuEiMWhEptv
14+
VroCEpMfp66XyGYH+hB5zhklH+/lOnUpoZyiMmBh56brpqP1J+Z5GZTlBFhXhUAl
15+
gnqVS6fCDpZu1mijZNyWZO0kIoLnWTd6eMYGE9AUynpqvtwX0eGze4KjQkAY24mj
16+
M8p2loUH5DeigD4h5aog4oUKfvYoegB9n4S5o+ukpYY6BzUDggEFAAKCAQAFfX4V
17+
q3ei1HhAGaJ/LBp3cwmEvZLuGcfyZCYS8QwIdmAHHut3O2cK7sQ0vQ68kSW6MLCU
18+
rw1P9U9FlyKkgUKI7d1mb+Up8vk7n4qnEU7gaiLge+39SjqPuUyqKuVTJs/ZWxMS
19+
UrMTVwx2hnMO3miTBzZ4hHDGYnKce/VEcR0X/CffZ7NZb93JpD0aVS+BKH4XK/ZR
20+
R1mY/Y3Iah3psbPDmyFs84Y4K4E4gS2wkl1nvhvfAJRDvGEF6T40HCaDnX53OY7H
21+
qIo4pJdtxvsbk1fEJvZuoOPhwy/5pr83wR9O0in8+twJxzKFciAgdV+1eNf/7imd
22+
p3k27MUkmZowblK9o1MwUTAdBgNVHQ4EFgQUcKihfiAes+nytWG9lBkNVv56gwgw
23+
HwYDVR0jBBgwFoAUcKihfiAes+nytWG9lBkNVv56gwgwDwYDVR0TAQH/BAUwAwEB
24+
/zALBglghkgBZQMEAwIDPwAwPAIcbiFkWhn84KIKUR//o0nAGwNMrqZ54KxaW7eR
25+
ZQIcDqkzw8eeGq9U1ClhWYN27vb5gT53OSc/Q6isRg==
26+
-----END CERTIFICATE-----

src/test/resources/tls/dsa-key.pem

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
-----BEGIN PRIVATE KEY-----
2+
MIICXgIBADCCAjYGByqGSM44BAEwggIpAoIBAQDfxy8WtSqub6Lx8wZNtZ9r/EEl
3+
jxOxns9qjtvkjew5SFuQtMwr8y6dTMPf+qumUse1okmxsPU0c3Iof3yGByYe1jUx
4+
AJVEtL0TYdDTvwA+ttNwPnQndFzKAc2MFBxMOTjZIiuhKvBmo6SDgLvflcQbyVdT
5+
g0tCkcui+hBel/M/CnWZEy6/fOY6u7chMv+R1dAFRo1y64VAyTV9+4WU2oIrU26Z
6+
soM/TDJWJxEnNck15dzOXY1O4w0FDi0hTkR9j2Xrumc6R9uvnVsRmuP5TzfHqI7E
7+
eWpSiaNYLOevkIcXHmg+pi0H/8XFdddgT007Sd0Bu6D8rhkAKczedu4Bg75HAh0A
8+
xcvFdwdZZefPAdsfQ13PWJwvVvMBZrJs/FFFEQKCAQEAm/S5T8+WCM9hv8OHayEQ
9+
oqJfa0LkCZMXT4lPqa/NiKDQEGmjtcvc06T1Nmnboq4AqUrlswKojpvu5vdXDk3g
10+
Zf2qzUOZspLEpXlHDJ9XwCNnrb9UBUK4yVXbDeFqsdBPa09CW/5f901bAyz/l7/i
11+
fJYyOwsL6ZQWKWJQbhWweqeoCCVBkPpTQyc4J869K4LHyghA+sXC1/BQMS2EfJVH
12+
IcLkWmyHuPKGOo914bnamg5ofeFHTgUUGWIAr81uw41AEiKrYyT0dkO5o7K7Q0iW
13+
xj7wAiYuFCQkD3QUGTa3LBoBMgEJQGITIgz1RaJy6EP+ANZmah0CSrqeD0tl86hT
14+
YgQfAh0AmIlpe0R/PsdbBmDDKMgnfJM1qnj3hLj0VL0HjA==
15+
-----END PRIVATE KEY-----
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIBbjCCASWgAwIBAgIUMdzHTBEjEXAMlBO0J6da9KtC1KowCgYIKoZIzj0EAwIw
3+
HDEaMBgGA1UEAwwRd2Vhay1lYy1sb2NhbGhvc3QwIBcNMjYwNTIxMTE0NjI1WhgP
4+
MjEyNjA0MjcxMTQ2MjVaMBwxGjAYBgNVBAMMEXdlYWstZWMtbG9jYWxob3N0MEkw
5+
EwYHKoZIzj0CAQYIKoZIzj0DAQEDMgAEcOYb3OnogqFQUG3Ua6xhiJ2iIftE+xin
6+
TNBUPGbprqaz4fwp/IiyaCxOD1/V6f9Uo1MwUTAdBgNVHQ4EFgQUnI1V6NkJRrt7
7+
Nj+DebVnQPcDYF4wHwYDVR0jBBgwFoAUnI1V6NkJRrt7Nj+DebVnQPcDYF4wDwYD
8+
VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgM3ADA0Ahhbie15KevgEt4nY1SILbxJ
9+
mbt78OGM5GcCGEKBaKXGDzY6Q/GkcAuT1mvBiKDMAzGYQA==
10+
-----END CERTIFICATE-----
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
-----BEGIN PRIVATE KEY-----
2+
MG8CAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQEEVTBTAgEBBBj236RAh4V7+Ncz7Qtn
3+
94smhfxZXP13By+hNAMyAARw5hvc6eiCoVBQbdRrrGGInaIh+0T7GKdM0FQ8Zumu
4+
prPh/Cn8iLJoLE4PX9Xp/1Q=
5+
-----END PRIVATE KEY-----

0 commit comments

Comments
 (0)