Zeichenkodierung im Subject Distinguished Name von Zertifikatanforderungen und ausgestellten Zertifikaten

Üblicherweise ist die Kodierung von Zeichen und Zeichenketten in Zertifikaten kein Thema, welches die Nutzer einer PKI groß interessiert. Es gibt jedoch Fälle, in welchen die Standardeinstellungen der Zertifizierungsstelle nicht die gewünschten Ergebnisse liefern.

Für die Relative Distinguished Names (RDNs) innerhalb des Subject Distiguished Name (Subject DN), welcher als Typ "DirectoryString" abgebildet ist, sieht das einschlägige RFC 5280 folgende Varianten für die Abbildung von Zeichenketten vor.

DirectoryString ::= CHOICE {
         teletexString           TeletexString (SIZE (1..MAX)),
         printableString         PrintableString (SIZE (1..MAX)),
         universalString         UniversalString (SIZE (1..MAX)),
         utf8String              UTF8String (SIZE (1..MAX)),
         bmpString               BMPString (SIZE (1..MAX)) }

Bei näherer Betrachtung zeigt sich jedoch, dass überwiegend nur zwei der fünf möglichen Datentypen von Relevanz sind:

CAs conforming to this profile MUST use either the PrintableString or UTF8String encoding of DirectoryString […].

RFC 5280

Im Kontext relevante Kodierungen

Für uns als Nutzer einer Microsoft-PKI sind in der Regel folgende Kodierungen, bzw. Begrifflichkeiten von Interesse:

TypAbbildungBeschreibung
ASN.1 PrintableStringprintableStringUntermenge des ASCII-Zeichensatzes (nur "druckbare" Zeichen). Nur wenige Sonderzeichen abbildbar, z.B. keine Umlaute.
UnicodebmpStringInternationaler Standard für Kodierung von Zeichenketten (Strings).
Flexible Kodierung der enthaltenen Zeichen, kann unter anderem UTF-8 oder UTF-16 verwenden. Windows interpretiert Unicode als UTF-16, Linux als UTF-8, was zu unterschiedlichem Verhalten führen kann.
UTF-8utf8StringEine von mehreren Möglichkeiten, Zeichen in Unicode-Zeichenketten abzubilden.

Der countryName RDN soll lediglich die in ISO3166 spezifizierte zweistelligen Ländercodes beinhalten, die sich immer aus ASCII Zeichen zusammensetzen und wird daher immer als ASN.1 PrintableString kodiert, da kein Bedarf an einer erweiterten Kodierung besteht.

Inspizieren von Zertifikaten und Zertifikatanforderungen

Sowohl für Zertifikate als auch Zertifikatanforderungen kann relativ einfach überprüft werden, welche Kodierungen die jeweiligen RDNs verwenden.

certutil -asn {Dateiname}

Eine komfortablere Möglichkeit bietet der ASN.1 Editor von PKI Solutions.

Beispiel printableString

Beispiel bmpString (Unicode)

Beispiel utf8String

Die Einstellungen

Microsoft Active Directory Certificate Services bietet die Möglichkeit, auf die Kodierung von Zeichen und Zeichenkodierungen im Rahmen der Zertifikatausstellung Einfluss zu nehmen. Die entsprechenden Einstellungen finden sich in folgendem Registierungs-Schlüssel auf der Zertifizierungsstelle:

HKLM:\SYSTEM\CurrentControlSet\Services\CertSvc\Configuration\{Common-Name-der-Zertifizierungsstelle}\ForceTeletex

Die Einstellungen in ForceTeletex werden durch das Flag CRLF_REBUILD_MODIFIED_SUBJECT_ONLY (unter CA\CRLFlags), welches bewirkt, dass der beantragte Subject DN 1:1 in das ausgestellte Zertifikat übernommen wird, außer Kraft gesetzt.

Ausgelesen können die gesetzten Flags mit folgendem Kommandozeilenbefehl:

certutil -v -getreg CA\ForceTeletex

Einzelne Flags können mit folgenden Kommandozeilenbefehlen aktiviert werden:

 certutil -setreg CA\ForceTeletex +{FLAG}

Ebenso können Flags auch deaktiviert werden.

certutil -setreg CA\ForceTeletex -{FLAG}

Der Zertifizierungsstellen-Dienst muss anschließend neu gestartet werden, damit die Änderungen angewendet werden.

Folgende Flags können gesetzt werden. Sie entscheiden dann darüber, welche Flags beim Kodieren eines RDN an die Funktion CryptEncodeObjectEx weitergegeben werden.

