Scenario 2.3: Create Multi-SAN CSR
Category: Certificate Signing Requests (CSR)
Complexity: * (Medium-High)
Prerequisites: Key pair available
Estimated Time: 10-15 minutes
</WRAP>
—-
===== Description =====
This scenario describes creating a CSR with multiple Subject Alternative Names (SANs). This is necessary for certificates that need to secure multiple domains, subdomains, or IP addresses.
Use cases:
* Multi-domain certificates (SAN certificates)
* Wildcard + explicit domains combined
* Internal + external names
* Load balancer with multiple backends
—-
===== SAN Types =====
^ Type ^ GeneralName Tag ^ Example ^ Usage ^
| DNS | dNSName (2) | www.example.com | Websites, APIs |
| IP | iPAddress (7) | 192.168.1.100 | Internal services |
| Email | rfc822Name (1) | admin@example.com | S/MIME |
| URI | uniformResourceIdentifier (6) | https://example.com | SAML, OIDC |
| UPN | otherName (0) | user@domain.local | Windows Auth |
—-
===== Code Example (C#) =====
<code csharp>
using WvdS.Security.Cryptography.X509Certificates.Extensions.PQ;
using var ctx = PqCryptoContext.Initialize();
using var key = ctx.GenerateKeyPair(PqAlgorithm.MlDsa65);
var dn = new DnBuilder()
.AddCN(„example.com“) Primary domain
.AddO(„Example GmbH“)
.AddC(„DE“)
.Build();
Multi-SAN with different types
var extensions = new ExtBuilder()
.SubjectAlternativeName(new[] {
DNS names
„dns:example.com“,
„dns:www.example.com“,
„dns:api.example.com“,
„dns:app.example.com“,
„dns:*.dev.example.com“, Wildcard for dev
IP addresses (for internal access)
„ip:10.0.0.100“,
„ip:192.168.1.50“,
IPv6
„ip:2001:db8::1“
})
.KeyUsage(KeyUsageFlags.DigitalSignature | KeyUsageFlags.KeyEncipherment)
.ExtendedKeyUsage(ExtKeyUsage.ServerAuth)
.Build();
var csr = ctx.CreateCertificateRequest(key, dn, extensions);
Output all SANs
Console.WriteLine(„Subject Alternative Names:“);
foreach (var san in csr.SubjectAlternativeNames)
{
Console.WriteLine($„ - {san}“);
}
File.WriteAllText(„multi-san.csr.pem“, csr.ToPem());
</code>
—-
===== Combining Wildcard + Explicit =====
<code csharp>
var extensions = new ExtBuilder()
.SubjectAlternativeName(new[] {
„dns:example.com“, Root domain (wildcard does not cover this!)
„dns:*.example.com“, All 1st level subdomains
„dns:*.api.example.com“, API subdomains
„dns:legacy.old-domain.com“ Alternative domain
})
.Build();
</code>
Important: Wildcards (*.example.com) only cover one level and not the root domain itself! Therefore always specify both example.com AND *.example.com.
—- ===== Kubernetes / Cloud-Native ===== <code csharp> var extensions = new ExtBuilder() .SubjectAlternativeName(new[] { Kubernetes Service DNS „dns:my-service“, „dns:my-service.default“, „dns:my-service.default.svc“, „dns:my-service.default.svc.cluster.local“, Headless Service (Pod DNS) „dns:*.my-service.default.svc.cluster.local“, External Ingress Domain „dns:api.example.com“ }) .Build(); </code> —- ===== Limits and Best Practices ===== ^ Aspect ^ Recommendation ^ Reason ^ | Number of SANs | Max. 100 | Performance, certificate size | | Wildcard levels | Only 1 level | RFC 6125 restriction | | IP addresses | Only when necessary | IPs change more frequently | | Internal names | Separate certificates | Security separation | —- ===== Related Scenarios ===== ^ Relationship ^ Scenario ^ Description ^ | Next Step | 3.1 Server Certificate | Sign CSR | | Alternative | 3.5 Wildcard Certificate | Wildcard only | | Foundation** | 2.1 Server CSR | Simple server CSR |
« <- 2.2 Client CSR | ^ CSR Overview | 2.4 Process CSR -> »
Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional