twisted / twisted/twisted

Cannot load a PEM certificate with Unicode in subject

Open
#9,804 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

assigned bug core priority-normal ssl tls unicode
Dominant language
Python
Stars
6k
Forks
1.2k
Avg merge
2d 10h
Merged PRs (30d)
10

Description

Phidica's avatar Phidica reported
Trac ID trac#9804
Type defect
Created 2020-04-17 15:40:27Z
Branch https://github.com/wiml/twisted/tree/non_ascii_DNs

I'm using the Python 3.7 interface to Twisted 19.2.1 (Fedora 31).

I have the following certificate in PEM format that I'm trying to load:

-----BEGIN CERTIFICATE-----
MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQG
EwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3
MDUGA1UECwwuVGFuw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNl
cnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBBcmFueSAoQ2xhc3MgR29sZCkgRsWR
dGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgxMjA2MTUwODIxWjCB
pzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxOZXRM
b2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlm
aWNhdGlvbiBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNz
IEdvbGQpIEbFkXRhbsO6c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEAxCRec75LbRTDofTjl5Bu0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrT
lF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw/HpYzY6b7cNGbIRwXdrz
AZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAkH3B5r9s5
VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRG
ILdwfzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2
BJtr+UBdADTHLpl1neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAG
AQH/AgEEMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2M
U9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwWqZw8UQCgwBEIBaeZ5m8BiFRh
bvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTtaYtOUZcTh5m2C
+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC
bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2F
uLjbvrW5KfnaNwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2
XjG4Kvte9nHfRCaexOYNkbQudZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E=
-----END CERTIFICATE-----

(For your interest, this happens to be one of the root certificates in the system CA bundle, not some certificate I just made up.)

I do so as follows:

from twisted.internet.ssl import Certificate
with open('cert.pem') as file:
  Certificate.loadPEM( file.read() )

This returns the following error:

Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "/usr/lib64/python3.7/site-packages/twisted/internet/_sslverify.py", line 456, in __repr__
    self.getSubject().commonName,
  File "/usr/lib64/python3.7/site-packages/twisted/internet/_sslverify.py", line 411, in getSubject
    return self._copyName('subject')
  File "/usr/lib64/python3.7/site-packages/twisted/internet/_sslverify.py", line 400, in _copyName
    dn._copyFrom(getattr(self.original, 'get_'+suffix)())
  File "/usr/lib64/python3.7/site-packages/twisted/internet/_sslverify.py", line 331, in _copyFrom
    setattr(self, name, value)
  File "/usr/lib64/python3.7/site-packages/twisted/internet/_sslverify.py", line 355, in __setattr__
    value = value.encode("ascii")
UnicodeEncodeError: 'ascii' codec can't encode character '\u0151' in position 28: ordinal not in range(128)

It appears the problem is that X.509 name fields in the subject are forcibly encoded to 'ascii', which fails in this case because the OrganizationalUnitName and CommonName contain Unicode characters.

$ openssl x509 -in cert.pem -subject -noout
subject=C = HU, L = Budapest, O = NetLock Kft., OU = Tan\C3\BAs\C3\ADtv\C3\A1nykiad\C3\B3k (Certification Services), CN = NetLock Arany (Class Gold) F\C5\91tan\C3\BAs\C3\ADtv\C3\A1ny
$ openssl x509 -in cert.pem -subject -noout -nameopt utf8
subject=C=HU, L=Budapest, O=NetLock Kft., OU=Tanúsítványkiadók (Certification Services), CN=NetLock Arany (Class Gold) Főtanúsítvány

What confuses me the most is that what I can see and interpret of X.509 specs implies that UTF-8 is not only a valid encoding for these fields, it is recommended. So I can't really understand why these fields are forcibly encoded to (and later, decoded from) ASCII, giving rise to this issue.

Searchable metadata
trac-id__9804 9804
type__defect defect
reporter__Phidica Phidica
priority__normal normal
milestone__None None
branch__https___github_com_wiml_twisted_tree_non_ascii_DNs https://github.com/wiml/twisted/tree/non_ascii_DNs
branch_author__ 
status__assigned assigned
resolution__None None
component__core core
keywords__ssl_tls_unicode ssl tls unicode
time__1587138027873608 1587138027873608
changetime__1590807088264726 1590807088264726
version__None None
owner__wiml wiml
cc__Phidica

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in twisted/internet/_sslverify.py, especially _copyName and DistinguishedName attribute handling, and reproduce the failure through Certificate.loadPEM using the Unicode-containing certificate in the report. Check how subject fields are copied and encoded, then verify that loading and inspecting the certificate succeeds without the reported UnicodeEncodeError.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
security
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.