This is an automated email from the ASF dual-hosted git repository.

chrisdutz pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit d7616bb6b79beaaf86d6a945c67a2e660a641298
Author: Christofer Dutz <[email protected]>
AuthorDate: Fri Aug 14 17:37:53 2026 +0200

    fix(plc4j/opcua): Make the test certificate serial a fixed DER length
    
    ChunkFactoryTest failed intermittently on off-by-one size assertions, in
    clusters of 20-40 cases at a time. The cause was the certificate serial:
    BigInteger.valueOf(new Random().nextLong()) usually encodes to 8 DER bytes 
but
    sometimes fewer, since DER strips redundant leading bytes. One byte less in 
the
    serial means one byte less in the certificate, and the expected
    securityHeaderSize embeds that length - so every asymmetric row for the 
affected
    key size failed at once.
    
    Measured over 400 certificates per key size: 412x3 / 413x397 at 1024 bit,
    673x2 / 674x398 at 2048 bit.
    
    The serial is now a random 63-bit value, which always encodes to 8 bytes 
while
    staying unique (PinnedCertificateVerifierTest distinguishes a pinned 
certificate
    from an impostor). Keys are still generated per run; only the encoded 
length is
    deterministic, and the resulting lengths are the ones the chunk-calculation 
CSVs
    were authored against, so no expectation changed.
---
 .../plc4x/java/opcua/TestCertificateGenerator.java      | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git 
a/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/TestCertificateGenerator.java
 
b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/TestCertificateGenerator.java
index a633479cb9..e9e5392e89 100644
--- 
a/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/TestCertificateGenerator.java
+++ 
b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/TestCertificateGenerator.java
@@ -30,7 +30,6 @@ import java.security.cert.X509Certificate;
 import java.util.Date;
 import java.util.Map;
 import java.util.Map.Entry;
-import java.util.Random;
 import java.util.concurrent.TimeUnit;
 import javax.security.auth.x500.X500Principal;
 import org.bouncycastle.cert.X509CertificateHolder;
@@ -42,6 +41,20 @@ import 
org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
 
 public class TestCertificateGenerator {
 
+    /**
+     * A random serial number that always encodes to the same number of DER 
bytes.
+     * <p>
+     * DER drops redundant leading bytes of an INTEGER, so a plain {@code 
Random.nextLong()} serial
+     * encodes to 8 bytes most of the time but occasionally to 7 or fewer - 
which changes the
+     * certificate's total DER length. Test expectations that contain a 
certificate's size (the
+     * OPC UA asymmetric security header, see ChunkFactoryTest) then fail by 
one byte every few
+     * hundred runs. Forcing the value to exactly 63 bits keeps it random and 
unique while pinning
+     * the encoded length at 8 bytes.
+     */
+    private static BigInteger serialNumber() {
+        return new BigInteger(62, new SecureRandom()).setBit(62);
+    }
+
     public static Entry<PrivateKey, X509Certificate> generate(int keySize, 
String dn, long validitySec) {
         try {
             KeyPairGenerator keyPairGenerator = 
KeyPairGenerator.getInstance("RSA");
@@ -50,7 +63,7 @@ public class TestCertificateGenerator {
 
             X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(
                 new X500Principal(dn),
-                BigInteger.valueOf(new Random().nextLong()),
+                serialNumber(),
                 new Date(),
                 new Date(System.currentTimeMillis() + 
TimeUnit.SECONDS.toMillis(validitySec)),
                 new X500Principal(dn),

Reply via email to