macOS SecureTransport 拒绝导入 OpenSSL 接受的证书

macOS SecureTransport refuses to import a certificate accepted by OpenSSL

我正在尝试修复 urllib3 开源 Python 项目中的一个失败测试。

此测试名为 test_client_no_intermediate,并尝试使用名为 client_no_intermediate.pem 的 X.509 证书。目标是失败并出现 "unknown CA" 错误。使用 OpenSSL 时测试按预期工作:导入成功但证书被拒绝。

但是,在带有 SecureTransport 的 macOS 上,导入失败 Import/Export format unsupported.。令人惊讶的是,它在我使用 macOS 10.13.5 和 Xcode 9.4.1 的机器上始终失败,但是 only fails intermittently in continuous integration 使用 macOS 10.12 和 XCode 8.3.

这是证书:

-----BEGIN CERTIFICATE-----
MIIC/jCCAmegAwIBAgImFhgDOYh0mJSEggRYaDQ2VjgRdyAwkXmAV2KGITVEhiJw
UmBGKBgwDQYJKoZIhvcNAQELBQAwcTELMAkGA1UEBhMCRkkxDjAMBgNVBAgMBWR1
bW15MQ4wDAYDVQQKDAVkdW1teTEOMAwGA1UECwwFZHVtbXkxETAPBgNVBAMMCFNu
YWtlT2lsMR8wHQYJKoZIhvcNAQkBFhBkdW1teUB0ZXN0LmxvY2FsMB4XDTE3MDUx
MjE4MzQyNloXDTIxMTIxOTE4MzQyNlowdzELMAkGA1UEBhMCRkkxDjAMBgNVBAgM
BWR1bW15MQ4wDAYDVQQKDAVkdW1teTEOMAwGA1UECwwFZHVtbXkxFzAVBgNVBAMM
DlNuYWtlT2lsQ2xpZW50MR8wHQYJKoZIhvcNAQkBFhBkdW1teUB0ZXN0LmxvY2Fs
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCadkbPLXPfA1bNjgL9F6+rVLs3
uZdbXemHf1oKkT4q9uruZTQCTDFvvWHq32r6G8KV7MASariSz+bIgpx1euZEOmwu
cd+ULs0HMdfqorRa3MuUtKuIzYiQvCsv788VoNKjs+NNMIexO6p6S9E36ce2trze
BCmpYmi0WofO0bSwnwIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQf
Fh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUbe9reSw2
C72JuGVpc+/L/O2hVjwwHwYDVR0jBBgwFoAUnltsnuh2mjtqqDWk2RNSwC7njHkw
DQYJKoZIhvcNAQELBQADgYEADlJp3uMKxgS2hgCK+JZV4qsXGuZ/rcHgq5qlrfg0
i76+wwZ6fs3WQe+zNgXbJnRviM0VScSUBM8IuclyovFWLvs0Z0piELtZ7KPwrDVf
5S5ynJHnJSG+sj4N6v+tvtpGDb1S3ueLQm79MGXv9pmbaYBmUJ0YSEnrScWy90Bv
Tno=
-----END CERTIFICATE-----

OpenSSL 愉快地解码它:

$ openssl x509 -noout -in client_no_intermediate.pem -text
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            16:18:03:39:88:74:98:94:84:82:04:58:68:34:36:56:38:11:77:20:30:91:79:80:57:62:86:21:35:44:86:22:70:52:60:46:28:18
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=FI, ST=dummy, O=dummy, OU=dummy, CN=SnakeOil/emailAddress=dummy@test.local
        Validity
            Not Before: May 12 18:34:26 2017 GMT
            Not After : Dec 19 18:34:26 2021 GMT
        Subject: C=FI, ST=dummy, O=dummy, OU=dummy, CN=SnakeOilClient/emailAddress=dummy@test.local
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (1024 bit)
                Modulus:
                    00:9a:76:46:cf:2d:73:df:03:56:cd:8e:02:fd:17:
                    af:ab:54:bb:37:b9:97:5b:5d:e9:87:7f:5a:0a:91:
                    3e:2a:f6:ea:ee:65:34:02:4c:31:6f:bd:61:ea:df:
                    6a:fa:1b:c2:95:ec:c0:12:6a:b8:92:cf:e6:c8:82:
                    9c:75:7a:e6:44:3a:6c:2e:71:df:94:2e:cd:07:31:
                    d7:ea:a2:b4:5a:dc:cb:94:b4:ab:88:cd:88:90:bc:
                    2b:2f:ef:cf:15:a0:d2:a3:b3:e3:4d:30:87:b1:3b:
                    aa:7a:4b:d1:37:e9:c7:b6:b6:bc:de:04:29:a9:62:
                    68:b4:5a:87:ce:d1:b4:b0:9f
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            Netscape Comment:
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier:
                6D:EF:6B:79:2C:36:0B:BD:89:B8:65:69:73:EF:CB:FC:ED:A1:56:3C
            X509v3 Authority Key Identifier:
                keyid:9E:5B:6C:9E:E8:76:9A:3B:6A:A8:35:A4:D9:13:52:C0:2E:E7:8C:79

    Signature Algorithm: sha256WithRSAEncryption
         0e:52:69:de:e3:0a:c6:04:b6:86:00:8a:f8:96:55:e2:ab:17:
         1a:e6:7f:ad:c1:e0:ab:9a:a5:ad:f8:34:8b:be:be:c3:06:7a:
         7e:cd:d6:41:ef:b3:36:05:db:26:74:6f:88:cd:15:49:c4:94:
         04:cf:08:b9:c9:72:a2:f1:56:2e:fb:34:67:4a:62:10:bb:59:
         ec:a3:f0:ac:35:5f:e5:2e:72:9c:91:e7:25:21:be:b2:3e:0d:
         ea:ff:ad:be:da:46:0d:bd:52:de:e7:8b:42:6e:fd:30:65:ef:
         f6:99:9b:69:80:66:50:9d:18:48:49:eb:49:c5:b2:f7:40:6f:
         4e:7a

但 SecureTransport 在这个特定证书上失败:

$ security verify-cert -c cacert.pem
Cert Verify Result: CSSMERR_TP_NOT_TRUSTED
$ security verify-cert -c client_no_intermediate.pem
SecCertificateCreateFromData: Unknown format in import.

这个证书有什么问题?

证书唯一明显“错误”的是序列号长 38 个字节。

https://www.rfc-editor.org/rfc/rfc3280#section-4.1.2.2

Given the uniqueness requirements above, serial numbers can be expected to contain long integers. Certificate users MUST be able to handle serialNumber values up to 20 octets. Conformant CAs MUST NOT use serialNumber values longer than 20 octets.

虽然也存在不符合要求的 CA 的指南,但 Apple 设置的限制可能低于 38 字节。

这不能解释间歇性,但拥有看起来不“合规”的证书总是要求不可靠。