FlagWertStandardmäßig aktiviert (Windows 2012 bis 2022)
ENUM_TELETEX_OFF0nein
ENUM_TELETEX_ON1nein
ENUM_TELETEX_AUTO2ja
ENUM_TELETEX_MASK0xFnein
ENUM_TELETEX_UTF80x10ja
ENUM_TELETEX_FORCEUTF80x20nein

ENUM_TELETEX_UTF8 (0x10)

Ist dieses Flag aktiviert, wird an CryptEncodeObjectEx das Flag CRYPT_UNICODE_NAME_ENCODE_ENABLE_UTF8_UNICODE_FLAG übergeben.

This flag is applicable when encoding an X509_UNICODE_NAME. When set, CERT_RDN_UTF8_STRING is selected instead of CERT_RDN_UNICODE_STRING.

Somit bewirkt diese Einstellung, dass für eine eingereichte Zertifikatanforderung, bei welcher ein RDN Unicode-kodiert ist (…und somit die Interpretation der Zeichenkodierung nicht eindeutig ist), bei aktiviertem Flag für das RDN im ausgestellten Zertifikat die UTF-8 Zeichenkodierung verwendet wird.

Ist ein RDN hingegen in printableString kodiert, wird diese Kodierung im ausgestellten Zertifikat beibehalten.

ENUM_TELETEX_FORCEUTF8 (0x20)

Ist dieses Flag aktiviert, wird an CryptEncodeObjectEx das Flag CRYPT_UNICODE_NAME_ENCODE_FORCE_UTF8_UNICODE_FLAG übergeben.

This flag is applicable when encoding an X509_UNICODE_NAME. When set, CERT_RDN_UTF8_STRING is selected instead of CERT_RDN_PRINTABLE_STRING for directory string types. Also, this flag enables CRYPT_UNICODE_NAME_ENCODE_ENABLE_UTF8_UNICODE_FLAG.

Ist das Flag gesetzt, aktiviert es somit auch automatisch die Wirkung von ENUM_TELETEX_UTF8.

Somit bewirkt diese Einstellung, dass für eine eingereichte Zertifikatanforderung grundsätzlich im ausgestellten Zertifikat die UTF-8 Zeichenkodierung verwendet wird.

Entgegen der originalen Dokumentation von Microsoft ist es auch für die Konformität zu ISIS-MTT bzw. Common PKI nicht notwendig, das ENUM_TELETEX_FORCEUTF8 Flag zu aktivieren.

Testen des Verhaltens

Zum Testen eignet sich das PSCertificateEnrollment PowerShell Modul sehr gut. Es verwendet in der Standardeinstellung ASN.1 PrintableString bzw. Unicode, wenn der RDN entsprechende Zeichen beinhaltet. Ein Schalter zum Verwenden von UTF-8 ist ebenfalls vorhanden.

# Ergebnis: printableString (PRINTABLE_STRING)
New-CertificateRequest -Subject "CN=Max Meier"

# Ergebnis: bmpString (UNICODE_STRING)
New-CertificateRequest -Subject "CN=Max Müller"

# Ergebnis: utf8String (UTF8_STRING)
New-CertificateRequest -Subject "CN=Max Meier" -SubjectEncoding utf8

# Ergebnis: utf8String (UTF8_STRING)
New-CertificateRequest -Subject "CN=Max Müller" -SubjectEncoding utf8

Die Tests führten zu folgendem Ergebnis:

Kodierung in der ZertifikatanforderungEnthält Sonderzeichen…UTF8 Flag aktiviert…FORCEUTF8 Flag aktiviertKodierung im ausgestellten Zertifikat
printableStringneinneinneinprintableString
printableString neinjaneinprintableString
printableString neinneinja utf8String
printableString neinjajautf8String
bmpString (Unicode)janeinneinbmpString (Unicode)
bmpString (Unicode) jajaneinutf8String
bmpString (Unicode) janeinja utf8String
bmpString (Unicode) jajajautf8String
utf8StringneinneinneinbmpString (Unicode)
utf8Stringjaneinneinutf8String
utf8Stringneinjaneinutf8String
utf8String neinneinjautf8String
utf8Stringneinjajautf8String

Die Tests bestätigen somit das dokumentierte und entsprechend erwartete Verhalten.

