1# Copyright (c) Jean-Paul Calderone 2# See LICENSE file for details. 3 4""" 5Unit tests for :py:mod:`OpenSSL.crypto`. 6""" 7 8from warnings import simplefilter 9 10import base64 11from subprocess import PIPE, Popen 12from datetime import datetime, timedelta 13import sys 14 15import pytest 16 17from cryptography import x509 18from cryptography.hazmat.backends.openssl.backend import backend 19from cryptography.hazmat.primitives import serialization 20from cryptography.hazmat.primitives.asymmetric import rsa 21 22import flaky 23 24from OpenSSL.crypto import TYPE_RSA, TYPE_DSA, Error, PKey 25from OpenSSL.crypto import X509, X509Name 26from OpenSSL.crypto import ( 27 X509Store, 28 X509StoreFlags, 29 X509StoreContext, 30 X509StoreContextError, 31) 32from OpenSSL.crypto import X509Req 33from OpenSSL.crypto import X509Extension 34from OpenSSL.crypto import load_certificate, load_privatekey 35from OpenSSL.crypto import load_publickey, dump_publickey 36from OpenSSL.crypto import FILETYPE_PEM, FILETYPE_ASN1, FILETYPE_TEXT 37from OpenSSL.crypto import dump_certificate, load_certificate_request 38from OpenSSL.crypto import dump_certificate_request, dump_privatekey 39from OpenSSL.crypto import PKCS7, load_pkcs7_data 40from OpenSSL.crypto import PKCS12, load_pkcs12 41from OpenSSL.crypto import CRL, Revoked, dump_crl, load_crl 42from OpenSSL.crypto import NetscapeSPKI 43from OpenSSL.crypto import ( 44 sign, 45 verify, 46 get_elliptic_curve, 47 get_elliptic_curves, 48) 49 50from OpenSSL._util import ffi as _ffi, lib as _lib 51 52from .util import ( 53 EqualityTestsMixin, 54 is_consistent_type, 55 WARNING_TYPE_EXPECTED, 56 NON_ASCII, 57) 58 59 60def normalize_privatekey_pem(pem): 61 return dump_privatekey(FILETYPE_PEM, load_privatekey(FILETYPE_PEM, pem)) 62 63 64GOOD_CIPHER = "blowfish" 65BAD_CIPHER = "zippers" 66 67GOOD_DIGEST = "SHA1" 68BAD_DIGEST = "monkeys" 69 70old_root_cert_pem = b"""-----BEGIN CERTIFICATE----- 71MIIC7TCCAlagAwIBAgIIPQzE4MbeufQwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE 72BhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdU 73ZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwIhgPMjAwOTAzMjUxMjM2 74NThaGA8yMDE3MDYxMTEyMzY1OFowWDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklM 75MRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9U 76ZXN0aW5nIFJvb3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPmaQumL 77urpE527uSEHdL1pqcDRmWzu+98Y6YHzT/J7KWEamyMCNZ6fRW1JCR782UQ8a07fy 782xXsKy4WdKaxyG8CcatwmXvpvRQ44dSANMihHELpANTdyVp6DCysED6wkQFurHlF 791dshEaJw8b/ypDhmbVIo6Ci1xvCJqivbLFnbAgMBAAGjgbswgbgwHQYDVR0OBBYE 80FINVdy1eIfFJDAkk51QJEo3IfgSuMIGIBgNVHSMEgYAwfoAUg1V3LV4h8UkMCSTn 81VAkSjch+BK6hXKRaMFgxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UE 82BxMHQ2hpY2FnbzEQMA4GA1UEChMHVGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBS 83b290IENBggg9DMTgxt659DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB 84AGGCDazMJGoWNBpc03u6+smc95dEead2KlZXBATOdFT1VesY3+nUOqZhEhTGlDMi 85hkgaZnzoIq/Uamidegk4hirsCT/R+6vsKAAxNTcBjUeZjlykCJWy5ojShGftXIKY 86w/njVbKMXrvc83qmTdGl3TAM0fxQIpqgcglFLveEBgzn 87-----END CERTIFICATE----- 88""" 89 90root_cert_pem = b"""-----BEGIN CERTIFICATE----- 91MIIE7jCCA1agAwIBAgIIPQzE4MbeufQwDQYJKoZIhvcNAQELBQAwWDELMAkGA1UE 92BhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdU 93ZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwHhcNMjAwODAyMTcxMTE5 94WhcNNDcxMjIwMTcxMTE5WjBYMQswCQYDVQQGEwJVUzELMAkGA1UECBMCSUwxEDAO 95BgNVBAcTB0NoaWNhZ28xEDAOBgNVBAoTB1Rlc3RpbmcxGDAWBgNVBAMTD1Rlc3Rp 96bmcgUm9vdCBDQTCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBALpY5jb+ 97S7AUbx9gzN06wkqUeb+eNLTjCOKofiMTn8Y0TqCA2ZyY3XMcNBMaIS7hdFTgmmqt 98fFntYobxLAl/twfbz9AnRaVDh2HyUvHvMBxKn1HSDLALLtqdF0pcXIjP04S7NKPQ 99Umgkv2H0KwcUpYlgjTFtXRiP+7wDSiQeP1YVSriEoE0TXK14F8np6ZKK0oQ+u16d 100Wn3MGQwFzS+Ipgoz0jbi5D2KzmK2dzHdxY8M2Dktkz/W3DUfUwaTohYed2DG39LP 101NUFOxekgXdIZ3vQbDfsEQt27TUzOztbo/BqK7YkRLzzOQFz+dKAxH6Hy6Bu9op7e 102DWS9TfD/+UmDxr3IeoLMpmUBKxmzTC4qpej+W1UuCE12dMo4LoadlkG+/l1oABqd 103Ucf45WgaFk3xpyEuGnDxjs6rqYPoEapIichxN2fgN+jkgH9ed44r0yOoVeG2pmwD 104YFCCxzkmiuzLADlfM1LUzqUNKVFcOakD3iujHEalnDIJsc/znYsqaRvCkQIDAQAB 105o4G7MIG4MB0GA1UdDgQWBBSDVXctXiHxSQwJJOdUCRKNyH4ErjCBiAYDVR0jBIGA 106MH6AFINVdy1eIfFJDAkk51QJEo3IfgSuoVykWjBYMQswCQYDVQQGEwJVUzELMAkG 107A1UECBMCSUwxEDAOBgNVBAcTB0NoaWNhZ28xEDAOBgNVBAoTB1Rlc3RpbmcxGDAW 108BgNVBAMTD1Rlc3RpbmcgUm9vdCBDQYIIPQzE4MbeufQwDAYDVR0TBAUwAwEB/zAN 109BgkqhkiG9w0BAQsFAAOCAYEAFIMFxLHaVDY/nsbYzI7+zxe4GJeUqRIj2g4XK/nF 1106lHLRFL2YP5yJ+Jm4JDkoZqKq/tcEQLIssQS++s6tBSdvFwdY6imfpEZgFPuodrZ 111KbYm4Xuouw09EQCEjPxBOQ1NEcPuwuDtvD6/BOfm3SRFRTq/gQwxKlZ7C/4l8b1+ 112OQPIUryqdlFBpyE/M95GzaNdmkQx41PevEih2nqWnbTsXLeiSXLGoubMTxKEK4T+ 113J7Ci2KTRJ3SYMgTNU6MNcl7b9Tpw9/KVG80IbpzNQ1LDh3ZtkOfqoou1lmBTeNPu 114g2C/oiW6lVAmZx1TL9gbUtkJ0Q2iW4D9TF+zuYi2qpbVU3RvoqK25x3AuIWf4JOL 1153cTNjJ/3zmGSORRJvcGyvVnL30R+vwpaxvyuqMjz3kBjkK2Z2pvElZMJiZhbGG7k 116MHZQ5A26v0/iQVno6FRv3cQb9EeAZtNHcIEgsNhPZ53XVnwZ58ByvATMLKNN8dWF 117Q+8Bbr7QFxeWvQfHYX2yaQZ/ 118-----END CERTIFICATE----- 119""" 120 121root_key_pem = b"""-----BEGIN RSA PRIVATE KEY----- 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 159-----END RSA PRIVATE KEY----- 160""" 161 162root_key_der = base64.b64decode( 163 """ 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' 201""" 202) 203 204normalized_root_key_pem = normalize_privatekey_pem(root_key_pem) 205 206intermediate_cert_pem = b"""-----BEGIN CERTIFICATE----- 207MIIEXDCCAsSgAwIBAgIRAMPzhm6//0Y/g2pmnHR2C4cwDQYJKoZIhvcNAQELBQAw 208WDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAw 209DgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwHhcNMjAw 210ODAyMTcxMTIwWhcNNDcxMjIwMTcxMTIwWjBmMRUwEwYDVQQDEwxpbnRlcm1lZGlh 211dGUxDDAKBgNVBAoTA29yZzERMA8GA1UECxMIb3JnLXVuaXQxCzAJBgNVBAYTAlVT 212MQswCQYDVQQIEwJDQTESMBAGA1UEBxMJU2FuIERpZWdvMIIBojANBgkqhkiG9w0B 213AQEFAAOCAY8AMIIBigKCAYEAo3rOxOVrdLdRsR1o0+JG7MRpCtMoafA63TM/DczL 214Q4jURv5MzyTE7FFdXq4xNJRYgD16vUavZluQGj30+5Lkt07CuO/BK3itl8UW+dsH 215p95gzBvgnj5AVZGkNOQ0Y4CbXO087Ywep7tpBfZ5fzURLeH+OHQGseEFZ5e0w8Az 216AarWu+Ez5RGpkaZ61iiJa53mAgkrjw+o83UrpDT2nrXiyR6Fx4K4eb1rarodWqGv 217jSkdT5MA4i0gDhsIBnTarPB+0KM8M7od8DkLsTHBt4rYYCHgCX1bWavzGlqPEw9h 218ksK+LAbQKD9J2AxYDkL0PAeUuvWMhxEmN6hXePiw63sJzukRunAvut5A2+42JMkW 219guDyqIvAjlCYcIyBvUbphP3qSFqww/hpZ2wh5UZOc1mzYJKR9MgI8/UhRJEJ7NyY 220pF24EJbisjNE30ot8aM2/5cI5KevclcuPJWH8PjT/i1VnNpM4S8MqoPw6F+d75d/ 221CtfI+LLfns4k3G9I+Qgxmpa5AgMBAAGjEzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJ 222KoZIhvcNAQELBQADggGBAFVQ3Dmljrnbjys9ZIqcTs/B5ktKUAU2KNMO9TmoFymE 223YhHKbCb5u/CnWq3jtBW6jgkQHrhfY9leUlH87BkB2o16BcSKjHknHZ2MCdEvQvOM 224/nkkMDkOEoRn8mfCCxxgt8Kxf07wHDcnKoeJ3h9BXIl6nyJqJAcVWEJm1d75ayDG 2250Kr0z+LcqMtQqYI0csK/XDQkunlE95qti1HzxW+JeAf6nRkr7RNZLtGmUGAMfyBK 2269A0Db8QLR7O92YEmwoXtp+euN6uDdjw4A7KHjNXMdvqZoRfbZEA9c6XJTBj22h87 227gYUFRVpkNDrC/c9u6WgA943yMgFCwjrlTsmi+uoweT9U5r4TA+dVCDAv943aWCNm 228A+TiuIXlJAHl2PlH7Umu/oMQKDEt+0n4QcQLBZyK3CYU5kg+ms9vOvE19Lhp8HeS 229xqm6dwKpdm7/8EfGNW3s8Gm4KM26mb7dtSdHJFuR/BQ5y/cn4qIMyeGfHvsVew+2 230neyFR2Oc/nUlZMKfyHI+pA== 231-----END CERTIFICATE----- 232""" 233 234intermediate_key_pem = b"""-----BEGIN RSA PRIVATE KEY----- 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 272-----END RSA PRIVATE KEY----- 273""" 274 275server_cert_pem = b"""-----BEGIN CERTIFICATE----- 276MIIEKTCCApGgAwIBAgIJAJn/HpR21r/8MA0GCSqGSIb3DQEBCwUAMFgxCzAJBgNV 277BAYTAlVTMQswCQYDVQQIDAJJTDEQMA4GA1UEBwwHQ2hpY2FnbzEQMA4GA1UECgwH 278VGVzdGluZzEYMBYGA1UEAwwPVGVzdGluZyBSb290IENBMB4XDTIwMDgwMjE3MTEy 279MFoXDTQ3MTIyMDE3MTEyMFowGDEWMBQGA1UEAwwNbG92ZWx5IHNlcnZlcjCCAaIw 280DQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAKU9txhKg6Nc0dVK9Vv4MYuYP6Hs 281oR483+wC53V8axkfy2TynrBSug8HapeSFW5jwdwcsjaDwEIAugZfRoz0N1vR/Q6T 282OFAYn2hRwlAgUXVk3NXpDNV/QRliGvxhLAVpvu1a4ExfVZoOQyPa8pogDgrUdB3e 283tYmmFHNa09Lv1nyMZWi6t7zH2weq6/Dxpm0BWf+THFcunv9TNfAqmDV5qbxvaUPh 284uvRpN+X2N3tejB8WKt+UmzAXUi3P3OgYimWXwq8Rmorc1rk5j+ksl6qYwZvi7rRV 285g1ZAH7bGhXC9eEU/1Z9q26OhAPdTyJD0pc+G9vMz6VijLRXcgHBUP09lSeqxnNxc 286pWoX6nRdGn6PkDhewHM05iqAE3ZHnc8kSBcRX85SoW5dGOhvvUTs4ePVNTo3vHdQ 287vftTDD+I3rbFnYTKUAzHTPSWGE7LVEiWJ94RKSADXgve0qq8o377UMnY7W3UygSY 288odyUZ29B5EfZ88EpIs/h5NomDv5VcQEoCWN1owIDAQABozYwNDAdBgNVHQ4EFgQU 289g1V3LV4h8UkMCSTnVAkSjch+BK4wEwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZI 290hvcNAQELBQADggGBACn0LsqO94tk8i+RbG5hryNduem9n8b8doYD97iaux6QLvY/ 291A8DFduJtUevZ3OCsRYQSGa3V/ysMzN7/DIUkpRLevZmdw+1L6PGR7peR2xIQ+yEW 292bL88vLjezaYIzMKHJRmN8oP3DQtGJm6U2fMMiEHWqRtULIVpnFppzPI2z7+tDeyg 293PFD2YeiFWoq5lmXStrK+KYPJbhTn0gz4QlGBs7PLY2JMDRSVj6ctkvrpXbC3Rb3m 294qo2FY/y51ACg77Txc6NAmNE6tCknwaUjRQP2MuoYFm5/Z6O9/g49AEVIE101zHqV 295N6SkcTUaXAuQIyZaqwdndfOB4rrFyAkoxTM5OamIQl80hZKf4R5rM7D7Sz8kAWJi 296BPIcewN0XnI6lm+zPAVUAE8dZfgJmJR5ifZHYCuv96EX0RpYsddeik8UmjkZ2/ch 297vRzvRSNNxVC6Zoe6vKNUb89XMtJZqY80WxfWG3Z2Hwf9KvS+2KAH/6MiSMj0RI5F 298SCB2PMQm6DYXwM1EyA== 299-----END CERTIFICATE----- 300""" 301 302server_key_pem = normalize_privatekey_pem( 303 b"""-----BEGIN RSA PRIVATE KEY----- 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 341-----END RSA PRIVATE KEY----- 342""" 343) 344 345intermediate_server_cert_pem = b"""-----BEGIN CERTIFICATE----- 346MIIEXTCCAsWgAwIBAgIRAPQFY9jfskSihdiNSNdt6GswDQYJKoZIhvcNAQELBQAw 347ZjEVMBMGA1UEAxMMaW50ZXJtZWRpYXRlMQwwCgYDVQQKEwNvcmcxETAPBgNVBAsT 348CG9yZy11bml0MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVNh 349biBEaWVnbzAeFw0yMDA4MDIxNzExMjBaFw00NzEyMjAxNzExMjBaMG4xHTAbBgNV 350BAMTFGludGVybWVkaWF0ZS1zZXJ2aWNlMQwwCgYDVQQKEwNvcmcxETAPBgNVBAsT 351CG9yZy11bml0MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVNh 352biBEaWVnbzCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAL3UcTxwCsMZ 353qIE+7lolm8t6lT0IYZkE4L7u2qI64m9CvztudqqKYZcrprZobZxqPhqc8IO3CFR2 354nVzwZWxrHCcm6nAzJjVXUFrc4TLsVYYJL1QvKXxr97VIiySU7x6xWrQQsqDtlrb0 355jH59EYFbM2eMk2fBT2X4h6YMXlqyrDjZF6apClXtkdxGJGqR5PCTs4cvrYW7TpIm 356cuJq0S+MRBguZpriM+wOK7cXrqfRPFRzZtPXskpQPSAMDDAOGKl8OZfoVFYzG8KG 357omOa0hcHtgYX2GCDs1g1maY6Haw9bgs041BoApH9aQxehy5dfU39DcFoKSE3dCjR 358FaR6ryCA+f8L1F3xVaHsvX443CYF0/holfsptTjNd1T1z8WR5h1jtY0gJ/ERgcJZ 359UgDRE3lEkTLExS/nuGVfdwnlkxny9jbtYp2YcjYjUkChLtTgz4ommeIdBdDvSu8M 360wWHMtQNxECs5qA5J384cLh11Nd9exWUjiQ9yAZ0qTOzTkdH7VPHfxQIDAQABMA0G 361CSqGSIb3DQEBCwUAA4IBgQA2jC5hJ/+46RLBuaZiJhBawiY+HqybEAZWM/IBGZO4 362UKcRotovU+sb1jg+vpXwePSBPEtQoZce0jN0TKiCdlLM4/9lybAvc6qBLJ0d4VS5 363BU5QsCs9IKyvswAFVipQZi0szYwHk8T145SH/fPao8oznf5ae4a6rK9PyZqT7Ix1 364nnKGffbJs0dY+jlxmx/BPlbsGfTwPL6LexghjvbpbXWUdVLP3gAW6DPCtRd6lhWj 365JvgCkF2SnbQ7GgnPEYi8h09j0c6/sK6jLoNAatJyIlRGE1cdGYZVUlVW/xP6lYM0 366Mi1KKl0ZXOne4vPTtnTBBqrpjdLydH3WM1IxdwSRbmF15OD6BWzzKV4IYUJ21GDh 367YrVrcIeN49pUoKVTTn0Sql8f8mXxJhJ54wo9TKdIGZeuwTZrfWjcjWghXgghXGoP 368RI/I5fk/OMu0Oc06/+xdwCBHCSge0/vxK6fhTu7PxmJhQcZF0sDZyb6LXm2feVkG 3696FsxnsvstVNO3oJdpa8daLs= 370-----END CERTIFICATE----- 371""" 372 373intermediate_server_key_pem = b"""-----BEGIN RSA PRIVATE KEY----- 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 411-----END RSA PRIVATE KEY----- 412""" 413 414client_cert_pem = b"""-----BEGIN CERTIFICATE----- 415MIIEJzCCAo+gAwIBAgIJAKxpFI5lODkjMA0GCSqGSIb3DQEBCwUAMFgxCzAJBgNV 416BAYTAlVTMQswCQYDVQQIDAJJTDEQMA4GA1UEBwwHQ2hpY2FnbzEQMA4GA1UECgwH 417VGVzdGluZzEYMBYGA1UEAwwPVGVzdGluZyBSb290IENBMB4XDTIwMDgwMjE3MTEy 418MVoXDTQ3MTIyMDE3MTEyMVowFjEUMBIGA1UEAwwLdWdseSBjbGllbnQwggGiMA0G 419CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDGChdOMY164FScJqfiJ5LEtjYOKEg4 420nmMAMGuHIT8wZZEfzaaHhBbypzKq2cPP1qtyHgvtUMM6KOFEj4y9AonqzzdlVxbM 421i6+AvYLWlPoB5r/G1GdslUvXbc7F02B/6sB/+iFXmcdjOjAQcLWxVgUL+1CoeoY1 422awNYmzQueK/T82a/6AYTdrx7XRX4wfxjYb1o3bnnRD/jGSakIylXeUGFsiSNkBs/ 423dJMkUONxizAdAE2tW6NhPuE2O0UipzUhdgFnH6WPfJ0J1S7jZ3eQTUrLkFpWSp/Z 424hx/l/Ql9vO0wagHaT2wOiZdKVT8S6V6OPzJ7/H1evCoM6EuSPBC5DDP1nPetCK1v 425uC9kb7Dg6yFPt1CKrVFt0Y6W5Y5/GzisUtvYV/OGtX4DOwL9It68D04Qrvun1t/a 426Dh/c5gKqfqIGHUvUucFmOi6DrRpadfraLZMRGN2ysPjoVwhMgwwSmSWhziQIUfxK 427oyz1CUsyr5Gh5gdifbe1AOYwu6YdtlmhqCsCAwEAAaM2MDQwHQYDVR0OBBYEFINV 428dy1eIfFJDAkk51QJEo3IfgSuMBMGA1UdJQQMMAoGCCsGAQUFBwMCMA0GCSqGSIb3 429DQEBCwUAA4IBgQAhAEACc1j6EYoSfVJD8N/FlYfHRizdfVJyrmMnC8ID1vtfrU2z 430S2q+49ja2NyM4Sq+Cf+i+sFfzFG92LayZt9Mc1BnHZMdNzQL7Ynr2nDLxHsHzuYa 431N21/ucTpHEFGLmvQ/eWBMxQQ9TbiNXn+tnnqg46dRzN3vHJp+g5+ijtMcuh007z2 432niiO8F07wlb960XviejWejMC8hBLWlA7i3EjAkDO8RFQnG2Py5cQX9GgmWH1sDy3 433rIsWlU+e46ysSWK/bnudnAlzZMB9KJATVZu5+xmCumH2hLJv5vz+jnKcgU9MBZMO 434cKgNdFUbtRlU/gfTaohmLIuSquunCCrXLsLD8ygbKKXfSPGVo2XkvX3oxqUo6dmA 435LvU4N4sCQGiSzW+a13HBtk3TBZFsJSWUGSW/H7TVFiAonumJKRqRxMOkkB9JxX+V 4369LZBYuBLpOeK4wZ8BUSNlHKnGpDzl0DzdYrGlzWz0jXlLGZ8KMfXAn9h0mOZ+IyK 437eUlgMBYyAspCQzM= 438-----END CERTIFICATE----- 439""" 440 441client_key_pem = normalize_privatekey_pem( 442 b"""-----BEGIN RSA PRIVATE KEY----- 443MIIG5AIBAAKCAYEAxgoXTjGNeuBUnCan4ieSxLY2DihIOJ5jADBrhyE/MGWRH82m 444h4QW8qcyqtnDz9arch4L7VDDOijhRI+MvQKJ6s83ZVcWzIuvgL2C1pT6Aea/xtRn 445bJVL123OxdNgf+rAf/ohV5nHYzowEHC1sVYFC/tQqHqGNWsDWJs0Lniv0/Nmv+gG 446E3a8e10V+MH8Y2G9aN2550Q/4xkmpCMpV3lBhbIkjZAbP3STJFDjcYswHQBNrVuj 447YT7hNjtFIqc1IXYBZx+lj3ydCdUu42d3kE1Ky5BaVkqf2Ycf5f0JfbztMGoB2k9s 448DomXSlU/Eulejj8ye/x9XrwqDOhLkjwQuQwz9Zz3rQitb7gvZG+w4OshT7dQiq1R 449bdGOluWOfxs4rFLb2FfzhrV+AzsC/SLevA9OEK77p9bf2g4f3OYCqn6iBh1L1LnB 450Zjoug60aWnX62i2TERjdsrD46FcITIMMEpkloc4kCFH8SqMs9QlLMq+RoeYHYn23 451tQDmMLumHbZZoagrAgMBAAECggGAAXA5UxwRBv9yHeA5/+6BpmQcaGXqgF7GIU44 452ubaIGvXh4/U+bGWNNR35xDvorC3G+QE23PZlNJrvZ+wS/ZxzG/19TYMga0Podmrp 4539F0Io9LlObB5P9SlxF7LzawHW2Z9F3DdpSE8zX+ysavf5fXV+4xLva2GJAUu9QnL 454izrdLBDsgiBRSvrly4+VhUUDbEVddtGFdCSOwjuAiFipCDWdQDdXBKAzUnaqSu07 455eaulIdDKv6OWwDIQuLAdhG7qd9+/h5MB/rAG8v4bgbHz1H/RZw5VIOuOhfCodzJx 4563Smfh5td21jwJ2RfZYEPNOMtFa9eRFtH2/uRa5jbJiZb8YWIzWy0xCNQpKheSoBO 457wiuMDBS2HCYm2SgEYDdJiE2OkRAk0UwTiUmlmZd0a3NfJ/rfQE+JiDQ28Arj3EZl 458SY/V3KdviM4MbaoX7f9j9sjAe5Rk1M+yI8OsnM/hf77m0CSiJJpLpvgqhMjjT+NI 459aBm1FyTq6qu506d0YUZy+Wr2DRsBAoHBAPfshuOiDXo9UmJxM1mSJQ0rQlxWSWmX 460bIAsPrpKslTFYHk7xbcCbJCqMbHmCsyvYy3oW3SpJs6Vi2wQWuUQmsm0YC7qdkXF 461Fyo2f7vF7roQcXLxVmQRo0OxZ9JpLAZ9DKMEcNfYyUiQiqJmZuIyWKngqBl6OoL2 4628EJSFjTY1tR/nDxGLpZSsqoZJWQGd9B2bK4y6NktDF1GkexCpKaSyXZT612JGPG2 4630gSIwRq1OgZH3SPHevhVMjJtxGue2XARywKBwQDMfZHtdJI9RuurM9UuULZ72SmW 464oLzki3LwFQ/QoS9wrHK+OqQDWH2ddON1PoB4LOCpwB4CC83pMyfxurgLHut6saHL 465hQ5N+h0jUC2pSJOXZSfF2Hx8YHCT7Dga5kmgEy89c1TF48IL2LdUZQQIGZt8+FxM 4664nxT9NFlu/UWY2oftT+ZwFsIock/DYYUKxDXw9YkOmt1lO5u1SKte0NdQ4RhBeqK 467nRADMSS9oKZkSUxkwaDJH2GkUVTyBsF/kmh+dyECgcEA6jy3yRQPxcFwOAAZ8vOo 468PAP2I8WGgNQHOCYVce8nA/6jwocdq2YH6rpST3E4HOFMRFB3MAas2pvh6UyehDOm 469+xGHmmv9KLgoxcJN9rvwbC0i8uVfqRYc+dUAcYTaiprVOKP2dYilzAB8ayly5R2K 470NZ5DVCbuZ1Ql9ZMW1gFVH9odY7kvROmHUjyF3jZaN0PcNM12v9HXD72gGudwJs0i 471uMBa7LmeLql7TbtjLvewhcSaA7bx0PS1g33ACapAZ6j3AoHAN2PsGz3wPtjvDTjF 472Df6e730rXrm7cMy1HYMW/ZQrnYGYsx5/PsjBfd0jn6aGdgbx9AkuF6/K3tgUgc3p 473/Fkrv9hN0yr/bO/K5L3bIHegQuoLk/PIBIi69daOe/rVBp8rtKGA3PmMnljdj+as 4746OTG0VsU5V6T/snZzozTHnVfUaduyt7nybbJJGMtZlkj/s31O2r3oKnuy+a/te4l 475mSWovf80QMe6hqLRKOxTJecU4lXwj4oIkNHXCJf74epuk5MBAoHBALyvg90KzMFX 476ZEjdPIXULR6/3rub8yD7LVYbNhhYWGo8GybzsBUC0kczRpRXFnmbq1GDIXQf5A+2 4773ZaGsWzAxLjvL3KwH1LUaXVWwFMOM2n6zTk18XEXrNvp+E5QtPwpO5c4VlPr0cAC 478tTPAmbu6kVPlQ6mKiqlPAsfh0BD2mRVo2cTjZgDotKshb5uCHD8/PnCfOjCXFxOf 479DWjBuR73/r5Bj+ktRoD4V2SFdO6loJwH6B8rsBjD0NbAGs9otKvy+Q== 480-----END RSA PRIVATE KEY----- 481""" 482) 483 484cleartextCertificateRequestPEM = b"""-----BEGIN CERTIFICATE REQUEST----- 485MIIBnjCCAQcCAQAwXjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQH 486EwdDaGljYWdvMRcwFQYDVQQKEw5NeSBDb21wYW55IEx0ZDEXMBUGA1UEAxMORnJl 487ZGVyaWNrIERlYW4wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANp6Y17WzKSw 488BsUWkXdqg6tnXy8H8hA1msCMWpc+/2KJ4mbv5NyD6UD+/SqagQqulPbF/DFea9nA 489E0zhmHJELcM8gUTIlXv/cgDWnmK4xj8YkjVUiCdqKRAKeuzLG1pGmwwF5lGeJpXN 490xQn5ecR0UYSOWj6TTGXB9VyUMQzCClcBAgMBAAGgADANBgkqhkiG9w0BAQUFAAOB 491gQAAJGuF/R/GGbeC7FbFW+aJgr9ee0Xbl6nlhu7pTe67k+iiKT2dsl2ti68MVTnu 492Vrb3HUNqOkiwsJf6kCtq5oPn3QVYzTa76Dt2y3Rtzv6boRSlmlfrgS92GNma8JfR 493oICQk3nAudi6zl1Dix3BCv1pUp5KMtGn3MeDEi6QFGy2rA== 494-----END CERTIFICATE REQUEST----- 495""" 496 497encryptedPrivateKeyPEM = b"""-----BEGIN RSA PRIVATE KEY----- 498Proc-Type: 4,ENCRYPTED 499DEK-Info: DES-EDE3-CBC,9573604A18579E9E 500 501SHOho56WxDkT0ht10UTeKc0F5u8cqIa01kzFAmETw0MAs8ezYtK15NPdCXUm3X/2 502a17G7LSF5bkxOgZ7vpXyMzun/owrj7CzvLxyncyEFZWvtvzaAhPhvTJtTIB3kf8B 5038+qRcpTGK7NgXEgYBW5bj1y4qZkD4zCL9o9NQzsKI3Ie8i0239jsDOWR38AxjXBH 504mGwAQ4Z6ZN5dnmM4fhMIWsmFf19sNyAML4gHenQCHhmXbjXeVq47aC2ProInJbrm 505+00TcisbAQ40V9aehVbcDKtS4ZbMVDwncAjpXpcncC54G76N6j7F7wL7L/FuXa3A 506fvSVy9n2VfF/pJ3kYSflLHH2G/DFxjF7dl0GxhKPxJjp3IJi9VtuvmN9R2jZWLQF 507tfC8dXgy/P9CfFQhlinqBTEwgH0oZ/d4k4NVFDSdEMaSdmBAjlHpc+Vfdty3HVnV 508rKXj//wslsFNm9kIwJGIgKUa/n2jsOiydrsk1mgH7SmNCb3YHgZhbbnq0qLat/HC 509gHDt3FHpNQ31QzzL3yrenFB2L9osIsnRsDTPFNi4RX4SpDgNroxOQmyzCCV6H+d4 510o1mcnNiZSdxLZxVKccq0AfRpHqpPAFnJcQHP6xyT9MZp6fBa0XkxDnt9kNU8H3Qw 5117SJWZ69VXjBUzMlQViLuaWMgTnL+ZVyFZf9hTF7U/ef4HMLMAVNdiaGG+G+AjCV/ 512MbzjS007Oe4qqBnCWaFPSnJX6uLApeTbqAxAeyCql56ULW5x6vDMNC3dwjvS/CEh 51311n8RkgFIQA0AhuKSIg3CbuartRsJnWOLwgLTzsrKYL4yRog1RJrtw== 514-----END RSA PRIVATE KEY----- 515""" 516 517encryptedPrivateKeyPEMPassphrase = b"foobar" 518 519cleartextPrivateKeyPEM = """-----BEGIN PRIVATE KEY----- 520MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMcRMugJ4kvkOEuT 521AvMFr9+3A6+HAB6nKYcXXZz93ube8rJpBZQEfWn73H10dQiQR/a+rhxYEeLy8dPc 522UkFcGR9miVkukJ59zex7iySJY76bdBD8gyx1LTKrkCstP2XHKEYqgbj+tm7VzJnY 523sQLqoaa5NeyWJnUC3MJympkAS7p3AgMBAAECgYAoBAcNqd75jnjaiETRgVUnTWzK 524PgMCJmwsob/JrSa/lhWHU6Exbe2f/mcGOQDFpesxaIcrX3DJBDkkc2d9h/vsfo5v 525JLk/rbHoItWxwuY5n5raAPeQPToKpTDxDrL6Ejhgcxd19wNht7/XSrYZ+dq3iU6G 526mOEvU2hrnfIW3kwVYQJBAP62G6R0gucNfaKGtHzfR3TN9G/DnCItchF+TxGTtpdh 527Cz32MG+7pirT/0xunekmUIp15QHdRy496sVxWTCooLkCQQDIEwXTAwhLNRGFEs5S 528jSkxNfTVeNiOzlG8jPBJJDAdlLt1gUqjZWnk9yU+itMSGi/6eeuH2n04FFk+SV/T 5297ryvAkB0y0ZDk5VOozX/p2rtc2iNm77A3N4kIdiTQuq4sZXhNgN0pwWwxke8jbcb 5308gEAnqwBwWt//locTxHu9TmjgT8pAkEAlbF16B0atXptM02QxT8MlN8z4gxaqu4/ 531RX2FwpOq1FcVsqMbvwj/o+ouGY8wwRiK0TMrQCf/DFhdNTcc1aqHzQJBAKWtq4LI 532uVZjCAuyrqEnt7R1bOiLrar+/ezJPY2z+f2rb1TGr31ztPeFvO3edLw+QdhzwJGp 533QKImYzqMe+zkIOQ= 534-----END PRIVATE KEY----- 535""" 536 537cleartextPublicKeyPEM = b"""-----BEGIN PUBLIC KEY----- 538MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxszlc+b71LvlLS0ypt/l 539gT/JzSVJtnEqw9WUNGeiChywX2mmQLHEt7KP0JikqUFZOtPclNY823Q4pErMTSWC 54090qlUxI47vNJbXGRfmO2q6Zfw6SE+E9iUb74xezbOJLjBuUIkQzEKEFV+8taiRV+ 541ceg1v01yCT2+OjhQW3cxG42zxyRFmqesbQAUWgS3uhPrUQqYQUEiTmVhh4FBUKZ5 542XIneGUpX1S7mXRxTLH6YzRoGFqRoc9A0BBNcoXHTWnxV215k4TeHMFYE5RG0KYAS 5438Xk5iKICEXwnZreIt3jyygqoOKsKZMK/Zl2VhMGhJR6HXRpQCyASzEG7bgtROLhL 544ywIDAQAB 545-----END PUBLIC KEY----- 546""" 547 548# Some PKCS#7 stuff. Generated with the openssl command line: 549# 550# openssl crl2pkcs7 -inform pem -outform pem -certfile s.pem -nocrl 551# 552# with a certificate and key (but the key should be irrelevant) in s.pem 553pkcs7Data = b"""\ 554-----BEGIN PKCS7----- 555MIIDNwYJKoZIhvcNAQcCoIIDKDCCAyQCAQExADALBgkqhkiG9w0BBwGgggMKMIID 556BjCCAm+gAwIBAgIBATANBgkqhkiG9w0BAQQFADB7MQswCQYDVQQGEwJTRzERMA8G 557A1UEChMITTJDcnlwdG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtN 558MkNyeXB0byBDZXJ0aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNA 559cG9zdDEuY29tMB4XDTAwMDkxMDA5NTEzMFoXDTAyMDkxMDA5NTEzMFowUzELMAkG 560A1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwlsb2NhbGhvc3Qx 561HTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tMFwwDQYJKoZIhvcNAQEBBQAD 562SwAwSAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh5kwI 563zOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEAAaOCAQQwggEAMAkGA1UdEwQCMAAw 564LAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0G 565A1UdDgQWBBTPhIKSvnsmYsBVNWjj0m3M2z0qVTCBpQYDVR0jBIGdMIGagBT7hyNp 56665w6kxXlxb8pUU/+7Sg4AaF/pH0wezELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0y 567Q3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlwdG8g 568Q2VydGlmaWNhdGUgTWFzdGVyMR0wGwYJKoZIhvcNAQkBFg5uZ3BzQHBvc3QxLmNv 569bYIBADANBgkqhkiG9w0BAQQFAAOBgQA7/CqT6PoHycTdhEStWNZde7M/2Yc6BoJu 570VwnW8YxGO8Sn6UJ4FeffZNcYZddSDKosw8LtPOeWoK3JINjAk5jiPQ2cww++7QGG 571/g5NDjxFZNDJP1dGiLAxPW6JXwov4v0FmdzfLOZ01jDcgQQZqEpYlgpuI5JEWUQ9 572Ho4EzbYCOaEAMQA= 573-----END PKCS7----- 574""" 575 576pkcs7DataASN1 = base64.b64decode( 577 b""" 578MIIDNwYJKoZIhvcNAQcCoIIDKDCCAyQCAQExADALBgkqhkiG9w0BBwGgggMKMIID 579BjCCAm+gAwIBAgIBATANBgkqhkiG9w0BAQQFADB7MQswCQYDVQQGEwJTRzERMA8G 580A1UEChMITTJDcnlwdG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtN 581MkNyeXB0byBDZXJ0aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNA 582cG9zdDEuY29tMB4XDTAwMDkxMDA5NTEzMFoXDTAyMDkxMDA5NTEzMFowUzELMAkG 583A1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwlsb2NhbGhvc3Qx 584HTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tMFwwDQYJKoZIhvcNAQEBBQAD 585SwAwSAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh5kwI 586zOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEAAaOCAQQwggEAMAkGA1UdEwQCMAAw 587LAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0G 588A1UdDgQWBBTPhIKSvnsmYsBVNWjj0m3M2z0qVTCBpQYDVR0jBIGdMIGagBT7hyNp 58965w6kxXlxb8pUU/+7Sg4AaF/pH0wezELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0y 590Q3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlwdG8g 591Q2VydGlmaWNhdGUgTWFzdGVyMR0wGwYJKoZIhvcNAQkBFg5uZ3BzQHBvc3QxLmNv 592bYIBADANBgkqhkiG9w0BAQQFAAOBgQA7/CqT6PoHycTdhEStWNZde7M/2Yc6BoJu 593VwnW8YxGO8Sn6UJ4FeffZNcYZddSDKosw8LtPOeWoK3JINjAk5jiPQ2cww++7QGG 594/g5NDjxFZNDJP1dGiLAxPW6JXwov4v0FmdzfLOZ01jDcgQQZqEpYlgpuI5JEWUQ9 595Ho4EzbYCOaEAMQA= 596""" 597) 598 599crlData = b"""\ 600-----BEGIN X509 CRL----- 601MIIBWzCBxTANBgkqhkiG9w0BAQQFADBYMQswCQYDVQQGEwJVUzELMAkGA1UECBMC 602SUwxEDAOBgNVBAcTB0NoaWNhZ28xEDAOBgNVBAoTB1Rlc3RpbmcxGDAWBgNVBAMT 603D1Rlc3RpbmcgUm9vdCBDQRcNMDkwNzI2MDQzNDU2WhcNMTIwOTI3MDI0MTUyWjA8 604MBUCAgOrGA8yMDA5MDcyNTIzMzQ1NlowIwICAQAYDzIwMDkwNzI1MjMzNDU2WjAM 605MAoGA1UdFQQDCgEEMA0GCSqGSIb3DQEBBAUAA4GBAEBt7xTs2htdD3d4ErrcGAw1 6064dKcVnIWTutoI7xxen26Wwvh8VCsT7i/UeP+rBl9rC/kfjWjzQk3/zleaarGTpBT 6070yp4HXRFFoRhhSE/hP+eteaPXRgrsNRLHe9ZDd69wmh7J1wMDb0m81RG7kqcbsid 608vrzEeLDRiiPl92dyyWmu 609-----END X509 CRL----- 610""" 611 612crlDataUnsupportedExtension = b"""\ 613-----BEGIN X509 CRL----- 614MIIGRzCCBS8CAQIwDQYJKoZIhvcNAQELBQAwJzELMAkGA1UEBhMCVVMxGDAWBgNV 615BAMMD2NyeXB0b2dyYXBoeS5pbxgPMjAxNTAxMDEwMDAwMDBaGA8yMDE2MDEwMTAw 616MDAwMFowggTOMBQCAQAYDzIwMTUwMTAxMDAwMDAwWjByAgEBGA8yMDE1MDEwMTAw 617MDAwMFowXDAYBgNVHRgEERgPMjAxNTAxMDEwMDAwMDBaMDQGA1UdHQQtMCukKTAn 618MQswCQYDVQQGEwJVUzEYMBYGA1UEAwwPY3J5cHRvZ3JhcGh5LmlvMAoGA1UdFQQD 619CgEAMHICAQIYDzIwMTUwMTAxMDAwMDAwWjBcMBgGA1UdGAQRGA8yMDE1MDEwMTAw 620MDAwMFowNAYDVR0dBC0wK6QpMCcxCzAJBgNVBAYTAlVTMRgwFgYDVQQDDA9jcnlw 621dG9ncmFwaHkuaW8wCgYDVR0VBAMKAQEwcgIBAxgPMjAxNTAxMDEwMDAwMDBaMFww 622GAYDVR0YBBEYDzIwMTUwMTAxMDAwMDAwWjA0BgNVHR0ELTArpCkwJzELMAkGA1UE 623BhMCVVMxGDAWBgNVBAMMD2NyeXB0b2dyYXBoeS5pbzAKBgNVHRUEAwoBAjByAgEE 624GA8yMDE1MDEwMTAwMDAwMFowXDAYBgNVHRgEERgPMjAxNTAxMDEwMDAwMDBaMDQG 625A1UdHQQtMCukKTAnMQswCQYDVQQGEwJVUzEYMBYGA1UEAwwPY3J5cHRvZ3JhcGh5 626LmlvMAoGA1UdFQQDCgEDMHICAQUYDzIwMTUwMTAxMDAwMDAwWjBcMBgGA1UdGAQR 627GA8yMDE1MDEwMTAwMDAwMFowNAYDVR0dBC0wK6QpMCcxCzAJBgNVBAYTAlVTMRgw 628FgYDVQQDDA9jcnlwdG9ncmFwaHkuaW8wCgYDVR0VBAMKAQQwcgIBBhgPMjAxNTAx 629MDEwMDAwMDBaMFwwGAYDVR0YBBEYDzIwMTUwMTAxMDAwMDAwWjA0BgNVHR0ELTAr 630pCkwJzELMAkGA1UEBhMCVVMxGDAWBgNVBAMMD2NyeXB0b2dyYXBoeS5pbzAKBgNV 631HRUEAwoBBTByAgEHGA8yMDE1MDEwMTAwMDAwMFowXDAYBgNVHRgEERgPMjAxNTAx 632MDEwMDAwMDBaMDQGA1UdHQQtMCukKTAnMQswCQYDVQQGEwJVUzEYMBYGA1UEAwwP 633Y3J5cHRvZ3JhcGh5LmlvMAoGA1UdFQQDCgEGMHICAQgYDzIwMTUwMTAxMDAwMDAw 634WjBcMBgGA1UdGAQRGA8yMDE1MDEwMTAwMDAwMFowNAYDVR0dBC0wK6QpMCcxCzAJ 635BgNVBAYTAlVTMRgwFgYDVQQDDA9jcnlwdG9ncmFwaHkuaW8wCgYDVR0VBAMKAQgw 636cgIBCRgPMjAxNTAxMDEwMDAwMDBaMFwwGAYDVR0YBBEYDzIwMTUwMTAxMDAwMDAw 637WjA0BgNVHR0ELTArpCkwJzELMAkGA1UEBhMCVVMxGDAWBgNVBAMMD2NyeXB0b2dy 638YXBoeS5pbzAKBgNVHRUEAwoBCTByAgEKGA8yMDE1MDEwMTAwMDAwMFowXDAYBgNV 639HRgEERgPMjAxNTAxMDEwMDAwMDBaMDQGA1UdHQQtMCukKTAnMQswCQYDVQQGEwJV 640UzEYMBYGA1UEAwwPY3J5cHRvZ3JhcGh5LmlvMAoGA1UdFQQDCgEKMC4CAQsYDzIw 641MTUwMTAxMDAwMDAwWjAYMAoGA1UdFQQDCgEBMAoGAyoDBAQDCgEAMA0GCSqGSIb3 642DQEBCwUAA4IBAQBTaloHlPaCZzYee8LxkWej5meiqxQVNWFoVdjesroa+f1FRrH+ 643drRU60Nq97KCKf7f9GNN/J3ZIlQmYhmuDqh12f+XLpotoj1ZRfBz2hjFCkJlv+2c 644oWWGNHgA70ndFoVtcmX088SYpX8E3ARATivS4q2h9WlwV6rO93mhg3HGIe3JpcK4 6457BcW6Poi/ut/zsDOkVbI00SqaujRpdmdCTht82MH3ztjyDkI9KYaD/YEweKSrWOz 646SdEILd164bfBeLuplVI+xpmTEMVNpXBlSXl7+xIw9Vk7p7Q1Pa3k/SvhOldYCm6y 647C1xAg/AAq6w78yzYt18j5Mj0s6eeHi1YpHKw 648-----END X509 CRL----- 649""" 650 651 652# A broken RSA private key which can be used to test the error path through 653# PKey.check. 654inconsistentPrivateKeyPEM = b"""-----BEGIN RSA PRIVATE KEY----- 655MIIBPAIBAAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh 6565kwIzOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEaAQJBAIqm/bz4NA1H++Vx5Ewx 657OcKp3w19QSaZAwlGRtsUxrP7436QjnREM3Bm8ygU11BjkPVmtrKm6AayQfCHqJoT 658zIECIQDW0BoMoL0HOYM/mrTLhaykYAVqgIeJsPjvkEhTFXWBuQIhAM3deFAvWNu4 659nklUQ37XsCT2c9tmNt1LAT+slG2JOTTRAiAuXDtC/m3NYVwyHfFm+zKHRzHkClk2 660HjubeEgjpj32AQIhAJqMGTaZVOwevTXvvHwNeH+vRWsAYU/gbx+OQB+7VOcBAiEA 661oolb6NMg/R3enNPvS1O4UU1H8wpaF77L4yiSWlE0p4w= 662-----END RSA PRIVATE KEY----- 663""" 664 665# certificate with NULL bytes in subjectAltName and common name 666 667nulbyteSubjectAltNamePEM = b"""-----BEGIN CERTIFICATE----- 668MIIE2DCCA8CgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBxTELMAkGA1UEBhMCVVMx 669DzANBgNVBAgMBk9yZWdvbjESMBAGA1UEBwwJQmVhdmVydG9uMSMwIQYDVQQKDBpQ 670eXRob24gU29mdHdhcmUgRm91bmRhdGlvbjEgMB4GA1UECwwXUHl0aG9uIENvcmUg 671RGV2ZWxvcG1lbnQxJDAiBgNVBAMMG251bGwucHl0aG9uLm9yZwBleGFtcGxlLm9y 672ZzEkMCIGCSqGSIb3DQEJARYVcHl0aG9uLWRldkBweXRob24ub3JnMB4XDTEzMDgw 673NzEzMTE1MloXDTEzMDgwNzEzMTI1MlowgcUxCzAJBgNVBAYTAlVTMQ8wDQYDVQQI 674DAZPcmVnb24xEjAQBgNVBAcMCUJlYXZlcnRvbjEjMCEGA1UECgwaUHl0aG9uIFNv 675ZnR3YXJlIEZvdW5kYXRpb24xIDAeBgNVBAsMF1B5dGhvbiBDb3JlIERldmVsb3Bt 676ZW50MSQwIgYDVQQDDBtudWxsLnB5dGhvbi5vcmcAZXhhbXBsZS5vcmcxJDAiBgkq 677hkiG9w0BCQEWFXB5dGhvbi1kZXZAcHl0aG9uLm9yZzCCASIwDQYJKoZIhvcNAQEB 678BQADggEPADCCAQoCggEBALXq7cn7Rn1vO3aA3TrzA5QLp6bb7B3f/yN0CJ2XFj+j 679pHs+Gw6WWSUDpybiiKnPec33BFawq3kyblnBMjBU61ioy5HwQqVkJ8vUVjGIUq3P 680vX/wBmQfzCe4o4uM89gpHyUL9UYGG8oCRa17dgqcv7u5rg0Wq2B1rgY+nHwx3JIv 681KRrgSwyRkGzpN8WQ1yrXlxWjgI9de0mPVDDUlywcWze1q2kwaEPTM3hLAmD1PESA 682oY/n8A/RXoeeRs9i/Pm/DGUS8ZPINXk/yOzsR/XvvkTVroIeLZqfmFpnZeF0cHzL 68308LODkVJJ9zjLdT7SA4vnne4FEbAxDbKAq5qkYzaL4UCAwEAAaOB0DCBzTAMBgNV 684HRMBAf8EAjAAMB0GA1UdDgQWBBSIWlXAUv9hzVKjNQ/qWpwkOCL3XDALBgNVHQ8E 685BAMCBeAwgZAGA1UdEQSBiDCBhYIeYWx0bnVsbC5weXRob24ub3JnAGV4YW1wbGUu 686Y29tgSBudWxsQHB5dGhvbi5vcmcAdXNlckBleGFtcGxlLm9yZ4YpaHR0cDovL251 687bGwucHl0aG9uLm9yZwBodHRwOi8vZXhhbXBsZS5vcmeHBMAAAgGHECABDbgAAAAA 688AAAAAAAAAAEwDQYJKoZIhvcNAQEFBQADggEBAKxPRe99SaghcI6IWT7UNkJw9aO9 689i9eo0Fj2MUqxpKbdb9noRDy2CnHWf7EIYZ1gznXPdwzSN4YCjV5d+Q9xtBaowT0j 690HPERs1ZuytCNNJTmhyqZ8q6uzMLoht4IqH/FBfpvgaeC5tBTnTT0rD5A/olXeimk 691kX4LxlEx5RAvpGB2zZVRGr6LobD9rVK91xuHYNIxxxfEGE8tCCWjp0+3ksri9SXx 692VHWBnbM9YaL32u3hxm8sYB/Yb8WSBavJCWJJqRStVRHM1koZlJmXNx2BX4vPo6iW 693RFEIPQsFZRLrtnCAiEhyT8bC2s/Njlu6ly9gtJZWSV46Q3ZjBL4q9sHKqZQ= 694-----END CERTIFICATE-----""" 695 696large_key_pem = b"""-----BEGIN RSA PRIVATE KEY----- 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 747vYeU7Ab/ 748-----END RSA PRIVATE KEY-----""" 749 750ec_private_key_pem = b"""-----BEGIN PRIVATE KEY----- 751MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgYirTZSx+5O8Y6tlG 752cka6W6btJiocdrdolfcukSoTEk+hRANCAAQkvPNu7Pa1GcsWU4v7ptNfqCJVq8Cx 753zo0MUVPQgwJ3aJtNM1QMOQUayCrRwfklg+D/rFSUwEUqtZh7fJDiFqz3 754-----END PRIVATE KEY----- 755""" 756 757ec_root_key_pem = b"""-----BEGIN EC PRIVATE KEY----- 758MIGlAgEBBDEAz/HOBFPYLB0jLWeTpJn4Yc4m/C4mdWymVHBjOmnwiPHKT326iYN/ 759ZhmSs+RM94RsoAcGBSuBBAAioWQDYgAEwE5vDdla/nLpWAPAQ0yFGqwLuw4BcN2r 760U+sKab5EAEHzLeceRa8ffncYdCXNoVsBcdob1y66CFZMEWLetPTmGapyWkBAs6/L 7618kUlkU9OsE+7IVo4QQJkgV5gM+Dim1XE 762-----END EC PRIVATE KEY----- 763""" 764 765ec_root_cert_pem = b"""-----BEGIN CERTIFICATE----- 766MIICLTCCAbKgAwIBAgIMWW/hwTl6ufz6/WkCMAoGCCqGSM49BAMDMFgxGDAWBgNV 767BAMTD1Rlc3RpbmcgUm9vdCBDQTEQMA4GA1UEChMHVGVzdGluZzEQMA4GA1UEBxMH 768Q2hpY2FnbzELMAkGA1UECBMCSUwxCzAJBgNVBAYTAlVTMCAXDTE3MDcxOTIyNDgz 769M1oYDzk5OTkxMjMxMjM1OTU5WjBYMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0Ex 770EDAOBgNVBAoTB1Rlc3RpbmcxEDAOBgNVBAcTB0NoaWNhZ28xCzAJBgNVBAgTAklM 771MQswCQYDVQQGEwJVUzB2MBAGByqGSM49AgEGBSuBBAAiA2IABMBObw3ZWv5y6VgD 772wENMhRqsC7sOAXDdq1PrCmm+RABB8y3nHkWvH353GHQlzaFbAXHaG9cuughWTBFi 7733rT05hmqclpAQLOvy/JFJZFPTrBPuyFaOEECZIFeYDPg4ptVxKNDMEEwDwYDVR0T 774AQH/BAUwAwEB/zAPBgNVHQ8BAf8EBQMDBwQAMB0GA1UdDgQWBBSoTrF0H2m8RDzB 775MnY2KReEPfz7ZjAKBggqhkjOPQQDAwNpADBmAjEA3+G1oVCxGjYX4iUN93QYcNHe 776e3fJQJwX9+KsHRut6qNZDUbvRbtO1YIAwB4UJZjwAjEAtXCPURS5A4McZHnSwgTi 777Td8GMrwKz0557OxxtKN6uVVy4ACFMqEw0zN/KJI1vxc9 778-----END CERTIFICATE-----""" 779 780rsa_p_not_prime_pem = """ 781-----BEGIN RSA PRIVATE KEY----- 782MBsCAQACAS0CAQcCAQACAQ8CAQMCAQACAQACAQA= 783-----END RSA PRIVATE KEY----- 784""" 785 786 787@pytest.fixture 788def x509_data(): 789 """ 790 Create a new private key and start a certificate request (for a test 791 to finish in one way or another). 792 """ 793 # Basic setup stuff to generate a certificate 794 pkey = PKey() 795 pkey.generate_key(TYPE_RSA, 512) 796 req = X509Req() 797 req.set_pubkey(pkey) 798 # Authority good you have. 799 req.get_subject().commonName = "Yoda root CA" 800 x509 = X509() 801 subject = x509.get_subject() 802 subject.commonName = req.get_subject().commonName 803 x509.set_issuer(subject) 804 x509.set_pubkey(pkey) 805 now = datetime.now() 806 expire = datetime.now() + timedelta(days=100) 807 x509.set_notBefore(now.strftime("%Y%m%d%H%M%SZ").encode()) 808 x509.set_notAfter(expire.strftime("%Y%m%d%H%M%SZ").encode()) 809 yield pkey, x509 810 811 812class TestX509Ext(object): 813 """ 814 Tests for `OpenSSL.crypto.X509Extension`. 815 """ 816 817 def test_str(self): 818 """ 819 The string representation of `X509Extension` instances as 820 returned by `str` includes stuff. 821 """ 822 # This isn't necessarily the best string representation. Perhaps it 823 # will be changed/improved in the future. 824 assert ( 825 str(X509Extension(b"basicConstraints", True, b"CA:false")) 826 == "CA:FALSE" 827 ) 828 829 def test_type(self): 830 """ 831 `X509Extension` can be used to create instances of that type. 832 """ 833 assert is_consistent_type( 834 X509Extension, 835 "X509Extension", 836 b"basicConstraints", 837 True, 838 b"CA:true", 839 ) 840 841 def test_construction(self): 842 """ 843 `X509Extension` accepts an extension type name, a critical flag, 844 and an extension value and returns an `X509Extension` instance. 845 """ 846 basic = X509Extension(b"basicConstraints", True, b"CA:true") 847 assert isinstance(basic, X509Extension) 848 849 comment = X509Extension(b"nsComment", False, b"pyOpenSSL unit test") 850 assert isinstance(comment, X509Extension) 851 852 @pytest.mark.parametrize( 853 "type_name, critical, value", 854 [ 855 (b"thisIsMadeUp", False, b"hi"), 856 (b"basicConstraints", False, b"blah blah"), 857 # Exercise a weird one (an extension which uses the r2i method). 858 # This exercises the codepath that requires a non-NULL ctx to be 859 # passed to X509V3_EXT_nconf. It can't work now because we provide 860 # no configuration database. It might be made to work in the 861 # future. 862 ( 863 b"proxyCertInfo", 864 True, 865 b"language:id-ppl-anyLanguage,pathlen:1,policy:text:AB", 866 ), 867 ], 868 ) 869 def test_invalid_extension(self, type_name, critical, value): 870 """ 871 `X509Extension` raises something if it is passed a bad 872 extension name or value. 873 """ 874 with pytest.raises(Error): 875 X509Extension(type_name, critical, value) 876 877 @pytest.mark.parametrize("critical_flag", [True, False]) 878 def test_get_critical(self, critical_flag): 879 """ 880 `X509ExtensionType.get_critical` returns the value of the 881 extension's critical flag. 882 """ 883 ext = X509Extension(b"basicConstraints", critical_flag, b"CA:true") 884 assert ext.get_critical() == critical_flag 885 886 @pytest.mark.parametrize( 887 "short_name, value", 888 [(b"basicConstraints", b"CA:true"), (b"nsComment", b"foo bar")], 889 ) 890 def test_get_short_name(self, short_name, value): 891 """ 892 `X509ExtensionType.get_short_name` returns a string giving the 893 short type name of the extension. 894 """ 895 ext = X509Extension(short_name, True, value) 896 assert ext.get_short_name() == short_name 897 898 def test_get_data(self): 899 """ 900 `X509Extension.get_data` returns a string giving the data of 901 the extension. 902 """ 903 ext = X509Extension(b"basicConstraints", True, b"CA:true") 904 # Expect to get back the DER encoded form of CA:true. 905 assert ext.get_data() == b"0\x03\x01\x01\xff" 906 907 def test_unused_subject(self, x509_data): 908 """ 909 The `subject` parameter to `X509Extension` may be provided for an 910 extension which does not use it and is ignored in this case. 911 """ 912 pkey, x509 = x509_data 913 ext1 = X509Extension( 914 b"basicConstraints", False, b"CA:TRUE", subject=x509 915 ) 916 x509.add_extensions([ext1]) 917 x509.sign(pkey, "sha1") 918 # This is a little lame. Can we think of a better way? 919 text = dump_certificate(FILETYPE_TEXT, x509) 920 assert b"X509v3 Basic Constraints:" in text 921 assert b"CA:TRUE" in text 922 923 def test_subject(self, x509_data): 924 """ 925 If an extension requires a subject, the `subject` parameter to 926 `X509Extension` provides its value. 927 """ 928 pkey, x509 = x509_data 929 ext3 = X509Extension( 930 b"subjectKeyIdentifier", False, b"hash", subject=x509 931 ) 932 x509.add_extensions([ext3]) 933 x509.sign(pkey, "sha1") 934 text = dump_certificate(FILETYPE_TEXT, x509) 935 assert b"X509v3 Subject Key Identifier:" in text 936 937 def test_missing_subject(self): 938 """ 939 If an extension requires a subject and the `subject` parameter 940 is given no value, something happens. 941 """ 942 with pytest.raises(Error): 943 X509Extension(b"subjectKeyIdentifier", False, b"hash") 944 945 @pytest.mark.parametrize("bad_obj", [True, object(), "hello", []]) 946 def test_invalid_subject(self, bad_obj): 947 """ 948 If the `subject` parameter is given a value which is not an 949 `X509` instance, `TypeError` is raised. 950 """ 951 with pytest.raises(TypeError): 952 X509Extension( 953 "basicConstraints", False, "CA:TRUE", subject=bad_obj 954 ) 955 956 def test_unused_issuer(self, x509_data): 957 """ 958 The `issuer` parameter to `X509Extension` may be provided for an 959 extension which does not use it and is ignored in this case. 960 """ 961 pkey, x509 = x509_data 962 ext1 = X509Extension( 963 b"basicConstraints", False, b"CA:TRUE", issuer=x509 964 ) 965 x509.add_extensions([ext1]) 966 x509.sign(pkey, "sha1") 967 text = dump_certificate(FILETYPE_TEXT, x509) 968 assert b"X509v3 Basic Constraints:" in text 969 assert b"CA:TRUE" in text 970 971 def test_issuer(self, x509_data): 972 """ 973 If an extension requires an issuer, the `issuer` parameter to 974 `X509Extension` provides its value. 975 """ 976 pkey, x509 = x509_data 977 ext2 = X509Extension( 978 b"authorityKeyIdentifier", False, b"issuer:always", issuer=x509 979 ) 980 x509.add_extensions([ext2]) 981 x509.sign(pkey, "sha1") 982 text = dump_certificate(FILETYPE_TEXT, x509) 983 assert b"X509v3 Authority Key Identifier:" in text 984 assert b"DirName:/CN=Yoda root CA" in text 985 986 def test_missing_issuer(self): 987 """ 988 If an extension requires an issue and the `issuer` parameter is 989 given no value, something happens. 990 """ 991 with pytest.raises(Error): 992 X509Extension( 993 b"authorityKeyIdentifier", False, b"keyid:always,issuer:always" 994 ) 995 996 @pytest.mark.parametrize("bad_obj", [True, object(), "hello", []]) 997 def test_invalid_issuer(self, bad_obj): 998 """ 999 If the `issuer` parameter is given a value which is not an 1000 `X509` instance, `TypeError` is raised. 1001 """ 1002 with pytest.raises(TypeError): 1003 X509Extension( 1004 "basicConstraints", 1005 False, 1006 "keyid:always,issuer:always", 1007 issuer=bad_obj, 1008 ) 1009 1010 1011class TestPKey(object): 1012 """ 1013 Tests for `OpenSSL.crypto.PKey`. 1014 """ 1015 1016 def test_convert_from_cryptography_private_key(self): 1017 """ 1018 PKey.from_cryptography_key creates a proper private PKey. 1019 """ 1020 key = serialization.load_pem_private_key( 1021 intermediate_key_pem, None, backend 1022 ) 1023 pkey = PKey.from_cryptography_key(key) 1024 1025 assert isinstance(pkey, PKey) 1026 assert pkey.bits() == key.key_size 1027 assert pkey._only_public is False 1028 assert pkey._initialized is True 1029 1030 def test_convert_from_cryptography_public_key(self): 1031 """ 1032 PKey.from_cryptography_key creates a proper public PKey. 1033 """ 1034 key = serialization.load_pem_public_key(cleartextPublicKeyPEM, backend) 1035 pkey = PKey.from_cryptography_key(key) 1036 1037 assert isinstance(pkey, PKey) 1038 assert pkey.bits() == key.key_size 1039 assert pkey._only_public is True 1040 assert pkey._initialized is True 1041 1042 def test_convert_from_cryptography_unsupported_type(self): 1043 """ 1044 PKey.from_cryptography_key raises TypeError with an unsupported type. 1045 """ 1046 key = serialization.load_pem_private_key( 1047 ec_private_key_pem, None, backend 1048 ) 1049 with pytest.raises(TypeError): 1050 PKey.from_cryptography_key(key) 1051 1052 def test_convert_public_pkey_to_cryptography_key(self): 1053 """ 1054 PKey.to_cryptography_key creates a proper cryptography public key. 1055 """ 1056 pkey = load_publickey(FILETYPE_PEM, cleartextPublicKeyPEM) 1057 key = pkey.to_cryptography_key() 1058 1059 assert isinstance(key, rsa.RSAPublicKey) 1060 assert pkey.bits() == key.key_size 1061 1062 def test_convert_private_pkey_to_cryptography_key(self): 1063 """ 1064 PKey.to_cryptography_key creates a proper cryptography private key. 1065 """ 1066 pkey = load_privatekey(FILETYPE_PEM, root_key_pem) 1067 key = pkey.to_cryptography_key() 1068 1069 assert isinstance(key, rsa.RSAPrivateKey) 1070 assert pkey.bits() == key.key_size 1071 1072 def test_type(self): 1073 """ 1074 `PKey` can be used to create instances of that type. 1075 """ 1076 assert is_consistent_type(PKey, "PKey") 1077 1078 def test_construction(self): 1079 """ 1080 `PKey` takes no arguments and returns a new `PKey` instance. 1081 """ 1082 key = PKey() 1083 assert isinstance(key, PKey) 1084 1085 def test_pregeneration(self): 1086 """ 1087 `PKey.bits` and `PKey.type` return `0` before the key is generated. 1088 `PKey.check` raises `TypeError` before the key is generated. 1089 """ 1090 key = PKey() 1091 assert key.type() == 0 1092 assert key.bits() == 0 1093 with pytest.raises(TypeError): 1094 key.check() 1095 1096 def test_failed_generation(self): 1097 """ 1098 `PKey.generate_key` takes two arguments, the first giving the key type 1099 as one of `TYPE_RSA` or `TYPE_DSA` and the second giving the number of 1100 bits to generate. If an invalid type is specified or generation fails, 1101 `Error` is raised. If an invalid number of bits is specified, 1102 `ValueError` or `Error` is raised. 1103 """ 1104 key = PKey() 1105 with pytest.raises(TypeError): 1106 key.generate_key("foo", "bar") 1107 with pytest.raises(Error): 1108 key.generate_key(-1, 0) 1109 1110 with pytest.raises(ValueError): 1111 key.generate_key(TYPE_RSA, -1) 1112 with pytest.raises(ValueError): 1113 key.generate_key(TYPE_RSA, 0) 1114 1115 with pytest.raises(TypeError): 1116 key.generate_key(TYPE_RSA, object()) 1117 1118 # XXX RSA generation for small values of bits is fairly buggy in a wide 1119 # range of OpenSSL versions. I need to figure out what the safe lower 1120 # bound for a reasonable number of OpenSSL versions is and explicitly 1121 # check for that in the wrapper. The failure behavior is typically an 1122 # infinite loop inside OpenSSL. 1123 1124 # with pytest.raises(Error): 1125 # key.generate_key(TYPE_RSA, 2) 1126 1127 # XXX DSA generation seems happy with any number of bits. The DSS 1128 # says bits must be between 512 and 1024 inclusive. OpenSSL's DSA 1129 # generator doesn't seem to care about the upper limit at all. For 1130 # the lower limit, it uses 512 if anything smaller is specified. 1131 # So, it doesn't seem possible to make generate_key fail for 1132 # TYPE_DSA with a bits argument which is at least an int. 1133 1134 # with pytest.raises(Error): 1135 # key.generate_key(TYPE_DSA, -7) 1136 1137 def test_rsa_generation(self): 1138 """ 1139 `PKey.generate_key` generates an RSA key when passed `TYPE_RSA` as a 1140 type and a reasonable number of bits. 1141 """ 1142 bits = 512 1143 key = PKey() 1144 key.generate_key(TYPE_RSA, bits) 1145 assert key.type() == TYPE_RSA 1146 assert key.bits() == bits 1147 assert key.check() 1148 1149 def test_dsa_generation(self): 1150 """ 1151 `PKey.generate_key` generates a DSA key when passed `TYPE_DSA` as a 1152 type and a reasonable number of bits. 1153 """ 1154 # 512 is a magic number. The DSS (Digital Signature Standard) 1155 # allows a minimum of 512 bits for DSA. DSA_generate_parameters 1156 # will silently promote any value below 512 to 512. 1157 bits = 512 1158 key = PKey() 1159 key.generate_key(TYPE_DSA, bits) 1160 assert key.type() == TYPE_DSA 1161 assert key.bits() == bits 1162 with pytest.raises(TypeError): 1163 key.check() 1164 1165 def test_regeneration(self): 1166 """ 1167 `PKey.generate_key` can be called multiple times on the same key to 1168 generate new keys. 1169 """ 1170 key = PKey() 1171 for type, bits in [(TYPE_RSA, 512), (TYPE_DSA, 576)]: 1172 key.generate_key(type, bits) 1173 assert key.type() == type 1174 assert key.bits() == bits 1175 1176 def test_inconsistent_key(self): 1177 """ 1178 `PKey.check` returns `Error` if the key is not consistent. 1179 """ 1180 key = load_privatekey(FILETYPE_PEM, inconsistentPrivateKeyPEM) 1181 with pytest.raises(Error): 1182 key.check() 1183 1184 def test_check_public_key(self): 1185 """ 1186 `PKey.check` raises `TypeError` if only the public part of the key 1187 is available. 1188 """ 1189 # A trick to get a public-only key 1190 key = PKey() 1191 key.generate_key(TYPE_RSA, 512) 1192 cert = X509() 1193 cert.set_pubkey(key) 1194 pub = cert.get_pubkey() 1195 with pytest.raises(TypeError): 1196 pub.check() 1197 1198 def test_check_pr_897(self): 1199 """ 1200 `PKey.check` raises `OpenSSL.crypto.Error` if provided with broken key 1201 """ 1202 pkey = load_privatekey(FILETYPE_PEM, rsa_p_not_prime_pem) 1203 with pytest.raises(Error): 1204 pkey.check() 1205 1206 1207def x509_name(**attrs): 1208 """ 1209 Return a new X509Name with the given attributes. 1210 """ 1211 # XXX There's no other way to get a new X509Name yet. 1212 name = X509().get_subject() 1213 attrs = list(attrs.items()) 1214 1215 # Make the order stable - order matters! 1216 def key(attr): 1217 return attr[1] 1218 1219 attrs.sort(key=key) 1220 for k, v in attrs: 1221 setattr(name, k, v) 1222 return name 1223 1224 1225class TestX509Name(object): 1226 """ 1227 Unit tests for `OpenSSL.crypto.X509Name`. 1228 """ 1229 1230 def test_type(self): 1231 """ 1232 The type of X509Name objects is `X509Name`. 1233 """ 1234 name = x509_name() 1235 assert isinstance(name, X509Name) 1236 1237 def test_only_string_attributes(self): 1238 """ 1239 Attempting to set a non-`str` attribute name on an `X509Name` instance 1240 causes `TypeError` to be raised. 1241 """ 1242 name = x509_name() 1243 # Beyond these cases, you may also think that unicode should be 1244 # rejected. Sorry, you're wrong. unicode is automatically converted 1245 # to str outside of the control of X509Name, so there's no way to 1246 # reject it. 1247 1248 # Also, this used to test str subclasses, but that test is less 1249 # relevant now that the implementation is in Python instead of C. Also 1250 # PyPy automatically converts str subclasses to str when they are 1251 # passed to setattr, so we can't test it on PyPy. Apparently CPython 1252 # does this sometimes as well. 1253 with pytest.raises(TypeError): 1254 setattr(name, None, "hello") 1255 with pytest.raises(TypeError): 1256 setattr(name, 30, "hello") 1257 1258 def test_set_invalid_attribute(self): 1259 """ 1260 Attempting to set any attribute name on an `X509Name` instance for 1261 which no corresponding NID is defined causes `AttributeError` to be 1262 raised. 1263 """ 1264 name = x509_name() 1265 with pytest.raises(AttributeError): 1266 setattr(name, "no such thing", None) 1267 1268 def test_attributes(self): 1269 """ 1270 `X509Name` instances have attributes for each standard (?) 1271 X509Name field. 1272 """ 1273 name = x509_name() 1274 name.commonName = "foo" 1275 assert name.commonName == "foo" 1276 assert name.CN == "foo" 1277 1278 name.CN = "baz" 1279 assert name.commonName == "baz" 1280 assert name.CN == "baz" 1281 1282 name.commonName = "bar" 1283 assert name.commonName == "bar" 1284 assert name.CN == "bar" 1285 1286 name.CN = "quux" 1287 assert name.commonName == "quux" 1288 assert name.CN == "quux" 1289 1290 assert name.OU is None 1291 1292 with pytest.raises(AttributeError): 1293 name.foobar 1294 1295 def test_copy(self): 1296 """ 1297 `X509Name` creates a new `X509Name` instance with all the same 1298 attributes as an existing `X509Name` instance when called with one. 1299 """ 1300 name = x509_name(commonName="foo", emailAddress="bar@example.com") 1301 1302 copy = X509Name(name) 1303 assert copy.commonName == "foo" 1304 assert copy.emailAddress == "bar@example.com" 1305 1306 # Mutate the copy and ensure the original is unmodified. 1307 copy.commonName = "baz" 1308 assert name.commonName == "foo" 1309 1310 # Mutate the original and ensure the copy is unmodified. 1311 name.emailAddress = "quux@example.com" 1312 assert copy.emailAddress == "bar@example.com" 1313 1314 def test_repr(self): 1315 """ 1316 `repr` passed an `X509Name` instance should return a string containing 1317 a description of the type and the NIDs which have been set on it. 1318 """ 1319 name = x509_name(commonName="foo", emailAddress="bar") 1320 assert repr(name) == "<X509Name object '/emailAddress=bar/CN=foo'>" 1321 1322 def test_comparison(self): 1323 """ 1324 `X509Name` instances should compare based on their NIDs. 1325 """ 1326 1327 def _equality(a, b, assert_true, assert_false): 1328 assert_true(a == b) 1329 assert_false(a != b) 1330 assert_true(b == a) 1331 assert_false(b != a) 1332 1333 def assert_true(x): 1334 assert x 1335 1336 def assert_false(x): 1337 assert not x 1338 1339 def assert_equal(a, b): 1340 _equality(a, b, assert_true, assert_false) 1341 1342 # Instances compare equal to themselves. 1343 name = x509_name() 1344 assert_equal(name, name) 1345 1346 # Empty instances should compare equal to each other. 1347 assert_equal(x509_name(), x509_name()) 1348 1349 # Instances with equal NIDs should compare equal to each other. 1350 assert_equal(x509_name(commonName="foo"), x509_name(commonName="foo")) 1351 1352 # Instance with equal NIDs set using different aliases should compare 1353 # equal to each other. 1354 assert_equal(x509_name(commonName="foo"), x509_name(CN="foo")) 1355 1356 # Instances with more than one NID with the same values should compare 1357 # equal to each other. 1358 assert_equal( 1359 x509_name(CN="foo", organizationalUnitName="bar"), 1360 x509_name(commonName="foo", OU="bar"), 1361 ) 1362 1363 def assert_not_equal(a, b): 1364 _equality(a, b, assert_false, assert_true) 1365 1366 # Instances with different values for the same NID should not compare 1367 # equal to each other. 1368 assert_not_equal(x509_name(CN="foo"), x509_name(CN="bar")) 1369 1370 # Instances with different NIDs should not compare equal to each other. 1371 assert_not_equal(x509_name(CN="foo"), x509_name(OU="foo")) 1372 1373 assert_not_equal(x509_name(), object()) 1374 1375 def _inequality(a, b, assert_true, assert_false): 1376 assert_true(a < b) 1377 assert_true(a <= b) 1378 assert_true(b > a) 1379 assert_true(b >= a) 1380 assert_false(a > b) 1381 assert_false(a >= b) 1382 assert_false(b < a) 1383 assert_false(b <= a) 1384 1385 def assert_less_than(a, b): 1386 _inequality(a, b, assert_true, assert_false) 1387 1388 # An X509Name with a NID with a value which sorts less than the value 1389 # of the same NID on another X509Name compares less than the other 1390 # X509Name. 1391 assert_less_than(x509_name(CN="abc"), x509_name(CN="def")) 1392 1393 def assert_greater_than(a, b): 1394 _inequality(a, b, assert_false, assert_true) 1395 1396 # An X509Name with a NID with a value which sorts greater than the 1397 # value of the same NID on another X509Name compares greater than the 1398 # other X509Name. 1399 assert_greater_than(x509_name(CN="def"), x509_name(CN="abc")) 1400 1401 def test_hash(self): 1402 """ 1403 `X509Name.hash` returns an integer hash based on the value of the name. 1404 """ 1405 a = x509_name(CN="foo") 1406 b = x509_name(CN="foo") 1407 assert a.hash() == b.hash() 1408 a.CN = "bar" 1409 assert a.hash() != b.hash() 1410 1411 def test_der(self): 1412 """ 1413 `X509Name.der` returns the DER encoded form of the name. 1414 """ 1415 a = x509_name(CN="foo", C="US") 1416 assert ( 1417 a.der() == b"0\x1b1\x0b0\t\x06\x03U\x04\x06\x13\x02US" 1418 b"1\x0c0\n\x06\x03U\x04\x03\x0c\x03foo" 1419 ) 1420 1421 def test_get_components(self): 1422 """ 1423 `X509Name.get_components` returns a `list` of two-tuples of `str` 1424 giving the NIDs and associated values which make up the name. 1425 """ 1426 a = x509_name() 1427 assert a.get_components() == [] 1428 a.CN = "foo" 1429 assert a.get_components() == [(b"CN", b"foo")] 1430 a.organizationalUnitName = "bar" 1431 assert a.get_components() == [(b"CN", b"foo"), (b"OU", b"bar")] 1432 1433 def test_load_nul_byte_attribute(self): 1434 """ 1435 An `X509Name` from an `X509` instance loaded from a file can have a 1436 NUL byte in the value of one of its attributes. 1437 """ 1438 cert = load_certificate(FILETYPE_PEM, nulbyteSubjectAltNamePEM) 1439 subject = cert.get_subject() 1440 assert "null.python.org\x00example.org" == subject.commonName 1441 1442 def test_load_nul_byte_components(self): 1443 """ 1444 An `X509Name` from an `X509` instance loaded from a file can have a 1445 NUL byte in the value of its components 1446 """ 1447 cert = load_certificate(FILETYPE_PEM, nulbyteSubjectAltNamePEM) 1448 subject = cert.get_subject() 1449 components = subject.get_components() 1450 ccn = [value for name, value in components if name == b"CN"] 1451 assert ccn[0] == b"null.python.org\x00example.org" 1452 1453 def test_set_attribute_failure(self): 1454 """ 1455 If the value of an attribute cannot be set for some reason then 1456 `Error` is raised. 1457 """ 1458 name = x509_name() 1459 # This value is too long 1460 with pytest.raises(Error): 1461 setattr(name, "O", b"x" * 512) 1462 1463 1464class _PKeyInteractionTestsMixin: 1465 """ 1466 Tests which involve another thing and a PKey. 1467 """ 1468 1469 def signable(self): 1470 """ 1471 Return something with a `set_pubkey`, `set_pubkey`, and `sign` method. 1472 """ 1473 raise NotImplementedError() 1474 1475 def test_sign_with_ungenerated(self): 1476 """ 1477 `X509Req.sign` raises `ValueError` when passed a `PKey` with no parts. 1478 """ 1479 request = self.signable() 1480 key = PKey() 1481 with pytest.raises(ValueError): 1482 request.sign(key, GOOD_DIGEST) 1483 1484 def test_sign_with_public_key(self): 1485 """ 1486 `X509Req.sign` raises `ValueError` when passed a `PKey` with no private 1487 part as the signing key. 1488 """ 1489 request = self.signable() 1490 key = PKey() 1491 key.generate_key(TYPE_RSA, 512) 1492 request.set_pubkey(key) 1493 pub = request.get_pubkey() 1494 with pytest.raises(ValueError): 1495 request.sign(pub, GOOD_DIGEST) 1496 1497 def test_sign_with_unknown_digest(self): 1498 """ 1499 `X509Req.sign` raises `ValueError` when passed a digest name which is 1500 not known. 1501 """ 1502 request = self.signable() 1503 key = PKey() 1504 key.generate_key(TYPE_RSA, 512) 1505 with pytest.raises(ValueError): 1506 request.sign(key, BAD_DIGEST) 1507 1508 def test_sign(self): 1509 """ 1510 `X509Req.sign` succeeds when passed a private key object and a 1511 valid digest function. `X509Req.verify` can be used to check 1512 the signature. 1513 """ 1514 request = self.signable() 1515 key = PKey() 1516 key.generate_key(TYPE_RSA, 512) 1517 request.set_pubkey(key) 1518 request.sign(key, GOOD_DIGEST) 1519 # If the type has a verify method, cover that too. 1520 if getattr(request, "verify", None) is not None: 1521 pub = request.get_pubkey() 1522 assert request.verify(pub) 1523 # Make another key that won't verify. 1524 key = PKey() 1525 key.generate_key(TYPE_RSA, 512) 1526 with pytest.raises(Error): 1527 request.verify(key) 1528 1529 1530class TestX509Req(_PKeyInteractionTestsMixin): 1531 """ 1532 Tests for `OpenSSL.crypto.X509Req`. 1533 """ 1534 1535 def signable(self): 1536 """ 1537 Create and return a new `X509Req`. 1538 """ 1539 return X509Req() 1540 1541 def test_type(self): 1542 """ 1543 `X509Req` can be used to create instances of that type. 1544 """ 1545 assert is_consistent_type(X509Req, "X509Req") 1546 1547 def test_construction(self): 1548 """ 1549 `X509Req` takes no arguments and returns an `X509Req` instance. 1550 """ 1551 request = X509Req() 1552 assert isinstance(request, X509Req) 1553 1554 def test_version(self): 1555 """ 1556 `X509Req.set_version` sets the X.509 version of the certificate 1557 request. `X509Req.get_version` returns the X.509 version of the 1558 certificate request. The initial value of the version is 0. 1559 """ 1560 request = X509Req() 1561 assert request.get_version() == 0 1562 request.set_version(1) 1563 assert request.get_version() == 1 1564 request.set_version(3) 1565 assert request.get_version() == 3 1566 1567 def test_version_wrong_args(self): 1568 """ 1569 `X509Req.set_version` raises `TypeError` if called with a non-`int` 1570 argument. 1571 """ 1572 request = X509Req() 1573 with pytest.raises(TypeError): 1574 request.set_version("foo") 1575 1576 def test_get_subject(self): 1577 """ 1578 `X509Req.get_subject` returns an `X509Name` for the subject of the 1579 request and which is valid even after the request object is 1580 otherwise dead. 1581 """ 1582 request = X509Req() 1583 subject = request.get_subject() 1584 assert isinstance(subject, X509Name) 1585 subject.commonName = "foo" 1586 assert request.get_subject().commonName == "foo" 1587 del request 1588 subject.commonName = "bar" 1589 assert subject.commonName == "bar" 1590 1591 def test_add_extensions(self): 1592 """ 1593 `X509Req.add_extensions` accepts a `list` of `X509Extension` instances 1594 and adds them to the X509 request. 1595 """ 1596 request = X509Req() 1597 request.add_extensions( 1598 [X509Extension(b"basicConstraints", True, b"CA:false")] 1599 ) 1600 exts = request.get_extensions() 1601 assert len(exts) == 1 1602 assert exts[0].get_short_name() == b"basicConstraints" 1603 assert exts[0].get_critical() == 1 1604 assert exts[0].get_data() == b"0\x00" 1605 1606 def test_get_extensions(self): 1607 """ 1608 `X509Req.get_extensions` returns a `list` of extensions added to this 1609 X509 request. 1610 """ 1611 request = X509Req() 1612 exts = request.get_extensions() 1613 assert exts == [] 1614 request.add_extensions( 1615 [ 1616 X509Extension(b"basicConstraints", True, b"CA:true"), 1617 X509Extension(b"keyUsage", False, b"digitalSignature"), 1618 ] 1619 ) 1620 exts = request.get_extensions() 1621 assert len(exts) == 2 1622 assert exts[0].get_short_name() == b"basicConstraints" 1623 assert exts[0].get_critical() == 1 1624 assert exts[0].get_data() == b"0\x03\x01\x01\xff" 1625 assert exts[1].get_short_name() == b"keyUsage" 1626 assert exts[1].get_critical() == 0 1627 assert exts[1].get_data() == b"\x03\x02\x07\x80" 1628 # Requesting it a second time should return the same list 1629 exts = request.get_extensions() 1630 assert len(exts) == 2 1631 1632 def test_add_extensions_wrong_args(self): 1633 """ 1634 `X509Req.add_extensions` raises `TypeError` if called with a 1635 non-`list`. Or it raises `ValueError` if called with a `list` 1636 containing objects other than `X509Extension` instances. 1637 """ 1638 request = X509Req() 1639 with pytest.raises(TypeError): 1640 request.add_extensions(object()) 1641 with pytest.raises(ValueError): 1642 request.add_extensions([object()]) 1643 1644 def test_verify_wrong_args(self): 1645 """ 1646 `X509Req.verify` raises `TypeError` if passed anything other than a 1647 `PKey` instance as its single argument. 1648 """ 1649 request = X509Req() 1650 with pytest.raises(TypeError): 1651 request.verify(object()) 1652 1653 def test_verify_uninitialized_key(self): 1654 """ 1655 `X509Req.verify` raises `OpenSSL.crypto.Error` if called with a 1656 `OpenSSL.crypto.PKey` which contains no key data. 1657 """ 1658 request = X509Req() 1659 pkey = PKey() 1660 with pytest.raises(Error): 1661 request.verify(pkey) 1662 1663 def test_verify_wrong_key(self): 1664 """ 1665 `X509Req.verify` raises `OpenSSL.crypto.Error` if called with a 1666 `OpenSSL.crypto.PKey` which does not represent the public part of the 1667 key which signed the request. 1668 """ 1669 request = X509Req() 1670 pkey = load_privatekey(FILETYPE_PEM, root_key_pem) 1671 request.sign(pkey, GOOD_DIGEST) 1672 another_pkey = load_privatekey(FILETYPE_PEM, client_key_pem) 1673 with pytest.raises(Error): 1674 request.verify(another_pkey) 1675 1676 def test_verify_success(self): 1677 """ 1678 `X509Req.verify` returns `True` if called with a `OpenSSL.crypto.PKey` 1679 which represents the public part of the key which signed the request. 1680 """ 1681 request = X509Req() 1682 pkey = load_privatekey(FILETYPE_PEM, root_key_pem) 1683 request.sign(pkey, GOOD_DIGEST) 1684 assert request.verify(pkey) 1685 1686 def test_convert_from_cryptography(self): 1687 crypto_req = x509.load_pem_x509_csr( 1688 cleartextCertificateRequestPEM, backend 1689 ) 1690 req = X509Req.from_cryptography(crypto_req) 1691 assert isinstance(req, X509Req) 1692 1693 def test_convert_from_cryptography_unsupported_type(self): 1694 with pytest.raises(TypeError): 1695 X509Req.from_cryptography(object()) 1696 1697 def test_convert_to_cryptography_key(self): 1698 req = load_certificate_request( 1699 FILETYPE_PEM, cleartextCertificateRequestPEM 1700 ) 1701 crypto_req = req.to_cryptography() 1702 assert isinstance(crypto_req, x509.CertificateSigningRequest) 1703 1704 1705class TestX509(_PKeyInteractionTestsMixin): 1706 """ 1707 Tests for `OpenSSL.crypto.X509`. 1708 """ 1709 1710 pemData = root_cert_pem + root_key_pem 1711 1712 def signable(self): 1713 """ 1714 Create and return a new `X509`. 1715 """ 1716 return X509() 1717 1718 def test_type(self): 1719 """ 1720 `X509` can be used to create instances of that type. 1721 """ 1722 assert is_consistent_type(X509, "X509") 1723 1724 def test_construction(self): 1725 """ 1726 `X509` takes no arguments and returns an instance of `X509`. 1727 """ 1728 certificate = X509() 1729 assert isinstance(certificate, X509) 1730 assert type(certificate).__name__ == "X509" 1731 assert type(certificate) == X509 1732 1733 def test_set_version_wrong_args(self): 1734 """ 1735 `X509.set_version` raises `TypeError` if invoked with an argument 1736 not of type `int`. 1737 """ 1738 cert = X509() 1739 with pytest.raises(TypeError): 1740 cert.set_version(None) 1741 1742 def test_version(self): 1743 """ 1744 `X509.set_version` sets the certificate version number. 1745 `X509.get_version` retrieves it. 1746 """ 1747 cert = X509() 1748 cert.set_version(1234) 1749 assert cert.get_version() == 1234 1750 1751 def test_serial_number(self): 1752 """ 1753 The serial number of an `X509` can be retrieved and 1754 modified with `X509.get_serial_number` and 1755 `X509.set_serial_number`. 1756 """ 1757 certificate = X509() 1758 with pytest.raises(TypeError): 1759 certificate.set_serial_number("1") 1760 assert certificate.get_serial_number() == 0 1761 certificate.set_serial_number(1) 1762 assert certificate.get_serial_number() == 1 1763 certificate.set_serial_number(2 ** 32 + 1) 1764 assert certificate.get_serial_number() == 2 ** 32 + 1 1765 certificate.set_serial_number(2 ** 64 + 1) 1766 assert certificate.get_serial_number() == 2 ** 64 + 1 1767 certificate.set_serial_number(2 ** 128 + 1) 1768 assert certificate.get_serial_number() == 2 ** 128 + 1 1769 1770 def _setBoundTest(self, which): 1771 """ 1772 `X509.set_notBefore` takes a string in the format of an 1773 ASN1 GENERALIZEDTIME and sets the beginning of the certificate's 1774 validity period to it. 1775 """ 1776 certificate = X509() 1777 set = getattr(certificate, "set_not" + which) 1778 get = getattr(certificate, "get_not" + which) 1779 1780 # Starts with no value. 1781 assert get() is None 1782 1783 # GMT (Or is it UTC?) -exarkun 1784 when = b"20040203040506Z" 1785 set(when) 1786 assert get() == when 1787 1788 # A plus two hours and thirty minutes offset 1789 when = b"20040203040506+0530" 1790 set(when) 1791 assert get() == when 1792 1793 # A minus one hour fifteen minutes offset 1794 when = b"20040203040506-0115" 1795 set(when) 1796 assert get() == when 1797 1798 # An invalid string results in a ValueError 1799 with pytest.raises(ValueError): 1800 set(b"foo bar") 1801 1802 # The wrong number of arguments results in a TypeError. 1803 with pytest.raises(TypeError): 1804 set() 1805 with pytest.raises(TypeError): 1806 set(b"20040203040506Z", b"20040203040506Z") 1807 with pytest.raises(TypeError): 1808 get(b"foo bar") 1809 1810 # XXX ASN1_TIME (not GENERALIZEDTIME) 1811 1812 def test_set_notBefore(self): 1813 """ 1814 `X509.set_notBefore` takes a string in the format of an 1815 ASN1 GENERALIZEDTIME and sets the beginning of the certificate's 1816 validity period to it. 1817 """ 1818 self._setBoundTest("Before") 1819 1820 def test_set_notAfter(self): 1821 """ 1822 `X509.set_notAfter` takes a string in the format of an ASN1 1823 GENERALIZEDTIME and sets the end of the certificate's validity period 1824 to it. 1825 """ 1826 self._setBoundTest("After") 1827 1828 def test_get_notBefore(self): 1829 """ 1830 `X509.get_notBefore` returns a string in the format of an 1831 ASN1 GENERALIZEDTIME even for certificates which store it as UTCTIME 1832 internally. 1833 """ 1834 cert = load_certificate(FILETYPE_PEM, old_root_cert_pem) 1835 assert cert.get_notBefore() == b"20090325123658Z" 1836 1837 def test_get_notAfter(self): 1838 """ 1839 `X509.get_notAfter` returns a string in the format of an 1840 ASN1 GENERALIZEDTIME even for certificates which store it as UTCTIME 1841 internally. 1842 """ 1843 cert = load_certificate(FILETYPE_PEM, old_root_cert_pem) 1844 assert cert.get_notAfter() == b"20170611123658Z" 1845 1846 def test_gmtime_adj_notBefore_wrong_args(self): 1847 """ 1848 `X509.gmtime_adj_notBefore` raises `TypeError` if called with a 1849 non-`int` argument. 1850 """ 1851 cert = X509() 1852 with pytest.raises(TypeError): 1853 cert.gmtime_adj_notBefore(None) 1854 1855 @flaky.flaky 1856 def test_gmtime_adj_notBefore(self): 1857 """ 1858 `X509.gmtime_adj_notBefore` changes the not-before timestamp to be the 1859 current time plus the number of seconds passed in. 1860 """ 1861 cert = load_certificate(FILETYPE_PEM, self.pemData) 1862 not_before_min = datetime.utcnow().replace(microsecond=0) + timedelta( 1863 seconds=100 1864 ) 1865 cert.gmtime_adj_notBefore(100) 1866 not_before = datetime.strptime( 1867 cert.get_notBefore().decode(), "%Y%m%d%H%M%SZ" 1868 ) 1869 not_before_max = datetime.utcnow() + timedelta(seconds=100) 1870 assert not_before_min <= not_before <= not_before_max 1871 1872 def test_gmtime_adj_notAfter_wrong_args(self): 1873 """ 1874 `X509.gmtime_adj_notAfter` raises `TypeError` if called with a 1875 non-`int` argument. 1876 """ 1877 cert = X509() 1878 with pytest.raises(TypeError): 1879 cert.gmtime_adj_notAfter(None) 1880 1881 @flaky.flaky 1882 def test_gmtime_adj_notAfter(self): 1883 """ 1884 `X509.gmtime_adj_notAfter` changes the not-after timestamp 1885 to be the current time plus the number of seconds passed in. 1886 """ 1887 cert = load_certificate(FILETYPE_PEM, self.pemData) 1888 not_after_min = datetime.utcnow().replace(microsecond=0) + timedelta( 1889 seconds=100 1890 ) 1891 cert.gmtime_adj_notAfter(100) 1892 not_after = datetime.strptime( 1893 cert.get_notAfter().decode(), "%Y%m%d%H%M%SZ" 1894 ) 1895 not_after_max = datetime.utcnow() + timedelta(seconds=100) 1896 assert not_after_min <= not_after <= not_after_max 1897 1898 def test_has_expired(self): 1899 """ 1900 `X509.has_expired` returns `True` if the certificate's not-after time 1901 is in the past. 1902 """ 1903 cert = X509() 1904 cert.gmtime_adj_notAfter(-1) 1905 assert cert.has_expired() 1906 1907 def test_has_not_expired(self): 1908 """ 1909 `X509.has_expired` returns `False` if the certificate's not-after time 1910 is in the future. 1911 """ 1912 cert = X509() 1913 cert.gmtime_adj_notAfter(2) 1914 assert not cert.has_expired() 1915 1916 def test_root_has_not_expired(self): 1917 """ 1918 `X509.has_expired` returns `False` if the certificate's not-after time 1919 is in the future. 1920 """ 1921 cert = load_certificate(FILETYPE_PEM, root_cert_pem) 1922 assert not cert.has_expired() 1923 1924 def test_digest(self): 1925 """ 1926 `X509.digest` returns a string giving ":"-separated hex-encoded 1927 words of the digest of the certificate. 1928 """ 1929 cert = load_certificate(FILETYPE_PEM, old_root_cert_pem) 1930 assert ( 1931 # This is MD5 instead of GOOD_DIGEST because the digest algorithm 1932 # actually matters to the assertion (ie, another arbitrary, good 1933 # digest will not product the same digest). 1934 # Digest verified with the command: 1935 # openssl x509 -in root_cert.pem -noout -fingerprint -md5 1936 cert.digest("MD5") 1937 == b"19:B3:05:26:2B:F8:F2:FF:0B:8F:21:07:A8:28:B8:75" 1938 ) 1939 1940 def _extcert(self, pkey, extensions): 1941 cert = X509() 1942 # Certificates with extensions must be X.509v3, which is encoded with a 1943 # version of two. 1944 cert.set_version(2) 1945 cert.set_pubkey(pkey) 1946 cert.get_subject().commonName = "Unit Tests" 1947 cert.get_issuer().commonName = "Unit Tests" 1948 when = datetime.now().strftime("%Y%m%d%H%M%SZ").encode("ascii") 1949 cert.set_notBefore(when) 1950 cert.set_notAfter(when) 1951 1952 cert.add_extensions(extensions) 1953 cert.sign(pkey, "sha1") 1954 return load_certificate( 1955 FILETYPE_PEM, dump_certificate(FILETYPE_PEM, cert) 1956 ) 1957 1958 def test_extension_count(self): 1959 """ 1960 `X509.get_extension_count` returns the number of extensions 1961 that are present in the certificate. 1962 """ 1963 pkey = load_privatekey(FILETYPE_PEM, client_key_pem) 1964 ca = X509Extension(b"basicConstraints", True, b"CA:FALSE") 1965 key = X509Extension(b"keyUsage", True, b"digitalSignature") 1966 subjectAltName = X509Extension( 1967 b"subjectAltName", True, b"DNS:example.com" 1968 ) 1969 1970 # Try a certificate with no extensions at all. 1971 c = self._extcert(pkey, []) 1972 assert c.get_extension_count() == 0 1973 1974 # And a certificate with one 1975 c = self._extcert(pkey, [ca]) 1976 assert c.get_extension_count() == 1 1977 1978 # And a certificate with several 1979 c = self._extcert(pkey, [ca, key, subjectAltName]) 1980 assert c.get_extension_count() == 3 1981 1982 def test_get_extension(self): 1983 """ 1984 `X509.get_extension` takes an integer and returns an 1985 `X509Extension` corresponding to the extension at that index. 1986 """ 1987 pkey = load_privatekey(FILETYPE_PEM, client_key_pem) 1988 ca = X509Extension(b"basicConstraints", True, b"CA:FALSE") 1989 key = X509Extension(b"keyUsage", True, b"digitalSignature") 1990 subjectAltName = X509Extension( 1991 b"subjectAltName", False, b"DNS:example.com" 1992 ) 1993 1994 cert = self._extcert(pkey, [ca, key, subjectAltName]) 1995 1996 ext = cert.get_extension(0) 1997 assert isinstance(ext, X509Extension) 1998 assert ext.get_critical() 1999 assert ext.get_short_name() == b"basicConstraints" 2000 2001 ext = cert.get_extension(1) 2002 assert isinstance(ext, X509Extension) 2003 assert ext.get_critical() 2004 assert ext.get_short_name() == b"keyUsage" 2005 2006 ext = cert.get_extension(2) 2007 assert isinstance(ext, X509Extension) 2008 assert not ext.get_critical() 2009 assert ext.get_short_name() == b"subjectAltName" 2010 2011 with pytest.raises(IndexError): 2012 cert.get_extension(-1) 2013 with pytest.raises(IndexError): 2014 cert.get_extension(4) 2015 with pytest.raises(TypeError): 2016 cert.get_extension("hello") 2017 2018 def test_nullbyte_subjectAltName(self): 2019 """ 2020 The fields of a `subjectAltName` extension on an X509 may contain NUL 2021 bytes and this value is reflected in the string representation of the 2022 extension object. 2023 """ 2024 cert = load_certificate(FILETYPE_PEM, nulbyteSubjectAltNamePEM) 2025 2026 ext = cert.get_extension(3) 2027 assert ext.get_short_name() == b"subjectAltName" 2028 assert ( 2029 b"DNS:altnull.python.org\x00example.com, " 2030 b"email:null@python.org\x00user@example.org, " 2031 b"URI:http://null.python.org\x00http://example.org, " 2032 b"IP Address:192.0.2.1, IP Address:2001:DB8:0:0:0:0:0:1\n" 2033 == str(ext).encode("ascii") 2034 ) 2035 2036 def test_invalid_digest_algorithm(self): 2037 """ 2038 `X509.digest` raises `ValueError` if called with an unrecognized hash 2039 algorithm. 2040 """ 2041 cert = X509() 2042 with pytest.raises(ValueError): 2043 cert.digest(BAD_DIGEST) 2044 2045 def test_get_subject(self): 2046 """ 2047 `X509.get_subject` returns an `X509Name` instance. 2048 """ 2049 cert = load_certificate(FILETYPE_PEM, self.pemData) 2050 subj = cert.get_subject() 2051 assert isinstance(subj, X509Name) 2052 assert subj.get_components() == [ 2053 (b"C", b"US"), 2054 (b"ST", b"IL"), 2055 (b"L", b"Chicago"), 2056 (b"O", b"Testing"), 2057 (b"CN", b"Testing Root CA"), 2058 ] 2059 2060 def test_set_subject_wrong_args(self): 2061 """ 2062 `X509.set_subject` raises a `TypeError` if called with an argument not 2063 of type `X509Name`. 2064 """ 2065 cert = X509() 2066 with pytest.raises(TypeError): 2067 cert.set_subject(None) 2068 2069 def test_set_subject(self): 2070 """ 2071 `X509.set_subject` changes the subject of the certificate to the one 2072 passed in. 2073 """ 2074 cert = X509() 2075 name = cert.get_subject() 2076 name.C = "AU" 2077 name.OU = "Unit Tests" 2078 cert.set_subject(name) 2079 assert cert.get_subject().get_components() == [ 2080 (b"C", b"AU"), 2081 (b"OU", b"Unit Tests"), 2082 ] 2083 2084 def test_get_issuer(self): 2085 """ 2086 `X509.get_issuer` returns an `X509Name` instance. 2087 """ 2088 cert = load_certificate(FILETYPE_PEM, self.pemData) 2089 subj = cert.get_issuer() 2090 assert isinstance(subj, X509Name) 2091 comp = subj.get_components() 2092 assert comp == [ 2093 (b"C", b"US"), 2094 (b"ST", b"IL"), 2095 (b"L", b"Chicago"), 2096 (b"O", b"Testing"), 2097 (b"CN", b"Testing Root CA"), 2098 ] 2099 2100 def test_set_issuer_wrong_args(self): 2101 """ 2102 `X509.set_issuer` raises a `TypeError` if called with an argument not 2103 of type `X509Name`. 2104 """ 2105 cert = X509() 2106 with pytest.raises(TypeError): 2107 cert.set_issuer(None) 2108 2109 def test_set_issuer(self): 2110 """ 2111 `X509.set_issuer` changes the issuer of the certificate to the 2112 one passed in. 2113 """ 2114 cert = X509() 2115 name = cert.get_issuer() 2116 name.C = "AU" 2117 name.OU = "Unit Tests" 2118 cert.set_issuer(name) 2119 assert cert.get_issuer().get_components() == [ 2120 (b"C", b"AU"), 2121 (b"OU", b"Unit Tests"), 2122 ] 2123 2124 def test_get_pubkey_uninitialized(self): 2125 """ 2126 When called on a certificate with no public key, `X509.get_pubkey` 2127 raises `OpenSSL.crypto.Error`. 2128 """ 2129 cert = X509() 2130 with pytest.raises(Error): 2131 cert.get_pubkey() 2132 2133 def test_set_pubkey_wrong_type(self): 2134 """ 2135 `X509.set_pubkey` raises `TypeError` when given an object of the 2136 wrong type. 2137 """ 2138 cert = X509() 2139 with pytest.raises(TypeError): 2140 cert.set_pubkey(object()) 2141 2142 def test_subject_name_hash(self): 2143 """ 2144 `X509.subject_name_hash` returns the hash of the certificate's 2145 subject name. 2146 """ 2147 cert = load_certificate(FILETYPE_PEM, self.pemData) 2148 # SHA1 2149 assert cert.subject_name_hash() == 3278919224 2150 2151 def test_get_signature_algorithm(self): 2152 """ 2153 `X509.get_signature_algorithm` returns a string which means 2154 the algorithm used to sign the certificate. 2155 """ 2156 cert = load_certificate(FILETYPE_PEM, self.pemData) 2157 assert b"sha256WithRSAEncryption" == cert.get_signature_algorithm() 2158 2159 def test_get_undefined_signature_algorithm(self): 2160 """ 2161 `X509.get_signature_algorithm` raises `ValueError` if the signature 2162 algorithm is undefined or unknown. 2163 """ 2164 # This certificate has been modified to indicate a bogus OID in the 2165 # signature algorithm field so that OpenSSL does not recognize it. 2166 certPEM = b"""\ 2167-----BEGIN CERTIFICATE----- 2168MIIC/zCCAmigAwIBAgIBATAGBgJ8BQUAMHsxCzAJBgNVBAYTAlNHMREwDwYDVQQK 2169EwhNMkNyeXB0bzEUMBIGA1UECxMLTTJDcnlwdG8gQ0ExJDAiBgNVBAMTG00yQ3J5 2170cHRvIENlcnRpZmljYXRlIE1hc3RlcjEdMBsGCSqGSIb3DQEJARYObmdwc0Bwb3N0 2171MS5jb20wHhcNMDAwOTEwMDk1MTMwWhcNMDIwOTEwMDk1MTMwWjBTMQswCQYDVQQG 2172EwJTRzERMA8GA1UEChMITTJDcnlwdG8xEjAQBgNVBAMTCWxvY2FsaG9zdDEdMBsG 2173CSqGSIb3DQEJARYObmdwc0Bwb3N0MS5jb20wXDANBgkqhkiG9w0BAQEFAANLADBI 2174AkEArL57d26W9fNXvOhNlZzlPOACmvwOZ5AdNgLzJ1/MfsQQJ7hHVeHmTAjM664V 2175+fXvwUGJLziCeBo1ysWLRnl8CQIDAQABo4IBBDCCAQAwCQYDVR0TBAIwADAsBglg 2176hkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0O 2177BBYEFM+EgpK+eyZiwFU1aOPSbczbPSpVMIGlBgNVHSMEgZ0wgZqAFPuHI2nrnDqT 2178FeXFvylRT/7tKDgBoX+kfTB7MQswCQYDVQQGEwJTRzERMA8GA1UEChMITTJDcnlw 2179dG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtNMkNyeXB0byBDZXJ0 2180aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tggEA 2181MA0GCSqGSIb3DQEBBAUAA4GBADv8KpPo+gfJxN2ERK1Y1l17sz/ZhzoGgm5XCdbx 2182jEY7xKfpQngV599k1xhl11IMqizDwu0855agrckg2MCTmOI9DZzDD77tAYb+Dk0O 2183PEVk0Mk/V0aIsDE9bolfCi/i/QWZ3N8s5nTWMNyBBBmoSliWCm4jkkRZRD0ejgTN 2184tgI5 2185-----END CERTIFICATE----- 2186""" 2187 cert = load_certificate(FILETYPE_PEM, certPEM) 2188 with pytest.raises(ValueError): 2189 cert.get_signature_algorithm() 2190 2191 def test_sign_bad_pubkey_type(self): 2192 """ 2193 `X509.sign` raises `TypeError` when called with the wrong type. 2194 """ 2195 cert = X509() 2196 with pytest.raises(TypeError): 2197 cert.sign(object(), b"sha256") 2198 2199 def test_convert_from_cryptography(self): 2200 crypto_cert = x509.load_pem_x509_certificate( 2201 intermediate_cert_pem, backend 2202 ) 2203 cert = X509.from_cryptography(crypto_cert) 2204 2205 assert isinstance(cert, X509) 2206 assert cert.get_version() == crypto_cert.version.value 2207 2208 def test_convert_from_cryptography_unsupported_type(self): 2209 with pytest.raises(TypeError): 2210 X509.from_cryptography(object()) 2211 2212 def test_convert_to_cryptography_key(self): 2213 cert = load_certificate(FILETYPE_PEM, intermediate_cert_pem) 2214 crypto_cert = cert.to_cryptography() 2215 2216 assert isinstance(crypto_cert, x509.Certificate) 2217 assert crypto_cert.version.value == cert.get_version() 2218 2219 2220class TestX509Store(object): 2221 """ 2222 Test for `OpenSSL.crypto.X509Store`. 2223 """ 2224 2225 def test_type(self): 2226 """ 2227 `X509Store` is a type object. 2228 """ 2229 assert is_consistent_type(X509Store, "X509Store") 2230 2231 def test_add_cert(self): 2232 """ 2233 `X509Store.add_cert` adds a `X509` instance to the certificate store. 2234 """ 2235 cert = load_certificate(FILETYPE_PEM, root_cert_pem) 2236 store = X509Store() 2237 store.add_cert(cert) 2238 2239 @pytest.mark.parametrize("cert", [None, 1.0, "cert", object()]) 2240 def test_add_cert_wrong_args(self, cert): 2241 """ 2242 `X509Store.add_cert` raises `TypeError` if passed a non-X509 object 2243 as its first argument. 2244 """ 2245 store = X509Store() 2246 with pytest.raises(TypeError): 2247 store.add_cert(cert) 2248 2249 def test_add_cert_accepts_duplicate(self): 2250 """ 2251 `X509Store.add_cert` doesn't raise `OpenSSL.crypto.Error` if an attempt 2252 is made to add the same certificate to the store more than once. 2253 """ 2254 cert = load_certificate(FILETYPE_PEM, root_cert_pem) 2255 store = X509Store() 2256 store.add_cert(cert) 2257 store.add_cert(cert) 2258 2259 @pytest.mark.parametrize( 2260 "cafile, capath, call_cafile, call_capath", 2261 [ 2262 ( 2263 "/cafile" + NON_ASCII, 2264 None, 2265 b"/cafile" + NON_ASCII.encode(sys.getfilesystemencoding()), 2266 _ffi.NULL, 2267 ), 2268 ( 2269 b"/cafile" + NON_ASCII.encode("utf-8"), 2270 None, 2271 b"/cafile" + NON_ASCII.encode("utf-8"), 2272 _ffi.NULL, 2273 ), 2274 ( 2275 None, 2276 "/capath" + NON_ASCII, 2277 _ffi.NULL, 2278 b"/capath" + NON_ASCII.encode(sys.getfilesystemencoding()), 2279 ), 2280 ( 2281 None, 2282 b"/capath" + NON_ASCII.encode("utf-8"), 2283 _ffi.NULL, 2284 b"/capath" + NON_ASCII.encode("utf-8"), 2285 ), 2286 ], 2287 ) 2288 def test_load_locations_parameters( 2289 self, cafile, capath, call_cafile, call_capath, monkeypatch 2290 ): 2291 class LibMock(object): 2292 def load_locations(self, store, cafile, capath): 2293 self.cafile = cafile 2294 self.capath = capath 2295 return 1 2296 2297 lib_mock = LibMock() 2298 monkeypatch.setattr( 2299 _lib, "X509_STORE_load_locations", lib_mock.load_locations 2300 ) 2301 2302 store = X509Store() 2303 store.load_locations(cafile=cafile, capath=capath) 2304 2305 assert call_cafile == lib_mock.cafile 2306 assert call_capath == lib_mock.capath 2307 2308 def test_load_locations_fails_when_all_args_are_none(self): 2309 store = X509Store() 2310 with pytest.raises(Error): 2311 store.load_locations(None, None) 2312 2313 def test_load_locations_raises_error_on_failure(self, tmpdir): 2314 invalid_ca_file = tmpdir.join("invalid.pem") 2315 invalid_ca_file.write("This is not a certificate") 2316 2317 store = X509Store() 2318 with pytest.raises(Error): 2319 store.load_locations(cafile=str(invalid_ca_file)) 2320 2321 2322class TestPKCS12(object): 2323 """ 2324 Test for `OpenSSL.crypto.PKCS12` and `OpenSSL.crypto.load_pkcs12`. 2325 """ 2326 2327 def test_type(self): 2328 """ 2329 `PKCS12` is a type object. 2330 """ 2331 assert is_consistent_type(PKCS12, "PKCS12") 2332 2333 def test_empty_construction(self): 2334 """ 2335 `PKCS12` returns a new instance of `PKCS12` with no certificate, 2336 private key, CA certificates, or friendly name. 2337 """ 2338 p12 = PKCS12() 2339 assert None is p12.get_certificate() 2340 assert None is p12.get_privatekey() 2341 assert None is p12.get_ca_certificates() 2342 assert None is p12.get_friendlyname() 2343 2344 def test_type_errors(self): 2345 """ 2346 The `PKCS12` setter functions (`set_certificate`, `set_privatekey`, 2347 `set_ca_certificates`, and `set_friendlyname`) raise `TypeError` 2348 when passed objects of types other than those expected. 2349 """ 2350 p12 = PKCS12() 2351 for bad_arg in [3, PKey(), X509]: 2352 with pytest.raises(TypeError): 2353 p12.set_certificate(bad_arg) 2354 for bad_arg in [3, "legbone", X509()]: 2355 with pytest.raises(TypeError): 2356 p12.set_privatekey(bad_arg) 2357 for bad_arg in [3, X509(), (3, 4), (PKey(),)]: 2358 with pytest.raises(TypeError): 2359 p12.set_ca_certificates(bad_arg) 2360 for bad_arg in [6, ("foo", "bar")]: 2361 with pytest.raises(TypeError): 2362 p12.set_friendlyname(bad_arg) 2363 2364 def test_key_only(self): 2365 """ 2366 A `PKCS12` with only a private key can be exported using 2367 `PKCS12.export` and loaded again using `load_pkcs12`. 2368 """ 2369 passwd = b"blah" 2370 p12 = PKCS12() 2371 pkey = load_privatekey(FILETYPE_PEM, root_key_pem) 2372 p12.set_privatekey(pkey) 2373 assert None is p12.get_certificate() 2374 assert pkey == p12.get_privatekey() 2375 try: 2376 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3) 2377 except Error: 2378 # Some versions of OpenSSL will throw an exception 2379 # for this nearly useless PKCS12 we tried to generate: 2380 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')] 2381 return 2382 p12 = load_pkcs12(dumped_p12, passwd) 2383 assert None is p12.get_ca_certificates() 2384 assert None is p12.get_certificate() 2385 2386 # OpenSSL fails to bring the key back to us. So sad. Perhaps in the 2387 # future this will be improved. 2388 assert isinstance(p12.get_privatekey(), (PKey, type(None))) 2389 2390 def test_cert_only(self): 2391 """ 2392 A `PKCS12` with only a certificate can be exported using 2393 `PKCS12.export` and loaded again using `load_pkcs12`. 2394 """ 2395 passwd = b"blah" 2396 p12 = PKCS12() 2397 cert = load_certificate(FILETYPE_PEM, root_cert_pem) 2398 p12.set_certificate(cert) 2399 assert cert == p12.get_certificate() 2400 assert None is p12.get_privatekey() 2401 try: 2402 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3) 2403 except Error: 2404 # Some versions of OpenSSL will throw an exception 2405 # for this nearly useless PKCS12 we tried to generate: 2406 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')] 2407 return 2408 p12 = load_pkcs12(dumped_p12, passwd) 2409 assert None is p12.get_privatekey() 2410 2411 # OpenSSL fails to bring the cert back to us. Groany mcgroan. 2412 assert isinstance(p12.get_certificate(), (X509, type(None))) 2413 2414 # Oh ho. It puts the certificate into the ca certificates list, in 2415 # fact. Totally bogus, I would think. Nevertheless, let's exploit 2416 # that to check to see if it reconstructed the certificate we expected 2417 # it to. At some point, hopefully this will change so that 2418 # p12.get_certificate() is actually what returns the loaded 2419 # certificate. 2420 assert root_cert_pem == dump_certificate( 2421 FILETYPE_PEM, p12.get_ca_certificates()[0] 2422 ) 2423 2424 def gen_pkcs12( 2425 self, cert_pem=None, key_pem=None, ca_pem=None, friendly_name=None 2426 ): 2427 """ 2428 Generate a PKCS12 object with components from PEM. Verify that the set 2429 functions return None. 2430 """ 2431 p12 = PKCS12() 2432 if cert_pem: 2433 ret = p12.set_certificate(load_certificate(FILETYPE_PEM, cert_pem)) 2434 assert ret is None 2435 if key_pem: 2436 ret = p12.set_privatekey(load_privatekey(FILETYPE_PEM, key_pem)) 2437 assert ret is None 2438 if ca_pem: 2439 ret = p12.set_ca_certificates( 2440 (load_certificate(FILETYPE_PEM, ca_pem),) 2441 ) 2442 assert ret is None 2443 if friendly_name: 2444 ret = p12.set_friendlyname(friendly_name) 2445 assert ret is None 2446 return p12 2447 2448 def check_recovery( 2449 self, p12_str, key=None, cert=None, ca=None, passwd=b"", extra=() 2450 ): 2451 """ 2452 Use openssl program to confirm three components are recoverable from a 2453 PKCS12 string. 2454 """ 2455 if key: 2456 recovered_key = _runopenssl( 2457 p12_str, 2458 b"pkcs12", 2459 b"-nocerts", 2460 b"-nodes", 2461 b"-passin", 2462 b"pass:" + passwd, 2463 *extra 2464 ) 2465 assert recovered_key[-len(key) :] == key 2466 if cert: 2467 recovered_cert = _runopenssl( 2468 p12_str, 2469 b"pkcs12", 2470 b"-clcerts", 2471 b"-nodes", 2472 b"-passin", 2473 b"pass:" + passwd, 2474 b"-nokeys", 2475 *extra 2476 ) 2477 assert recovered_cert[-len(cert) :] == cert 2478 if ca: 2479 recovered_cert = _runopenssl( 2480 p12_str, 2481 b"pkcs12", 2482 b"-cacerts", 2483 b"-nodes", 2484 b"-passin", 2485 b"pass:" + passwd, 2486 b"-nokeys", 2487 *extra 2488 ) 2489 assert recovered_cert[-len(ca) :] == ca 2490 2491 def verify_pkcs12_container(self, p12): 2492 """ 2493 Verify that the PKCS#12 container contains the correct client 2494 certificate and private key. 2495 2496 :param p12: The PKCS12 instance to verify. 2497 :type p12: `PKCS12` 2498 """ 2499 cert_pem = dump_certificate(FILETYPE_PEM, p12.get_certificate()) 2500 key_pem = dump_privatekey(FILETYPE_PEM, p12.get_privatekey()) 2501 assert (client_cert_pem, client_key_pem, None) == ( 2502 cert_pem, 2503 key_pem, 2504 p12.get_ca_certificates(), 2505 ) 2506 2507 def test_load_pkcs12(self): 2508 """ 2509 A PKCS12 string generated using the openssl command line can be loaded 2510 with `load_pkcs12` and its components extracted and examined. 2511 """ 2512 passwd = b"whatever" 2513 pem = client_key_pem + client_cert_pem 2514 p12_str = _runopenssl( 2515 pem, 2516 b"pkcs12", 2517 b"-export", 2518 b"-clcerts", 2519 b"-passout", 2520 b"pass:" + passwd, 2521 ) 2522 p12 = load_pkcs12(p12_str, passphrase=passwd) 2523 self.verify_pkcs12_container(p12) 2524 2525 def test_load_pkcs12_text_passphrase(self): 2526 """ 2527 A PKCS12 string generated using the openssl command line can be loaded 2528 with `load_pkcs12` and its components extracted and examined. 2529 Using text as passphrase instead of bytes. DeprecationWarning expected. 2530 """ 2531 pem = client_key_pem + client_cert_pem 2532 passwd = b"whatever" 2533 p12_str = _runopenssl( 2534 pem, 2535 b"pkcs12", 2536 b"-export", 2537 b"-clcerts", 2538 b"-passout", 2539 b"pass:" + passwd, 2540 ) 2541 with pytest.warns(DeprecationWarning) as w: 2542 simplefilter("always") 2543 p12 = load_pkcs12(p12_str, passphrase=b"whatever".decode("ascii")) 2544 msg = "{0} for passphrase is no longer accepted, use bytes".format( 2545 WARNING_TYPE_EXPECTED 2546 ) 2547 assert msg == str(w[-1].message) 2548 2549 self.verify_pkcs12_container(p12) 2550 2551 def test_load_pkcs12_no_passphrase(self): 2552 """ 2553 A PKCS12 string generated using openssl command line can be loaded with 2554 `load_pkcs12` without a passphrase and its components extracted 2555 and examined. 2556 """ 2557 pem = client_key_pem + client_cert_pem 2558 p12_str = _runopenssl( 2559 pem, b"pkcs12", b"-export", b"-clcerts", b"-passout", b"pass:" 2560 ) 2561 p12 = load_pkcs12(p12_str) 2562 self.verify_pkcs12_container(p12) 2563 2564 def _dump_and_load(self, dump_passphrase, load_passphrase): 2565 """ 2566 A helper method to dump and load a PKCS12 object. 2567 """ 2568 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem) 2569 dumped_p12 = p12.export(passphrase=dump_passphrase, iter=2, maciter=3) 2570 return load_pkcs12(dumped_p12, passphrase=load_passphrase) 2571 2572 def test_load_pkcs12_null_passphrase_load_empty(self): 2573 """ 2574 A PKCS12 string can be dumped with a null passphrase, loaded with an 2575 empty passphrase with `load_pkcs12`, and its components 2576 extracted and examined. 2577 """ 2578 self.verify_pkcs12_container( 2579 self._dump_and_load(dump_passphrase=None, load_passphrase=b"") 2580 ) 2581 2582 def test_load_pkcs12_null_passphrase_load_null(self): 2583 """ 2584 A PKCS12 string can be dumped with a null passphrase, loaded with a 2585 null passphrase with `load_pkcs12`, and its components 2586 extracted and examined. 2587 """ 2588 self.verify_pkcs12_container( 2589 self._dump_and_load(dump_passphrase=None, load_passphrase=None) 2590 ) 2591 2592 def test_load_pkcs12_empty_passphrase_load_empty(self): 2593 """ 2594 A PKCS12 string can be dumped with an empty passphrase, loaded with an 2595 empty passphrase with `load_pkcs12`, and its components 2596 extracted and examined. 2597 """ 2598 self.verify_pkcs12_container( 2599 self._dump_and_load(dump_passphrase=b"", load_passphrase=b"") 2600 ) 2601 2602 def test_load_pkcs12_empty_passphrase_load_null(self): 2603 """ 2604 A PKCS12 string can be dumped with an empty passphrase, loaded with a 2605 null passphrase with `load_pkcs12`, and its components 2606 extracted and examined. 2607 """ 2608 self.verify_pkcs12_container( 2609 self._dump_and_load(dump_passphrase=b"", load_passphrase=None) 2610 ) 2611 2612 def test_load_pkcs12_garbage(self): 2613 """ 2614 `load_pkcs12` raises `OpenSSL.crypto.Error` when passed 2615 a string which is not a PKCS12 dump. 2616 """ 2617 passwd = b"whatever" 2618 with pytest.raises(Error) as err: 2619 load_pkcs12(b"fruit loops", passwd) 2620 assert err.value.args[0][0][0] == "asn1 encoding routines" 2621 assert len(err.value.args[0][0]) == 3 2622 2623 def test_replace(self): 2624 """ 2625 `PKCS12.set_certificate` replaces the certificate in a PKCS12 2626 cluster. `PKCS12.set_privatekey` replaces the private key. 2627 `PKCS12.set_ca_certificates` replaces the CA certificates. 2628 """ 2629 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem) 2630 p12.set_certificate(load_certificate(FILETYPE_PEM, server_cert_pem)) 2631 p12.set_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem)) 2632 root_cert = load_certificate(FILETYPE_PEM, root_cert_pem) 2633 client_cert = load_certificate(FILETYPE_PEM, client_cert_pem) 2634 p12.set_ca_certificates([root_cert]) # not a tuple 2635 assert 1 == len(p12.get_ca_certificates()) 2636 assert root_cert == p12.get_ca_certificates()[0] 2637 p12.set_ca_certificates([client_cert, root_cert]) 2638 assert 2 == len(p12.get_ca_certificates()) 2639 assert client_cert == p12.get_ca_certificates()[0] 2640 assert root_cert == p12.get_ca_certificates()[1] 2641 2642 def test_friendly_name(self): 2643 """ 2644 The *friendlyName* of a PKCS12 can be set and retrieved via 2645 `PKCS12.get_friendlyname` and `PKCS12_set_friendlyname`, and a 2646 `PKCS12` with a friendly name set can be dumped with `PKCS12.export`. 2647 """ 2648 passwd = b'Dogmeat[]{}!@#$%^&*()~`?/.,<>-_+=";:' 2649 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem) 2650 for friendly_name in [b"Serverlicious", None, b"###"]: 2651 p12.set_friendlyname(friendly_name) 2652 assert p12.get_friendlyname() == friendly_name 2653 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3) 2654 reloaded_p12 = load_pkcs12(dumped_p12, passwd) 2655 assert p12.get_friendlyname() == reloaded_p12.get_friendlyname() 2656 # We would use the openssl program to confirm the friendly 2657 # name, but it is not possible. The pkcs12 command 2658 # does not store the friendly name in the cert's 2659 # alias, which we could then extract. 2660 self.check_recovery( 2661 dumped_p12, 2662 key=server_key_pem, 2663 cert=server_cert_pem, 2664 ca=root_cert_pem, 2665 passwd=passwd, 2666 ) 2667 2668 def test_various_empty_passphrases(self): 2669 """ 2670 Test that missing, None, and '' passphrases are identical for PKCS12 2671 export. 2672 """ 2673 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem) 2674 passwd = b"" 2675 dumped_p12_empty = p12.export(iter=2, maciter=0, passphrase=passwd) 2676 dumped_p12_none = p12.export(iter=3, maciter=2, passphrase=None) 2677 dumped_p12_nopw = p12.export(iter=9, maciter=4) 2678 for dumped_p12 in [dumped_p12_empty, dumped_p12_none, dumped_p12_nopw]: 2679 self.check_recovery( 2680 dumped_p12, 2681 key=client_key_pem, 2682 cert=client_cert_pem, 2683 ca=root_cert_pem, 2684 passwd=passwd, 2685 ) 2686 2687 def test_removing_ca_cert(self): 2688 """ 2689 Passing `None` to `PKCS12.set_ca_certificates` removes all CA 2690 certificates. 2691 """ 2692 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem) 2693 p12.set_ca_certificates(None) 2694 assert None is p12.get_ca_certificates() 2695 2696 def test_export_without_mac(self): 2697 """ 2698 Exporting a PKCS12 with a `maciter` of `-1` excludes the MAC entirely. 2699 """ 2700 passwd = b"Lake Michigan" 2701 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem) 2702 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2) 2703 self.check_recovery( 2704 dumped_p12, 2705 key=server_key_pem, 2706 cert=server_cert_pem, 2707 passwd=passwd, 2708 extra=(b"-nomacver",), 2709 ) 2710 2711 def test_load_without_mac(self): 2712 """ 2713 Loading a PKCS12 without a MAC does something other than crash. 2714 """ 2715 passwd = b"Lake Michigan" 2716 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem) 2717 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2) 2718 try: 2719 recovered_p12 = load_pkcs12(dumped_p12, passwd) 2720 # The person who generated this PCKS12 should be flogged, 2721 # or better yet we should have a means to determine 2722 # whether a PCKS12 had a MAC that was verified. 2723 # Anyway, libopenssl chooses to allow it, so the 2724 # pyopenssl binding does as well. 2725 assert isinstance(recovered_p12, PKCS12) 2726 except Error: 2727 # Failing here with an exception is preferred as some openssl 2728 # versions do. 2729 pass 2730 2731 def test_zero_len_list_for_ca(self): 2732 """ 2733 A PKCS12 with an empty CA certificates list can be exported. 2734 """ 2735 passwd = b"Hobie 18" 2736 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem) 2737 p12.set_ca_certificates([]) 2738 assert () == p12.get_ca_certificates() 2739 dumped_p12 = p12.export(passphrase=passwd, iter=3) 2740 self.check_recovery( 2741 dumped_p12, key=server_key_pem, cert=server_cert_pem, passwd=passwd 2742 ) 2743 2744 def test_export_without_args(self): 2745 """ 2746 All the arguments to `PKCS12.export` are optional. 2747 """ 2748 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem) 2749 dumped_p12 = p12.export() # no args 2750 self.check_recovery( 2751 dumped_p12, key=server_key_pem, cert=server_cert_pem, passwd=b"" 2752 ) 2753 2754 def test_export_without_bytes(self): 2755 """ 2756 Test `PKCS12.export` with text not bytes as passphrase 2757 """ 2758 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem) 2759 2760 with pytest.warns(DeprecationWarning) as w: 2761 simplefilter("always") 2762 dumped_p12 = p12.export(passphrase=b"randomtext".decode("ascii")) 2763 msg = "{0} for passphrase is no longer accepted, use bytes".format( 2764 WARNING_TYPE_EXPECTED 2765 ) 2766 assert msg == str(w[-1].message) 2767 self.check_recovery( 2768 dumped_p12, 2769 key=server_key_pem, 2770 cert=server_cert_pem, 2771 passwd=b"randomtext", 2772 ) 2773 2774 def test_key_cert_mismatch(self): 2775 """ 2776 `PKCS12.export` raises an exception when a key and certificate 2777 mismatch. 2778 """ 2779 p12 = self.gen_pkcs12(server_cert_pem, client_key_pem, root_cert_pem) 2780 with pytest.raises(Error): 2781 p12.export() 2782 2783 2784def _runopenssl(pem, *args): 2785 """ 2786 Run the command line openssl tool with the given arguments and write 2787 the given PEM to its stdin. Not safe for quotes. 2788 """ 2789 proc = Popen([b"openssl"] + list(args), stdin=PIPE, stdout=PIPE) 2790 proc.stdin.write(pem) 2791 proc.stdin.close() 2792 output = proc.stdout.read() 2793 proc.stdout.close() 2794 proc.wait() 2795 return output 2796 2797 2798class TestLoadPublicKey(object): 2799 """ 2800 Tests for :func:`load_publickey`. 2801 """ 2802 2803 def test_loading_works(self): 2804 """ 2805 load_publickey loads public keys and sets correct attributes. 2806 """ 2807 key = load_publickey(FILETYPE_PEM, cleartextPublicKeyPEM) 2808 2809 assert True is key._only_public 2810 assert 2048 == key.bits() 2811 assert TYPE_RSA == key.type() 2812 2813 def test_invalid_type(self): 2814 """ 2815 load_publickey doesn't support FILETYPE_TEXT. 2816 """ 2817 with pytest.raises(ValueError): 2818 load_publickey(FILETYPE_TEXT, cleartextPublicKeyPEM) 2819 2820 def test_invalid_key_format(self): 2821 """ 2822 load_publickey explodes on incorrect keys. 2823 """ 2824 with pytest.raises(Error): 2825 load_publickey(FILETYPE_ASN1, cleartextPublicKeyPEM) 2826 2827 def test_tolerates_unicode_strings(self): 2828 """ 2829 load_publickey works with text strings, not just bytes. 2830 """ 2831 serialized = cleartextPublicKeyPEM.decode("ascii") 2832 key = load_publickey(FILETYPE_PEM, serialized) 2833 dumped_pem = dump_publickey(FILETYPE_PEM, key) 2834 2835 assert dumped_pem == cleartextPublicKeyPEM 2836 2837 2838class TestFunction(object): 2839 """ 2840 Tests for free-functions in the `OpenSSL.crypto` module. 2841 """ 2842 2843 def test_load_privatekey_invalid_format(self): 2844 """ 2845 `load_privatekey` raises `ValueError` if passed an unknown filetype. 2846 """ 2847 with pytest.raises(ValueError): 2848 load_privatekey(100, root_key_pem) 2849 2850 def test_load_privatekey_invalid_passphrase_type(self): 2851 """ 2852 `load_privatekey` raises `TypeError` if passed a passphrase that is 2853 neither a `str` nor a callable. 2854 """ 2855 with pytest.raises(TypeError): 2856 load_privatekey( 2857 FILETYPE_PEM, encryptedPrivateKeyPEMPassphrase, object() 2858 ) 2859 2860 def test_load_privatekey_wrongPassphrase(self): 2861 """ 2862 `load_privatekey` raises `OpenSSL.crypto.Error` when it is passed an 2863 encrypted PEM and an incorrect passphrase. 2864 """ 2865 with pytest.raises(Error) as err: 2866 load_privatekey(FILETYPE_PEM, encryptedPrivateKeyPEM, b"quack") 2867 assert err.value.args[0] != [] 2868 2869 def test_load_privatekey_passphraseWrongType(self): 2870 """ 2871 `load_privatekey` raises `ValueError` when it is passeda passphrase 2872 with a private key encoded in a format, that doesn't support 2873 encryption. 2874 """ 2875 key = load_privatekey(FILETYPE_PEM, root_key_pem) 2876 blob = dump_privatekey(FILETYPE_ASN1, key) 2877 with pytest.raises(ValueError): 2878 load_privatekey(FILETYPE_ASN1, blob, "secret") 2879 2880 def test_load_privatekey_passphrase(self): 2881 """ 2882 `load_privatekey` can create a `PKey` object from an encrypted PEM 2883 string if given the passphrase. 2884 """ 2885 key = load_privatekey( 2886 FILETYPE_PEM, 2887 encryptedPrivateKeyPEM, 2888 encryptedPrivateKeyPEMPassphrase, 2889 ) 2890 assert isinstance(key, PKey) 2891 2892 def test_load_privatekey_passphrase_exception(self): 2893 """ 2894 If the passphrase callback raises an exception, that exception is 2895 raised by `load_privatekey`. 2896 """ 2897 2898 def cb(ignored): 2899 raise ArithmeticError 2900 2901 with pytest.raises(ArithmeticError): 2902 load_privatekey(FILETYPE_PEM, encryptedPrivateKeyPEM, cb) 2903 2904 def test_load_privatekey_wrongPassphraseCallback(self): 2905 """ 2906 `load_privatekey` raises `OpenSSL.crypto.Error` when it 2907 is passed an encrypted PEM and a passphrase callback which returns an 2908 incorrect passphrase. 2909 """ 2910 called = [] 2911 2912 def cb(*a): 2913 called.append(None) 2914 return b"quack" 2915 2916 with pytest.raises(Error) as err: 2917 load_privatekey(FILETYPE_PEM, encryptedPrivateKeyPEM, cb) 2918 assert called 2919 assert err.value.args[0] != [] 2920 2921 def test_load_privatekey_passphraseCallback(self): 2922 """ 2923 `load_privatekey` can create a `PKey` object from an encrypted PEM 2924 string if given a passphrase callback which returns the correct 2925 password. 2926 """ 2927 called = [] 2928 2929 def cb(writing): 2930 called.append(writing) 2931 return encryptedPrivateKeyPEMPassphrase 2932 2933 key = load_privatekey(FILETYPE_PEM, encryptedPrivateKeyPEM, cb) 2934 assert isinstance(key, PKey) 2935 assert called == [False] 2936 2937 def test_load_privatekey_passphrase_wrong_return_type(self): 2938 """ 2939 `load_privatekey` raises `ValueError` if the passphrase callback 2940 returns something other than a byte string. 2941 """ 2942 with pytest.raises(ValueError): 2943 load_privatekey( 2944 FILETYPE_PEM, encryptedPrivateKeyPEM, lambda *args: 3 2945 ) 2946 2947 def test_dump_privatekey_wrong_args(self): 2948 """ 2949 `dump_privatekey` raises `TypeError` if called with a `cipher` 2950 argument but no `passphrase` argument. 2951 """ 2952 key = PKey() 2953 key.generate_key(TYPE_RSA, 512) 2954 with pytest.raises(TypeError): 2955 dump_privatekey(FILETYPE_PEM, key, cipher=GOOD_CIPHER) 2956 2957 def test_dump_privatekey_not_rsa_key(self): 2958 """ 2959 `dump_privatekey` raises `TypeError` if called with a key that is 2960 not RSA. 2961 """ 2962 key = PKey() 2963 key.generate_key(TYPE_DSA, 512) 2964 with pytest.raises(TypeError): 2965 dump_privatekey(FILETYPE_TEXT, key) 2966 2967 def test_dump_privatekey_invalid_pkey(self): 2968 with pytest.raises(TypeError): 2969 dump_privatekey(FILETYPE_TEXT, object()) 2970 2971 def test_dump_privatekey_unknown_cipher(self): 2972 """ 2973 `dump_privatekey` raises `ValueError` if called with an unrecognized 2974 cipher name. 2975 """ 2976 key = PKey() 2977 key.generate_key(TYPE_RSA, 512) 2978 with pytest.raises(ValueError): 2979 dump_privatekey(FILETYPE_PEM, key, BAD_CIPHER, "passphrase") 2980 2981 def test_dump_privatekey_invalid_passphrase_type(self): 2982 """ 2983 `dump_privatekey` raises `TypeError` if called with a passphrase which 2984 is neither a `str` nor a callable. 2985 """ 2986 key = PKey() 2987 key.generate_key(TYPE_RSA, 512) 2988 with pytest.raises(TypeError): 2989 dump_privatekey(FILETYPE_PEM, key, GOOD_CIPHER, object()) 2990 2991 def test_dump_privatekey_invalid_filetype(self): 2992 """ 2993 `dump_privatekey` raises `ValueError` if called with an unrecognized 2994 filetype. 2995 """ 2996 key = PKey() 2997 key.generate_key(TYPE_RSA, 512) 2998 with pytest.raises(ValueError): 2999 dump_privatekey(100, key) 3000 3001 def test_load_privatekey_passphrase_callback_length(self): 3002 """ 3003 `crypto.load_privatekey` should raise an error when the passphrase 3004 provided by the callback is too long, not silently truncate it. 3005 """ 3006 3007 def cb(ignored): 3008 return "a" * 1025 3009 3010 with pytest.raises(ValueError): 3011 load_privatekey(FILETYPE_PEM, encryptedPrivateKeyPEM, cb) 3012 3013 def test_dump_privatekey_passphrase(self): 3014 """ 3015 `dump_privatekey` writes an encrypted PEM when given a passphrase. 3016 """ 3017 passphrase = b"foo" 3018 key = load_privatekey(FILETYPE_PEM, root_key_pem) 3019 pem = dump_privatekey(FILETYPE_PEM, key, GOOD_CIPHER, passphrase) 3020 assert isinstance(pem, bytes) 3021 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase) 3022 assert isinstance(loadedKey, PKey) 3023 assert loadedKey.type() == key.type() 3024 assert loadedKey.bits() == key.bits() 3025 3026 def test_dump_privatekey_passphrase_wrong_type(self): 3027 """ 3028 `dump_privatekey` raises `ValueError` when it is passed a passphrase 3029 with a private key encoded in a format, that doesn't support 3030 encryption. 3031 """ 3032 key = load_privatekey(FILETYPE_PEM, root_key_pem) 3033 with pytest.raises(ValueError): 3034 dump_privatekey(FILETYPE_ASN1, key, GOOD_CIPHER, "secret") 3035 3036 def test_dump_certificate(self): 3037 """ 3038 `dump_certificate` writes PEM, DER, and text. 3039 """ 3040 pemData = root_cert_pem + root_key_pem 3041 cert = load_certificate(FILETYPE_PEM, pemData) 3042 dumped_pem = dump_certificate(FILETYPE_PEM, cert) 3043 assert dumped_pem == root_cert_pem 3044 dumped_der = dump_certificate(FILETYPE_ASN1, cert) 3045 good_der = _runopenssl(dumped_pem, b"x509", b"-outform", b"DER") 3046 assert dumped_der == good_der 3047 cert2 = load_certificate(FILETYPE_ASN1, dumped_der) 3048 dumped_pem2 = dump_certificate(FILETYPE_PEM, cert2) 3049 assert dumped_pem2 == root_cert_pem 3050 dumped_text = dump_certificate(FILETYPE_TEXT, cert) 3051 assert len(dumped_text) > 500 3052 3053 def test_dump_certificate_bad_type(self): 3054 """ 3055 `dump_certificate` raises a `ValueError` if it's called with 3056 a bad type. 3057 """ 3058 cert = load_certificate(FILETYPE_PEM, root_cert_pem) 3059 with pytest.raises(ValueError): 3060 dump_certificate(object(), cert) 3061 3062 def test_dump_privatekey_pem(self): 3063 """ 3064 `dump_privatekey` writes a PEM 3065 """ 3066 key = load_privatekey(FILETYPE_PEM, root_key_pem) 3067 assert key.check() 3068 dumped_pem = dump_privatekey(FILETYPE_PEM, key) 3069 assert dumped_pem == normalized_root_key_pem 3070 3071 def test_dump_privatekey_asn1(self): 3072 """ 3073 `dump_privatekey` writes a DER 3074 """ 3075 key = load_privatekey(FILETYPE_PEM, root_key_pem) 3076 3077 dumped_der = dump_privatekey(FILETYPE_ASN1, key) 3078 assert dumped_der == root_key_der 3079 3080 def test_load_privatekey_asn1(self): 3081 """ 3082 `dump_privatekey` writes a DER 3083 """ 3084 key = load_privatekey(FILETYPE_ASN1, root_key_der) 3085 assert key.bits() == 3072 3086 assert key.type() == TYPE_RSA 3087 3088 def test_dump_privatekey_text(self): 3089 """ 3090 `dump_privatekey` writes a text 3091 """ 3092 key = load_privatekey(FILETYPE_PEM, root_key_pem) 3093 dumped_text = dump_privatekey(FILETYPE_TEXT, key) 3094 assert len(dumped_text) > 500 3095 3096 def test_dump_publickey_pem(self): 3097 """ 3098 dump_publickey writes a PEM. 3099 """ 3100 key = load_publickey(FILETYPE_PEM, cleartextPublicKeyPEM) 3101 dumped_pem = dump_publickey(FILETYPE_PEM, key) 3102 assert dumped_pem == cleartextPublicKeyPEM 3103 3104 def test_dump_publickey_asn1(self): 3105 """ 3106 dump_publickey writes a DER. 3107 """ 3108 key = load_publickey(FILETYPE_PEM, cleartextPublicKeyPEM) 3109 dumped_der = dump_publickey(FILETYPE_ASN1, key) 3110 key2 = load_publickey(FILETYPE_ASN1, dumped_der) 3111 dumped_pem2 = dump_publickey(FILETYPE_PEM, key2) 3112 assert dumped_pem2 == cleartextPublicKeyPEM 3113 3114 def test_dump_publickey_invalid_type(self): 3115 """ 3116 dump_publickey doesn't support FILETYPE_TEXT. 3117 """ 3118 key = load_publickey(FILETYPE_PEM, cleartextPublicKeyPEM) 3119 3120 with pytest.raises(ValueError): 3121 dump_publickey(FILETYPE_TEXT, key) 3122 3123 def test_dump_certificate_request(self): 3124 """ 3125 `dump_certificate_request` writes a PEM, DER, and text. 3126 """ 3127 req = load_certificate_request( 3128 FILETYPE_PEM, cleartextCertificateRequestPEM 3129 ) 3130 dumped_pem = dump_certificate_request(FILETYPE_PEM, req) 3131 assert dumped_pem == cleartextCertificateRequestPEM 3132 dumped_der = dump_certificate_request(FILETYPE_ASN1, req) 3133 good_der = _runopenssl(dumped_pem, b"req", b"-outform", b"DER") 3134 assert dumped_der == good_der 3135 req2 = load_certificate_request(FILETYPE_ASN1, dumped_der) 3136 dumped_pem2 = dump_certificate_request(FILETYPE_PEM, req2) 3137 assert dumped_pem2 == cleartextCertificateRequestPEM 3138 dumped_text = dump_certificate_request(FILETYPE_TEXT, req) 3139 assert len(dumped_text) > 500 3140 with pytest.raises(ValueError): 3141 dump_certificate_request(100, req) 3142 3143 def test_dump_privatekey_passphrase_callback(self): 3144 """ 3145 `dump_privatekey` writes an encrypted PEM when given a callback 3146 which returns the correct passphrase. 3147 """ 3148 passphrase = b"foo" 3149 called = [] 3150 3151 def cb(writing): 3152 called.append(writing) 3153 return passphrase 3154 3155 key = load_privatekey(FILETYPE_PEM, root_key_pem) 3156 pem = dump_privatekey(FILETYPE_PEM, key, GOOD_CIPHER, cb) 3157 assert isinstance(pem, bytes) 3158 assert called == [True] 3159 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase) 3160 assert isinstance(loadedKey, PKey) 3161 assert loadedKey.type() == key.type() 3162 assert loadedKey.bits() == key.bits() 3163 3164 def test_dump_privatekey_passphrase_exception(self): 3165 """ 3166 `dump_privatekey` should not overwrite the exception raised 3167 by the passphrase callback. 3168 """ 3169 3170 def cb(ignored): 3171 raise ArithmeticError 3172 3173 key = load_privatekey(FILETYPE_PEM, root_key_pem) 3174 with pytest.raises(ArithmeticError): 3175 dump_privatekey(FILETYPE_PEM, key, GOOD_CIPHER, cb) 3176 3177 def test_dump_privatekey_passphraseCallbackLength(self): 3178 """ 3179 `crypto.dump_privatekey` should raise an error when the passphrase 3180 provided by the callback is too long, not silently truncate it. 3181 """ 3182 3183 def cb(ignored): 3184 return "a" * 1025 3185 3186 key = load_privatekey(FILETYPE_PEM, root_key_pem) 3187 with pytest.raises(ValueError): 3188 dump_privatekey(FILETYPE_PEM, key, GOOD_CIPHER, cb) 3189 3190 def test_dump_privatekey_truncated(self): 3191 """ 3192 `crypto.dump_privatekey` should not truncate a passphrase that contains 3193 a null byte. 3194 """ 3195 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM) 3196 passphrase = b"foo\x00bar" 3197 truncated_passphrase = passphrase.split(b"\x00", 1)[0] 3198 3199 # By dumping with the full passphrase load should raise an error if we 3200 # try to load using the truncated passphrase. If dump truncated the 3201 # passphrase, then we WILL load the privatekey and the test fails 3202 encrypted_key_pem = dump_privatekey( 3203 FILETYPE_PEM, key, "AES-256-CBC", passphrase 3204 ) 3205 with pytest.raises(Error): 3206 load_privatekey( 3207 FILETYPE_PEM, encrypted_key_pem, truncated_passphrase 3208 ) 3209 3210 def test_load_privatekey_truncated(self): 3211 """ 3212 `crypto.load_privatekey` should not truncate a passphrase that contains 3213 a null byte. 3214 """ 3215 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM) 3216 passphrase = b"foo\x00bar" 3217 truncated_passphrase = passphrase.split(b"\x00", 1)[0] 3218 3219 # By dumping using the truncated passphrase load should raise an error 3220 # if we try to load using the full passphrase. If load truncated the 3221 # passphrase, then we WILL load the privatekey and the test fails 3222 encrypted_key_pem = dump_privatekey( 3223 FILETYPE_PEM, key, "AES-256-CBC", truncated_passphrase 3224 ) 3225 with pytest.raises(Error): 3226 load_privatekey(FILETYPE_PEM, encrypted_key_pem, passphrase) 3227 3228 def test_load_pkcs7_data_pem(self): 3229 """ 3230 `load_pkcs7_data` accepts a PKCS#7 string and returns an instance of 3231 `PKCS`. 3232 """ 3233 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data) 3234 assert isinstance(pkcs7, PKCS7) 3235 3236 def test_load_pkcs7_data_asn1(self): 3237 """ 3238 `load_pkcs7_data` accepts a bytes containing ASN1 data representing 3239 PKCS#7 and returns an instance of `PKCS7`. 3240 """ 3241 pkcs7 = load_pkcs7_data(FILETYPE_ASN1, pkcs7DataASN1) 3242 assert isinstance(pkcs7, PKCS7) 3243 3244 def test_load_pkcs7_data_invalid(self): 3245 """ 3246 If the data passed to `load_pkcs7_data` is invalid, `Error` is raised. 3247 """ 3248 with pytest.raises(Error): 3249 load_pkcs7_data(FILETYPE_PEM, b"foo") 3250 3251 def test_load_pkcs7_type_invalid(self): 3252 """ 3253 If the type passed to `load_pkcs7_data`, `ValueError` is raised. 3254 """ 3255 with pytest.raises(ValueError): 3256 load_pkcs7_data(object(), b"foo") 3257 3258 3259class TestLoadCertificate(object): 3260 """ 3261 Tests for `load_certificate_request`. 3262 """ 3263 3264 def test_bad_file_type(self): 3265 """ 3266 If the file type passed to `load_certificate_request` is neither 3267 `FILETYPE_PEM` nor `FILETYPE_ASN1` then `ValueError` is raised. 3268 """ 3269 with pytest.raises(ValueError): 3270 load_certificate_request(object(), b"") 3271 with pytest.raises(ValueError): 3272 load_certificate(object(), b"") 3273 3274 def test_bad_certificate(self): 3275 """ 3276 If the bytes passed to `load_certificate` are not a valid certificate, 3277 an exception is raised. 3278 """ 3279 with pytest.raises(Error): 3280 load_certificate(FILETYPE_ASN1, b"lol") 3281 3282 3283class TestPKCS7(object): 3284 """ 3285 Tests for `PKCS7`. 3286 """ 3287 3288 def test_type_is_signed(self): 3289 """ 3290 `PKCS7.type_is_signed` returns `True` if the PKCS7 object is of 3291 the type *signed*. 3292 """ 3293 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data) 3294 assert pkcs7.type_is_signed() 3295 3296 def test_type_is_enveloped(self): 3297 """ 3298 `PKCS7.type_is_enveloped` returns `False` if the PKCS7 object is not 3299 of the type *enveloped*. 3300 """ 3301 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data) 3302 assert not pkcs7.type_is_enveloped() 3303 3304 def test_type_is_signed_and_enveloped(self): 3305 """ 3306 `PKCS7.type_is_signedAndEnveloped` returns `False` 3307 if the PKCS7 object is not of the type *signed and enveloped*. 3308 """ 3309 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data) 3310 assert not pkcs7.type_is_signedAndEnveloped() 3311 3312 def test_type_is_data(self): 3313 """ 3314 `PKCS7.type_is_data` returns `False` if the PKCS7 object is not of 3315 the type data. 3316 """ 3317 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data) 3318 assert not pkcs7.type_is_data() 3319 3320 def test_get_type_name(self): 3321 """ 3322 `PKCS7.get_type_name` returns a `str` giving the 3323 type name. 3324 """ 3325 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data) 3326 assert pkcs7.get_type_name() == b"pkcs7-signedData" 3327 3328 def test_attribute(self): 3329 """ 3330 If an attribute other than one of the methods tested here is accessed 3331 on an instance of `PKCS7`, `AttributeError` is raised. 3332 """ 3333 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data) 3334 with pytest.raises(AttributeError): 3335 pkcs7.foo 3336 3337 3338class TestNetscapeSPKI(_PKeyInteractionTestsMixin): 3339 """ 3340 Tests for `OpenSSL.crypto.NetscapeSPKI`. 3341 """ 3342 3343 def signable(self): 3344 """ 3345 Return a new `NetscapeSPKI` for use with signing tests. 3346 """ 3347 return NetscapeSPKI() 3348 3349 def test_type(self): 3350 """ 3351 `NetscapeSPKI` can be used to create instances of that type. 3352 """ 3353 assert is_consistent_type(NetscapeSPKI, "NetscapeSPKI") 3354 3355 def test_construction(self): 3356 """ 3357 `NetscapeSPKI` returns an instance of `NetscapeSPKI`. 3358 """ 3359 nspki = NetscapeSPKI() 3360 assert isinstance(nspki, NetscapeSPKI) 3361 3362 def test_invalid_attribute(self): 3363 """ 3364 Accessing a non-existent attribute of a `NetscapeSPKI` instance 3365 causes an `AttributeError` to be raised. 3366 """ 3367 nspki = NetscapeSPKI() 3368 with pytest.raises(AttributeError): 3369 nspki.foo 3370 3371 def test_b64_encode(self): 3372 """ 3373 `NetscapeSPKI.b64_encode` encodes the certificate to a base64 blob. 3374 """ 3375 nspki = NetscapeSPKI() 3376 blob = nspki.b64_encode() 3377 assert isinstance(blob, bytes) 3378 3379 3380class TestRevoked(object): 3381 """ 3382 Tests for `OpenSSL.crypto.Revoked`. 3383 """ 3384 3385 def test_ignores_unsupported_revoked_cert_extension_get_reason(self): 3386 """ 3387 The get_reason method on the Revoked class checks to see if the 3388 extension is NID_crl_reason and should skip it otherwise. This test 3389 loads a CRL with extensions it should ignore. 3390 """ 3391 crl = load_crl(FILETYPE_PEM, crlDataUnsupportedExtension) 3392 revoked = crl.get_revoked() 3393 reason = revoked[1].get_reason() 3394 assert reason == b"Unspecified" 3395 3396 def test_ignores_unsupported_revoked_cert_extension_set_new_reason(self): 3397 crl = load_crl(FILETYPE_PEM, crlDataUnsupportedExtension) 3398 revoked = crl.get_revoked() 3399 revoked[1].set_reason(None) 3400 reason = revoked[1].get_reason() 3401 assert reason is None 3402 3403 def test_construction(self): 3404 """ 3405 Confirm we can create `OpenSSL.crypto.Revoked`. Check that it is 3406 empty. 3407 """ 3408 revoked = Revoked() 3409 assert isinstance(revoked, Revoked) 3410 assert type(revoked) == Revoked 3411 assert revoked.get_serial() == b"00" 3412 assert revoked.get_rev_date() is None 3413 assert revoked.get_reason() is None 3414 3415 def test_serial(self): 3416 """ 3417 Confirm we can set and get serial numbers from 3418 `OpenSSL.crypto.Revoked`. Confirm errors are handled with grace. 3419 """ 3420 revoked = Revoked() 3421 ret = revoked.set_serial(b"10b") 3422 assert ret is None 3423 ser = revoked.get_serial() 3424 assert ser == b"010B" 3425 3426 revoked.set_serial(b"31ppp") # a type error would be nice 3427 ser = revoked.get_serial() 3428 assert ser == b"31" 3429 3430 with pytest.raises(ValueError): 3431 revoked.set_serial(b"pqrst") 3432 with pytest.raises(TypeError): 3433 revoked.set_serial(100) 3434 3435 def test_date(self): 3436 """ 3437 Confirm we can set and get revocation dates from 3438 `OpenSSL.crypto.Revoked`. Confirm errors are handled with grace. 3439 """ 3440 revoked = Revoked() 3441 date = revoked.get_rev_date() 3442 assert date is None 3443 3444 now = datetime.now().strftime("%Y%m%d%H%M%SZ").encode("ascii") 3445 ret = revoked.set_rev_date(now) 3446 assert ret is None 3447 date = revoked.get_rev_date() 3448 assert date == now 3449 3450 def test_reason(self): 3451 """ 3452 Confirm we can set and get revocation reasons from 3453 `OpenSSL.crypto.Revoked`. The "get" need to work as "set". 3454 Likewise, each reason of all_reasons() must work. 3455 """ 3456 revoked = Revoked() 3457 for r in revoked.all_reasons(): 3458 for x in range(2): 3459 ret = revoked.set_reason(r) 3460 assert ret is None 3461 reason = revoked.get_reason() 3462 assert reason.lower().replace(b" ", b"") == r.lower().replace( 3463 b" ", b"" 3464 ) 3465 r = reason # again with the resp of get 3466 3467 revoked.set_reason(None) 3468 assert revoked.get_reason() is None 3469 3470 @pytest.mark.parametrize("reason", [object(), 1.0, u"foo"]) 3471 def test_set_reason_wrong_args(self, reason): 3472 """ 3473 `Revoked.set_reason` raises `TypeError` if called with an argument 3474 which is neither `None` nor a byte string. 3475 """ 3476 revoked = Revoked() 3477 with pytest.raises(TypeError): 3478 revoked.set_reason(reason) 3479 3480 def test_set_reason_invalid_reason(self): 3481 """ 3482 Calling `OpenSSL.crypto.Revoked.set_reason` with an argument which 3483 isn't a valid reason results in `ValueError` being raised. 3484 """ 3485 revoked = Revoked() 3486 with pytest.raises(ValueError): 3487 revoked.set_reason(b"blue") 3488 3489 3490class TestCRL(object): 3491 """ 3492 Tests for `OpenSSL.crypto.CRL`. 3493 """ 3494 3495 cert = load_certificate(FILETYPE_PEM, root_cert_pem) 3496 pkey = load_privatekey(FILETYPE_PEM, root_key_pem) 3497 3498 root_cert = load_certificate(FILETYPE_PEM, root_cert_pem) 3499 root_key = load_privatekey(FILETYPE_PEM, root_key_pem) 3500 intermediate_cert = load_certificate(FILETYPE_PEM, intermediate_cert_pem) 3501 intermediate_key = load_privatekey(FILETYPE_PEM, intermediate_key_pem) 3502 intermediate_server_cert = load_certificate( 3503 FILETYPE_PEM, intermediate_server_cert_pem 3504 ) 3505 intermediate_server_key = load_privatekey( 3506 FILETYPE_PEM, intermediate_server_key_pem 3507 ) 3508 3509 def test_construction(self): 3510 """ 3511 Confirm we can create `OpenSSL.crypto.CRL`. Check 3512 that it is empty 3513 """ 3514 crl = CRL() 3515 assert isinstance(crl, CRL) 3516 assert crl.get_revoked() is None 3517 3518 def _get_crl(self): 3519 """ 3520 Get a new ``CRL`` with a revocation. 3521 """ 3522 crl = CRL() 3523 revoked = Revoked() 3524 now = datetime.now().strftime("%Y%m%d%H%M%SZ").encode("ascii") 3525 revoked.set_rev_date(now) 3526 revoked.set_serial(b"3ab") 3527 revoked.set_reason(b"sUpErSeDEd") 3528 crl.add_revoked(revoked) 3529 return crl 3530 3531 def test_export_pem(self): 3532 """ 3533 If not passed a format, ``CRL.export`` returns a "PEM" format string 3534 representing a serial number, a revoked reason, and certificate issuer 3535 information. 3536 """ 3537 # PEM format 3538 dumped_crl = self._get_crl().export( 3539 self.cert, self.pkey, days=20, digest=b"sha256" 3540 ) 3541 crl = x509.load_pem_x509_crl(dumped_crl, backend) 3542 revoked = crl.get_revoked_certificate_by_serial_number(0x03AB) 3543 assert revoked is not None 3544 assert crl.issuer == x509.Name( 3545 [ 3546 x509.NameAttribute(x509.NameOID.COUNTRY_NAME, u"US"), 3547 x509.NameAttribute(x509.NameOID.STATE_OR_PROVINCE_NAME, u"IL"), 3548 x509.NameAttribute(x509.NameOID.LOCALITY_NAME, u"Chicago"), 3549 x509.NameAttribute(x509.NameOID.ORGANIZATION_NAME, u"Testing"), 3550 x509.NameAttribute( 3551 x509.NameOID.COMMON_NAME, u"Testing Root CA" 3552 ), 3553 ] 3554 ) 3555 3556 def test_export_der(self): 3557 """ 3558 If passed ``FILETYPE_ASN1`` for the format, ``CRL.export`` returns a 3559 "DER" format string representing a serial number, a revoked reason, and 3560 certificate issuer information. 3561 """ 3562 crl = self._get_crl() 3563 3564 # DER format 3565 dumped_crl = self._get_crl().export( 3566 self.cert, self.pkey, FILETYPE_ASN1, digest=b"md5" 3567 ) 3568 crl = x509.load_der_x509_crl(dumped_crl, backend) 3569 revoked = crl.get_revoked_certificate_by_serial_number(0x03AB) 3570 assert revoked is not None 3571 assert crl.issuer == x509.Name( 3572 [ 3573 x509.NameAttribute(x509.NameOID.COUNTRY_NAME, u"US"), 3574 x509.NameAttribute(x509.NameOID.STATE_OR_PROVINCE_NAME, u"IL"), 3575 x509.NameAttribute(x509.NameOID.LOCALITY_NAME, u"Chicago"), 3576 x509.NameAttribute(x509.NameOID.ORGANIZATION_NAME, u"Testing"), 3577 x509.NameAttribute( 3578 x509.NameOID.COMMON_NAME, u"Testing Root CA" 3579 ), 3580 ] 3581 ) 3582 3583 def test_export_text(self): 3584 """ 3585 If passed ``FILETYPE_TEXT`` for the format, ``CRL.export`` returns a 3586 text format string like the one produced by the openssl command line 3587 tool. 3588 """ 3589 crl = self._get_crl() 3590 3591 # text format 3592 dumped_text = crl.export( 3593 self.cert, self.pkey, type=FILETYPE_TEXT, digest=b"md5" 3594 ) 3595 assert len(dumped_text) > 500 3596 3597 def test_export_custom_digest(self): 3598 """ 3599 If passed the name of a digest function, ``CRL.export`` uses a 3600 signature algorithm based on that digest function. 3601 """ 3602 crl = self._get_crl() 3603 dumped_crl = crl.export(self.cert, self.pkey, digest=b"sha1") 3604 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text") 3605 text.index(b"Signature Algorithm: sha1") 3606 3607 def test_export_md5_digest(self): 3608 """ 3609 If passed md5 as the digest function, ``CRL.export`` uses md5 and does 3610 not emit a deprecation warning. 3611 """ 3612 crl = self._get_crl() 3613 with pytest.warns(None) as catcher: 3614 simplefilter("always") 3615 assert 0 == len(catcher) 3616 dumped_crl = crl.export(self.cert, self.pkey, digest=b"md5") 3617 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text") 3618 text.index(b"Signature Algorithm: md5") 3619 3620 def test_export_default_digest(self): 3621 """ 3622 If not passed the name of a digest function, ``CRL.export`` raises a 3623 ``TypeError``. 3624 """ 3625 crl = self._get_crl() 3626 with pytest.raises(TypeError): 3627 crl.export(self.cert, self.pkey) 3628 3629 def test_export_invalid(self): 3630 """ 3631 If `CRL.export` is used with an uninitialized `X509` instance, 3632 `OpenSSL.crypto.Error` is raised. 3633 """ 3634 crl = CRL() 3635 with pytest.raises(Error): 3636 crl.export(X509(), PKey(), digest=b"sha256") 3637 3638 def test_add_revoked_keyword(self): 3639 """ 3640 `OpenSSL.CRL.add_revoked` accepts its single argument as the 3641 ``revoked`` keyword argument. 3642 """ 3643 crl = CRL() 3644 revoked = Revoked() 3645 revoked.set_serial(b"01") 3646 revoked.set_rev_date(b"20160310020145Z") 3647 crl.add_revoked(revoked=revoked) 3648 assert isinstance(crl.get_revoked()[0], Revoked) 3649 3650 def test_export_wrong_args(self): 3651 """ 3652 Calling `OpenSSL.CRL.export` with arguments other than the certificate, 3653 private key, integer file type, and integer number of days it 3654 expects, results in a `TypeError` being raised. 3655 """ 3656 crl = CRL() 3657 with pytest.raises(TypeError): 3658 crl.export(None, self.pkey, FILETYPE_PEM, 10) 3659 with pytest.raises(TypeError): 3660 crl.export(self.cert, None, FILETYPE_PEM, 10) 3661 with pytest.raises(TypeError): 3662 crl.export(self.cert, self.pkey, None, 10) 3663 with pytest.raises(TypeError): 3664 crl.export(self.cert, FILETYPE_PEM, None) 3665 3666 def test_export_unknown_filetype(self): 3667 """ 3668 Calling `OpenSSL.CRL.export` with a file type other than 3669 `FILETYPE_PEM`, `FILETYPE_ASN1`, or 3670 `FILETYPE_TEXT` results in a `ValueError` being raised. 3671 """ 3672 crl = CRL() 3673 with pytest.raises(ValueError): 3674 crl.export(self.cert, self.pkey, 100, 10, digest=b"sha256") 3675 3676 def test_export_unknown_digest(self): 3677 """ 3678 Calling `OpenSSL.CRL.export` with an unsupported digest results 3679 in a `ValueError` being raised. 3680 """ 3681 crl = CRL() 3682 with pytest.raises(ValueError): 3683 crl.export( 3684 self.cert, self.pkey, FILETYPE_PEM, 10, b"strange-digest" 3685 ) 3686 3687 def test_get_revoked(self): 3688 """ 3689 Use python to create a simple CRL with two revocations. Get back the 3690 `Revoked` using `OpenSSL.CRL.get_revoked` and verify them. 3691 """ 3692 crl = CRL() 3693 3694 revoked = Revoked() 3695 now = datetime.now().strftime("%Y%m%d%H%M%SZ").encode("ascii") 3696 revoked.set_rev_date(now) 3697 revoked.set_serial(b"3ab") 3698 crl.add_revoked(revoked) 3699 revoked.set_serial(b"100") 3700 revoked.set_reason(b"sUpErSeDEd") 3701 crl.add_revoked(revoked) 3702 3703 revs = crl.get_revoked() 3704 assert len(revs) == 2 3705 assert type(revs[0]) == Revoked 3706 assert type(revs[1]) == Revoked 3707 assert revs[0].get_serial() == b"03AB" 3708 assert revs[1].get_serial() == b"0100" 3709 assert revs[0].get_rev_date() == now 3710 assert revs[1].get_rev_date() == now 3711 3712 def test_load_crl(self): 3713 """ 3714 Load a known CRL and inspect its revocations. Both EM and DER formats 3715 are loaded. 3716 """ 3717 crl = load_crl(FILETYPE_PEM, crlData) 3718 revs = crl.get_revoked() 3719 assert len(revs) == 2 3720 assert revs[0].get_serial() == b"03AB" 3721 assert revs[0].get_reason() is None 3722 assert revs[1].get_serial() == b"0100" 3723 assert revs[1].get_reason() == b"Superseded" 3724 3725 der = _runopenssl(crlData, b"crl", b"-outform", b"DER") 3726 crl = load_crl(FILETYPE_ASN1, der) 3727 revs = crl.get_revoked() 3728 assert len(revs) == 2 3729 assert revs[0].get_serial() == b"03AB" 3730 assert revs[0].get_reason() is None 3731 assert revs[1].get_serial() == b"0100" 3732 assert revs[1].get_reason() == b"Superseded" 3733 3734 def test_load_crl_bad_filetype(self): 3735 """ 3736 Calling `OpenSSL.crypto.load_crl` with an unknown file type raises a 3737 `ValueError`. 3738 """ 3739 with pytest.raises(ValueError): 3740 load_crl(100, crlData) 3741 3742 def test_load_crl_bad_data(self): 3743 """ 3744 Calling `OpenSSL.crypto.load_crl` with file data which can't be loaded 3745 raises a `OpenSSL.crypto.Error`. 3746 """ 3747 with pytest.raises(Error): 3748 load_crl(FILETYPE_PEM, b"hello, world") 3749 3750 def test_get_issuer(self): 3751 """ 3752 Load a known CRL and assert its issuer's common name is what we expect 3753 from the encoded crlData string. 3754 """ 3755 crl = load_crl(FILETYPE_PEM, crlData) 3756 assert isinstance(crl.get_issuer(), X509Name) 3757 assert crl.get_issuer().CN == "Testing Root CA" 3758 3759 def test_dump_crl(self): 3760 """ 3761 The dumped CRL matches the original input. 3762 """ 3763 crl = load_crl(FILETYPE_PEM, crlData) 3764 buf = dump_crl(FILETYPE_PEM, crl) 3765 assert buf == crlData 3766 3767 def _make_test_crl(self, issuer_cert, issuer_key, certs=()): 3768 """ 3769 Create a CRL. 3770 3771 :param list[X509] certs: A list of certificates to revoke. 3772 :rtype: CRL 3773 """ 3774 crl = CRL() 3775 for cert in certs: 3776 revoked = Revoked() 3777 # FIXME: This string splicing is an unfortunate implementation 3778 # detail that has been reported in 3779 # https://github.com/pyca/pyopenssl/issues/258 3780 serial = hex(cert.get_serial_number())[2:].encode("utf-8") 3781 revoked.set_serial(serial) 3782 revoked.set_reason(b"unspecified") 3783 revoked.set_rev_date(b"20140601000000Z") 3784 crl.add_revoked(revoked) 3785 crl.set_version(1) 3786 crl.set_lastUpdate(b"20140601000000Z") 3787 crl.set_nextUpdate(b"20180601000000Z") 3788 crl.sign(issuer_cert, issuer_key, digest=b"sha512") 3789 return crl 3790 3791 def test_verify_with_revoked(self): 3792 """ 3793 `verify_certificate` raises error when an intermediate certificate is 3794 revoked. 3795 """ 3796 store = X509Store() 3797 store.add_cert(self.root_cert) 3798 store.add_cert(self.intermediate_cert) 3799 root_crl = self._make_test_crl( 3800 self.root_cert, self.root_key, certs=[self.intermediate_cert] 3801 ) 3802 intermediate_crl = self._make_test_crl( 3803 self.intermediate_cert, self.intermediate_key, certs=[] 3804 ) 3805 store.add_crl(root_crl) 3806 store.add_crl(intermediate_crl) 3807 store.set_flags( 3808 X509StoreFlags.CRL_CHECK | X509StoreFlags.CRL_CHECK_ALL 3809 ) 3810 store_ctx = X509StoreContext(store, self.intermediate_server_cert) 3811 with pytest.raises(X509StoreContextError) as err: 3812 store_ctx.verify_certificate() 3813 assert err.value.args[0][2] == "certificate revoked" 3814 3815 def test_verify_with_missing_crl(self): 3816 """ 3817 `verify_certificate` raises error when an intermediate certificate's 3818 CRL is missing. 3819 """ 3820 store = X509Store() 3821 store.add_cert(self.root_cert) 3822 store.add_cert(self.intermediate_cert) 3823 root_crl = self._make_test_crl( 3824 self.root_cert, self.root_key, certs=[self.intermediate_cert] 3825 ) 3826 store.add_crl(root_crl) 3827 store.set_flags( 3828 X509StoreFlags.CRL_CHECK | X509StoreFlags.CRL_CHECK_ALL 3829 ) 3830 store_ctx = X509StoreContext(store, self.intermediate_server_cert) 3831 with pytest.raises(X509StoreContextError) as err: 3832 store_ctx.verify_certificate() 3833 assert err.value.args[0][2] == "unable to get certificate CRL" 3834 assert err.value.certificate.get_subject().CN == "intermediate-service" 3835 3836 def test_convert_from_cryptography(self): 3837 crypto_crl = x509.load_pem_x509_crl(crlData, backend) 3838 crl = CRL.from_cryptography(crypto_crl) 3839 assert isinstance(crl, CRL) 3840 3841 def test_convert_from_cryptography_unsupported_type(self): 3842 with pytest.raises(TypeError): 3843 CRL.from_cryptography(object()) 3844 3845 def test_convert_to_cryptography_key(self): 3846 crl = load_crl(FILETYPE_PEM, crlData) 3847 crypto_crl = crl.to_cryptography() 3848 assert isinstance(crypto_crl, x509.CertificateRevocationList) 3849 3850 3851class TestX509StoreContext(object): 3852 """ 3853 Tests for `OpenSSL.crypto.X509StoreContext`. 3854 """ 3855 3856 root_cert = load_certificate(FILETYPE_PEM, root_cert_pem) 3857 intermediate_cert = load_certificate(FILETYPE_PEM, intermediate_cert_pem) 3858 intermediate_server_cert = load_certificate( 3859 FILETYPE_PEM, intermediate_server_cert_pem 3860 ) 3861 3862 def test_valid(self): 3863 """ 3864 `verify_certificate` returns ``None`` when called with a certificate 3865 and valid chain. 3866 """ 3867 store = X509Store() 3868 store.add_cert(self.root_cert) 3869 store.add_cert(self.intermediate_cert) 3870 store_ctx = X509StoreContext(store, self.intermediate_server_cert) 3871 assert store_ctx.verify_certificate() is None 3872 3873 def test_reuse(self): 3874 """ 3875 `verify_certificate` can be called multiple times with the same 3876 ``X509StoreContext`` instance to produce the same result. 3877 """ 3878 store = X509Store() 3879 store.add_cert(self.root_cert) 3880 store.add_cert(self.intermediate_cert) 3881 store_ctx = X509StoreContext(store, self.intermediate_server_cert) 3882 assert store_ctx.verify_certificate() is None 3883 assert store_ctx.verify_certificate() is None 3884 3885 @pytest.mark.parametrize( 3886 "root_cert, chain, verified_cert", 3887 [ 3888 pytest.param( 3889 root_cert, 3890 [intermediate_cert], 3891 intermediate_server_cert, 3892 id="intermediate in chain", 3893 ), 3894 pytest.param( 3895 root_cert, 3896 [], 3897 intermediate_cert, 3898 id="empty chain", 3899 ), 3900 pytest.param( 3901 root_cert, 3902 [root_cert, intermediate_server_cert, intermediate_cert], 3903 intermediate_server_cert, 3904 id="extra certs in chain", 3905 ), 3906 ], 3907 ) 3908 def test_verify_success_with_chain(self, root_cert, chain, verified_cert): 3909 store = X509Store() 3910 store.add_cert(root_cert) 3911 store_ctx = X509StoreContext(store, verified_cert, chain=chain) 3912 assert store_ctx.verify_certificate() is None 3913 3914 def test_valid_untrusted_chain_reuse(self): 3915 """ 3916 `verify_certificate` using an untrusted chain can be called multiple 3917 times with the same ``X509StoreContext`` instance to produce the same 3918 result. 3919 """ 3920 store = X509Store() 3921 store.add_cert(self.root_cert) 3922 chain = [self.intermediate_cert] 3923 3924 store_ctx = X509StoreContext( 3925 store, self.intermediate_server_cert, chain=chain 3926 ) 3927 assert store_ctx.verify_certificate() is None 3928 assert store_ctx.verify_certificate() is None 3929 3930 def test_chain_reference(self): 3931 """ 3932 ``X509StoreContext`` properly keeps references to the untrusted chain 3933 certificates. 3934 """ 3935 store = X509Store() 3936 store.add_cert(self.root_cert) 3937 chain = [load_certificate(FILETYPE_PEM, intermediate_cert_pem)] 3938 3939 store_ctx = X509StoreContext( 3940 store, self.intermediate_server_cert, chain=chain 3941 ) 3942 3943 del chain 3944 assert store_ctx.verify_certificate() is None 3945 3946 @pytest.mark.parametrize( 3947 "root_cert, chain, verified_cert", 3948 [ 3949 pytest.param( 3950 root_cert, 3951 [], 3952 intermediate_server_cert, 3953 id="intermediate missing", 3954 ), 3955 pytest.param( 3956 None, 3957 [intermediate_cert], 3958 intermediate_server_cert, 3959 id="no trusted root", 3960 ), 3961 pytest.param( 3962 None, 3963 [root_cert, intermediate_cert], 3964 intermediate_server_cert, 3965 id="untrusted root, full chain is available", 3966 ), 3967 pytest.param( 3968 intermediate_cert, 3969 [root_cert, intermediate_cert], 3970 intermediate_server_cert, 3971 id="untrusted root, intermediate is trusted and in chain", 3972 ), 3973 ], 3974 ) 3975 def test_verify_fail_with_chain(self, root_cert, chain, verified_cert): 3976 store = X509Store() 3977 if root_cert: 3978 store.add_cert(root_cert) 3979 3980 store_ctx = X509StoreContext(store, verified_cert, chain=chain) 3981 3982 with pytest.raises(X509StoreContextError): 3983 store_ctx.verify_certificate() 3984 3985 @pytest.mark.parametrize( 3986 "chain, expected_error", 3987 [ 3988 pytest.param( 3989 [intermediate_cert, "This is not a certificate"], 3990 TypeError, 3991 id="non-certificate in chain", 3992 ), 3993 pytest.param( 3994 42, 3995 TypeError, 3996 id="non-list chain", 3997 ), 3998 ], 3999 ) 4000 def test_untrusted_chain_wrong_args(self, chain, expected_error): 4001 """ 4002 Creating ``X509StoreContext`` with wrong chain raises an exception. 4003 """ 4004 store = X509Store() 4005 store.add_cert(self.root_cert) 4006 4007 with pytest.raises(expected_error): 4008 X509StoreContext(store, self.intermediate_server_cert, chain=chain) 4009 4010 def test_failure_building_untrusted_chain_raises(self, monkeypatch): 4011 """ 4012 Creating ``X509StoreContext`` raises ``OpenSSL.crypto.Error`` when 4013 the underlying lib fails to add the certificate to the stack. 4014 """ 4015 monkeypatch.setattr(_lib, "sk_X509_push", lambda _stack, _x509: -1) 4016 4017 store = X509Store() 4018 store.add_cert(self.root_cert) 4019 chain = [self.intermediate_cert] 4020 4021 with pytest.raises(Error): 4022 X509StoreContext(store, self.intermediate_server_cert, chain=chain) 4023 4024 def test_trusted_self_signed(self): 4025 """ 4026 `verify_certificate` returns ``None`` when called with a self-signed 4027 certificate and itself in the chain. 4028 """ 4029 store = X509Store() 4030 store.add_cert(self.root_cert) 4031 store_ctx = X509StoreContext(store, self.root_cert) 4032 assert store_ctx.verify_certificate() is None 4033 4034 def test_untrusted_self_signed(self): 4035 """ 4036 `verify_certificate` raises error when a self-signed certificate is 4037 verified without itself in the chain. 4038 """ 4039 store = X509Store() 4040 store_ctx = X509StoreContext(store, self.root_cert) 4041 with pytest.raises(X509StoreContextError) as exc: 4042 store_ctx.verify_certificate() 4043 4044 assert exc.value.args[0][2] == "self signed certificate" 4045 assert exc.value.certificate.get_subject().CN == "Testing Root CA" 4046 4047 def test_invalid_chain_no_root(self): 4048 """ 4049 `verify_certificate` raises error when a root certificate is missing 4050 from the chain. 4051 """ 4052 store = X509Store() 4053 store.add_cert(self.intermediate_cert) 4054 store_ctx = X509StoreContext(store, self.intermediate_server_cert) 4055 4056 with pytest.raises(X509StoreContextError) as exc: 4057 store_ctx.verify_certificate() 4058 4059 assert exc.value.args[0][2] == "unable to get issuer certificate" 4060 assert exc.value.certificate.get_subject().CN == "intermediate" 4061 4062 def test_invalid_chain_no_intermediate(self): 4063 """ 4064 `verify_certificate` raises error when an intermediate certificate is 4065 missing from the chain. 4066 """ 4067 store = X509Store() 4068 store.add_cert(self.root_cert) 4069 store_ctx = X509StoreContext(store, self.intermediate_server_cert) 4070 4071 with pytest.raises(X509StoreContextError) as exc: 4072 store_ctx.verify_certificate() 4073 4074 assert exc.value.args[0][2] == "unable to get local issuer certificate" 4075 assert exc.value.certificate.get_subject().CN == "intermediate-service" 4076 4077 def test_modification_pre_verify(self): 4078 """ 4079 `verify_certificate` can use a store context modified after 4080 instantiation. 4081 """ 4082 store_bad = X509Store() 4083 store_bad.add_cert(self.intermediate_cert) 4084 store_good = X509Store() 4085 store_good.add_cert(self.root_cert) 4086 store_good.add_cert(self.intermediate_cert) 4087 store_ctx = X509StoreContext(store_bad, self.intermediate_server_cert) 4088 4089 with pytest.raises(X509StoreContextError) as exc: 4090 store_ctx.verify_certificate() 4091 4092 assert exc.value.args[0][2] == "unable to get issuer certificate" 4093 assert exc.value.certificate.get_subject().CN == "intermediate" 4094 4095 store_ctx.set_store(store_good) 4096 assert store_ctx.verify_certificate() is None 4097 4098 def test_verify_with_time(self): 4099 """ 4100 `verify_certificate` raises error when the verification time is 4101 set at notAfter. 4102 """ 4103 store = X509Store() 4104 store.add_cert(self.root_cert) 4105 store.add_cert(self.intermediate_cert) 4106 4107 expire_time = self.intermediate_server_cert.get_notAfter() 4108 expire_datetime = datetime.strptime( 4109 expire_time.decode("utf-8"), "%Y%m%d%H%M%SZ" 4110 ) 4111 store.set_time(expire_datetime) 4112 4113 store_ctx = X509StoreContext(store, self.intermediate_server_cert) 4114 with pytest.raises(X509StoreContextError) as exc: 4115 store_ctx.verify_certificate() 4116 4117 assert exc.value.args[0][2] == "certificate has expired" 4118 4119 def test_get_verified_chain(self): 4120 """ 4121 `get_verified_chain` returns the verified chain. 4122 """ 4123 store = X509Store() 4124 store.add_cert(self.root_cert) 4125 store.add_cert(self.intermediate_cert) 4126 store_ctx = X509StoreContext(store, self.intermediate_server_cert) 4127 chain = store_ctx.get_verified_chain() 4128 assert len(chain) == 3 4129 intermediate_subject = self.intermediate_server_cert.get_subject() 4130 assert chain[0].get_subject() == intermediate_subject 4131 assert chain[1].get_subject() == self.intermediate_cert.get_subject() 4132 assert chain[2].get_subject() == self.root_cert.get_subject() 4133 # Test reuse 4134 chain = store_ctx.get_verified_chain() 4135 assert len(chain) == 3 4136 assert chain[0].get_subject() == intermediate_subject 4137 assert chain[1].get_subject() == self.intermediate_cert.get_subject() 4138 assert chain[2].get_subject() == self.root_cert.get_subject() 4139 4140 def test_get_verified_chain_invalid_chain_no_root(self): 4141 """ 4142 `get_verified_chain` raises error when cert verification fails. 4143 """ 4144 store = X509Store() 4145 store.add_cert(self.intermediate_cert) 4146 store_ctx = X509StoreContext(store, self.intermediate_server_cert) 4147 4148 with pytest.raises(X509StoreContextError) as exc: 4149 store_ctx.get_verified_chain() 4150 4151 assert exc.value.args[0][2] == "unable to get issuer certificate" 4152 assert exc.value.certificate.get_subject().CN == "intermediate" 4153 4154 @pytest.fixture 4155 def root_ca_file(self, tmpdir): 4156 return self._create_ca_file(tmpdir, "root_ca_hash_dir", self.root_cert) 4157 4158 @pytest.fixture 4159 def intermediate_ca_file(self, tmpdir): 4160 return self._create_ca_file( 4161 tmpdir, "intermediate_ca_hash_dir", self.intermediate_cert 4162 ) 4163 4164 @staticmethod 4165 def _create_ca_file(base_path, hash_directory, cacert): 4166 ca_hash = "{:08x}.0".format(cacert.subject_name_hash()) 4167 cafile = base_path.join(hash_directory, ca_hash) 4168 cafile.write_binary( 4169 dump_certificate(FILETYPE_PEM, cacert), ensure=True 4170 ) 4171 return cafile 4172 4173 def test_verify_with_ca_file_location(self, root_ca_file): 4174 store = X509Store() 4175 store.load_locations(str(root_ca_file)) 4176 4177 store_ctx = X509StoreContext(store, self.intermediate_cert) 4178 store_ctx.verify_certificate() 4179 4180 def test_verify_with_ca_path_location(self, root_ca_file): 4181 store = X509Store() 4182 store.load_locations(None, str(root_ca_file.dirname)) 4183 4184 store_ctx = X509StoreContext(store, self.intermediate_cert) 4185 store_ctx.verify_certificate() 4186 4187 def test_verify_with_cafile_and_capath( 4188 self, root_ca_file, intermediate_ca_file 4189 ): 4190 store = X509Store() 4191 store.load_locations( 4192 cafile=str(root_ca_file), capath=str(intermediate_ca_file.dirname) 4193 ) 4194 4195 store_ctx = X509StoreContext(store, self.intermediate_server_cert) 4196 store_ctx.verify_certificate() 4197 4198 def test_verify_with_multiple_ca_files( 4199 self, root_ca_file, intermediate_ca_file 4200 ): 4201 store = X509Store() 4202 store.load_locations(str(root_ca_file)) 4203 store.load_locations(str(intermediate_ca_file)) 4204 4205 store_ctx = X509StoreContext(store, self.intermediate_server_cert) 4206 store_ctx.verify_certificate() 4207 4208 def test_verify_failure_with_empty_ca_directory(self, tmpdir): 4209 store = X509Store() 4210 store.load_locations(None, str(tmpdir)) 4211 4212 store_ctx = X509StoreContext(store, self.intermediate_cert) 4213 with pytest.raises(X509StoreContextError) as exc: 4214 store_ctx.verify_certificate() 4215 4216 assert exc.value.args[0][2] == "unable to get local issuer certificate" 4217 4218 4219class TestSignVerify(object): 4220 """ 4221 Tests for `OpenSSL.crypto.sign` and `OpenSSL.crypto.verify`. 4222 """ 4223 4224 def test_sign_verify(self): 4225 """ 4226 `sign` generates a cryptographic signature which `verify` can check. 4227 """ 4228 content = ( 4229 b"It was a bright cold day in April, and the clocks were striking " 4230 b"thirteen. Winston Smith, his chin nuzzled into his breast in an " 4231 b"effort to escape the vile wind, slipped quickly through the " 4232 b"glass doors of Victory Mansions, though not quickly enough to " 4233 b"prevent a swirl of gritty dust from entering along with him." 4234 ) 4235 4236 # sign the content with this private key 4237 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem) 4238 # verify the content with this cert 4239 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem) 4240 # certificate unrelated to priv_key, used to trigger an error 4241 bad_cert = load_certificate(FILETYPE_PEM, server_cert_pem) 4242 4243 for digest in ["md5", "sha1"]: 4244 sig = sign(priv_key, content, digest) 4245 4246 # Verify the signature of content, will throw an exception if 4247 # error. 4248 verify(good_cert, sig, content, digest) 4249 4250 # This should fail because the certificate doesn't match the 4251 # private key that was used to sign the content. 4252 with pytest.raises(Error): 4253 verify(bad_cert, sig, content, digest) 4254 4255 # This should fail because we've "tainted" the content after 4256 # signing it. 4257 with pytest.raises(Error): 4258 verify(good_cert, sig, content + b"tainted", digest) 4259 4260 # test that unknown digest types fail 4261 with pytest.raises(ValueError): 4262 sign(priv_key, content, "strange-digest") 4263 with pytest.raises(ValueError): 4264 verify(good_cert, sig, content, "strange-digest") 4265 4266 def test_sign_verify_with_text(self): 4267 """ 4268 `sign` generates a cryptographic signature which 4269 `verify` can check. Deprecation warnings raised because using 4270 text instead of bytes as content 4271 """ 4272 content = ( 4273 b"It was a bright cold day in April, and the clocks were striking " 4274 b"thirteen. Winston Smith, his chin nuzzled into his breast in an " 4275 b"effort to escape the vile wind, slipped quickly through the " 4276 b"glass doors of Victory Mansions, though not quickly enough to " 4277 b"prevent a swirl of gritty dust from entering along with him." 4278 ).decode("ascii") 4279 4280 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem) 4281 cert = load_certificate(FILETYPE_PEM, root_cert_pem) 4282 for digest in ["md5", "sha1"]: 4283 with pytest.warns(DeprecationWarning) as w: 4284 simplefilter("always") 4285 sig = sign(priv_key, content, digest) 4286 assert "{0} for data is no longer accepted, use bytes".format( 4287 WARNING_TYPE_EXPECTED 4288 ) == str(w[-1].message) 4289 4290 with pytest.warns(DeprecationWarning) as w: 4291 simplefilter("always") 4292 verify(cert, sig, content, digest) 4293 assert "{0} for data is no longer accepted, use bytes".format( 4294 WARNING_TYPE_EXPECTED 4295 ) == str(w[-1].message) 4296 4297 def test_sign_verify_ecdsa(self): 4298 """ 4299 `sign` generates a cryptographic signature which `verify` can check. 4300 ECDSA Signatures in the X9.62 format may have variable length, 4301 different from the length of the private key. 4302 """ 4303 content = ( 4304 b"It was a bright cold day in April, and the clocks were striking " 4305 b"thirteen. Winston Smith, his chin nuzzled into his breast in an " 4306 b"effort to escape the vile wind, slipped quickly through the " 4307 b"glass doors of Victory Mansions, though not quickly enough to " 4308 b"prevent a swirl of gritty dust from entering along with him." 4309 ) 4310 priv_key = load_privatekey(FILETYPE_PEM, ec_root_key_pem) 4311 cert = load_certificate(FILETYPE_PEM, ec_root_cert_pem) 4312 sig = sign(priv_key, content, "sha1") 4313 verify(cert, sig, content, "sha1") 4314 4315 def test_sign_nulls(self): 4316 """ 4317 `sign` produces a signature for a string with embedded nulls. 4318 """ 4319 content = b"Watch out! \0 Did you see it?" 4320 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem) 4321 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem) 4322 sig = sign(priv_key, content, "sha1") 4323 verify(good_cert, sig, content, "sha1") 4324 4325 def test_sign_with_large_key(self): 4326 """ 4327 `sign` produces a signature for a string when using a long key. 4328 """ 4329 content = ( 4330 b"It was a bright cold day in April, and the clocks were striking " 4331 b"thirteen. Winston Smith, his chin nuzzled into his breast in an " 4332 b"effort to escape the vile wind, slipped quickly through the " 4333 b"glass doors of Victory Mansions, though not quickly enough to " 4334 b"prevent a swirl of gritty dust from entering along with him." 4335 ) 4336 4337 priv_key = load_privatekey(FILETYPE_PEM, large_key_pem) 4338 sign(priv_key, content, "sha1") 4339 4340 4341class TestEllipticCurve(object): 4342 """ 4343 Tests for `_EllipticCurve`, `get_elliptic_curve`, and 4344 `get_elliptic_curves`. 4345 """ 4346 4347 def test_set(self): 4348 """ 4349 `get_elliptic_curves` returns a `set`. 4350 """ 4351 assert isinstance(get_elliptic_curves(), set) 4352 4353 def test_a_curve(self): 4354 """ 4355 `get_elliptic_curve` can be used to retrieve a particular supported 4356 curve. 4357 """ 4358 curves = get_elliptic_curves() 4359 curve = next(iter(curves)) 4360 assert curve.name == get_elliptic_curve(curve.name).name 4361 4362 def test_not_a_curve(self): 4363 """ 4364 `get_elliptic_curve` raises `ValueError` if called with a name which 4365 does not identify a supported curve. 4366 """ 4367 with pytest.raises(ValueError): 4368 get_elliptic_curve(u"this curve was just invented") 4369 4370 def test_repr(self): 4371 """ 4372 The string representation of a curve object includes simply states the 4373 object is a curve and what its name is. 4374 """ 4375 curves = get_elliptic_curves() 4376 curve = next(iter(curves)) 4377 assert "<Curve %r>" % (curve.name,) == repr(curve) 4378 4379 def test_to_EC_KEY(self): 4380 """ 4381 The curve object can export a version of itself as an EC_KEY* via the 4382 private `_EllipticCurve._to_EC_KEY`. 4383 """ 4384 curves = get_elliptic_curves() 4385 curve = next(iter(curves)) 4386 # It's not easy to assert anything about this object. However, see 4387 # leakcheck/crypto.py for a test that demonstrates it at least does 4388 # not leak memory. 4389 curve._to_EC_KEY() 4390 4391 4392class EllipticCurveFactory(object): 4393 """ 4394 A helper to get the names of two curves. 4395 """ 4396 4397 def __init__(self): 4398 curves = iter(get_elliptic_curves()) 4399 self.curve_name = next(curves).name 4400 self.another_curve_name = next(curves).name 4401 4402 4403class TestEllipticCurveEquality(EqualityTestsMixin): 4404 """ 4405 Tests `_EllipticCurve`'s implementation of ``==`` and ``!=``. 4406 """ 4407 4408 curve_factory = EllipticCurveFactory() 4409 4410 if curve_factory.curve_name is None: 4411 skip = "There are no curves available there can be no curve objects." 4412 4413 def anInstance(self): 4414 """ 4415 Get the curve object for an arbitrary curve supported by the system. 4416 """ 4417 return get_elliptic_curve(self.curve_factory.curve_name) 4418 4419 def anotherInstance(self): 4420 """ 4421 Get the curve object for an arbitrary curve supported by the system - 4422 but not the one returned by C{anInstance}. 4423 """ 4424 return get_elliptic_curve(self.curve_factory.another_curve_name) 4425 4426 4427class TestEllipticCurveHash(object): 4428 """ 4429 Tests for `_EllipticCurve`'s implementation of hashing (thus use as 4430 an item in a `dict` or `set`). 4431 """ 4432 4433 curve_factory = EllipticCurveFactory() 4434 4435 if curve_factory.curve_name is None: 4436 skip = "There are no curves available there can be no curve objects." 4437 4438 def test_contains(self): 4439 """ 4440 The ``in`` operator reports that a `set` containing a curve does 4441 contain that curve. 4442 """ 4443 curve = get_elliptic_curve(self.curve_factory.curve_name) 4444 curves = set([curve]) 4445 assert curve in curves 4446 4447 def test_does_not_contain(self): 4448 """ 4449 The ``in`` operator reports that a `set` not containing a curve 4450 does not contain that curve. 4451 """ 4452 curve = get_elliptic_curve(self.curve_factory.curve_name) 4453 curves = set( 4454 [get_elliptic_curve(self.curve_factory.another_curve_name)] 4455 ) 4456 assert curve not in curves 4457