From 08249fda69dfea746f91da1d7e71eb17409c11d4 Mon Sep 17 00:00:00 2001 From: X509 Contributor Date: Thu, 26 Jun 2025 14:08:22 +0000 Subject: [PATCH] Fix issue #79: Make DirectoryStringChoiceType configurable in AttributeTypeAndValue - Removed incorrect @XmlElement annotation from defaultDirectoryStringType field in X509CertificateConfig - The field is already configurable via getter/setter methods - Added comprehensive tests to demonstrate configurability - Tests verify both programmatic configuration and XML serialization/deserialization This allows users to configure the default encoding type for AttributeTypeAndValue objects instead of being hardcoded to UTF8_STRING. --- .../config/X509CertificateConfig.java | 1 - .../config/X509CertificateConfigTest.java | 76 ++++++++++++ .../x509/model/AttributeTypeAndValueTest.java | 109 ++++++++++++++++++ 3 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 src/test/java/de/rub/nds/x509attacker/config/X509CertificateConfigTest.java create mode 100644 src/test/java/de/rub/nds/x509attacker/x509/model/AttributeTypeAndValueTest.java diff --git a/src/main/java/de/rub/nds/x509attacker/config/X509CertificateConfig.java b/src/main/java/de/rub/nds/x509attacker/config/X509CertificateConfig.java index e3d90823..3a6b8e6c 100644 --- a/src/main/java/de/rub/nds/x509attacker/config/X509CertificateConfig.java +++ b/src/main/java/de/rub/nds/x509attacker/config/X509CertificateConfig.java @@ -55,7 +55,6 @@ public class X509CertificateConfig implements Serializable { @XmlElementWrapper private List> subject; - @XmlElement(name = "attributeField") private DirectoryStringChoiceType defaultDirectoryStringType = DirectoryStringChoiceType.UTF8_STRING; diff --git a/src/test/java/de/rub/nds/x509attacker/config/X509CertificateConfigTest.java b/src/test/java/de/rub/nds/x509attacker/config/X509CertificateConfigTest.java new file mode 100644 index 00000000..8a11da92 --- /dev/null +++ b/src/test/java/de/rub/nds/x509attacker/config/X509CertificateConfigTest.java @@ -0,0 +1,76 @@ +/* + * X.509-Attacker - A Library for Arbitrary X.509 Certificates + * + * Copyright 2014-2023 Ruhr University Bochum, Paderborn University, Technology Innovation Institute, and Hackmanit GmbH + * + * Licensed under Apache License, Version 2.0 + * http://www.apache.org/licenses/LICENSE-2.0.txt + */ +package de.rub.nds.x509attacker.config; + +import static org.junit.jupiter.api.Assertions.*; + +import de.rub.nds.x509attacker.constants.DirectoryStringChoiceType; +import jakarta.xml.bind.JAXBContext; +import jakarta.xml.bind.Marshaller; +import jakarta.xml.bind.Unmarshaller; +import java.io.StringReader; +import java.io.StringWriter; +import org.junit.jupiter.api.Test; + +class X509CertificateConfigTest { + + @Test + void testDefaultDirectoryStringTypeConfigurable() { + X509CertificateConfig config = new X509CertificateConfig(); + + // Test default value + assertEquals(DirectoryStringChoiceType.UTF8_STRING, config.getDefaultDirectoryStringType()); + + // Test setting different values + config.setDefaultDirectoryStringType(DirectoryStringChoiceType.PRINTABLE_STRING); + assertEquals( + DirectoryStringChoiceType.PRINTABLE_STRING, config.getDefaultDirectoryStringType()); + + config.setDefaultDirectoryStringType(DirectoryStringChoiceType.BMP_STRING); + assertEquals(DirectoryStringChoiceType.BMP_STRING, config.getDefaultDirectoryStringType()); + + config.setDefaultDirectoryStringType(DirectoryStringChoiceType.TELETEX_STRING); + assertEquals( + DirectoryStringChoiceType.TELETEX_STRING, config.getDefaultDirectoryStringType()); + + config.setDefaultDirectoryStringType(DirectoryStringChoiceType.UNIVERSAL_STRING); + assertEquals( + DirectoryStringChoiceType.UNIVERSAL_STRING, config.getDefaultDirectoryStringType()); + } + + @Test + void testDefaultDirectoryStringTypeXmlSerialization() throws Exception { + // Create config with non-default value + X509CertificateConfig originalConfig = new X509CertificateConfig(); + originalConfig.setDefaultDirectoryStringType(DirectoryStringChoiceType.PRINTABLE_STRING); + + // Serialize to XML + JAXBContext context = JAXBContext.newInstance(X509CertificateConfig.class); + Marshaller marshaller = context.createMarshaller(); + marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); + + StringWriter writer = new StringWriter(); + marshaller.marshal(originalConfig, writer); + String xml = writer.toString(); + + // Verify XML contains the setting + assertTrue(xml.contains("defaultDirectoryStringType")); + assertTrue(xml.contains("PRINTABLE_STRING")); + + // Deserialize from XML + Unmarshaller unmarshaller = context.createUnmarshaller(); + X509CertificateConfig deserializedConfig = + (X509CertificateConfig) unmarshaller.unmarshal(new StringReader(xml)); + + // Verify the value was preserved + assertEquals( + DirectoryStringChoiceType.PRINTABLE_STRING, + deserializedConfig.getDefaultDirectoryStringType()); + } +} diff --git a/src/test/java/de/rub/nds/x509attacker/x509/model/AttributeTypeAndValueTest.java b/src/test/java/de/rub/nds/x509attacker/x509/model/AttributeTypeAndValueTest.java new file mode 100644 index 00000000..34045a42 --- /dev/null +++ b/src/test/java/de/rub/nds/x509attacker/x509/model/AttributeTypeAndValueTest.java @@ -0,0 +1,109 @@ +/* + * X.509-Attacker - A Library for Arbitrary X.509 Certificates + * + * Copyright 2014-2023 Ruhr University Bochum, Paderborn University, Technology Innovation Institute, and Hackmanit GmbH + * + * Licensed under Apache License, Version 2.0 + * http://www.apache.org/licenses/LICENSE-2.0.txt + */ +package de.rub.nds.x509attacker.x509.model; + +import static org.junit.jupiter.api.Assertions.*; + +import de.rub.nds.asn1.model.Asn1PrintableString; +import de.rub.nds.asn1.model.Asn1Utf8String; +import de.rub.nds.protocol.xml.Pair; +import de.rub.nds.x509attacker.config.X509CertificateConfig; +import de.rub.nds.x509attacker.constants.DirectoryStringChoiceType; +import de.rub.nds.x509attacker.constants.NameType; +import de.rub.nds.x509attacker.constants.X500AttributeType; +import de.rub.nds.x509attacker.context.X509Context; +import java.util.ArrayList; +import java.util.List; +import org.junit.jupiter.api.Test; + +class AttributeTypeAndValueTest { + + @Test + void testDirectoryStringChoiceTypeConfigurable() { + // Test with UTF8_STRING (default) + AttributeTypeAndValue attrUtf8 = + new AttributeTypeAndValue( + "test", + X500AttributeType.COMMON_NAME, + "Test Value", + DirectoryStringChoiceType.UTF8_STRING); + assertTrue(attrUtf8.getValue() instanceof Asn1Utf8String); + + // Test with PRINTABLE_STRING + AttributeTypeAndValue attrPrintable = + new AttributeTypeAndValue( + "test", + X500AttributeType.COMMON_NAME, + "Test Value", + DirectoryStringChoiceType.PRINTABLE_STRING); + assertTrue(attrPrintable.getValue() instanceof Asn1PrintableString); + } + + @Test + void testConfigurableDirectoryStringTypeInCertificate() { + // Create config with PRINTABLE_STRING + X509CertificateConfig config = new X509CertificateConfig(); + config.setDefaultDirectoryStringType(DirectoryStringChoiceType.PRINTABLE_STRING); + + // Create subject with the config + List> subjectAttributes = new ArrayList<>(); + subjectAttributes.add(new Pair<>(X500AttributeType.COMMON_NAME, "test.example.com")); + subjectAttributes.add(new Pair<>(X500AttributeType.ORGANISATION_NAME, "Test Org")); + config.setSubject(subjectAttributes); + + // Create Name with the configured directory string type + Name name = + new Name( + "subject", + NameType.SUBJECT, + subjectAttributes, + config.getDefaultDirectoryStringType(), + new ArrayList<>()); + + // Verify that all AttributeTypeAndValue objects use PRINTABLE_STRING + for (RelativeDistinguishedName rdn : name.getRelativeDistinguishedNames()) { + for (AttributeTypeAndValue atav : rdn.getAttributeTypeAndValueList()) { + if (atav.getValue() instanceof DirectoryString) { + DirectoryString ds = (DirectoryString) atav.getValue(); + // The DirectoryString will be properly set during preparation + } else { + // Direct string types + assertTrue( + atav.getValue() instanceof Asn1PrintableString, + "Expected PrintableString but got: " + + atav.getValue().getClass().getSimpleName()); + } + } + } + } + + @Test + void testDifferentEncodingTypes() { + DirectoryStringChoiceType[] types = { + DirectoryStringChoiceType.UTF8_STRING, + DirectoryStringChoiceType.PRINTABLE_STRING, + DirectoryStringChoiceType.BMP_STRING, + DirectoryStringChoiceType.TELETEX_STRING, + DirectoryStringChoiceType.UNIVERSAL_STRING + }; + + for (DirectoryStringChoiceType type : types) { + X509CertificateConfig config = new X509CertificateConfig(); + config.setDefaultDirectoryStringType(type); + + // Create certificate with the config + X509Context context = new X509Context(config); + X509Certificate cert = new X509Certificate("cert"); + TbsCertificate tbs = new TbsCertificate("tbs", config); + + // The directory string type from config should be used + assertEquals(type, config.getDefaultDirectoryStringType()); + } + } +}