Wichtig ist somit auch, wie die eingehende Zertifikatanforderung kodiert ist. Beispielsweise kodieren certreq.exe und die Microsoft Management Console (MMC) automatisch alle RDN (bis auf den countryName) in UTF-8. Entsprechend wird auch das RDN im ausgestellten Zertifikat in den meisten Fällen in UTF-8 kodiert sein.

Verhalten ändern für certreq.exe

Wird eine Zertifikatanforderung mit certreq.exe erstellt, kann unter Verwendung der X500NameFlags Direktive ein Fallback auf printableString bzw. Unicode erzwungen werden.

Hierzu wird in der entsprechenden .inf-Datei folgende Zeile eingetragen:

[NewRequest]
X500NameFlags = 0x100000 # CERT_NAME_STR_DISABLE_UTF8_DIR_STR_FLAG

Kompatibilitätsprobleme

Manche Anwendungen verstehen auch kein UTF-8

Die originalen Empfehlungen von Microsoft aus dem Jahr 2003 für die Konformität zum ISIS-MTT bzw. Common PKI Standard erzwingen die Verwendung von UTF8 auch wenn der jeweilige Subject Relative Distinguished Name (RDN) dies gar nicht erfordert.

Der Common PKI Standard weist explizit auf mögliche Kompatibilitätsprobleme mit UTF-8 hin und wie es zeigt gibt es mit Windows Defender Application Control (WDAC) mindestens ein Microsoft-Produkt, welches hiermit auch nicht kompatibel ist.

Boot failure (blue screen) may occur if your signing certificate does not follow these rules:
[…]
Don’t use UTF-8 encoding for certificate fields, like ’subject common name' and 'issuer common name'. These strings must be encoded as PRINTABLE_STRING, IA5STRING or BMPSTRING.

Use signed policies to protect Windows Defender Application Control against tampering (Microsoft Corpotation)

Wichtig ist hierbei somit, dass für das WDAC-Signaturzertifikat die Zertifikatanforderung bereits in der korrekten Kodierung erstellt wird, nur mit ASCII Zeichen im RDN und nicht mit einem Werkzeug, welches in der Standardeinstellung UTF-8 für die Kodierung der RDNs verwendet.

Die Zertifizierungsstelle darf bei Ausstellung des Zertifikats das ENUM_TELETEX_FORCEUTF8 Flag nicht gesetzt haben. Ebenso dürfen die RDNs für Subject DN und Issuer DN der Zertifizierungsstellen-Zertifikate in der Zertifikatkette nicht in UTF-8 kodiert sein.

Für Subject DN und Issuer DN aller Zertifikate in der Zertifikatkette gilt darüber hinaus, dass keine Zeichen enthalten sein dürfen, die nicht mit ASN.1 PrintableString abgebildet werden können. Dies schließt beispielsweise die Verwendung von Sonderzeichen wie Umlauten aus.

Bildung der Zertifikatkette (wäre) nicht mehr möglich

Bei Zertifizierungsstellen, welche andere Zertifizierungsstellen-Zertifikate ausstellen, sollte (sofern man beabsichtigt, die Zertifizierungsstellen-Zertifikate einer Zertifizierungsstelle mit dem gleichen Schlüssel zu erneuern anstatt eine neue Zertifizierungsstelle als Ersatz bereitzustellen) darauf verzichtet werden, Änderungen am Verhalten für die Zeichenkodierung für ausgestellte Zertifikate vorzunehmen, da die Zertifizierungsstellen die ausgestellten Zertifikate womöglich nicht akzeptieren werden.

Fazit

Zusammenfassend kann man feststellen, dass die Standardeinstellungen der Microsoft Zertifizierungsstelle automatisch dafür sorgen, dass die ausgestellten Zertifikate sowohl zu RFC 5280 als auch ISIS-MTT bzw. Common PKI kompatibel sind. Eine Änderung der Einstellungen wird zwar hin und wieder empfohlen, ist in der Regel jedoch nicht nötig.

Funktionsweise in der Standardeinstellung zusammengefasst

Die Standardeinstellungen kann man grob wie folgt zusammenfassen:

  • Wird ein RDN in der eingereichten Zertifikatanforderung in printableString kodiert, ist er dies auch im ausgestellten Zertifikat.
  • Wird ein RDN in der eingereichten Zertifikatanforderung in UTF-8 kodiert, ist er dies auch im ausgestellten Zertifikat.
  • Wird ein RDN in der eingereichten Zertifikatanforderung in Unicode kodiert, wird er im ausgestellten Zertifikat als UTF-8 kodiert.

Weiterführende Links:

Externe Quellen

de_DEDeutsch