Browse Source

Add ECDSA P-384 test, refactor to parameterized tests

- Add EC_P384 key type alongside RSA_2048
- Parameterize separateCertAndKeyFiles and combinedPemFile tests
- Write private keys in PKCS#8 format for EC compatibility

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
pull/15205/head
Sergey Matvienko 7 months ago
parent
commit
c149927a6e
  1. 77
      application/src/test/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSslTest.java

77
application/src/test/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSslTest.java

@ -28,9 +28,12 @@ import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
import org.bouncycastle.openssl.jcajce.JcePEMEncryptorBuilder;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.transport.config.ssl.PemSslCredentials;
import org.thingsboard.server.gen.edge.v1.EdgeRpcServiceGrpc;
@ -45,6 +48,7 @@ import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.X509Certificate;
import java.security.spec.ECGenParameterSpec;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@ -61,6 +65,7 @@ import static org.awaitility.Awaitility.await;
* 2. Combined PEM file (cert + key)
* 3. Encrypted private key + key_password
* 4. Error when combined PEM has no private key and private_key is empty
* 5. ECDSA P-384 key support
*/
class EdgeGrpcSslTest {
@ -70,6 +75,33 @@ class EdgeGrpcSslTest {
}
}
enum KeyType {
RSA_2048("RSA", 2048, null, "SHA256withRSA"),
EC_P384("EC", 384, "secp384r1", "SHA384withECDSA");
final String algorithm;
final int size;
final String curve;
final String sigAlg;
KeyType(String algorithm, int size, String curve, String sigAlg) {
this.algorithm = algorithm;
this.size = size;
this.curve = curve;
this.sigAlg = sigAlg;
}
KeyPair generateKeyPair() throws Exception {
KeyPairGenerator kpg = KeyPairGenerator.getInstance(algorithm);
if (curve != null) {
kpg.initialize(new ECGenParameterSpec(curve));
} else {
kpg.initialize(size);
}
return kpg.generateKeyPair();
}
}
private final List<Path> tempFiles = new ArrayList<>();
private Server server;
private ManagedChannel channel;
@ -87,10 +119,11 @@ class EdgeGrpcSslTest {
}
}
@Test
void separateCertAndKeyFiles() throws Exception {
KeyPair kp = generateKeyPair();
X509Certificate cert = generateSelfSignedCert(kp);
@ParameterizedTest(name = "separateCertAndKeyFiles_{0}")
@EnumSource(KeyType.class)
void separateCertAndKeyFiles(KeyType keyType) throws Exception {
KeyPair kp = keyType.generateKeyPair();
X509Certificate cert = generateSelfSignedCert(kp, keyType.sigAlg);
Path certFile = writeTempPem("cert", cert);
Path keyFile = writeTempPem("key", kp.getPrivate());
@ -99,10 +132,11 @@ class EdgeGrpcSslTest {
assertTlsConnectivity(cert);
}
@Test
void combinedPemFile() throws Exception {
KeyPair kp = generateKeyPair();
X509Certificate cert = generateSelfSignedCert(kp);
@ParameterizedTest(name = "combinedPemFile_{0}")
@EnumSource(KeyType.class)
void combinedPemFile(KeyType keyType) throws Exception {
KeyPair kp = keyType.generateKeyPair();
X509Certificate cert = generateSelfSignedCert(kp, keyType.sigAlg);
Path combinedFile = writeTempPem("combined", cert, kp.getPrivate());
@ -112,8 +146,8 @@ class EdgeGrpcSslTest {
@Test
void encryptedPrivateKey() throws Exception {
KeyPair kp = generateKeyPair();
X509Certificate cert = generateSelfSignedCert(kp);
KeyPair kp = KeyType.RSA_2048.generateKeyPair();
X509Certificate cert = generateSelfSignedCert(kp, KeyType.RSA_2048.sigAlg);
String password = "test-password";
Path combinedFile = writeTempPemEncrypted("enc-combined", password, cert, kp.getPrivate());
@ -124,8 +158,8 @@ class EdgeGrpcSslTest {
@Test
void combinedPemWithoutKey_throwsException() throws Exception {
KeyPair kp = generateKeyPair();
X509Certificate cert = generateSelfSignedCert(kp);
KeyPair kp = KeyType.RSA_2048.generateKeyPair();
X509Certificate cert = generateSelfSignedCert(kp, KeyType.RSA_2048.sigAlg);
Path certOnlyFile = writeTempPem("cert-only", cert);
@ -176,13 +210,7 @@ class EdgeGrpcSslTest {
// --- Cert/key generation ---
private KeyPair generateKeyPair() throws Exception {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(2048);
return kpg.generateKeyPair();
}
private X509Certificate generateSelfSignedCert(KeyPair kp) throws Exception {
private X509Certificate generateSelfSignedCert(KeyPair kp, String sigAlg) throws Exception {
X500Name subject = new X500Name("CN=localhost");
Date now = new Date();
return new JcaX509CertificateConverter().getCertificate(
@ -190,7 +218,7 @@ class EdgeGrpcSslTest {
subject, BigInteger.ONE, now,
new Date(now.getTime() + TimeUnit.DAYS.toMillis(1)),
subject, kp.getPublic())
.build(new JcaContentSignerBuilder("SHA256withRSA").build(kp.getPrivate())));
.build(new JcaContentSignerBuilder(sigAlg).build(kp.getPrivate())));
}
// --- PEM file helpers ---
@ -208,7 +236,7 @@ class EdgeGrpcSslTest {
tempFiles.add(p);
try (JcaPEMWriter w = new JcaPEMWriter(Files.newBufferedWriter(p))) {
for (Object o : objects) {
w.writeObject(o);
w.writeObject(toPkcs8IfKey(o));
}
}
return p;
@ -231,4 +259,11 @@ class EdgeGrpcSslTest {
}
return p;
}
private Object toPkcs8IfKey(Object o) {
if (o instanceof PrivateKey pk) {
return new PemObject("PRIVATE KEY", pk.getEncoded());
}
return o;
}
}

Loading…
Cancel
Save