Ü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
Kennen Sie TameMyCerts? TameMyCerts ist ein Add-On für die Microsoft Zertifizierungsstelle (Active Directory Certificate Services). Es erweitert die Funktion der Zertifizierungsstelle und ermöglicht die Anwendung von Regelwerken, um die sichere Automatisierung von Zertifikat-Ausstellungen zu realisieren. TameMyCerts ist einzigartig im Microsoft-Ökosystem, hat sich bereits in unzähligen Unternehmen auf der ganzen Welt bewährt und steht unter einer freien Lizenz. Es kann über GitHub heruntergeladen und kostenlos verwendet werden. Professionelle Wartung wird ebenfalls angeboten.
Im Kontext relevante Kodierungen
Für uns als Nutzer einer Microsoft-PKI sind in der Regel folgende Kodierungen, bzw. Begrifflichkeiten von Interesse:
Typ | Abbildung | Beschreibung |
---|---|---|
ASN.1 PrintableString | printableString | Untermenge des ASCII-Zeichensatzes (nur "druckbare" Zeichen). Nur wenige Sonderzeichen abbildbar, z.B. keine Umlaute. |
Unicode | bmpString | Internationaler 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-8 | utf8String | Eine 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.
Flag | Wert | Standardmäßig aktiviert (Windows 2012 bis 2022) |
---|---|---|
ENUM_TELETEX_OFF | 0 | nein |
ENUM_TELETEX_ON | 1 | nein |
ENUM_TELETEX_AUTO | 2 | ja |
ENUM_TELETEX_MASK | 0xF | nein |
ENUM_TELETEX_UTF8 | 0x10 | ja |
ENUM_TELETEX_FORCEUTF8 | 0x20 | nein |
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 Zertifikatanforderung | Enthält Sonderzeichen | …UTF8 Flag aktiviert | …FORCEUTF8 Flag aktiviert | Kodierung im ausgestellten Zertifikat |
---|---|---|---|---|
printableString | nein | nein | nein | printableString |
printableString | nein | ja | nein | printableString |
printableString | nein | nein | ja | utf8String |
printableString | nein | ja | ja | utf8String |
bmpString (Unicode) | ja | nein | nein | bmpString (Unicode) |
bmpString (Unicode) | ja | ja | nein | utf8String |
bmpString (Unicode) | ja | nein | ja | utf8String |
bmpString (Unicode) | ja | ja | ja | utf8String |
utf8String | nein | nein | nein | bmpString (Unicode) |
utf8String | ja | nein | nein | utf8String |
utf8String | nein | ja | nein | utf8String |
utf8String | nein | nein | ja | utf8String |
utf8String | nein | ja | ja | utf8String |
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:
Use signed policies to protect Windows Defender Application Control against tampering (Microsoft Corpotation)
[…]
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.
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:
- Verwenden von nicht definierten Relative Distinguished Names (RDN) in ausgestellten Zertifikaten
- Beschreibung der notwendigen Konfigurationseinstellungen für das "Common PKI" Zertifikatprofil
- Umlaute in Zertifizierungsstellen-Zertifikaten
- Die Installation eines neuen Zertifizierungsstellen-Zertifikats schlägt fehl mit Fehlercode "ERROR_INVALID_PARAMETER"
Externe Quellen
- CryptEncodeObjectEx function (wincrypt.h) (Microsoft Corporation)
- CERT_RDN_ATTR structure (wincrypt.h) (Microsoft Corporation)
- ITU T.61 (Wikipedia)
- Unicode (Wikipedia)
- Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile (Internet Engineering Task Force, IETF)
- What is the difference between UTF-8 and Unicode? (Diskussion auf Stack Overflow)
- Difference between CaPolicy.inf with ForceUTF8=1 versus certutil -setreg ca\forceteletex +0x20 (Diskussion in Microsoft TechNet Foren)
4 Gedanken zu „Zeichenkodierung im Subject Distinguished Name von Zertifikatanforderungen und ausgestellten Zertifikaten“
Kommentare sind geschlossen.