From 59bb14aac8f0bf701edb96d2b25a3627e251fed6 Mon Sep 17 00:00:00 2001 From: Kevin Jones Date: Tue, 14 Apr 2026 14:56:30 -0400 Subject: [PATCH] Add AddRegisteredId to SubjectAlternativeNameBuilder --- .../ref/System.Security.Cryptography.cs | 1 + .../SubjectAlternativeNameBuilder.cs | 18 +++++++++ .../SubjectAltNameBuilderTests.cs | 37 +++++++++++++++++++ 3 files changed, 56 insertions(+) diff --git a/src/libraries/System.Security.Cryptography/ref/System.Security.Cryptography.cs b/src/libraries/System.Security.Cryptography/ref/System.Security.Cryptography.cs index 690e3091df5495..dc2d4f36f5f9cd 100644 --- a/src/libraries/System.Security.Cryptography/ref/System.Security.Cryptography.cs +++ b/src/libraries/System.Security.Cryptography/ref/System.Security.Cryptography.cs @@ -3627,6 +3627,7 @@ public SubjectAlternativeNameBuilder() { } public void AddDnsName(string dnsName) { } public void AddEmailAddress(string emailAddress) { } public void AddIpAddress(System.Net.IPAddress ipAddress) { } + public void AddRegisteredId(string registeredId) { } public void AddUri(System.Uri uri) { } public void AddUserPrincipalName(string upn) { } public System.Security.Cryptography.X509Certificates.X509Extension Build(bool critical = false) { throw null; } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/SubjectAlternativeNameBuilder.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/SubjectAlternativeNameBuilder.cs index 4764b023f806af..17894ceb80f279 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/SubjectAlternativeNameBuilder.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/SubjectAlternativeNameBuilder.cs @@ -47,6 +47,24 @@ public void AddIpAddress(IPAddress ipAddress) AddGeneralName(new GeneralNameAsn { IPAddress = ipAddress.GetAddressBytes() }); } + /// + /// Adds a Registered ID (OID) to the Subject Alternative Name. + /// + /// The registered ID OID to add, in dotted decimal notation. + /// + /// is or . + /// + /// + /// is not a valid OID. + /// + public void AddRegisteredId(string registeredId) + { + if (string.IsNullOrEmpty(registeredId)) + throw new ArgumentOutOfRangeException(nameof(registeredId), SR.Arg_EmptyOrNullString); + + AddGeneralName(new GeneralNameAsn { RegisteredId = registeredId }); + } + public void AddUserPrincipalName(string upn) { if (string.IsNullOrEmpty(upn)) diff --git a/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/SubjectAltNameBuilderTests.cs b/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/SubjectAltNameBuilderTests.cs index d2c7eb7f273c41..9d372c2e84109c 100644 --- a/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/SubjectAltNameBuilderTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/SubjectAltNameBuilderTests.cs @@ -24,6 +24,8 @@ public static void ArgumentValidation() AssertExtensions.Throws("ipAddress", () => builder.AddIpAddress(null)); AssertExtensions.Throws("upn", () => builder.AddUserPrincipalName(null)); AssertExtensions.Throws("upn", () => builder.AddUserPrincipalName(string.Empty)); + AssertExtensions.Throws("registeredId", () => builder.AddRegisteredId(null)); + AssertExtensions.Throws("registeredId", () => builder.AddRegisteredId(string.Empty)); } [Fact] @@ -162,6 +164,25 @@ public static void SingleValue_Upn() extension.RawData.ByteArrayToHex()); } + [Fact] + public static void SingleValue_RegisteredId() + { + SubjectAlternativeNameBuilder builder = new(); + + builder.AddRegisteredId("1.2.3.4"); + + X509Extension extension = builder.Build(); + Assert.Equal(SubjectAltNameOid, extension.Oid.Value); + Assert.Equal("300588032A0304", extension.RawData.ByteArrayToHex()); + } + + [Fact] + public static void SingleValue_RegisteredId_InvalidOid() + { + SubjectAlternativeNameBuilder builder = new(); + Assert.Throws(() => builder.AddRegisteredId("not-an-oid")); + } + [Fact] public static void MultiValue() { @@ -206,6 +227,22 @@ public static void MultiValue() extension.RawData.ByteArrayToHex()); } + [Fact] + public static void MultiValue_WithRegisteredId() + { + const string expectedHex = "3021820F7777772E6578616D706C652E6F726788032A030487047F0000018803550403"; + + SubjectAlternativeNameBuilder builder = new(); + builder.AddDnsName("www.example.org"); + builder.AddRegisteredId("1.2.3.4"); + builder.AddIpAddress(IPAddress.Loopback); + builder.AddRegisteredId("2.5.4.3"); + + X509Extension extension = builder.Build(); + Assert.Equal(SubjectAltNameOid, extension.Oid.Value); + Assert.Equal(expectedHex, extension.RawData.ByteArrayToHex()); + } + [Fact] public static void MultipleBuilds() {