blob: ba4e0d59e20c2280bf1559708083e2e370717420 [file] [log] [blame]
Jean-Paul Calderone8671c852011-03-02 19:26:20 -05001# Copyright (c) Jean-Paul Calderone
2# See LICENSE file for details.
Jean-Paul Calderone8b63d452008-03-21 18:31:12 -04003
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -05004"""
Jonathan Ballet648875f2011-07-16 14:14:58 +09005Unit tests for :py:mod:`OpenSSL.crypto`.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -05006"""
7
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04008from unittest import main
9
Alex Gaynor4b9c96a2014-08-14 09:51:48 -070010import base64
11import os
12import re
Jean-Paul Calderone62ca8da2010-08-11 19:58:08 -040013from subprocess import PIPE, Popen
Rick Dean47262da2009-07-08 16:17:17 -050014from datetime import datetime, timedelta
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -050015
Abraham Martinc5484ba2015-03-25 15:33:05 +000016from six import u, b, binary_type, PY3
17from warnings import simplefilter
18from warnings import catch_warnings
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050019
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -050020from OpenSSL.crypto import TYPE_RSA, TYPE_DSA, Error, PKey, PKeyType
Jean-Paul Calderone78381d22008-03-06 23:35:22 -050021from OpenSSL.crypto import X509, X509Type, X509Name, X509NameType
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080022from OpenSSL.crypto import X509Store, X509StoreType, X509Req, X509ReqType
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -050023from OpenSSL.crypto import X509Extension, X509ExtensionType
Rick Dean5b7b6372009-04-01 11:34:06 -050024from OpenSSL.crypto import load_certificate, load_privatekey
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -040025from OpenSSL.crypto import FILETYPE_PEM, FILETYPE_ASN1, FILETYPE_TEXT
Jean-Paul Calderone71919862009-04-01 13:01:19 -040026from OpenSSL.crypto import dump_certificate, load_certificate_request
27from OpenSSL.crypto import dump_certificate_request, dump_privatekey
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -040028from OpenSSL.crypto import PKCS7Type, load_pkcs7_data
Jean-Paul Calderone9178ee62010-01-25 17:55:30 -050029from OpenSSL.crypto import PKCS12, PKCS12Type, load_pkcs12
Rick Dean536ba022009-07-24 23:57:27 -050030from OpenSSL.crypto import CRL, Revoked, load_crl
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -040031from OpenSSL.crypto import NetscapeSPKI, NetscapeSPKIType
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040032from OpenSSL.crypto import (
33 sign, verify, get_elliptic_curve, get_elliptic_curves)
Jean-Paul Calderone1be77082014-04-30 18:17:41 -040034from OpenSSL.test.util import EqualityTestsMixin, TestCase
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040035from OpenSSL._util import native, lib
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040036
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -040037def normalize_certificate_pem(pem):
38 return dump_certificate(FILETYPE_PEM, load_certificate(FILETYPE_PEM, pem))
39
40
41def normalize_privatekey_pem(pem):
42 return dump_privatekey(FILETYPE_PEM, load_privatekey(FILETYPE_PEM, pem))
43
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040044
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050045GOOD_CIPHER = "blowfish"
46BAD_CIPHER = "zippers"
47
48GOOD_DIGEST = "MD5"
49BAD_DIGEST = "monkeys"
50
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040051root_cert_pem = b("""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -050052MIIC7TCCAlagAwIBAgIIPQzE4MbeufQwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE
53BhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdU
54ZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwIhgPMjAwOTAzMjUxMjM2
55NThaGA8yMDE3MDYxMTEyMzY1OFowWDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklM
56MRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9U
57ZXN0aW5nIFJvb3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPmaQumL
58urpE527uSEHdL1pqcDRmWzu+98Y6YHzT/J7KWEamyMCNZ6fRW1JCR782UQ8a07fy
592xXsKy4WdKaxyG8CcatwmXvpvRQ44dSANMihHELpANTdyVp6DCysED6wkQFurHlF
601dshEaJw8b/ypDhmbVIo6Ci1xvCJqivbLFnbAgMBAAGjgbswgbgwHQYDVR0OBBYE
61FINVdy1eIfFJDAkk51QJEo3IfgSuMIGIBgNVHSMEgYAwfoAUg1V3LV4h8UkMCSTn
62VAkSjch+BK6hXKRaMFgxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UE
63BxMHQ2hpY2FnbzEQMA4GA1UEChMHVGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBS
64b290IENBggg9DMTgxt659DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB
65AGGCDazMJGoWNBpc03u6+smc95dEead2KlZXBATOdFT1VesY3+nUOqZhEhTGlDMi
66hkgaZnzoIq/Uamidegk4hirsCT/R+6vsKAAxNTcBjUeZjlykCJWy5ojShGftXIKY
67w/njVbKMXrvc83qmTdGl3TAM0fxQIpqgcglFLveEBgzn
68-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040069""")
Rick Dean94e46fd2009-07-18 14:51:24 -050070
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040071root_key_pem = b("""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -050072MIICXQIBAAKBgQD5mkLpi7q6ROdu7khB3S9aanA0Zls7vvfGOmB80/yeylhGpsjA
73jWen0VtSQke/NlEPGtO38tsV7CsuFnSmschvAnGrcJl76b0UOOHUgDTIoRxC6QDU
743claegwsrBA+sJEBbqx5RdXbIRGicPG/8qQ4Zm1SKOgotcbwiaor2yxZ2wIDAQAB
75AoGBAPCgMpmLxzwDaUmcFbTJUvlLW1hoxNNYSu2jIZm1k/hRAcE60JYwvBkgz3UB
76yMEh0AtLxYe0bFk6EHah11tMUPgscbCq73snJ++8koUw+csk22G65hOs51bVb7Aa
776JBe67oLzdtvgCUFAA2qfrKzWRZzAdhUirQUZgySZk+Xq1pBAkEA/kZG0A6roTSM
78BVnx7LnPfsycKUsTumorpXiylZJjTi9XtmzxhrYN6wgZlDOOwOLgSQhszGpxVoMD
79u3gByT1b2QJBAPtL3mSKdvwRu/+40zaZLwvSJRxaj0mcE4BJOS6Oqs/hS1xRlrNk
80PpQ7WJ4yM6ZOLnXzm2mKyxm50Mv64109FtMCQQDOqS2KkjHaLowTGVxwC0DijMfr
81I9Lf8sSQk32J5VWCySWf5gGTfEnpmUa41gKTMJIbqZZLucNuDcOtzUaeWZlZAkA8
82ttXigLnCqR486JDPTi9ZscoZkZ+w7y6e/hH8t6d5Vjt48JVyfjPIaJY+km58LcN3
836AWSeGAdtRFHVzR7oHjVAkB4hutvxiOeiIVQNBhM6RSI9aBPMI21DoX2JRoxvNW2
84cbvAhow217X9V0dVerEOKxnNYspXRrh36h7k4mQA+sDq
85-----END RSA PRIVATE KEY-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040086""")
Rick Dean94e46fd2009-07-18 14:51:24 -050087
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040088server_cert_pem = b("""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -050089MIICKDCCAZGgAwIBAgIJAJn/HpR21r/8MA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
90BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
91VGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBSb290IENBMCIYDzIwMDkwMzI1MTIz
92NzUzWhgPMjAxNzA2MTExMjM3NTNaMBgxFjAUBgNVBAMTDWxvdmVseSBzZXJ2ZXIw
93gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAL6m+G653V0tpBC/OKl22VxOi2Cv
94lK4TYu9LHSDP9uDVTe7V5D5Tl6qzFoRRx5pfmnkqT5B+W9byp2NU3FC5hLm5zSAr
95b45meUhjEJ/ifkZgbNUjHdBIGP9MAQUHZa5WKdkGIJvGAvs8UzUqlr4TBWQIB24+
96lJ+Ukk/CRgasrYwdAgMBAAGjNjA0MB0GA1UdDgQWBBS4kC7Ij0W1TZXZqXQFAM2e
97gKEG2DATBgNVHSUEDDAKBggrBgEFBQcDATANBgkqhkiG9w0BAQUFAAOBgQBh30Li
98dJ+NlxIOx5343WqIBka3UbsOb2kxWrbkVCrvRapCMLCASO4FqiKWM+L0VDBprqIp
992mgpFQ6FHpoIENGvJhdEKpptQ5i7KaGhnDNTfdy3x1+h852G99f1iyj0RmbuFcM8
100uzujnS8YXWvM7DM1Ilozk4MzPug8jzFp5uhKCQ==
101-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400102""")
Rick Dean94e46fd2009-07-18 14:51:24 -0500103
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -0400104server_key_pem = normalize_privatekey_pem(b("""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500105MIICWwIBAAKBgQC+pvhuud1dLaQQvzipdtlcTotgr5SuE2LvSx0gz/bg1U3u1eQ+
106U5eqsxaEUceaX5p5Kk+QflvW8qdjVNxQuYS5uc0gK2+OZnlIYxCf4n5GYGzVIx3Q
107SBj/TAEFB2WuVinZBiCbxgL7PFM1Kpa+EwVkCAduPpSflJJPwkYGrK2MHQIDAQAB
108AoGAbwuZ0AR6JveahBaczjfnSpiFHf+mve2UxoQdpyr6ROJ4zg/PLW5K/KXrC48G
109j6f3tXMrfKHcpEoZrQWUfYBRCUsGD5DCazEhD8zlxEHahIsqpwA0WWssJA2VOLEN
110j6DuV2pCFbw67rfTBkTSo32ahfXxEKev5KswZk0JIzH3ooECQQDgzS9AI89h0gs8
111Dt+1m11Rzqo3vZML7ZIyGApUzVan+a7hbc33nbGRkAXjHaUBJO31it/H6dTO+uwX
112msWwNG5ZAkEA2RyFKs5xR5USTFaKLWCgpH/ydV96KPOpBND7TKQx62snDenFNNbn
113FwwOhpahld+vqhYk+pfuWWUpQciE+Bu7ZQJASjfT4sQv4qbbKK/scePicnDdx9th
1144e1EeB9xwb+tXXXUo/6Bor/AcUNwfiQ6Zt9PZOK9sR3lMZSsP7rMi7kzuQJABie6
1151sXXjFH7nNJvRG4S39cIxq8YRYTy68II/dlB2QzGpKxV/POCxbJ/zu0CU79tuYK7
116NaeNCFfH3aeTrX0LyQJAMBWjWmeKM2G2sCExheeQK0ROnaBC8itCECD4Jsve4nqf
117r50+LF74iLXFwqysVCebPKMOpDWp/qQ1BbJQIPs7/A==
118-----END RSA PRIVATE KEY-----
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -0400119"""))
Rick Dean94e46fd2009-07-18 14:51:24 -0500120
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400121client_cert_pem = b("""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500122MIICJjCCAY+gAwIBAgIJAKxpFI5lODkjMA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
123BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
124VGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBSb290IENBMCIYDzIwMDkwMzI1MTIz
125ODA1WhgPMjAxNzA2MTExMjM4MDVaMBYxFDASBgNVBAMTC3VnbHkgY2xpZW50MIGf
126MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDAZh/SRtNm5ntMT4qb6YzEpTroMlq2
127rn+GrRHRiZ+xkCw/CGNhbtPir7/QxaUj26BSmQrHw1bGKEbPsWiW7bdXSespl+xK
128iku4G/KvnnmWdeJHqsiXeUZtqurMELcPQAw9xPHEuhqqUJvvEoMTsnCEqGM+7Dtb
129oCRajYyHfluARQIDAQABozYwNDAdBgNVHQ4EFgQUNQB+qkaOaEVecf1J3TTUtAff
1300fAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQEFBQADgYEAyv/Jh7gM
131Q3OHvmsFEEvRI+hsW8y66zK4K5de239Y44iZrFYkt7Q5nBPMEWDj4F2hLYWL/qtI
1329Zdr0U4UDCU9SmmGYh4o7R4TZ5pGFvBYvjhHbkSFYFQXZxKUi+WUxplP6I0wr2KJ
133PSTJCjJOn3xo2NTKRgV1gaoTf2EhL+RG8TQ=
134-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400135""")
Rick Dean94e46fd2009-07-18 14:51:24 -0500136
Jean-Paul Calderone22cbe502011-05-04 17:01:43 -0400137client_key_pem = normalize_privatekey_pem(b("""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500138MIICXgIBAAKBgQDAZh/SRtNm5ntMT4qb6YzEpTroMlq2rn+GrRHRiZ+xkCw/CGNh
139btPir7/QxaUj26BSmQrHw1bGKEbPsWiW7bdXSespl+xKiku4G/KvnnmWdeJHqsiX
140eUZtqurMELcPQAw9xPHEuhqqUJvvEoMTsnCEqGM+7DtboCRajYyHfluARQIDAQAB
141AoGATkZ+NceY5Glqyl4mD06SdcKfV65814vg2EL7V9t8+/mi9rYL8KztSXGlQWPX
142zuHgtRoMl78yQ4ZJYOBVo+nsx8KZNRCEBlE19bamSbQLCeQMenWnpeYyQUZ908gF
143h6L9qsFVJepgA9RDgAjyDoS5CaWCdCCPCH2lDkdcqC54SVUCQQDseuduc4wi8h4t
144V8AahUn9fn9gYfhoNuM0gdguTA0nPLVWz4hy1yJiWYQe0H7NLNNTmCKiLQaJpAbb
145TC6vE8C7AkEA0Ee8CMJUc20BnGEmxwgWcVuqFWaKCo8jTH1X38FlATUsyR3krjW2
146dL3yDD9NwHxsYP7nTKp/U8MV7U9IBn4y/wJBAJl7H0/BcLeRmuJk7IqJ7b635iYB
147D/9beFUw3MUXmQXZUfyYz39xf6CDZsu1GEdEC5haykeln3Of4M9d/4Kj+FcCQQCY
148si6xwT7GzMDkk/ko684AV3KPc/h6G0yGtFIrMg7J3uExpR/VdH2KgwMkZXisSMvw
149JJEQjOMCVsEJlRk54WWjAkEAzoZNH6UhDdBK5F38rVt/y4SEHgbSfJHIAmPS32Kq
150f6GGcfNpip0Uk7q7udTKuX7Q/buZi/C4YW7u3VKAquv9NA==
151-----END RSA PRIVATE KEY-----
Jean-Paul Calderone22cbe502011-05-04 17:01:43 -0400152"""))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400153
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400154cleartextCertificatePEM = b("""-----BEGIN CERTIFICATE-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400155MIIC7TCCAlagAwIBAgIIPQzE4MbeufQwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE
156BhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdU
157ZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwIhgPMjAwOTAzMjUxMjM2
158NThaGA8yMDE3MDYxMTEyMzY1OFowWDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklM
159MRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9U
160ZXN0aW5nIFJvb3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPmaQumL
161urpE527uSEHdL1pqcDRmWzu+98Y6YHzT/J7KWEamyMCNZ6fRW1JCR782UQ8a07fy
1622xXsKy4WdKaxyG8CcatwmXvpvRQ44dSANMihHELpANTdyVp6DCysED6wkQFurHlF
1631dshEaJw8b/ypDhmbVIo6Ci1xvCJqivbLFnbAgMBAAGjgbswgbgwHQYDVR0OBBYE
164FINVdy1eIfFJDAkk51QJEo3IfgSuMIGIBgNVHSMEgYAwfoAUg1V3LV4h8UkMCSTn
165VAkSjch+BK6hXKRaMFgxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UE
166BxMHQ2hpY2FnbzEQMA4GA1UEChMHVGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBS
167b290IENBggg9DMTgxt659DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB
168AGGCDazMJGoWNBpc03u6+smc95dEead2KlZXBATOdFT1VesY3+nUOqZhEhTGlDMi
169hkgaZnzoIq/Uamidegk4hirsCT/R+6vsKAAxNTcBjUeZjlykCJWy5ojShGftXIKY
170w/njVbKMXrvc83qmTdGl3TAM0fxQIpqgcglFLveEBgzn
171-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400172""")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400173
Jean-Paul Calderoned50d2042011-05-04 17:00:49 -0400174cleartextPrivateKeyPEM = normalize_privatekey_pem(b("""\
175-----BEGIN RSA PRIVATE KEY-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400176MIICXQIBAAKBgQD5mkLpi7q6ROdu7khB3S9aanA0Zls7vvfGOmB80/yeylhGpsjA
177jWen0VtSQke/NlEPGtO38tsV7CsuFnSmschvAnGrcJl76b0UOOHUgDTIoRxC6QDU
1783claegwsrBA+sJEBbqx5RdXbIRGicPG/8qQ4Zm1SKOgotcbwiaor2yxZ2wIDAQAB
179AoGBAPCgMpmLxzwDaUmcFbTJUvlLW1hoxNNYSu2jIZm1k/hRAcE60JYwvBkgz3UB
180yMEh0AtLxYe0bFk6EHah11tMUPgscbCq73snJ++8koUw+csk22G65hOs51bVb7Aa
1816JBe67oLzdtvgCUFAA2qfrKzWRZzAdhUirQUZgySZk+Xq1pBAkEA/kZG0A6roTSM
182BVnx7LnPfsycKUsTumorpXiylZJjTi9XtmzxhrYN6wgZlDOOwOLgSQhszGpxVoMD
183u3gByT1b2QJBAPtL3mSKdvwRu/+40zaZLwvSJRxaj0mcE4BJOS6Oqs/hS1xRlrNk
184PpQ7WJ4yM6ZOLnXzm2mKyxm50Mv64109FtMCQQDOqS2KkjHaLowTGVxwC0DijMfr
185I9Lf8sSQk32J5VWCySWf5gGTfEnpmUa41gKTMJIbqZZLucNuDcOtzUaeWZlZAkA8
186ttXigLnCqR486JDPTi9ZscoZkZ+w7y6e/hH8t6d5Vjt48JVyfjPIaJY+km58LcN3
1876AWSeGAdtRFHVzR7oHjVAkB4hutvxiOeiIVQNBhM6RSI9aBPMI21DoX2JRoxvNW2
188cbvAhow217X9V0dVerEOKxnNYspXRrh36h7k4mQA+sDq
189-----END RSA PRIVATE KEY-----
Jean-Paul Calderoned50d2042011-05-04 17:00:49 -0400190"""))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400191
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400192cleartextCertificateRequestPEM = b("""-----BEGIN CERTIFICATE REQUEST-----
193MIIBnjCCAQcCAQAwXjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQH
194EwdDaGljYWdvMRcwFQYDVQQKEw5NeSBDb21wYW55IEx0ZDEXMBUGA1UEAxMORnJl
195ZGVyaWNrIERlYW4wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANp6Y17WzKSw
196BsUWkXdqg6tnXy8H8hA1msCMWpc+/2KJ4mbv5NyD6UD+/SqagQqulPbF/DFea9nA
197E0zhmHJELcM8gUTIlXv/cgDWnmK4xj8YkjVUiCdqKRAKeuzLG1pGmwwF5lGeJpXN
198xQn5ecR0UYSOWj6TTGXB9VyUMQzCClcBAgMBAAGgADANBgkqhkiG9w0BAQUFAAOB
199gQAAJGuF/R/GGbeC7FbFW+aJgr9ee0Xbl6nlhu7pTe67k+iiKT2dsl2ti68MVTnu
200Vrb3HUNqOkiwsJf6kCtq5oPn3QVYzTa76Dt2y3Rtzv6boRSlmlfrgS92GNma8JfR
201oICQk3nAudi6zl1Dix3BCv1pUp5KMtGn3MeDEi6QFGy2rA==
202-----END CERTIFICATE REQUEST-----
203""")
Rick Dean5b7b6372009-04-01 11:34:06 -0500204
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400205encryptedPrivateKeyPEM = b("""-----BEGIN RSA PRIVATE KEY-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400206Proc-Type: 4,ENCRYPTED
207DEK-Info: DES-EDE3-CBC,9573604A18579E9E
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400208
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400209SHOho56WxDkT0ht10UTeKc0F5u8cqIa01kzFAmETw0MAs8ezYtK15NPdCXUm3X/2
210a17G7LSF5bkxOgZ7vpXyMzun/owrj7CzvLxyncyEFZWvtvzaAhPhvTJtTIB3kf8B
2118+qRcpTGK7NgXEgYBW5bj1y4qZkD4zCL9o9NQzsKI3Ie8i0239jsDOWR38AxjXBH
212mGwAQ4Z6ZN5dnmM4fhMIWsmFf19sNyAML4gHenQCHhmXbjXeVq47aC2ProInJbrm
213+00TcisbAQ40V9aehVbcDKtS4ZbMVDwncAjpXpcncC54G76N6j7F7wL7L/FuXa3A
214fvSVy9n2VfF/pJ3kYSflLHH2G/DFxjF7dl0GxhKPxJjp3IJi9VtuvmN9R2jZWLQF
215tfC8dXgy/P9CfFQhlinqBTEwgH0oZ/d4k4NVFDSdEMaSdmBAjlHpc+Vfdty3HVnV
216rKXj//wslsFNm9kIwJGIgKUa/n2jsOiydrsk1mgH7SmNCb3YHgZhbbnq0qLat/HC
217gHDt3FHpNQ31QzzL3yrenFB2L9osIsnRsDTPFNi4RX4SpDgNroxOQmyzCCV6H+d4
218o1mcnNiZSdxLZxVKccq0AfRpHqpPAFnJcQHP6xyT9MZp6fBa0XkxDnt9kNU8H3Qw
2197SJWZ69VXjBUzMlQViLuaWMgTnL+ZVyFZf9hTF7U/ef4HMLMAVNdiaGG+G+AjCV/
220MbzjS007Oe4qqBnCWaFPSnJX6uLApeTbqAxAeyCql56ULW5x6vDMNC3dwjvS/CEh
22111n8RkgFIQA0AhuKSIg3CbuartRsJnWOLwgLTzsrKYL4yRog1RJrtw==
222-----END RSA PRIVATE KEY-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400223""")
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400224
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400225encryptedPrivateKeyPEMPassphrase = b("foobar")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400226
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400227# Some PKCS#7 stuff. Generated with the openssl command line:
228#
229# openssl crl2pkcs7 -inform pem -outform pem -certfile s.pem -nocrl
230#
231# with a certificate and key (but the key should be irrelevant) in s.pem
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400232pkcs7Data = b("""\
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400233-----BEGIN PKCS7-----
234MIIDNwYJKoZIhvcNAQcCoIIDKDCCAyQCAQExADALBgkqhkiG9w0BBwGgggMKMIID
235BjCCAm+gAwIBAgIBATANBgkqhkiG9w0BAQQFADB7MQswCQYDVQQGEwJTRzERMA8G
236A1UEChMITTJDcnlwdG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtN
237MkNyeXB0byBDZXJ0aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNA
238cG9zdDEuY29tMB4XDTAwMDkxMDA5NTEzMFoXDTAyMDkxMDA5NTEzMFowUzELMAkG
239A1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwlsb2NhbGhvc3Qx
240HTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tMFwwDQYJKoZIhvcNAQEBBQAD
241SwAwSAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh5kwI
242zOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEAAaOCAQQwggEAMAkGA1UdEwQCMAAw
243LAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0G
244A1UdDgQWBBTPhIKSvnsmYsBVNWjj0m3M2z0qVTCBpQYDVR0jBIGdMIGagBT7hyNp
24565w6kxXlxb8pUU/+7Sg4AaF/pH0wezELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0y
246Q3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlwdG8g
247Q2VydGlmaWNhdGUgTWFzdGVyMR0wGwYJKoZIhvcNAQkBFg5uZ3BzQHBvc3QxLmNv
248bYIBADANBgkqhkiG9w0BAQQFAAOBgQA7/CqT6PoHycTdhEStWNZde7M/2Yc6BoJu
249VwnW8YxGO8Sn6UJ4FeffZNcYZddSDKosw8LtPOeWoK3JINjAk5jiPQ2cww++7QGG
250/g5NDjxFZNDJP1dGiLAxPW6JXwov4v0FmdzfLOZ01jDcgQQZqEpYlgpuI5JEWUQ9
251Ho4EzbYCOaEAMQA=
252-----END PKCS7-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400253""")
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400254
Alex Gaynor8fa1dd62014-08-14 09:57:51 -0700255pkcs7DataASN1 = base64.b64decode(b"""
Alex Gaynor4b9c96a2014-08-14 09:51:48 -0700256MIIDNwYJKoZIhvcNAQcCoIIDKDCCAyQCAQExADALBgkqhkiG9w0BBwGgggMKMIID
257BjCCAm+gAwIBAgIBATANBgkqhkiG9w0BAQQFADB7MQswCQYDVQQGEwJTRzERMA8G
258A1UEChMITTJDcnlwdG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtN
259MkNyeXB0byBDZXJ0aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNA
260cG9zdDEuY29tMB4XDTAwMDkxMDA5NTEzMFoXDTAyMDkxMDA5NTEzMFowUzELMAkG
261A1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwlsb2NhbGhvc3Qx
262HTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tMFwwDQYJKoZIhvcNAQEBBQAD
263SwAwSAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh5kwI
264zOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEAAaOCAQQwggEAMAkGA1UdEwQCMAAw
265LAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0G
266A1UdDgQWBBTPhIKSvnsmYsBVNWjj0m3M2z0qVTCBpQYDVR0jBIGdMIGagBT7hyNp
26765w6kxXlxb8pUU/+7Sg4AaF/pH0wezELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0y
268Q3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlwdG8g
269Q2VydGlmaWNhdGUgTWFzdGVyMR0wGwYJKoZIhvcNAQkBFg5uZ3BzQHBvc3QxLmNv
270bYIBADANBgkqhkiG9w0BAQQFAAOBgQA7/CqT6PoHycTdhEStWNZde7M/2Yc6BoJu
271VwnW8YxGO8Sn6UJ4FeffZNcYZddSDKosw8LtPOeWoK3JINjAk5jiPQ2cww++7QGG
272/g5NDjxFZNDJP1dGiLAxPW6JXwov4v0FmdzfLOZ01jDcgQQZqEpYlgpuI5JEWUQ9
273Ho4EzbYCOaEAMQA=
Alex Gaynor8fa1dd62014-08-14 09:57:51 -0700274""")
Alex Gaynor4b9c96a2014-08-14 09:51:48 -0700275
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400276crlData = b("""\
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -0500277-----BEGIN X509 CRL-----
278MIIBWzCBxTANBgkqhkiG9w0BAQQFADBYMQswCQYDVQQGEwJVUzELMAkGA1UECBMC
279SUwxEDAOBgNVBAcTB0NoaWNhZ28xEDAOBgNVBAoTB1Rlc3RpbmcxGDAWBgNVBAMT
280D1Rlc3RpbmcgUm9vdCBDQRcNMDkwNzI2MDQzNDU2WhcNMTIwOTI3MDI0MTUyWjA8
281MBUCAgOrGA8yMDA5MDcyNTIzMzQ1NlowIwICAQAYDzIwMDkwNzI1MjMzNDU2WjAM
282MAoGA1UdFQQDCgEEMA0GCSqGSIb3DQEBBAUAA4GBAEBt7xTs2htdD3d4ErrcGAw1
2834dKcVnIWTutoI7xxen26Wwvh8VCsT7i/UeP+rBl9rC/kfjWjzQk3/zleaarGTpBT
2840yp4HXRFFoRhhSE/hP+eteaPXRgrsNRLHe9ZDd69wmh7J1wMDb0m81RG7kqcbsid
285vrzEeLDRiiPl92dyyWmu
286-----END X509 CRL-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400287""")
Jean-Paul Calderonee890db32010-08-22 16:55:15 -0400288
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400289
290# A broken RSA private key which can be used to test the error path through
291# PKey.check.
292inconsistentPrivateKeyPEM = b("""-----BEGIN RSA PRIVATE KEY-----
293MIIBPAIBAAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh
2945kwIzOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEaAQJBAIqm/bz4NA1H++Vx5Ewx
295OcKp3w19QSaZAwlGRtsUxrP7436QjnREM3Bm8ygU11BjkPVmtrKm6AayQfCHqJoT
296zIECIQDW0BoMoL0HOYM/mrTLhaykYAVqgIeJsPjvkEhTFXWBuQIhAM3deFAvWNu4
297nklUQ37XsCT2c9tmNt1LAT+slG2JOTTRAiAuXDtC/m3NYVwyHfFm+zKHRzHkClk2
298HjubeEgjpj32AQIhAJqMGTaZVOwevTXvvHwNeH+vRWsAYU/gbx+OQB+7VOcBAiEA
299oolb6NMg/R3enNPvS1O4UU1H8wpaF77L4yiSWlE0p4w=
300-----END RSA PRIVATE KEY-----
301""")
302
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -0400303# certificate with NULL bytes in subjectAltName and common name
304
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400305nulbyteSubjectAltNamePEM = b("""-----BEGIN CERTIFICATE-----
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -0400306MIIE2DCCA8CgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBxTELMAkGA1UEBhMCVVMx
307DzANBgNVBAgMBk9yZWdvbjESMBAGA1UEBwwJQmVhdmVydG9uMSMwIQYDVQQKDBpQ
308eXRob24gU29mdHdhcmUgRm91bmRhdGlvbjEgMB4GA1UECwwXUHl0aG9uIENvcmUg
309RGV2ZWxvcG1lbnQxJDAiBgNVBAMMG251bGwucHl0aG9uLm9yZwBleGFtcGxlLm9y
310ZzEkMCIGCSqGSIb3DQEJARYVcHl0aG9uLWRldkBweXRob24ub3JnMB4XDTEzMDgw
311NzEzMTE1MloXDTEzMDgwNzEzMTI1MlowgcUxCzAJBgNVBAYTAlVTMQ8wDQYDVQQI
312DAZPcmVnb24xEjAQBgNVBAcMCUJlYXZlcnRvbjEjMCEGA1UECgwaUHl0aG9uIFNv
313ZnR3YXJlIEZvdW5kYXRpb24xIDAeBgNVBAsMF1B5dGhvbiBDb3JlIERldmVsb3Bt
314ZW50MSQwIgYDVQQDDBtudWxsLnB5dGhvbi5vcmcAZXhhbXBsZS5vcmcxJDAiBgkq
315hkiG9w0BCQEWFXB5dGhvbi1kZXZAcHl0aG9uLm9yZzCCASIwDQYJKoZIhvcNAQEB
316BQADggEPADCCAQoCggEBALXq7cn7Rn1vO3aA3TrzA5QLp6bb7B3f/yN0CJ2XFj+j
317pHs+Gw6WWSUDpybiiKnPec33BFawq3kyblnBMjBU61ioy5HwQqVkJ8vUVjGIUq3P
318vX/wBmQfzCe4o4uM89gpHyUL9UYGG8oCRa17dgqcv7u5rg0Wq2B1rgY+nHwx3JIv
319KRrgSwyRkGzpN8WQ1yrXlxWjgI9de0mPVDDUlywcWze1q2kwaEPTM3hLAmD1PESA
320oY/n8A/RXoeeRs9i/Pm/DGUS8ZPINXk/yOzsR/XvvkTVroIeLZqfmFpnZeF0cHzL
32108LODkVJJ9zjLdT7SA4vnne4FEbAxDbKAq5qkYzaL4UCAwEAAaOB0DCBzTAMBgNV
322HRMBAf8EAjAAMB0GA1UdDgQWBBSIWlXAUv9hzVKjNQ/qWpwkOCL3XDALBgNVHQ8E
323BAMCBeAwgZAGA1UdEQSBiDCBhYIeYWx0bnVsbC5weXRob24ub3JnAGV4YW1wbGUu
324Y29tgSBudWxsQHB5dGhvbi5vcmcAdXNlckBleGFtcGxlLm9yZ4YpaHR0cDovL251
325bGwucHl0aG9uLm9yZwBodHRwOi8vZXhhbXBsZS5vcmeHBMAAAgGHECABDbgAAAAA
326AAAAAAAAAAEwDQYJKoZIhvcNAQEFBQADggEBAKxPRe99SaghcI6IWT7UNkJw9aO9
327i9eo0Fj2MUqxpKbdb9noRDy2CnHWf7EIYZ1gznXPdwzSN4YCjV5d+Q9xtBaowT0j
328HPERs1ZuytCNNJTmhyqZ8q6uzMLoht4IqH/FBfpvgaeC5tBTnTT0rD5A/olXeimk
329kX4LxlEx5RAvpGB2zZVRGr6LobD9rVK91xuHYNIxxxfEGE8tCCWjp0+3ksri9SXx
330VHWBnbM9YaL32u3hxm8sYB/Yb8WSBavJCWJJqRStVRHM1koZlJmXNx2BX4vPo6iW
331RFEIPQsFZRLrtnCAiEhyT8bC2s/Njlu6ly9gtJZWSV46Q3ZjBL4q9sHKqZQ=
332-----END CERTIFICATE-----""")
333
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400334
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400335class X509ExtTests(TestCase):
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400336 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900337 Tests for :py:class:`OpenSSL.crypto.X509Extension`.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400338 """
339
340 def setUp(self):
341 """
342 Create a new private key and start a certificate request (for a test
343 method to finish in one way or another).
344 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -0800345 super(X509ExtTests, self).setUp()
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400346 # Basic setup stuff to generate a certificate
347 self.pkey = PKey()
348 self.pkey.generate_key(TYPE_RSA, 384)
349 self.req = X509Req()
350 self.req.set_pubkey(self.pkey)
351 # Authority good you have.
352 self.req.get_subject().commonName = "Yoda root CA"
353 self.x509 = X509()
354 self.subject = self.x509.get_subject()
355 self.subject.commonName = self.req.get_subject().commonName
356 self.x509.set_issuer(self.subject)
357 self.x509.set_pubkey(self.pkey)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400358 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
359 expire = b((datetime.now() + timedelta(days=100)).strftime("%Y%m%d%H%M%SZ"))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400360 self.x509.set_notBefore(now)
361 self.x509.set_notAfter(expire)
362
363
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -0800364 def tearDown(self):
365 """
366 Forget all of the pyOpenSSL objects so they can be garbage collected,
367 their memory released, and not interfere with the leak detection code.
368 """
369 self.pkey = self.req = self.x509 = self.subject = None
370 super(X509ExtTests, self).tearDown()
371
372
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400373 def test_str(self):
374 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900375 The string representation of :py:class:`X509Extension` instances as returned by
376 :py:data:`str` includes stuff.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400377 """
378 # This isn't necessarily the best string representation. Perhaps it
379 # will be changed/improved in the future.
380 self.assertEquals(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400381 str(X509Extension(b('basicConstraints'), True, b('CA:false'))),
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400382 'CA:FALSE')
383
384
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400385 def test_type(self):
386 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900387 :py:class:`X509Extension` and :py:class:`X509ExtensionType` refer to the same type object
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400388 and can be used to create instances of that type.
389 """
390 self.assertIdentical(X509Extension, X509ExtensionType)
391 self.assertConsistentType(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400392 X509Extension,
393 'X509Extension', b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400394
395
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500396 def test_construction(self):
397 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900398 :py:class:`X509Extension` accepts an extension type name, a critical flag,
399 and an extension value and returns an :py:class:`X509ExtensionType` instance.
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500400 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400401 basic = X509Extension(b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500402 self.assertTrue(
403 isinstance(basic, X509ExtensionType),
404 "%r is of type %r, should be %r" % (
405 basic, type(basic), X509ExtensionType))
406
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400407 comment = X509Extension(
408 b('nsComment'), False, b('pyOpenSSL unit test'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500409 self.assertTrue(
410 isinstance(comment, X509ExtensionType),
411 "%r is of type %r, should be %r" % (
412 comment, type(comment), X509ExtensionType))
413
414
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500415 def test_invalid_extension(self):
416 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900417 :py:class:`X509Extension` raises something if it is passed a bad extension
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500418 name or value.
419 """
420 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400421 Error, X509Extension, b('thisIsMadeUp'), False, b('hi'))
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500422 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400423 Error, X509Extension, b('basicConstraints'), False, b('blah blah'))
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500424
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500425 # Exercise a weird one (an extension which uses the r2i method). This
426 # exercises the codepath that requires a non-NULL ctx to be passed to
427 # X509V3_EXT_nconf. It can't work now because we provide no
428 # configuration database. It might be made to work in the future.
429 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400430 Error, X509Extension, b('proxyCertInfo'), True,
431 b('language:id-ppl-anyLanguage,pathlen:1,policy:text:AB'))
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500432
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500433
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500434 def test_get_critical(self):
435 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900436 :py:meth:`X509ExtensionType.get_critical` returns the value of the
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500437 extension's critical flag.
438 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400439 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500440 self.assertTrue(ext.get_critical())
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400441 ext = X509Extension(b('basicConstraints'), False, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500442 self.assertFalse(ext.get_critical())
443
Jean-Paul Calderone7535dab2008-03-06 18:53:11 -0500444
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500445 def test_get_short_name(self):
446 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900447 :py:meth:`X509ExtensionType.get_short_name` returns a string giving the short
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500448 type name of the extension.
449 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400450 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
451 self.assertEqual(ext.get_short_name(), b('basicConstraints'))
452 ext = X509Extension(b('nsComment'), True, b('foo bar'))
453 self.assertEqual(ext.get_short_name(), b('nsComment'))
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500454
455
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400456 def test_get_data(self):
457 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900458 :py:meth:`X509Extension.get_data` returns a string giving the data of the
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400459 extension.
460 """
461 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
462 # Expect to get back the DER encoded form of CA:true.
463 self.assertEqual(ext.get_data(), b('0\x03\x01\x01\xff'))
464
465
466 def test_get_data_wrong_args(self):
467 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900468 :py:meth:`X509Extension.get_data` raises :py:exc:`TypeError` if passed any arguments.
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400469 """
470 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
471 self.assertRaises(TypeError, ext.get_data, None)
472 self.assertRaises(TypeError, ext.get_data, "foo")
473 self.assertRaises(TypeError, ext.get_data, 7)
474
475
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400476 def test_unused_subject(self):
Rick Dean47262da2009-07-08 16:17:17 -0500477 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900478 The :py:data:`subject` parameter to :py:class:`X509Extension` may be provided for an
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400479 extension which does not use it and is ignored in this case.
Rick Dean47262da2009-07-08 16:17:17 -0500480 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400481 ext1 = X509Extension(
482 b('basicConstraints'), False, b('CA:TRUE'), subject=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400483 self.x509.add_extensions([ext1])
484 self.x509.sign(self.pkey, 'sha1')
485 # This is a little lame. Can we think of a better way?
486 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400487 self.assertTrue(b('X509v3 Basic Constraints:') in text)
488 self.assertTrue(b('CA:TRUE') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400489
490
491 def test_subject(self):
492 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900493 If an extension requires a subject, the :py:data:`subject` parameter to
494 :py:class:`X509Extension` provides its value.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400495 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400496 ext3 = X509Extension(
497 b('subjectKeyIdentifier'), False, b('hash'), subject=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400498 self.x509.add_extensions([ext3])
499 self.x509.sign(self.pkey, 'sha1')
500 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400501 self.assertTrue(b('X509v3 Subject Key Identifier:') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400502
503
504 def test_missing_subject(self):
505 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900506 If an extension requires a subject and the :py:data:`subject` parameter is
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400507 given no value, something happens.
508 """
509 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400510 Error, X509Extension, b('subjectKeyIdentifier'), False, b('hash'))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400511
512
513 def test_invalid_subject(self):
514 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900515 If the :py:data:`subject` parameter is given a value which is not an
516 :py:class:`X509` instance, :py:exc:`TypeError` is raised.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400517 """
518 for badObj in [True, object(), "hello", [], self]:
519 self.assertRaises(
520 TypeError,
521 X509Extension,
522 'basicConstraints', False, 'CA:TRUE', subject=badObj)
523
524
525 def test_unused_issuer(self):
526 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900527 The :py:data:`issuer` parameter to :py:class:`X509Extension` may be provided for an
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400528 extension which does not use it and is ignored in this case.
529 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400530 ext1 = X509Extension(
531 b('basicConstraints'), False, b('CA:TRUE'), issuer=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400532 self.x509.add_extensions([ext1])
533 self.x509.sign(self.pkey, 'sha1')
534 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400535 self.assertTrue(b('X509v3 Basic Constraints:') in text)
536 self.assertTrue(b('CA:TRUE') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400537
538
539 def test_issuer(self):
540 """
Alex Gaynor3b0ee972014-11-15 09:17:33 -0800541 If an extension requires an issuer, the :py:data:`issuer` parameter to
Jonathan Ballet648875f2011-07-16 14:14:58 +0900542 :py:class:`X509Extension` provides its value.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400543 """
544 ext2 = X509Extension(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400545 b('authorityKeyIdentifier'), False, b('issuer:always'),
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400546 issuer=self.x509)
547 self.x509.add_extensions([ext2])
548 self.x509.sign(self.pkey, 'sha1')
549 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400550 self.assertTrue(b('X509v3 Authority Key Identifier:') in text)
551 self.assertTrue(b('DirName:/CN=Yoda root CA') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400552
553
554 def test_missing_issuer(self):
555 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900556 If an extension requires an issue and the :py:data:`issuer` parameter is given
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400557 no value, something happens.
558 """
559 self.assertRaises(
560 Error,
561 X509Extension,
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400562 b('authorityKeyIdentifier'), False,
563 b('keyid:always,issuer:always'))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400564
565
566 def test_invalid_issuer(self):
567 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900568 If the :py:data:`issuer` parameter is given a value which is not an
569 :py:class:`X509` instance, :py:exc:`TypeError` is raised.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400570 """
571 for badObj in [True, object(), "hello", [], self]:
572 self.assertRaises(
573 TypeError,
574 X509Extension,
575 'authorityKeyIdentifier', False, 'keyid:always,issuer:always',
576 issuer=badObj)
Rick Dean47262da2009-07-08 16:17:17 -0500577
578
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500579
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400580class PKeyTests(TestCase):
Jean-Paul Calderoneac930e12008-03-06 18:50:51 -0500581 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900582 Unit tests for :py:class:`OpenSSL.crypto.PKey`.
Jean-Paul Calderoneac930e12008-03-06 18:50:51 -0500583 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400584 def test_type(self):
585 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900586 :py:class:`PKey` and :py:class:`PKeyType` refer to the same type object
587 and can be used to create instances of that type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400588 """
589 self.assertIdentical(PKey, PKeyType)
590 self.assertConsistentType(PKey, 'PKey')
591
592
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500593 def test_construction(self):
594 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900595 :py:class:`PKey` takes no arguments and returns a new :py:class:`PKey` instance.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500596 """
597 self.assertRaises(TypeError, PKey, None)
598 key = PKey()
599 self.assertTrue(
600 isinstance(key, PKeyType),
601 "%r is of type %r, should be %r" % (key, type(key), PKeyType))
602
603
604 def test_pregeneration(self):
605 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900606 :py:attr:`PKeyType.bits` and :py:attr:`PKeyType.type` return :py:data:`0` before the key is
607 generated. :py:attr:`PKeyType.check` raises :py:exc:`TypeError` before the key is
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500608 generated.
609 """
610 key = PKey()
611 self.assertEqual(key.type(), 0)
612 self.assertEqual(key.bits(), 0)
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400613 self.assertRaises(TypeError, key.check)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500614
615
616 def test_failedGeneration(self):
617 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900618 :py:meth:`PKeyType.generate_key` takes two arguments, the first giving the key
619 type as one of :py:data:`TYPE_RSA` or :py:data:`TYPE_DSA` and the second giving the
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500620 number of bits to generate. If an invalid type is specified or
Jonathan Ballet648875f2011-07-16 14:14:58 +0900621 generation fails, :py:exc:`Error` is raised. If an invalid number of bits is
622 specified, :py:exc:`ValueError` or :py:exc:`Error` is raised.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500623 """
624 key = PKey()
625 self.assertRaises(TypeError, key.generate_key)
626 self.assertRaises(TypeError, key.generate_key, 1, 2, 3)
627 self.assertRaises(TypeError, key.generate_key, "foo", "bar")
628 self.assertRaises(Error, key.generate_key, -1, 0)
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500629
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500630 self.assertRaises(ValueError, key.generate_key, TYPE_RSA, -1)
631 self.assertRaises(ValueError, key.generate_key, TYPE_RSA, 0)
Jean-Paul Calderoned71fe982008-03-06 00:31:50 -0500632
633 # XXX RSA generation for small values of bits is fairly buggy in a wide
634 # range of OpenSSL versions. I need to figure out what the safe lower
635 # bound for a reasonable number of OpenSSL versions is and explicitly
636 # check for that in the wrapper. The failure behavior is typically an
637 # infinite loop inside OpenSSL.
638
639 # self.assertRaises(Error, key.generate_key, TYPE_RSA, 2)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500640
641 # XXX DSA generation seems happy with any number of bits. The DSS
642 # says bits must be between 512 and 1024 inclusive. OpenSSL's DSA
643 # generator doesn't seem to care about the upper limit at all. For
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500644 # the lower limit, it uses 512 if anything smaller is specified.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500645 # So, it doesn't seem possible to make generate_key fail for
646 # TYPE_DSA with a bits argument which is at least an int.
647
648 # self.assertRaises(Error, key.generate_key, TYPE_DSA, -7)
649
650
651 def test_rsaGeneration(self):
652 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900653 :py:meth:`PKeyType.generate_key` generates an RSA key when passed
654 :py:data:`TYPE_RSA` as a type and a reasonable number of bits.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500655 """
656 bits = 128
657 key = PKey()
658 key.generate_key(TYPE_RSA, bits)
659 self.assertEqual(key.type(), TYPE_RSA)
660 self.assertEqual(key.bits(), bits)
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -0400661 self.assertTrue(key.check())
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500662
663
664 def test_dsaGeneration(self):
665 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900666 :py:meth:`PKeyType.generate_key` generates a DSA key when passed
667 :py:data:`TYPE_DSA` as a type and a reasonable number of bits.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500668 """
669 # 512 is a magic number. The DSS (Digital Signature Standard)
670 # allows a minimum of 512 bits for DSA. DSA_generate_parameters
671 # will silently promote any value below 512 to 512.
672 bits = 512
673 key = PKey()
674 key.generate_key(TYPE_DSA, bits)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800675 # self.assertEqual(key.type(), TYPE_DSA)
676 # self.assertEqual(key.bits(), bits)
677 # self.assertRaises(TypeError, key.check)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500678
679
680 def test_regeneration(self):
681 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900682 :py:meth:`PKeyType.generate_key` can be called multiple times on the same
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500683 key to generate new keys.
684 """
685 key = PKey()
686 for type, bits in [(TYPE_RSA, 512), (TYPE_DSA, 576)]:
687 key.generate_key(type, bits)
688 self.assertEqual(key.type(), type)
689 self.assertEqual(key.bits(), bits)
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500690
691
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400692 def test_inconsistentKey(self):
693 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900694 :py:`PKeyType.check` returns :py:exc:`Error` if the key is not consistent.
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400695 """
696 key = load_privatekey(FILETYPE_PEM, inconsistentPrivateKeyPEM)
Jean-Paul Calderoned338e4e2009-05-13 15:45:07 -0400697 self.assertRaises(Error, key.check)
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400698
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500699
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400700 def test_check_wrong_args(self):
701 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900702 :py:meth:`PKeyType.check` raises :py:exc:`TypeError` if called with any arguments.
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400703 """
704 self.assertRaises(TypeError, PKey().check, None)
705 self.assertRaises(TypeError, PKey().check, object())
706 self.assertRaises(TypeError, PKey().check, 1)
707
708
Jean-Paul Calderone02d01972011-10-31 10:39:29 -0400709 def test_check_public_key(self):
710 """
711 :py:meth:`PKeyType.check` raises :py:exc:`TypeError` if only the public
712 part of the key is available.
713 """
714 # A trick to get a public-only key
715 key = PKey()
716 key.generate_key(TYPE_RSA, 512)
717 cert = X509()
718 cert.set_pubkey(key)
719 pub = cert.get_pubkey()
720 self.assertRaises(TypeError, pub.check)
721
722
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400723
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400724class X509NameTests(TestCase):
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500725 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900726 Unit tests for :py:class:`OpenSSL.crypto.X509Name`.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500727 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500728 def _x509name(self, **attrs):
729 # XXX There's no other way to get a new X509Name yet.
730 name = X509().get_subject()
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400731 attrs = list(attrs.items())
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500732 # Make the order stable - order matters!
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400733 def key(attr):
734 return attr[1]
735 attrs.sort(key=key)
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500736 for k, v in attrs:
737 setattr(name, k, v)
738 return name
739
740
Rick Deane15b1472009-07-09 15:53:42 -0500741 def test_type(self):
742 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900743 The type of X509Name objects is :py:class:`X509NameType`.
Rick Deane15b1472009-07-09 15:53:42 -0500744 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400745 self.assertIdentical(X509Name, X509NameType)
746 self.assertEqual(X509NameType.__name__, 'X509Name')
747 self.assertTrue(isinstance(X509NameType, type))
748
Rick Deane15b1472009-07-09 15:53:42 -0500749 name = self._x509name()
750 self.assertTrue(
751 isinstance(name, X509NameType),
752 "%r is of type %r, should be %r" % (
753 name, type(name), X509NameType))
Rick Deane15b1472009-07-09 15:53:42 -0500754
755
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400756 def test_onlyStringAttributes(self):
757 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900758 Attempting to set a non-:py:data:`str` attribute name on an :py:class:`X509NameType`
759 instance causes :py:exc:`TypeError` to be raised.
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400760 """
761 name = self._x509name()
762 # Beyond these cases, you may also think that unicode should be
763 # rejected. Sorry, you're wrong. unicode is automatically converted to
764 # str outside of the control of X509Name, so there's no way to reject
765 # it.
Jean-Paul Calderoneff363be2013-03-03 10:21:23 -0800766
767 # Also, this used to test str subclasses, but that test is less relevant
768 # now that the implementation is in Python instead of C. Also PyPy
769 # automatically converts str subclasses to str when they are passed to
770 # setattr, so we can't test it on PyPy. Apparently CPython does this
771 # sometimes as well.
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400772 self.assertRaises(TypeError, setattr, name, None, "hello")
773 self.assertRaises(TypeError, setattr, name, 30, "hello")
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400774
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -0500775
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400776 def test_setInvalidAttribute(self):
777 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900778 Attempting to set any attribute name on an :py:class:`X509NameType` instance for
779 which no corresponding NID is defined causes :py:exc:`AttributeError` to be
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400780 raised.
781 """
782 name = self._x509name()
783 self.assertRaises(AttributeError, setattr, name, "no such thing", None)
784
785
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500786 def test_attributes(self):
787 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900788 :py:class:`X509NameType` instances have attributes for each standard (?)
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500789 X509Name field.
790 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500791 name = self._x509name()
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500792 name.commonName = "foo"
793 self.assertEqual(name.commonName, "foo")
794 self.assertEqual(name.CN, "foo")
795 name.CN = "baz"
796 self.assertEqual(name.commonName, "baz")
797 self.assertEqual(name.CN, "baz")
798 name.commonName = "bar"
799 self.assertEqual(name.commonName, "bar")
800 self.assertEqual(name.CN, "bar")
801 name.CN = "quux"
802 self.assertEqual(name.commonName, "quux")
803 self.assertEqual(name.CN, "quux")
804
805
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500806 def test_copy(self):
807 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900808 :py:class:`X509Name` creates a new :py:class:`X509NameType` instance with all the same
809 attributes as an existing :py:class:`X509NameType` instance when called with
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500810 one.
811 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500812 name = self._x509name(commonName="foo", emailAddress="bar@example.com")
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500813
814 copy = X509Name(name)
815 self.assertEqual(copy.commonName, "foo")
816 self.assertEqual(copy.emailAddress, "bar@example.com")
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500817
818 # Mutate the copy and ensure the original is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500819 copy.commonName = "baz"
820 self.assertEqual(name.commonName, "foo")
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500821
822 # Mutate the original and ensure the copy is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500823 name.emailAddress = "quux@example.com"
824 self.assertEqual(copy.emailAddress, "bar@example.com")
825
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500826
827 def test_repr(self):
828 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900829 :py:func:`repr` passed an :py:class:`X509NameType` instance should return a string
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500830 containing a description of the type and the NIDs which have been set
831 on it.
832 """
833 name = self._x509name(commonName="foo", emailAddress="bar")
834 self.assertEqual(
835 repr(name),
836 "<X509Name object '/emailAddress=bar/CN=foo'>")
837
838
839 def test_comparison(self):
840 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900841 :py:class:`X509NameType` instances should compare based on their NIDs.
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500842 """
843 def _equality(a, b, assertTrue, assertFalse):
844 assertTrue(a == b, "(%r == %r) --> False" % (a, b))
845 assertFalse(a != b)
846 assertTrue(b == a)
847 assertFalse(b != a)
848
849 def assertEqual(a, b):
850 _equality(a, b, self.assertTrue, self.assertFalse)
851
852 # Instances compare equal to themselves.
853 name = self._x509name()
854 assertEqual(name, name)
855
856 # Empty instances should compare equal to each other.
857 assertEqual(self._x509name(), self._x509name())
858
859 # Instances with equal NIDs should compare equal to each other.
860 assertEqual(self._x509name(commonName="foo"),
861 self._x509name(commonName="foo"))
862
863 # Instance with equal NIDs set using different aliases should compare
864 # equal to each other.
865 assertEqual(self._x509name(commonName="foo"),
866 self._x509name(CN="foo"))
867
868 # Instances with more than one NID with the same values should compare
869 # equal to each other.
870 assertEqual(self._x509name(CN="foo", organizationalUnitName="bar"),
871 self._x509name(commonName="foo", OU="bar"))
872
873 def assertNotEqual(a, b):
874 _equality(a, b, self.assertFalse, self.assertTrue)
875
876 # Instances with different values for the same NID should not compare
877 # equal to each other.
878 assertNotEqual(self._x509name(CN="foo"),
879 self._x509name(CN="bar"))
880
881 # Instances with different NIDs should not compare equal to each other.
882 assertNotEqual(self._x509name(CN="foo"),
883 self._x509name(OU="foo"))
884
885 def _inequality(a, b, assertTrue, assertFalse):
886 assertTrue(a < b)
887 assertTrue(a <= b)
888 assertTrue(b > a)
889 assertTrue(b >= a)
890 assertFalse(a > b)
891 assertFalse(a >= b)
892 assertFalse(b < a)
893 assertFalse(b <= a)
894
895 def assertLessThan(a, b):
896 _inequality(a, b, self.assertTrue, self.assertFalse)
897
898 # An X509Name with a NID with a value which sorts less than the value
899 # of the same NID on another X509Name compares less than the other
900 # X509Name.
901 assertLessThan(self._x509name(CN="abc"),
902 self._x509name(CN="def"))
903
904 def assertGreaterThan(a, b):
905 _inequality(a, b, self.assertFalse, self.assertTrue)
906
907 # An X509Name with a NID with a value which sorts greater than the
908 # value of the same NID on another X509Name compares greater than the
909 # other X509Name.
910 assertGreaterThan(self._x509name(CN="def"),
911 self._x509name(CN="abc"))
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -0500912
913
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400914 def test_hash(self):
915 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900916 :py:meth:`X509Name.hash` returns an integer hash based on the value of the
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400917 name.
918 """
919 a = self._x509name(CN="foo")
920 b = self._x509name(CN="foo")
921 self.assertEqual(a.hash(), b.hash())
922 a.CN = "bar"
923 self.assertNotEqual(a.hash(), b.hash())
924
925
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400926 def test_der(self):
927 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900928 :py:meth:`X509Name.der` returns the DER encoded form of the name.
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400929 """
930 a = self._x509name(CN="foo", C="US")
931 self.assertEqual(
932 a.der(),
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -0400933 b('0\x1b1\x0b0\t\x06\x03U\x04\x06\x13\x02US'
934 '1\x0c0\n\x06\x03U\x04\x03\x13\x03foo'))
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400935
936
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400937 def test_get_components(self):
938 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900939 :py:meth:`X509Name.get_components` returns a :py:data:`list` of
940 two-tuples of :py:data:`str`
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400941 giving the NIDs and associated values which make up the name.
942 """
943 a = self._x509name()
944 self.assertEqual(a.get_components(), [])
945 a.CN = "foo"
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -0400946 self.assertEqual(a.get_components(), [(b("CN"), b("foo"))])
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400947 a.organizationalUnitName = "bar"
948 self.assertEqual(
949 a.get_components(),
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -0400950 [(b("CN"), b("foo")), (b("OU"), b("bar"))])
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400951
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400952
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400953 def test_load_nul_byte_attribute(self):
954 """
Jean-Paul Calderone9af07b02013-08-23 16:07:31 -0400955 An :py:class:`OpenSSL.crypto.X509Name` from an
956 :py:class:`OpenSSL.crypto.X509` instance loaded from a file can have a
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400957 NUL byte in the value of one of its attributes.
958 """
959 cert = load_certificate(FILETYPE_PEM, nulbyteSubjectAltNamePEM)
960 subject = cert.get_subject()
961 self.assertEqual(
Jean-Paul Calderone06754fc2013-08-23 15:47:47 -0400962 "null.python.org\x00example.org", subject.commonName)
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400963
964
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -0500965 def test_setAttributeFailure(self):
966 """
967 If the value of an attribute cannot be set for some reason then
968 :py:class:`OpenSSL.crypto.Error` is raised.
969 """
970 name = self._x509name()
971 # This value is too long
972 self.assertRaises(Error, setattr, name, "O", b"x" * 512)
973
974
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400975
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400976class _PKeyInteractionTestsMixin:
977 """
978 Tests which involve another thing and a PKey.
979 """
980 def signable(self):
981 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900982 Return something with a :py:meth:`set_pubkey`, :py:meth:`set_pubkey`,
983 and :py:meth:`sign` method.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400984 """
985 raise NotImplementedError()
986
987
988 def test_signWithUngenerated(self):
989 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900990 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when pass a
991 :py:class:`PKey` with no parts.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400992 """
993 request = self.signable()
994 key = PKey()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500995 self.assertRaises(ValueError, request.sign, key, GOOD_DIGEST)
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400996
997
998 def test_signWithPublicKey(self):
999 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001000 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when pass a
1001 :py:class:`PKey` with no private part as the signing key.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001002 """
1003 request = self.signable()
1004 key = PKey()
1005 key.generate_key(TYPE_RSA, 512)
1006 request.set_pubkey(key)
1007 pub = request.get_pubkey()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001008 self.assertRaises(ValueError, request.sign, pub, GOOD_DIGEST)
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001009
1010
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -04001011 def test_signWithUnknownDigest(self):
1012 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001013 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when passed a digest name which is
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -04001014 not known.
1015 """
1016 request = self.signable()
1017 key = PKey()
1018 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001019 self.assertRaises(ValueError, request.sign, key, BAD_DIGEST)
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -04001020
1021
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04001022 def test_sign(self):
1023 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001024 :py:meth:`X509Req.sign` succeeds when passed a private key object and a valid
1025 digest function. :py:meth:`X509Req.verify` can be used to check the signature.
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04001026 """
1027 request = self.signable()
1028 key = PKey()
1029 key.generate_key(TYPE_RSA, 512)
1030 request.set_pubkey(key)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001031 request.sign(key, GOOD_DIGEST)
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04001032 # If the type has a verify method, cover that too.
1033 if getattr(request, 'verify', None) is not None:
1034 pub = request.get_pubkey()
1035 self.assertTrue(request.verify(pub))
1036 # Make another key that won't verify.
1037 key = PKey()
1038 key.generate_key(TYPE_RSA, 512)
1039 self.assertRaises(Error, request.verify, key)
1040
1041
1042
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001043
Jean-Paul Calderone18808652009-07-05 12:54:05 -04001044class X509ReqTests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001045 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001046 Tests for :py:class:`OpenSSL.crypto.X509Req`.
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001047 """
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001048 def signable(self):
1049 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001050 Create and return a new :py:class:`X509Req`.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001051 """
1052 return X509Req()
1053
1054
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001055 def test_type(self):
1056 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001057 :py:obj:`X509Req` and :py:obj:`X509ReqType` refer to the same type object and can be
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001058 used to create instances of that type.
1059 """
1060 self.assertIdentical(X509Req, X509ReqType)
1061 self.assertConsistentType(X509Req, 'X509Req')
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001062
1063
1064 def test_construction(self):
1065 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001066 :py:obj:`X509Req` takes no arguments and returns an :py:obj:`X509ReqType` instance.
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001067 """
1068 request = X509Req()
1069 self.assertTrue(
1070 isinstance(request, X509ReqType),
1071 "%r is of type %r, should be %r" % (request, type(request), X509ReqType))
1072
1073
Jean-Paul Calderone8dd19b82008-12-28 20:41:16 -05001074 def test_version(self):
1075 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001076 :py:obj:`X509ReqType.set_version` sets the X.509 version of the certificate
1077 request. :py:obj:`X509ReqType.get_version` returns the X.509 version of
Jean-Paul Calderone8dd19b82008-12-28 20:41:16 -05001078 the certificate request. The initial value of the version is 0.
1079 """
1080 request = X509Req()
1081 self.assertEqual(request.get_version(), 0)
1082 request.set_version(1)
1083 self.assertEqual(request.get_version(), 1)
1084 request.set_version(3)
1085 self.assertEqual(request.get_version(), 3)
1086
1087
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001088 def test_version_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001089 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001090 :py:obj:`X509ReqType.set_version` raises :py:obj:`TypeError` if called with the wrong
1091 number of arguments or with a non-:py:obj:`int` argument.
1092 :py:obj:`X509ReqType.get_version` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001093 arguments.
1094 """
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001095 request = X509Req()
1096 self.assertRaises(TypeError, request.set_version)
1097 self.assertRaises(TypeError, request.set_version, "foo")
1098 self.assertRaises(TypeError, request.set_version, 1, 2)
1099 self.assertRaises(TypeError, request.get_version, None)
1100
1101
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001102 def test_get_subject(self):
1103 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001104 :py:obj:`X509ReqType.get_subject` returns an :py:obj:`X509Name` for the subject of
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001105 the request and which is valid even after the request object is
1106 otherwise dead.
1107 """
1108 request = X509Req()
1109 subject = request.get_subject()
1110 self.assertTrue(
1111 isinstance(subject, X509NameType),
1112 "%r is of type %r, should be %r" % (subject, type(subject), X509NameType))
1113 subject.commonName = "foo"
1114 self.assertEqual(request.get_subject().commonName, "foo")
1115 del request
1116 subject.commonName = "bar"
1117 self.assertEqual(subject.commonName, "bar")
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001118
1119
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001120 def test_get_subject_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001121 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001122 :py:obj:`X509ReqType.get_subject` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001123 arguments.
1124 """
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001125 request = X509Req()
1126 self.assertRaises(TypeError, request.get_subject, None)
1127
1128
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001129 def test_add_extensions(self):
1130 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001131 :py:obj:`X509Req.add_extensions` accepts a :py:obj:`list` of :py:obj:`X509Extension`
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001132 instances and adds them to the X509 request.
1133 """
1134 request = X509Req()
1135 request.add_extensions([
Jean-Paul Calderonee16f9f32010-08-22 19:20:37 -04001136 X509Extension(b('basicConstraints'), True, b('CA:false'))])
Stephen Holsappleca545b72014-01-28 21:43:25 -08001137 exts = request.get_extensions()
Stephen Holsapple7fbdf642014-03-01 20:05:47 -08001138 self.assertEqual(len(exts), 1)
1139 self.assertEqual(exts[0].get_short_name(), b('basicConstraints'))
1140 self.assertEqual(exts[0].get_critical(), 1)
1141 self.assertEqual(exts[0].get_data(), b('0\x00'))
1142
1143
1144 def test_get_extensions(self):
1145 """
1146 :py:obj:`X509Req.get_extensions` returns a :py:obj:`list` of
1147 extensions added to this X509 request.
1148 """
1149 request = X509Req()
1150 exts = request.get_extensions()
1151 self.assertEqual(exts, [])
1152 request.add_extensions([
1153 X509Extension(b('basicConstraints'), True, b('CA:true')),
1154 X509Extension(b('keyUsage'), False, b('digitalSignature'))])
1155 exts = request.get_extensions()
1156 self.assertEqual(len(exts), 2)
1157 self.assertEqual(exts[0].get_short_name(), b('basicConstraints'))
1158 self.assertEqual(exts[0].get_critical(), 1)
1159 self.assertEqual(exts[0].get_data(), b('0\x03\x01\x01\xff'))
1160 self.assertEqual(exts[1].get_short_name(), b('keyUsage'))
1161 self.assertEqual(exts[1].get_critical(), 0)
1162 self.assertEqual(exts[1].get_data(), b('\x03\x02\x07\x80'))
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001163
1164
1165 def test_add_extensions_wrong_args(self):
1166 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001167 :py:obj:`X509Req.add_extensions` raises :py:obj:`TypeError` if called with the wrong
1168 number of arguments or with a non-:py:obj:`list`. Or it raises :py:obj:`ValueError`
1169 if called with a :py:obj:`list` containing objects other than :py:obj:`X509Extension`
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001170 instances.
1171 """
1172 request = X509Req()
1173 self.assertRaises(TypeError, request.add_extensions)
1174 self.assertRaises(TypeError, request.add_extensions, object())
1175 self.assertRaises(ValueError, request.add_extensions, [object()])
1176 self.assertRaises(TypeError, request.add_extensions, [], None)
1177
1178
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001179 def test_verify_wrong_args(self):
1180 """
1181 :py:obj:`X509Req.verify` raises :py:obj:`TypeError` if called with zero
1182 arguments or more than one argument or if passed anything other than a
1183 :py:obj:`PKey` instance as its single argument.
1184 """
1185 request = X509Req()
1186 self.assertRaises(TypeError, request.verify)
1187 self.assertRaises(TypeError, request.verify, object())
1188 self.assertRaises(TypeError, request.verify, PKey(), object())
1189
1190
1191 def test_verify_uninitialized_key(self):
1192 """
1193 :py:obj:`X509Req.verify` raises :py:obj:`OpenSSL.crypto.Error` if called
1194 with a :py:obj:`OpenSSL.crypto.PKey` which contains no key data.
1195 """
1196 request = X509Req()
1197 pkey = PKey()
1198 self.assertRaises(Error, request.verify, pkey)
1199
1200
1201 def test_verify_wrong_key(self):
1202 """
1203 :py:obj:`X509Req.verify` raises :py:obj:`OpenSSL.crypto.Error` if called
1204 with a :py:obj:`OpenSSL.crypto.PKey` which does not represent the public
1205 part of the key which signed the request.
1206 """
1207 request = X509Req()
1208 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001209 request.sign(pkey, GOOD_DIGEST)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001210 another_pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
1211 self.assertRaises(Error, request.verify, another_pkey)
1212
1213
1214 def test_verify_success(self):
1215 """
1216 :py:obj:`X509Req.verify` returns :py:obj:`True` if called with a
Alex Gaynor3b0ee972014-11-15 09:17:33 -08001217 :py:obj:`OpenSSL.crypto.PKey` which represents the public part of the key
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001218 which signed the request.
1219 """
1220 request = X509Req()
1221 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001222 request.sign(pkey, GOOD_DIGEST)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001223 self.assertEqual(True, request.verify(pkey))
1224
1225
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001226
Jean-Paul Calderone18808652009-07-05 12:54:05 -04001227class X509Tests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001228 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001229 Tests for :py:obj:`OpenSSL.crypto.X509`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001230 """
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001231 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
Jean-Paul Calderone8114b452008-03-25 15:27:59 -04001232
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001233 extpem = """
1234-----BEGIN CERTIFICATE-----
1235MIIC3jCCAkegAwIBAgIJAJHFjlcCgnQzMA0GCSqGSIb3DQEBBQUAMEcxCzAJBgNV
1236BAYTAlNFMRUwEwYDVQQIEwxXZXN0ZXJib3R0b20xEjAQBgNVBAoTCUNhdGFsb2dp
1237eDENMAsGA1UEAxMEUm9vdDAeFw0wODA0MjIxNDQ1MzhaFw0wOTA0MjIxNDQ1Mzha
1238MFQxCzAJBgNVBAYTAlNFMQswCQYDVQQIEwJXQjEUMBIGA1UEChMLT3Blbk1ldGFk
1239aXIxIjAgBgNVBAMTGW5vZGUxLm9tMi5vcGVubWV0YWRpci5vcmcwgZ8wDQYJKoZI
1240hvcNAQEBBQADgY0AMIGJAoGBAPIcQMrwbk2nESF/0JKibj9i1x95XYAOwP+LarwT
1241Op4EQbdlI9SY+uqYqlERhF19w7CS+S6oyqx0DRZSk4Y9dZ9j9/xgm2u/f136YS1u
1242zgYFPvfUs6PqYLPSM8Bw+SjJ+7+2+TN+Tkiof9WP1cMjodQwOmdsiRbR0/J7+b1B
1243hec1AgMBAAGjgcQwgcEwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNT
1244TCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFIdHsBcMVVMbAO7j6NCj
124503HgLnHaMB8GA1UdIwQYMBaAFL2h9Bf9Mre4vTdOiHTGAt7BRY/8MEYGA1UdEQQ/
1246MD2CDSouZXhhbXBsZS5vcmeCESoub20yLmV4bWFwbGUuY29thwSC7wgKgRNvbTJA
1247b3Blbm1ldGFkaXIub3JnMA0GCSqGSIb3DQEBBQUAA4GBALd7WdXkp2KvZ7/PuWZA
1248MPlIxyjS+Ly11+BNE0xGQRp9Wz+2lABtpgNqssvU156+HkKd02rGheb2tj7MX9hG
1249uZzbwDAZzJPjzDQDD7d3cWsrVcfIdqVU7epHqIadnOF+X0ghJ39pAm6VVadnSXCt
1250WpOdIpB8KksUTCzV591Nr1wd
1251-----END CERTIFICATE-----
1252 """
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001253 def signable(self):
1254 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001255 Create and return a new :py:obj:`X509`.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001256 """
1257 return X509()
1258
1259
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001260 def test_type(self):
1261 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001262 :py:obj:`X509` and :py:obj:`X509Type` refer to the same type object and can be used
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001263 to create instances of that type.
1264 """
1265 self.assertIdentical(X509, X509Type)
1266 self.assertConsistentType(X509, 'X509')
1267
1268
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001269 def test_construction(self):
1270 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001271 :py:obj:`X509` takes no arguments and returns an instance of :py:obj:`X509Type`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001272 """
1273 certificate = X509()
1274 self.assertTrue(
1275 isinstance(certificate, X509Type),
1276 "%r is of type %r, should be %r" % (certificate,
1277 type(certificate),
1278 X509Type))
Rick Deane15b1472009-07-09 15:53:42 -05001279 self.assertEqual(type(X509Type).__name__, 'type')
1280 self.assertEqual(type(certificate).__name__, 'X509')
1281 self.assertEqual(type(certificate), X509Type)
Rick Dean04113e72009-07-16 12:06:35 -05001282 self.assertEqual(type(certificate), X509)
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001283
1284
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001285 def test_get_version_wrong_args(self):
1286 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001287 :py:obj:`X509.get_version` raises :py:obj:`TypeError` if invoked with any arguments.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001288 """
1289 cert = X509()
1290 self.assertRaises(TypeError, cert.get_version, None)
1291
1292
1293 def test_set_version_wrong_args(self):
1294 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001295 :py:obj:`X509.set_version` raises :py:obj:`TypeError` if invoked with the wrong number
1296 of arguments or an argument not of type :py:obj:`int`.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001297 """
1298 cert = X509()
1299 self.assertRaises(TypeError, cert.set_version)
1300 self.assertRaises(TypeError, cert.set_version, None)
1301 self.assertRaises(TypeError, cert.set_version, 1, None)
1302
1303
1304 def test_version(self):
1305 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001306 :py:obj:`X509.set_version` sets the certificate version number.
1307 :py:obj:`X509.get_version` retrieves it.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001308 """
1309 cert = X509()
1310 cert.set_version(1234)
1311 self.assertEquals(cert.get_version(), 1234)
1312
1313
1314 def test_get_serial_number_wrong_args(self):
1315 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001316 :py:obj:`X509.get_serial_number` raises :py:obj:`TypeError` if invoked with any
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001317 arguments.
1318 """
1319 cert = X509()
1320 self.assertRaises(TypeError, cert.get_serial_number, None)
1321
1322
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001323 def test_serial_number(self):
1324 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001325 The serial number of an :py:obj:`X509Type` can be retrieved and modified with
1326 :py:obj:`X509Type.get_serial_number` and :py:obj:`X509Type.set_serial_number`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001327 """
1328 certificate = X509()
1329 self.assertRaises(TypeError, certificate.set_serial_number)
1330 self.assertRaises(TypeError, certificate.set_serial_number, 1, 2)
1331 self.assertRaises(TypeError, certificate.set_serial_number, "1")
1332 self.assertRaises(TypeError, certificate.set_serial_number, 5.5)
1333 self.assertEqual(certificate.get_serial_number(), 0)
1334 certificate.set_serial_number(1)
1335 self.assertEqual(certificate.get_serial_number(), 1)
1336 certificate.set_serial_number(2 ** 32 + 1)
1337 self.assertEqual(certificate.get_serial_number(), 2 ** 32 + 1)
1338 certificate.set_serial_number(2 ** 64 + 1)
1339 self.assertEqual(certificate.get_serial_number(), 2 ** 64 + 1)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001340 certificate.set_serial_number(2 ** 128 + 1)
1341 self.assertEqual(certificate.get_serial_number(), 2 ** 128 + 1)
1342
1343
1344 def _setBoundTest(self, which):
1345 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001346 :py:obj:`X509Type.set_notBefore` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001347 GENERALIZEDTIME and sets the beginning of the certificate's validity
1348 period to it.
1349 """
1350 certificate = X509()
1351 set = getattr(certificate, 'set_not' + which)
1352 get = getattr(certificate, 'get_not' + which)
1353
Jean-Paul Calderonee0615b52008-03-09 21:44:46 -04001354 # Starts with no value.
1355 self.assertEqual(get(), None)
1356
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001357 # GMT (Or is it UTC?) -exarkun
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001358 when = b("20040203040506Z")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001359 set(when)
1360 self.assertEqual(get(), when)
1361
1362 # A plus two hours and thirty minutes offset
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001363 when = b("20040203040506+0530")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001364 set(when)
1365 self.assertEqual(get(), when)
1366
1367 # A minus one hour fifteen minutes offset
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001368 when = b("20040203040506-0115")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001369 set(when)
1370 self.assertEqual(get(), when)
1371
1372 # An invalid string results in a ValueError
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001373 self.assertRaises(ValueError, set, b("foo bar"))
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001374
Jean-Paul Calderone31ca2002010-01-30 15:14:43 -05001375 # The wrong number of arguments results in a TypeError.
1376 self.assertRaises(TypeError, set)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001377 self.assertRaises(TypeError, set, b("20040203040506Z"), b("20040203040506Z"))
1378 self.assertRaises(TypeError, get, b("foo bar"))
1379
Jean-Paul Calderone31ca2002010-01-30 15:14:43 -05001380
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001381 # XXX ASN1_TIME (not GENERALIZEDTIME)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001382
1383 def test_set_notBefore(self):
1384 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001385 :py:obj:`X509Type.set_notBefore` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001386 GENERALIZEDTIME and sets the beginning of the certificate's validity
1387 period to it.
1388 """
1389 self._setBoundTest("Before")
1390
1391
1392 def test_set_notAfter(self):
1393 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001394 :py:obj:`X509Type.set_notAfter` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001395 GENERALIZEDTIME and sets the end of the certificate's validity period
1396 to it.
1397 """
1398 self._setBoundTest("After")
Jean-Paul Calderone76576d52008-03-24 16:04:46 -04001399
1400
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001401 def test_get_notBefore(self):
1402 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001403 :py:obj:`X509Type.get_notBefore` returns a string in the format of an ASN1
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001404 GENERALIZEDTIME even for certificates which store it as UTCTIME
1405 internally.
1406 """
Jean-Paul Calderone8114b452008-03-25 15:27:59 -04001407 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001408 self.assertEqual(cert.get_notBefore(), b("20090325123658Z"))
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001409
Rick Dean38a05c82009-07-18 01:41:30 -05001410
1411 def test_get_notAfter(self):
1412 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001413 :py:obj:`X509Type.get_notAfter` returns a string in the format of an ASN1
Rick Dean38a05c82009-07-18 01:41:30 -05001414 GENERALIZEDTIME even for certificates which store it as UTCTIME
1415 internally.
1416 """
1417 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001418 self.assertEqual(cert.get_notAfter(), b("20170611123658Z"))
Rick Dean38a05c82009-07-18 01:41:30 -05001419
1420
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001421 def test_gmtime_adj_notBefore_wrong_args(self):
1422 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001423 :py:obj:`X509Type.gmtime_adj_notBefore` raises :py:obj:`TypeError` if called with the
1424 wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001425 """
1426 cert = X509()
1427 self.assertRaises(TypeError, cert.gmtime_adj_notBefore)
1428 self.assertRaises(TypeError, cert.gmtime_adj_notBefore, None)
1429 self.assertRaises(TypeError, cert.gmtime_adj_notBefore, 123, None)
1430
1431
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001432 def test_gmtime_adj_notBefore(self):
1433 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001434 :py:obj:`X509Type.gmtime_adj_notBefore` changes the not-before timestamp to be
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001435 the current time plus the number of seconds passed in.
1436 """
1437 cert = load_certificate(FILETYPE_PEM, self.pemData)
1438 now = datetime.utcnow() + timedelta(seconds=100)
1439 cert.gmtime_adj_notBefore(100)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001440 self.assertEqual(cert.get_notBefore(), b(now.strftime("%Y%m%d%H%M%SZ")))
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001441
1442
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001443 def test_gmtime_adj_notAfter_wrong_args(self):
1444 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001445 :py:obj:`X509Type.gmtime_adj_notAfter` raises :py:obj:`TypeError` if called with the
1446 wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001447 """
1448 cert = X509()
1449 self.assertRaises(TypeError, cert.gmtime_adj_notAfter)
1450 self.assertRaises(TypeError, cert.gmtime_adj_notAfter, None)
1451 self.assertRaises(TypeError, cert.gmtime_adj_notAfter, 123, None)
1452
1453
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001454 def test_gmtime_adj_notAfter(self):
1455 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001456 :py:obj:`X509Type.gmtime_adj_notAfter` changes the not-after timestamp to be
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001457 the current time plus the number of seconds passed in.
1458 """
1459 cert = load_certificate(FILETYPE_PEM, self.pemData)
1460 now = datetime.utcnow() + timedelta(seconds=100)
1461 cert.gmtime_adj_notAfter(100)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001462 self.assertEqual(cert.get_notAfter(), b(now.strftime("%Y%m%d%H%M%SZ")))
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001463
1464
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001465 def test_has_expired_wrong_args(self):
1466 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001467 :py:obj:`X509Type.has_expired` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001468 arguments.
1469 """
1470 cert = X509()
1471 self.assertRaises(TypeError, cert.has_expired, None)
1472
1473
1474 def test_has_expired(self):
1475 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001476 :py:obj:`X509Type.has_expired` returns :py:obj:`True` if the certificate's not-after
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001477 time is in the past.
1478 """
1479 cert = X509()
1480 cert.gmtime_adj_notAfter(-1)
1481 self.assertTrue(cert.has_expired())
1482
1483
1484 def test_has_not_expired(self):
1485 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001486 :py:obj:`X509Type.has_expired` returns :py:obj:`False` if the certificate's not-after
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001487 time is in the future.
1488 """
1489 cert = X509()
1490 cert.gmtime_adj_notAfter(2)
1491 self.assertFalse(cert.has_expired())
1492
1493
Rick Dean38a05c82009-07-18 01:41:30 -05001494 def test_digest(self):
1495 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001496 :py:obj:`X509.digest` returns a string giving ":"-separated hex-encoded words
Rick Dean38a05c82009-07-18 01:41:30 -05001497 of the digest of the certificate.
1498 """
1499 cert = X509()
1500 self.assertEqual(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001501 # This is MD5 instead of GOOD_DIGEST because the digest algorithm
1502 # actually matters to the assertion (ie, another arbitrary, good
1503 # digest will not product the same digest).
1504 cert.digest("MD5"),
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001505 b("A8:EB:07:F8:53:25:0A:F2:56:05:C5:A5:C4:C4:C7:15"))
Rick Dean38a05c82009-07-18 01:41:30 -05001506
1507
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001508 def _extcert(self, pkey, extensions):
1509 cert = X509()
1510 cert.set_pubkey(pkey)
1511 cert.get_subject().commonName = "Unit Tests"
1512 cert.get_issuer().commonName = "Unit Tests"
1513 when = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
1514 cert.set_notBefore(when)
1515 cert.set_notAfter(when)
1516
1517 cert.add_extensions(extensions)
1518 return load_certificate(
1519 FILETYPE_PEM, dump_certificate(FILETYPE_PEM, cert))
1520
1521
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001522 def test_extension_count(self):
1523 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001524 :py:obj:`X509.get_extension_count` returns the number of extensions that are
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001525 present in the certificate.
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001526 """
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001527 pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001528 ca = X509Extension(b('basicConstraints'), True, b('CA:FALSE'))
1529 key = X509Extension(b('keyUsage'), True, b('digitalSignature'))
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001530 subjectAltName = X509Extension(
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001531 b('subjectAltName'), True, b('DNS:example.com'))
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001532
1533 # Try a certificate with no extensions at all.
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001534 c = self._extcert(pkey, [])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001535 self.assertEqual(c.get_extension_count(), 0)
1536
1537 # And a certificate with one
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001538 c = self._extcert(pkey, [ca])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001539 self.assertEqual(c.get_extension_count(), 1)
1540
1541 # And a certificate with several
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001542 c = self._extcert(pkey, [ca, key, subjectAltName])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001543 self.assertEqual(c.get_extension_count(), 3)
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001544
1545
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001546 def test_get_extension(self):
1547 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001548 :py:obj:`X509.get_extension` takes an integer and returns an :py:obj:`X509Extension`
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001549 corresponding to the extension at that index.
1550 """
1551 pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001552 ca = X509Extension(b('basicConstraints'), True, b('CA:FALSE'))
1553 key = X509Extension(b('keyUsage'), True, b('digitalSignature'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001554 subjectAltName = X509Extension(
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001555 b('subjectAltName'), False, b('DNS:example.com'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001556
1557 cert = self._extcert(pkey, [ca, key, subjectAltName])
1558
1559 ext = cert.get_extension(0)
1560 self.assertTrue(isinstance(ext, X509Extension))
1561 self.assertTrue(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001562 self.assertEqual(ext.get_short_name(), b('basicConstraints'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001563
1564 ext = cert.get_extension(1)
1565 self.assertTrue(isinstance(ext, X509Extension))
1566 self.assertTrue(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001567 self.assertEqual(ext.get_short_name(), b('keyUsage'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001568
1569 ext = cert.get_extension(2)
1570 self.assertTrue(isinstance(ext, X509Extension))
1571 self.assertFalse(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001572 self.assertEqual(ext.get_short_name(), b('subjectAltName'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001573
1574 self.assertRaises(IndexError, cert.get_extension, -1)
1575 self.assertRaises(IndexError, cert.get_extension, 4)
1576 self.assertRaises(TypeError, cert.get_extension, "hello")
1577
1578
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001579 def test_nullbyte_subjectAltName(self):
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001580 """
Jean-Paul Calderone9af07b02013-08-23 16:07:31 -04001581 The fields of a `subjectAltName` extension on an X509 may contain NUL
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001582 bytes and this value is reflected in the string representation of the
1583 extension object.
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001584 """
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001585 cert = load_certificate(FILETYPE_PEM, nulbyteSubjectAltNamePEM)
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001586
1587 ext = cert.get_extension(3)
1588 self.assertEqual(ext.get_short_name(), b('subjectAltName'))
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001589 self.assertEqual(
1590 b("DNS:altnull.python.org\x00example.com, "
1591 "email:null@python.org\x00user@example.org, "
1592 "URI:http://null.python.org\x00http://example.org, "
1593 "IP Address:192.0.2.1, IP Address:2001:DB8:0:0:0:0:0:1\n"),
1594 b(str(ext)))
1595
Rick Dean38a05c82009-07-18 01:41:30 -05001596
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001597 def test_invalid_digest_algorithm(self):
1598 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001599 :py:obj:`X509.digest` raises :py:obj:`ValueError` if called with an unrecognized hash
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001600 algorithm.
1601 """
1602 cert = X509()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001603 self.assertRaises(ValueError, cert.digest, BAD_DIGEST)
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001604
1605
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001606 def test_get_subject_wrong_args(self):
1607 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001608 :py:obj:`X509.get_subject` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001609 """
1610 cert = X509()
1611 self.assertRaises(TypeError, cert.get_subject, None)
1612
1613
1614 def test_get_subject(self):
1615 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001616 :py:obj:`X509.get_subject` returns an :py:obj:`X509Name` instance.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001617 """
1618 cert = load_certificate(FILETYPE_PEM, self.pemData)
1619 subj = cert.get_subject()
1620 self.assertTrue(isinstance(subj, X509Name))
1621 self.assertEquals(
1622 subj.get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001623 [(b('C'), b('US')), (b('ST'), b('IL')), (b('L'), b('Chicago')),
1624 (b('O'), b('Testing')), (b('CN'), b('Testing Root CA'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001625
1626
1627 def test_set_subject_wrong_args(self):
1628 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001629 :py:obj:`X509.set_subject` raises a :py:obj:`TypeError` if called with the wrong
1630 number of arguments or an argument not of type :py:obj:`X509Name`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001631 """
1632 cert = X509()
1633 self.assertRaises(TypeError, cert.set_subject)
1634 self.assertRaises(TypeError, cert.set_subject, None)
1635 self.assertRaises(TypeError, cert.set_subject, cert.get_subject(), None)
1636
1637
1638 def test_set_subject(self):
1639 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001640 :py:obj:`X509.set_subject` changes the subject of the certificate to the one
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001641 passed in.
1642 """
1643 cert = X509()
1644 name = cert.get_subject()
1645 name.C = 'AU'
1646 name.O = 'Unit Tests'
1647 cert.set_subject(name)
1648 self.assertEquals(
1649 cert.get_subject().get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001650 [(b('C'), b('AU')), (b('O'), b('Unit Tests'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001651
1652
1653 def test_get_issuer_wrong_args(self):
1654 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001655 :py:obj:`X509.get_issuer` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001656 """
1657 cert = X509()
1658 self.assertRaises(TypeError, cert.get_issuer, None)
1659
1660
1661 def test_get_issuer(self):
1662 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001663 :py:obj:`X509.get_issuer` returns an :py:obj:`X509Name` instance.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001664 """
1665 cert = load_certificate(FILETYPE_PEM, self.pemData)
1666 subj = cert.get_issuer()
1667 self.assertTrue(isinstance(subj, X509Name))
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001668 comp = subj.get_components()
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001669 self.assertEquals(
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001670 comp,
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001671 [(b('C'), b('US')), (b('ST'), b('IL')), (b('L'), b('Chicago')),
1672 (b('O'), b('Testing')), (b('CN'), b('Testing Root CA'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001673
1674
1675 def test_set_issuer_wrong_args(self):
1676 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001677 :py:obj:`X509.set_issuer` raises a :py:obj:`TypeError` if called with the wrong
1678 number of arguments or an argument not of type :py:obj:`X509Name`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001679 """
1680 cert = X509()
1681 self.assertRaises(TypeError, cert.set_issuer)
1682 self.assertRaises(TypeError, cert.set_issuer, None)
1683 self.assertRaises(TypeError, cert.set_issuer, cert.get_issuer(), None)
1684
1685
1686 def test_set_issuer(self):
1687 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001688 :py:obj:`X509.set_issuer` changes the issuer of the certificate to the one
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001689 passed in.
1690 """
1691 cert = X509()
1692 name = cert.get_issuer()
1693 name.C = 'AU'
1694 name.O = 'Unit Tests'
1695 cert.set_issuer(name)
1696 self.assertEquals(
1697 cert.get_issuer().get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001698 [(b('C'), b('AU')), (b('O'), b('Unit Tests'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001699
1700
1701 def test_get_pubkey_uninitialized(self):
1702 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001703 When called on a certificate with no public key, :py:obj:`X509.get_pubkey`
1704 raises :py:obj:`OpenSSL.crypto.Error`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001705 """
1706 cert = X509()
1707 self.assertRaises(Error, cert.get_pubkey)
1708
1709
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001710 def test_subject_name_hash_wrong_args(self):
1711 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001712 :py:obj:`X509.subject_name_hash` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001713 arguments.
1714 """
1715 cert = X509()
1716 self.assertRaises(TypeError, cert.subject_name_hash, None)
1717
1718
1719 def test_subject_name_hash(self):
1720 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001721 :py:obj:`X509.subject_name_hash` returns the hash of the certificate's subject
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001722 name.
1723 """
1724 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -04001725 self.assertIn(
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001726 cert.subject_name_hash(),
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -04001727 [3350047874, # OpenSSL 0.9.8, MD5
1728 3278919224, # OpenSSL 1.0.0, SHA1
1729 ])
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001730
1731
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001732 def test_get_signature_algorithm(self):
1733 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001734 :py:obj:`X509Type.get_signature_algorithm` returns a string which means
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001735 the algorithm used to sign the certificate.
1736 """
1737 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001738 self.assertEqual(
1739 b("sha1WithRSAEncryption"), cert.get_signature_algorithm())
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001740
1741
1742 def test_get_undefined_signature_algorithm(self):
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001743 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001744 :py:obj:`X509Type.get_signature_algorithm` raises :py:obj:`ValueError` if the
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001745 signature algorithm is undefined or unknown.
1746 """
1747 # This certificate has been modified to indicate a bogus OID in the
1748 # signature algorithm field so that OpenSSL does not recognize it.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001749 certPEM = b("""\
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001750-----BEGIN CERTIFICATE-----
1751MIIC/zCCAmigAwIBAgIBATAGBgJ8BQUAMHsxCzAJBgNVBAYTAlNHMREwDwYDVQQK
1752EwhNMkNyeXB0bzEUMBIGA1UECxMLTTJDcnlwdG8gQ0ExJDAiBgNVBAMTG00yQ3J5
1753cHRvIENlcnRpZmljYXRlIE1hc3RlcjEdMBsGCSqGSIb3DQEJARYObmdwc0Bwb3N0
1754MS5jb20wHhcNMDAwOTEwMDk1MTMwWhcNMDIwOTEwMDk1MTMwWjBTMQswCQYDVQQG
1755EwJTRzERMA8GA1UEChMITTJDcnlwdG8xEjAQBgNVBAMTCWxvY2FsaG9zdDEdMBsG
1756CSqGSIb3DQEJARYObmdwc0Bwb3N0MS5jb20wXDANBgkqhkiG9w0BAQEFAANLADBI
1757AkEArL57d26W9fNXvOhNlZzlPOACmvwOZ5AdNgLzJ1/MfsQQJ7hHVeHmTAjM664V
1758+fXvwUGJLziCeBo1ysWLRnl8CQIDAQABo4IBBDCCAQAwCQYDVR0TBAIwADAsBglg
1759hkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0O
1760BBYEFM+EgpK+eyZiwFU1aOPSbczbPSpVMIGlBgNVHSMEgZ0wgZqAFPuHI2nrnDqT
1761FeXFvylRT/7tKDgBoX+kfTB7MQswCQYDVQQGEwJTRzERMA8GA1UEChMITTJDcnlw
1762dG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtNMkNyeXB0byBDZXJ0
1763aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tggEA
1764MA0GCSqGSIb3DQEBBAUAA4GBADv8KpPo+gfJxN2ERK1Y1l17sz/ZhzoGgm5XCdbx
1765jEY7xKfpQngV599k1xhl11IMqizDwu0855agrckg2MCTmOI9DZzDD77tAYb+Dk0O
1766PEVk0Mk/V0aIsDE9bolfCi/i/QWZ3N8s5nTWMNyBBBmoSliWCm4jkkRZRD0ejgTN
1767tgI5
1768-----END CERTIFICATE-----
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001769""")
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001770 cert = load_certificate(FILETYPE_PEM, certPEM)
1771 self.assertRaises(ValueError, cert.get_signature_algorithm)
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001772
1773
Rick Dean38a05c82009-07-18 01:41:30 -05001774
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001775class X509StoreTests(TestCase):
1776 """
1777 Test for :py:obj:`OpenSSL.crypto.X509Store`.
1778 """
1779 def test_type(self):
1780 """
1781 :py:obj:`X509StoreType` is a type object.
1782 """
1783 self.assertIdentical(X509Store, X509StoreType)
1784 self.assertConsistentType(X509Store, 'X509Store')
1785
1786
1787 def test_add_cert_wrong_args(self):
1788 store = X509Store()
1789 self.assertRaises(TypeError, store.add_cert)
1790 self.assertRaises(TypeError, store.add_cert, object())
1791 self.assertRaises(TypeError, store.add_cert, X509(), object())
1792
1793
1794 def test_add_cert(self):
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001795 """
1796 :py:obj:`X509Store.add_cert` adds a :py:obj:`X509` instance to the
1797 certificate store.
1798 """
1799 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001800 store = X509Store()
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001801 store.add_cert(cert)
1802
1803
1804 def test_add_cert_rejects_duplicate(self):
1805 """
1806 :py:obj:`X509Store.add_cert` raises :py:obj:`OpenSSL.crypto.Error` if an
1807 attempt is made to add the same certificate to the store more than once.
1808 """
1809 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
1810 store = X509Store()
1811 store.add_cert(cert)
1812 self.assertRaises(Error, store.add_cert, cert)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001813
1814
1815
Rick Dean623ee362009-07-17 12:22:16 -05001816class PKCS12Tests(TestCase):
1817 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001818 Test for :py:obj:`OpenSSL.crypto.PKCS12` and :py:obj:`OpenSSL.crypto.load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001819 """
1820 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
1821
Jean-Paul Calderonec3a41f72009-07-25 12:36:02 -04001822 def test_type(self):
1823 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001824 :py:obj:`PKCS12Type` is a type object.
Jean-Paul Calderonec3a41f72009-07-25 12:36:02 -04001825 """
1826 self.assertIdentical(PKCS12, PKCS12Type)
1827 self.assertConsistentType(PKCS12, 'PKCS12')
1828
1829
Rick Deanf94096c2009-07-18 14:23:06 -05001830 def test_empty_construction(self):
Rick Dean38a05c82009-07-18 01:41:30 -05001831 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001832 :py:obj:`PKCS12` returns a new instance of :py:obj:`PKCS12` with no certificate,
Jean-Paul Calderonedc857b52009-07-25 12:25:07 -04001833 private key, CA certificates, or friendly name.
Rick Dean38a05c82009-07-18 01:41:30 -05001834 """
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001835 p12 = PKCS12()
Rick Dean623ee362009-07-17 12:22:16 -05001836 self.assertEqual(None, p12.get_certificate())
1837 self.assertEqual(None, p12.get_privatekey())
1838 self.assertEqual(None, p12.get_ca_certificates())
Rick Dean42d69e12009-07-20 11:36:08 -05001839 self.assertEqual(None, p12.get_friendlyname())
Rick Dean623ee362009-07-17 12:22:16 -05001840
Rick Dean38a05c82009-07-18 01:41:30 -05001841
Rick Dean623ee362009-07-17 12:22:16 -05001842 def test_type_errors(self):
Rick Dean38a05c82009-07-18 01:41:30 -05001843 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001844 The :py:obj:`PKCS12` setter functions (:py:obj:`set_certificate`, :py:obj:`set_privatekey`,
1845 :py:obj:`set_ca_certificates`, and :py:obj:`set_friendlyname`) raise :py:obj:`TypeError`
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001846 when passed objects of types other than those expected.
Rick Dean38a05c82009-07-18 01:41:30 -05001847 """
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001848 p12 = PKCS12()
Rick Dean623ee362009-07-17 12:22:16 -05001849 self.assertRaises(TypeError, p12.set_certificate, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05001850 self.assertRaises(TypeError, p12.set_certificate, PKey())
1851 self.assertRaises(TypeError, p12.set_certificate, X509)
Rick Dean623ee362009-07-17 12:22:16 -05001852 self.assertRaises(TypeError, p12.set_privatekey, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05001853 self.assertRaises(TypeError, p12.set_privatekey, 'legbone')
1854 self.assertRaises(TypeError, p12.set_privatekey, X509())
Rick Dean623ee362009-07-17 12:22:16 -05001855 self.assertRaises(TypeError, p12.set_ca_certificates, 3)
1856 self.assertRaises(TypeError, p12.set_ca_certificates, X509())
1857 self.assertRaises(TypeError, p12.set_ca_certificates, (3, 4))
Rick Deanf94096c2009-07-18 14:23:06 -05001858 self.assertRaises(TypeError, p12.set_ca_certificates, ( PKey(), ))
Rick Dean42d69e12009-07-20 11:36:08 -05001859 self.assertRaises(TypeError, p12.set_friendlyname, 6)
1860 self.assertRaises(TypeError, p12.set_friendlyname, ('foo', 'bar'))
Rick Dean623ee362009-07-17 12:22:16 -05001861
Rick Dean38a05c82009-07-18 01:41:30 -05001862
Rick Dean623ee362009-07-17 12:22:16 -05001863 def test_key_only(self):
1864 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001865 A :py:obj:`PKCS12` with only a private key can be exported using
1866 :py:obj:`PKCS12.export` and loaded again using :py:obj:`load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001867 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001868 passwd = b"blah"
Rick Dean623ee362009-07-17 12:22:16 -05001869 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001870 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001871 p12.set_privatekey(pkey)
Rick Dean623ee362009-07-17 12:22:16 -05001872 self.assertEqual(None, p12.get_certificate())
1873 self.assertEqual(pkey, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05001874 try:
1875 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
1876 except Error:
1877 # Some versions of OpenSSL will throw an exception
1878 # for this nearly useless PKCS12 we tried to generate:
1879 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
1880 return
Rick Dean623ee362009-07-17 12:22:16 -05001881 p12 = load_pkcs12(dumped_p12, passwd)
1882 self.assertEqual(None, p12.get_ca_certificates())
1883 self.assertEqual(None, p12.get_certificate())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001884
1885 # OpenSSL fails to bring the key back to us. So sad. Perhaps in the
1886 # future this will be improved.
1887 self.assertTrue(isinstance(p12.get_privatekey(), (PKey, type(None))))
Rick Dean623ee362009-07-17 12:22:16 -05001888
Rick Dean38a05c82009-07-18 01:41:30 -05001889
Rick Dean623ee362009-07-17 12:22:16 -05001890 def test_cert_only(self):
1891 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001892 A :py:obj:`PKCS12` with only a certificate can be exported using
1893 :py:obj:`PKCS12.export` and loaded again using :py:obj:`load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001894 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001895 passwd = b"blah"
Rick Dean623ee362009-07-17 12:22:16 -05001896 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001897 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001898 p12.set_certificate(cert)
Rick Dean623ee362009-07-17 12:22:16 -05001899 self.assertEqual(cert, p12.get_certificate())
1900 self.assertEqual(None, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05001901 try:
1902 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
1903 except Error:
1904 # Some versions of OpenSSL will throw an exception
1905 # for this nearly useless PKCS12 we tried to generate:
1906 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
1907 return
Rick Dean623ee362009-07-17 12:22:16 -05001908 p12 = load_pkcs12(dumped_p12, passwd)
1909 self.assertEqual(None, p12.get_privatekey())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001910
1911 # OpenSSL fails to bring the cert back to us. Groany mcgroan.
1912 self.assertTrue(isinstance(p12.get_certificate(), (X509, type(None))))
1913
1914 # Oh ho. It puts the certificate into the ca certificates list, in
1915 # fact. Totally bogus, I would think. Nevertheless, let's exploit
1916 # that to check to see if it reconstructed the certificate we expected
1917 # it to. At some point, hopefully this will change so that
1918 # p12.get_certificate() is actually what returns the loaded
1919 # certificate.
1920 self.assertEqual(
1921 cleartextCertificatePEM,
1922 dump_certificate(FILETYPE_PEM, p12.get_ca_certificates()[0]))
Rick Dean623ee362009-07-17 12:22:16 -05001923
1924
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001925 def gen_pkcs12(self, cert_pem=None, key_pem=None, ca_pem=None, friendly_name=None):
Rick Dean623ee362009-07-17 12:22:16 -05001926 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001927 Generate a PKCS12 object with components from PEM. Verify that the set
1928 functions return None.
Rick Dean623ee362009-07-17 12:22:16 -05001929 """
Rick Deanf94096c2009-07-18 14:23:06 -05001930 p12 = PKCS12()
1931 if cert_pem:
1932 ret = p12.set_certificate(load_certificate(FILETYPE_PEM, cert_pem))
1933 self.assertEqual(ret, None)
1934 if key_pem:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001935 ret = p12.set_privatekey(load_privatekey(FILETYPE_PEM, key_pem))
Rick Deanf94096c2009-07-18 14:23:06 -05001936 self.assertEqual(ret, None)
1937 if ca_pem:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001938 ret = p12.set_ca_certificates((load_certificate(FILETYPE_PEM, ca_pem),))
Rick Deanf94096c2009-07-18 14:23:06 -05001939 self.assertEqual(ret, None)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001940 if friendly_name:
1941 ret = p12.set_friendlyname(friendly_name)
Rick Dean42d69e12009-07-20 11:36:08 -05001942 self.assertEqual(ret, None)
Rick Deanf94096c2009-07-18 14:23:06 -05001943 return p12
1944
1945
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001946 def check_recovery(self, p12_str, key=None, cert=None, ca=None, passwd=b"",
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001947 extra=()):
Rick Deanf94096c2009-07-18 14:23:06 -05001948 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001949 Use openssl program to confirm three components are recoverable from a
1950 PKCS12 string.
Rick Deanf94096c2009-07-18 14:23:06 -05001951 """
1952 if key:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001953 recovered_key = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001954 p12_str, b"pkcs12", b"-nocerts", b"-nodes", b"-passin",
1955 b"pass:" + passwd, *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001956 self.assertEqual(recovered_key[-len(key):], key)
1957 if cert:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001958 recovered_cert = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001959 p12_str, b"pkcs12", b"-clcerts", b"-nodes", b"-passin",
1960 b"pass:" + passwd, b"-nokeys", *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001961 self.assertEqual(recovered_cert[-len(cert):], cert)
1962 if ca:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001963 recovered_cert = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001964 p12_str, b"pkcs12", b"-cacerts", b"-nodes", b"-passin",
1965 b"pass:" + passwd, b"-nokeys", *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001966 self.assertEqual(recovered_cert[-len(ca):], ca)
1967
1968
Stephen Holsapple38482622014-04-05 20:29:34 -07001969 def verify_pkcs12_container(self, p12):
1970 """
1971 Verify that the PKCS#12 container contains the correct client
1972 certificate and private key.
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04001973
1974 :param p12: The PKCS12 instance to verify.
1975 :type p12: :py:class:`PKCS12`
Stephen Holsapple38482622014-04-05 20:29:34 -07001976 """
1977 cert_pem = dump_certificate(FILETYPE_PEM, p12.get_certificate())
1978 key_pem = dump_privatekey(FILETYPE_PEM, p12.get_privatekey())
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04001979 self.assertEqual(
1980 (client_cert_pem, client_key_pem, None),
1981 (cert_pem, key_pem, p12.get_ca_certificates()))
Stephen Holsapple38482622014-04-05 20:29:34 -07001982
1983
Rick Deanf94096c2009-07-18 14:23:06 -05001984 def test_load_pkcs12(self):
1985 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001986 A PKCS12 string generated using the openssl command line can be loaded
Jonathan Ballet648875f2011-07-16 14:14:58 +09001987 with :py:obj:`load_pkcs12` and its components extracted and examined.
Rick Deanf94096c2009-07-18 14:23:06 -05001988 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001989 passwd = b"whatever"
Rick Dean623ee362009-07-17 12:22:16 -05001990 pem = client_key_pem + client_cert_pem
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001991 p12_str = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001992 pem, b"pkcs12", b"-export", b"-clcerts", b"-passout", b"pass:" + passwd)
Stephen Holsapple38482622014-04-05 20:29:34 -07001993 p12 = load_pkcs12(p12_str, passphrase=passwd)
1994 self.verify_pkcs12_container(p12)
1995
1996
Abraham Martinc5484ba2015-03-25 15:33:05 +00001997 def test_load_pkcs12_text_passphrase(self):
1998 """
1999 A PKCS12 string generated using the openssl command line can be loaded
2000 with :py:obj:`load_pkcs12` and its components extracted and examined.
2001 Using text as passphrase instead of bytes. DeprecationWarning expected.
2002 """
2003 pem = client_key_pem + client_cert_pem
2004 passwd = b"whatever"
2005 p12_str = _runopenssl(pem, b"pkcs12", b"-export", b"-clcerts",
2006 b"-passout", b"pass:" + passwd)
2007 with catch_warnings(record=True) as w:
2008 simplefilter("always")
2009 if not PY3:
2010 p12 = load_pkcs12(p12_str, passphrase=unicode("whatever"))
2011 self.assertTrue("unicode in passphrase is no longer accepted, "
2012 "use bytes" in str(w[-1].message))
2013 else:
2014 p12 = load_pkcs12(p12_str, passphrase=b"whatever".decode())
2015 self.assertTrue("str in passphrase is no longer accepted, "
2016 "use bytes" in str(w[-1].message))
2017 self.verify_pkcs12_container(p12)
2018
2019
Stephen Holsapple38482622014-04-05 20:29:34 -07002020 def test_load_pkcs12_no_passphrase(self):
2021 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002022 A PKCS12 string generated using openssl command line can be loaded with
2023 :py:obj:`load_pkcs12` without a passphrase and its components extracted
2024 and examined.
Stephen Holsapple38482622014-04-05 20:29:34 -07002025 """
2026 pem = client_key_pem + client_cert_pem
2027 p12_str = _runopenssl(
2028 pem, b"pkcs12", b"-export", b"-clcerts", b"-passout", b"pass:")
2029 p12 = load_pkcs12(p12_str)
2030 self.verify_pkcs12_container(p12)
2031
2032
2033 def _dump_and_load(self, dump_passphrase, load_passphrase):
2034 """
2035 A helper method to dump and load a PKCS12 object.
2036 """
2037 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem)
2038 dumped_p12 = p12.export(passphrase=dump_passphrase, iter=2, maciter=3)
2039 return load_pkcs12(dumped_p12, passphrase=load_passphrase)
2040
2041
2042 def test_load_pkcs12_null_passphrase_load_empty(self):
2043 """
2044 A PKCS12 string can be dumped with a null passphrase, loaded with an
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002045 empty passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002046 extracted and examined.
2047 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002048 self.verify_pkcs12_container(
2049 self._dump_and_load(dump_passphrase=None, load_passphrase=b''))
Stephen Holsapple38482622014-04-05 20:29:34 -07002050
2051
2052 def test_load_pkcs12_null_passphrase_load_null(self):
2053 """
2054 A PKCS12 string can be dumped with a null passphrase, loaded with a
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002055 null passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002056 extracted and examined.
2057 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002058 self.verify_pkcs12_container(
2059 self._dump_and_load(dump_passphrase=None, load_passphrase=None))
Stephen Holsapple38482622014-04-05 20:29:34 -07002060
2061
2062 def test_load_pkcs12_empty_passphrase_load_empty(self):
2063 """
2064 A PKCS12 string can be dumped with an empty passphrase, loaded with an
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002065 empty passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002066 extracted and examined.
2067 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002068 self.verify_pkcs12_container(
2069 self._dump_and_load(dump_passphrase=b'', load_passphrase=b''))
Stephen Holsapple38482622014-04-05 20:29:34 -07002070
2071
2072 def test_load_pkcs12_empty_passphrase_load_null(self):
2073 """
2074 A PKCS12 string can be dumped with an empty passphrase, loaded with a
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002075 null passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002076 extracted and examined.
2077 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002078 self.verify_pkcs12_container(
2079 self._dump_and_load(dump_passphrase=b'', load_passphrase=None))
Rick Deanf94096c2009-07-18 14:23:06 -05002080
Rick Deanee568302009-07-24 09:56:29 -05002081
2082 def test_load_pkcs12_garbage(self):
2083 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002084 :py:obj:`load_pkcs12` raises :py:obj:`OpenSSL.crypto.Error` when passed a string
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002085 which is not a PKCS12 dump.
Rick Deanee568302009-07-24 09:56:29 -05002086 """
2087 passwd = 'whatever'
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002088 e = self.assertRaises(Error, load_pkcs12, b'fruit loops', passwd)
Jean-Paul Calderonede075462014-01-18 10:34:12 -05002089 self.assertEqual( e.args[0][0][0], 'asn1 encoding routines')
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -04002090 self.assertEqual( len(e.args[0][0]), 3)
Rick Deanee568302009-07-24 09:56:29 -05002091
2092
Rick Deanf94096c2009-07-18 14:23:06 -05002093 def test_replace(self):
2094 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002095 :py:obj:`PKCS12.set_certificate` replaces the certificate in a PKCS12 cluster.
2096 :py:obj:`PKCS12.set_privatekey` replaces the private key.
2097 :py:obj:`PKCS12.set_ca_certificates` replaces the CA certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05002098 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002099 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
2100 p12.set_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2101 p12.set_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002102 root_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05002103 client_cert = load_certificate(FILETYPE_PEM, client_cert_pem)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002104 p12.set_ca_certificates([root_cert]) # not a tuple
Rick Dean623ee362009-07-17 12:22:16 -05002105 self.assertEqual(1, len(p12.get_ca_certificates()))
2106 self.assertEqual(root_cert, p12.get_ca_certificates()[0])
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002107 p12.set_ca_certificates([client_cert, root_cert])
Rick Deanf94096c2009-07-18 14:23:06 -05002108 self.assertEqual(2, len(p12.get_ca_certificates()))
2109 self.assertEqual(client_cert, p12.get_ca_certificates()[0])
2110 self.assertEqual(root_cert, p12.get_ca_certificates()[1])
2111
2112
2113 def test_friendly_name(self):
2114 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002115 The *friendlyName* of a PKCS12 can be set and retrieved via
Jonathan Ballet648875f2011-07-16 14:14:58 +09002116 :py:obj:`PKCS12.get_friendlyname` and :py:obj:`PKCS12_set_friendlyname`, and a
2117 :py:obj:`PKCS12` with a friendly name set can be dumped with :py:obj:`PKCS12.export`.
Rick Deanf94096c2009-07-18 14:23:06 -05002118 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002119 passwd = b'Dogmeat[]{}!@#$%^&*()~`?/.,<>-_+=";:'
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002120 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -04002121 for friendly_name in [b('Serverlicious'), None, b('###')]:
Rick Dean42d69e12009-07-20 11:36:08 -05002122 p12.set_friendlyname(friendly_name)
2123 self.assertEqual(p12.get_friendlyname(), friendly_name)
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002124 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
Rick Dean42d69e12009-07-20 11:36:08 -05002125 reloaded_p12 = load_pkcs12(dumped_p12, passwd)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002126 self.assertEqual(
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -04002127 p12.get_friendlyname(), reloaded_p12.get_friendlyname())
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002128 # We would use the openssl program to confirm the friendly
2129 # name, but it is not possible. The pkcs12 command
2130 # does not store the friendly name in the cert's
Rick Dean42d69e12009-07-20 11:36:08 -05002131 # alias, which we could then extract.
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002132 self.check_recovery(
2133 dumped_p12, key=server_key_pem, cert=server_cert_pem,
2134 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05002135
2136
2137 def test_various_empty_passphrases(self):
2138 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002139 Test that missing, None, and '' passphrases are identical for PKCS12
2140 export.
Rick Deanf94096c2009-07-18 14:23:06 -05002141 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002142 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002143 passwd = b""
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002144 dumped_p12_empty = p12.export(iter=2, maciter=0, passphrase=passwd)
2145 dumped_p12_none = p12.export(iter=3, maciter=2, passphrase=None)
2146 dumped_p12_nopw = p12.export(iter=9, maciter=4)
2147 for dumped_p12 in [dumped_p12_empty, dumped_p12_none, dumped_p12_nopw]:
2148 self.check_recovery(
2149 dumped_p12, key=client_key_pem, cert=client_cert_pem,
2150 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05002151
2152
2153 def test_removing_ca_cert(self):
2154 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002155 Passing :py:obj:`None` to :py:obj:`PKCS12.set_ca_certificates` removes all CA
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002156 certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05002157 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002158 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
2159 p12.set_ca_certificates(None)
Rick Dean623ee362009-07-17 12:22:16 -05002160 self.assertEqual(None, p12.get_ca_certificates())
Rick Deanf94096c2009-07-18 14:23:06 -05002161
2162
2163 def test_export_without_mac(self):
2164 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002165 Exporting a PKCS12 with a :py:obj:`maciter` of ``-1`` excludes the MAC
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002166 entirely.
Rick Deanf94096c2009-07-18 14:23:06 -05002167 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002168 passwd = b"Lake Michigan"
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002169 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Dean623ee362009-07-17 12:22:16 -05002170 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002171 self.check_recovery(
2172 dumped_p12, key=server_key_pem, cert=server_cert_pem,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002173 passwd=passwd, extra=(b"-nomacver",))
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002174
2175
2176 def test_load_without_mac(self):
2177 """
2178 Loading a PKCS12 without a MAC does something other than crash.
2179 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002180 passwd = b"Lake Michigan"
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002181 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
2182 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Rick Dean321a0512009-08-13 17:21:29 -05002183 try:
2184 recovered_p12 = load_pkcs12(dumped_p12, passwd)
2185 # The person who generated this PCKS12 should be flogged,
2186 # or better yet we should have a means to determine
2187 # whether a PCKS12 had a MAC that was verified.
2188 # Anyway, libopenssl chooses to allow it, so the
2189 # pyopenssl binding does as well.
2190 self.assertTrue(isinstance(recovered_p12, PKCS12))
2191 except Error:
2192 # Failing here with an exception is preferred as some openssl
2193 # versions do.
2194 pass
Rick Dean623ee362009-07-17 12:22:16 -05002195
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002196
Rick Dean25bcc1f2009-07-20 11:53:13 -05002197 def test_zero_len_list_for_ca(self):
2198 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002199 A PKCS12 with an empty CA certificates list can be exported.
Rick Dean25bcc1f2009-07-20 11:53:13 -05002200 """
2201 passwd = 'Hobie 18'
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002202 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002203 # p12.set_ca_certificates([])
2204 # self.assertEqual((), p12.get_ca_certificates())
2205 # dumped_p12 = p12.export(passphrase=passwd, iter=3)
2206 # self.check_recovery(
2207 # dumped_p12, key=server_key_pem, cert=server_cert_pem,
2208 # passwd=passwd)
Rick Dean25bcc1f2009-07-20 11:53:13 -05002209
2210
Rick Deanf94096c2009-07-18 14:23:06 -05002211 def test_export_without_args(self):
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002212 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002213 All the arguments to :py:obj:`PKCS12.export` are optional.
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002214 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002215 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05002216 dumped_p12 = p12.export() # no args
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002217 self.check_recovery(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002218 dumped_p12, key=server_key_pem, cert=server_cert_pem, passwd=b"")
Rick Deanf94096c2009-07-18 14:23:06 -05002219
2220
Abraham Martinc5484ba2015-03-25 15:33:05 +00002221 def test_export_without_bytes(self):
2222 """
2223 Test :py:obj:`PKCS12.export` with text not bytes as passphrase
2224 """
2225 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
2226
2227 with catch_warnings(record=True) as w:
2228 simplefilter("always")
2229 if not PY3:
2230 dumped_p12 = p12.export(passphrase=unicode('randomtext'))
2231 self.assertTrue("unicode in passphrase is no longer accepted, "
2232 "use bytes" in str(w[-1].message))
2233 else:
2234 dumped_p12 = p12.export(passphrase=b'randomtext'.decode())
2235 self.assertTrue("str in passphrase is no longer accepted, "
2236 "use bytes" in str(w[-1].message))
2237 self.check_recovery(
2238 dumped_p12, key=server_key_pem, cert=server_cert_pem, passwd=b"randomtext")
2239
2240
Rick Deanf94096c2009-07-18 14:23:06 -05002241 def test_key_cert_mismatch(self):
2242 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002243 :py:obj:`PKCS12.export` raises an exception when a key and certificate
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002244 mismatch.
Rick Deanf94096c2009-07-18 14:23:06 -05002245 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002246 p12 = self.gen_pkcs12(server_cert_pem, client_key_pem, root_cert_pem)
2247 self.assertRaises(Error, p12.export)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002248
2249
2250
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002251# These quoting functions taken directly from Twisted's twisted.python.win32.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002252_cmdLineQuoteRe = re.compile(br'(\\*)"')
2253_cmdLineQuoteRe2 = re.compile(br'(\\+)\Z')
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002254def cmdLineQuote(s):
2255 """
2256 Internal method for quoting a single command-line argument.
2257
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002258 See http://www.perlmonks.org/?node_id=764004
2259
Jonathan Ballet648875f2011-07-16 14:14:58 +09002260 :type: :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002261 :param s: A single unquoted string to quote for something that is expecting
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002262 cmd.exe-style quoting
2263
Jonathan Ballet648875f2011-07-16 14:14:58 +09002264 :rtype: :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002265 :return: A cmd.exe-style quoted string
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002266 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002267 s = _cmdLineQuoteRe2.sub(br"\1\1", _cmdLineQuoteRe.sub(br'\1\1\\"', s))
2268 return b'"' + s + b'"'
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002269
2270
2271
2272def quoteArguments(arguments):
2273 """
2274 Quote an iterable of command-line arguments for passing to CreateProcess or
Jonathan Ballet648875f2011-07-16 14:14:58 +09002275 a similar API. This allows the list passed to :py:obj:`reactor.spawnProcess` to
2276 match the child process's :py:obj:`sys.argv` properly.
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002277
Jonathan Ballet648875f2011-07-16 14:14:58 +09002278 :type arguments: :py:obj:`iterable` of :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002279 :param arguments: An iterable of unquoted arguments to quote
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002280
Jonathan Ballet648875f2011-07-16 14:14:58 +09002281 :rtype: :py:obj:`str`
2282 :return: A space-delimited string containing quoted versions of :py:obj:`arguments`
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002283 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002284 return b' '.join(map(cmdLineQuote, arguments))
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002285
2286
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002287
Rick Dean4c9ad612009-07-17 15:05:22 -05002288def _runopenssl(pem, *args):
2289 """
2290 Run the command line openssl tool with the given arguments and write
Rick Dean55d1ce62009-08-13 17:40:24 -05002291 the given PEM to its stdin. Not safe for quotes.
Rick Dean4c9ad612009-07-17 15:05:22 -05002292 """
Jean-Paul Calderone038de952009-08-21 12:16:06 -04002293 if os.name == 'posix':
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002294 command = b"openssl " + b" ".join([
2295 (b"'" + arg.replace(b"'", b"'\\''") + b"'")
2296 for arg in args])
Rick Dean55d1ce62009-08-13 17:40:24 -05002297 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002298 command = b"openssl " + quoteArguments(args)
2299 proc = Popen(native(command), shell=True, stdin=PIPE, stdout=PIPE)
Jean-Paul Calderone62ca8da2010-08-11 19:58:08 -04002300 proc.stdin.write(pem)
2301 proc.stdin.close()
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002302 output = proc.stdout.read()
2303 proc.stdout.close()
2304 proc.wait()
2305 return output
Rick Dean4c9ad612009-07-17 15:05:22 -05002306
2307
2308
Jean-Paul Calderone18808652009-07-05 12:54:05 -04002309class FunctionTests(TestCase):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002310 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002311 Tests for free-functions in the :py:obj:`OpenSSL.crypto` module.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002312 """
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002313
2314 def test_load_privatekey_invalid_format(self):
2315 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002316 :py:obj:`load_privatekey` raises :py:obj:`ValueError` if passed an unknown filetype.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002317 """
2318 self.assertRaises(ValueError, load_privatekey, 100, root_key_pem)
2319
2320
2321 def test_load_privatekey_invalid_passphrase_type(self):
2322 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002323 :py:obj:`load_privatekey` raises :py:obj:`TypeError` if passed a passphrase that is
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002324 neither a :py:obj:`str` nor a callable.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002325 """
2326 self.assertRaises(
2327 TypeError,
2328 load_privatekey,
2329 FILETYPE_PEM, encryptedPrivateKeyPEMPassphrase, object())
2330
2331
2332 def test_load_privatekey_wrong_args(self):
2333 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002334 :py:obj:`load_privatekey` raises :py:obj:`TypeError` if called with the wrong number
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002335 of arguments.
2336 """
2337 self.assertRaises(TypeError, load_privatekey)
2338
2339
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002340 def test_load_privatekey_wrongPassphrase(self):
2341 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002342 :py:obj:`load_privatekey` raises :py:obj:`OpenSSL.crypto.Error` when it is passed an
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002343 encrypted PEM and an incorrect passphrase.
2344 """
2345 self.assertRaises(
2346 Error,
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002347 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, b("quack"))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002348
2349
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002350 def test_load_privatekey_passphraseWrongType(self):
2351 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002352 :py:obj:`load_privatekey` raises :py:obj:`ValueError` when it is passed a passphrase
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002353 with a private key encoded in a format, that doesn't support
2354 encryption.
2355 """
2356 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2357 blob = dump_privatekey(FILETYPE_ASN1, key)
2358 self.assertRaises(ValueError,
2359 load_privatekey, FILETYPE_ASN1, blob, "secret")
2360
2361
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002362 def test_load_privatekey_passphrase(self):
2363 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002364 :py:obj:`load_privatekey` can create a :py:obj:`PKey` object from an encrypted PEM
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002365 string if given the passphrase.
2366 """
2367 key = load_privatekey(
2368 FILETYPE_PEM, encryptedPrivateKeyPEM,
2369 encryptedPrivateKeyPEMPassphrase)
2370 self.assertTrue(isinstance(key, PKeyType))
2371
2372
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002373 def test_load_privatekey_passphrase_exception(self):
2374 """
2375 If the passphrase callback raises an exception, that exception is raised
2376 by :py:obj:`load_privatekey`.
2377 """
2378 def cb(ignored):
2379 raise ArithmeticError
2380
2381 self.assertRaises(ArithmeticError,
2382 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2383
2384
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002385 def test_load_privatekey_wrongPassphraseCallback(self):
2386 """
Jean-Paul Calderoned440a082011-09-14 11:02:05 -04002387 :py:obj:`load_privatekey` raises :py:obj:`OpenSSL.crypto.Error` when it
2388 is passed an encrypted PEM and a passphrase callback which returns an
2389 incorrect passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002390 """
2391 called = []
2392 def cb(*a):
2393 called.append(None)
Jean-Paul Calderoned440a082011-09-14 11:02:05 -04002394 return b("quack")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002395 self.assertRaises(
2396 Error,
2397 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2398 self.assertTrue(called)
2399
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002400
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002401 def test_load_privatekey_passphraseCallback(self):
2402 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002403 :py:obj:`load_privatekey` can create a :py:obj:`PKey` object from an encrypted PEM
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002404 string if given a passphrase callback which returns the correct
2405 password.
2406 """
2407 called = []
2408 def cb(writing):
2409 called.append(writing)
2410 return encryptedPrivateKeyPEMPassphrase
2411 key = load_privatekey(FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2412 self.assertTrue(isinstance(key, PKeyType))
2413 self.assertEqual(called, [False])
2414
2415
Jean-Paul Calderone105cb952011-09-14 10:16:46 -04002416 def test_load_privatekey_passphrase_wrong_return_type(self):
2417 """
2418 :py:obj:`load_privatekey` raises :py:obj:`ValueError` if the passphrase
2419 callback returns something other than a byte string.
2420 """
2421 self.assertRaises(
2422 ValueError,
2423 load_privatekey,
2424 FILETYPE_PEM, encryptedPrivateKeyPEM, lambda *args: 3)
2425
2426
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002427 def test_dump_privatekey_wrong_args(self):
2428 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002429 :py:obj:`dump_privatekey` raises :py:obj:`TypeError` if called with the wrong number
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002430 of arguments.
2431 """
2432 self.assertRaises(TypeError, dump_privatekey)
Jean-Paul Calderone1eeccd82011-09-14 10:18:52 -04002433 # If cipher name is given, password is required.
2434 self.assertRaises(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002435 TypeError, dump_privatekey, FILETYPE_PEM, PKey(), GOOD_CIPHER)
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002436
2437
2438 def test_dump_privatekey_unknown_cipher(self):
2439 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002440 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` if called with an unrecognized
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002441 cipher name.
2442 """
2443 key = PKey()
2444 key.generate_key(TYPE_RSA, 512)
2445 self.assertRaises(
2446 ValueError, dump_privatekey,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002447 FILETYPE_PEM, key, BAD_CIPHER, "passphrase")
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002448
2449
2450 def test_dump_privatekey_invalid_passphrase_type(self):
2451 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002452 :py:obj:`dump_privatekey` raises :py:obj:`TypeError` if called with a passphrase which
2453 is neither a :py:obj:`str` nor a callable.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002454 """
2455 key = PKey()
2456 key.generate_key(TYPE_RSA, 512)
2457 self.assertRaises(
2458 TypeError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002459 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, object())
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002460
2461
2462 def test_dump_privatekey_invalid_filetype(self):
2463 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002464 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` if called with an unrecognized
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002465 filetype.
2466 """
2467 key = PKey()
2468 key.generate_key(TYPE_RSA, 512)
2469 self.assertRaises(ValueError, dump_privatekey, 100, key)
2470
2471
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002472 def test_load_privatekey_passphraseCallbackLength(self):
2473 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002474 :py:obj:`crypto.load_privatekey` should raise an error when the passphrase
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002475 provided by the callback is too long, not silently truncate it.
2476 """
2477 def cb(ignored):
2478 return "a" * 1025
2479
2480 self.assertRaises(ValueError,
2481 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2482
2483
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002484 def test_dump_privatekey_passphrase(self):
2485 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002486 :py:obj:`dump_privatekey` writes an encrypted PEM when given a passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002487 """
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002488 passphrase = b("foo")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002489 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002490 pem = dump_privatekey(FILETYPE_PEM, key, GOOD_CIPHER, passphrase)
2491 self.assertTrue(isinstance(pem, binary_type))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002492 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
2493 self.assertTrue(isinstance(loadedKey, PKeyType))
2494 self.assertEqual(loadedKey.type(), key.type())
2495 self.assertEqual(loadedKey.bits(), key.bits())
2496
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002497
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002498 def test_dump_privatekey_passphraseWrongType(self):
2499 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002500 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` when it is passed a passphrase
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002501 with a private key encoded in a format, that doesn't support
2502 encryption.
2503 """
2504 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2505 self.assertRaises(ValueError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002506 dump_privatekey, FILETYPE_ASN1, key, GOOD_CIPHER, "secret")
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002507
2508
Rick Dean5b7b6372009-04-01 11:34:06 -05002509 def test_dump_certificate(self):
2510 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002511 :py:obj:`dump_certificate` writes PEM, DER, and text.
Rick Dean5b7b6372009-04-01 11:34:06 -05002512 """
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002513 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
Rick Dean5b7b6372009-04-01 11:34:06 -05002514 cert = load_certificate(FILETYPE_PEM, pemData)
2515 dumped_pem = dump_certificate(FILETYPE_PEM, cert)
2516 self.assertEqual(dumped_pem, cleartextCertificatePEM)
2517 dumped_der = dump_certificate(FILETYPE_ASN1, cert)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002518 good_der = _runopenssl(dumped_pem, b"x509", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002519 self.assertEqual(dumped_der, good_der)
2520 cert2 = load_certificate(FILETYPE_ASN1, dumped_der)
2521 dumped_pem2 = dump_certificate(FILETYPE_PEM, cert2)
2522 self.assertEqual(dumped_pem2, cleartextCertificatePEM)
2523 dumped_text = dump_certificate(FILETYPE_TEXT, cert)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002524 good_text = _runopenssl(dumped_pem, b"x509", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002525 self.assertEqual(dumped_text, good_text)
2526
2527
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002528 def test_dump_privatekey_pem(self):
Rick Dean5b7b6372009-04-01 11:34:06 -05002529 """
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002530 :py:obj:`dump_privatekey` writes a PEM
Rick Dean5b7b6372009-04-01 11:34:06 -05002531 """
2532 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -04002533 self.assertTrue(key.check())
Rick Dean5b7b6372009-04-01 11:34:06 -05002534 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2535 self.assertEqual(dumped_pem, cleartextPrivateKeyPEM)
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002536
2537
2538 def test_dump_privatekey_asn1(self):
2539 """
2540 :py:obj:`dump_privatekey` writes a DER
2541 """
2542 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2543 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2544
Rick Dean5b7b6372009-04-01 11:34:06 -05002545 dumped_der = dump_privatekey(FILETYPE_ASN1, key)
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002546 # XXX This OpenSSL call writes "writing RSA key" to standard out. Sad.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002547 good_der = _runopenssl(dumped_pem, b"rsa", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002548 self.assertEqual(dumped_der, good_der)
2549 key2 = load_privatekey(FILETYPE_ASN1, dumped_der)
2550 dumped_pem2 = dump_privatekey(FILETYPE_PEM, key2)
2551 self.assertEqual(dumped_pem2, cleartextPrivateKeyPEM)
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002552
2553
2554 def test_dump_privatekey_text(self):
2555 """
2556 :py:obj:`dump_privatekey` writes a text
2557 """
2558 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2559 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2560
Rick Dean5b7b6372009-04-01 11:34:06 -05002561 dumped_text = dump_privatekey(FILETYPE_TEXT, key)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002562 good_text = _runopenssl(dumped_pem, b"rsa", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002563 self.assertEqual(dumped_text, good_text)
2564
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002565
Rick Dean5b7b6372009-04-01 11:34:06 -05002566 def test_dump_certificate_request(self):
2567 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002568 :py:obj:`dump_certificate_request` writes a PEM, DER, and text.
Rick Dean5b7b6372009-04-01 11:34:06 -05002569 """
2570 req = load_certificate_request(FILETYPE_PEM, cleartextCertificateRequestPEM)
2571 dumped_pem = dump_certificate_request(FILETYPE_PEM, req)
2572 self.assertEqual(dumped_pem, cleartextCertificateRequestPEM)
2573 dumped_der = dump_certificate_request(FILETYPE_ASN1, req)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002574 good_der = _runopenssl(dumped_pem, b"req", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002575 self.assertEqual(dumped_der, good_der)
2576 req2 = load_certificate_request(FILETYPE_ASN1, dumped_der)
2577 dumped_pem2 = dump_certificate_request(FILETYPE_PEM, req2)
2578 self.assertEqual(dumped_pem2, cleartextCertificateRequestPEM)
2579 dumped_text = dump_certificate_request(FILETYPE_TEXT, req)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002580 good_text = _runopenssl(dumped_pem, b"req", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002581 self.assertEqual(dumped_text, good_text)
Jean-Paul Calderoneaf43cdf2010-08-03 18:40:52 -04002582 self.assertRaises(ValueError, dump_certificate_request, 100, req)
Rick Dean5b7b6372009-04-01 11:34:06 -05002583
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002584
2585 def test_dump_privatekey_passphraseCallback(self):
2586 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002587 :py:obj:`dump_privatekey` writes an encrypted PEM when given a callback which
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002588 returns the correct passphrase.
2589 """
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002590 passphrase = b("foo")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002591 called = []
2592 def cb(writing):
2593 called.append(writing)
2594 return passphrase
2595 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002596 pem = dump_privatekey(FILETYPE_PEM, key, GOOD_CIPHER, cb)
2597 self.assertTrue(isinstance(pem, binary_type))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002598 self.assertEqual(called, [True])
2599 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
2600 self.assertTrue(isinstance(loadedKey, PKeyType))
2601 self.assertEqual(loadedKey.type(), key.type())
2602 self.assertEqual(loadedKey.bits(), key.bits())
Rick Dean5b7b6372009-04-01 11:34:06 -05002603
2604
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002605 def test_dump_privatekey_passphrase_exception(self):
2606 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002607 :py:obj:`dump_privatekey` should not overwrite the exception raised
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002608 by the passphrase callback.
2609 """
2610 def cb(ignored):
2611 raise ArithmeticError
2612
2613 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2614 self.assertRaises(ArithmeticError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002615 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, cb)
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002616
2617
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002618 def test_dump_privatekey_passphraseCallbackLength(self):
2619 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002620 :py:obj:`crypto.dump_privatekey` should raise an error when the passphrase
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002621 provided by the callback is too long, not silently truncate it.
2622 """
2623 def cb(ignored):
2624 return "a" * 1025
2625
2626 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2627 self.assertRaises(ValueError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002628 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, cb)
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002629
2630
Alex Gaynor4b9c96a2014-08-14 09:51:48 -07002631 def test_load_pkcs7_data_pem(self):
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002632 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002633 :py:obj:`load_pkcs7_data` accepts a PKCS#7 string and returns an instance of
2634 :py:obj:`PKCS7Type`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002635 """
2636 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2637 self.assertTrue(isinstance(pkcs7, PKCS7Type))
2638
2639
Alex Gaynor4b9c96a2014-08-14 09:51:48 -07002640 def test_load_pkcs7_data_asn1(self):
Alex Gaynor9875a912014-08-14 13:35:05 -07002641 """
2642 :py:obj:`load_pkcs7_data` accepts a bytes containing ASN1 data
2643 representing PKCS#7 and returns an instance of :py:obj`PKCS7Type`.
2644 """
Alex Gaynor4b9c96a2014-08-14 09:51:48 -07002645 pkcs7 = load_pkcs7_data(FILETYPE_ASN1, pkcs7DataASN1)
2646 self.assertTrue(isinstance(pkcs7, PKCS7Type))
2647
2648
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002649 def test_load_pkcs7_data_invalid(self):
2650 """
2651 If the data passed to :py:obj:`load_pkcs7_data` is invalid,
2652 :py:obj:`Error` is raised.
2653 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002654 self.assertRaises(Error, load_pkcs7_data, FILETYPE_PEM, b"foo")
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002655
2656
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002657
Jean-Paul Calderone4a68b402013-12-29 16:54:58 -05002658class LoadCertificateTests(TestCase):
2659 """
2660 Tests for :py:obj:`load_certificate_request`.
2661 """
2662 def test_badFileType(self):
2663 """
2664 If the file type passed to :py:obj:`load_certificate_request` is
2665 neither :py:obj:`FILETYPE_PEM` nor :py:obj:`FILETYPE_ASN1` then
2666 :py:class:`ValueError` is raised.
2667 """
2668 self.assertRaises(ValueError, load_certificate_request, object(), b"")
2669
2670
2671
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002672class PKCS7Tests(TestCase):
2673 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002674 Tests for :py:obj:`PKCS7Type`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002675 """
2676 def test_type(self):
2677 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002678 :py:obj:`PKCS7Type` is a type object.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002679 """
2680 self.assertTrue(isinstance(PKCS7Type, type))
2681 self.assertEqual(PKCS7Type.__name__, 'PKCS7')
2682
2683 # XXX This doesn't currently work.
2684 # self.assertIdentical(PKCS7, PKCS7Type)
2685
2686
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002687 # XXX Opposite results for all these following methods
2688
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002689 def test_type_is_signed_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002690 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002691 :py:obj:`PKCS7Type.type_is_signed` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002692 arguments.
2693 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002694 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2695 self.assertRaises(TypeError, pkcs7.type_is_signed, None)
2696
2697
2698 def test_type_is_signed(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002699 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002700 :py:obj:`PKCS7Type.type_is_signed` returns :py:obj:`True` if the PKCS7 object is of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002701 the type *signed*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002702 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002703 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2704 self.assertTrue(pkcs7.type_is_signed())
2705
2706
2707 def test_type_is_enveloped_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002708 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002709 :py:obj:`PKCS7Type.type_is_enveloped` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002710 arguments.
2711 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002712 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2713 self.assertRaises(TypeError, pkcs7.type_is_enveloped, None)
2714
2715
2716 def test_type_is_enveloped(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002717 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002718 :py:obj:`PKCS7Type.type_is_enveloped` returns :py:obj:`False` if the PKCS7 object is
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002719 not of the type *enveloped*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002720 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002721 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2722 self.assertFalse(pkcs7.type_is_enveloped())
2723
2724
2725 def test_type_is_signedAndEnveloped_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002726 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002727 :py:obj:`PKCS7Type.type_is_signedAndEnveloped` raises :py:obj:`TypeError` if called
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002728 with any arguments.
2729 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002730 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2731 self.assertRaises(TypeError, pkcs7.type_is_signedAndEnveloped, None)
2732
2733
2734 def test_type_is_signedAndEnveloped(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002735 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002736 :py:obj:`PKCS7Type.type_is_signedAndEnveloped` returns :py:obj:`False` if the PKCS7
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002737 object is not of the type *signed and enveloped*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002738 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002739 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2740 self.assertFalse(pkcs7.type_is_signedAndEnveloped())
2741
2742
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002743 def test_type_is_data(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002744 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002745 :py:obj:`PKCS7Type.type_is_data` returns :py:obj:`False` if the PKCS7 object is not of
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002746 the type data.
2747 """
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002748 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2749 self.assertFalse(pkcs7.type_is_data())
2750
2751
2752 def test_type_is_data_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002753 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002754 :py:obj:`PKCS7Type.type_is_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002755 arguments.
2756 """
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002757 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2758 self.assertRaises(TypeError, pkcs7.type_is_data, None)
2759
2760
Jean-Paul Calderone97b28ca2010-07-30 10:56:07 -04002761 def test_get_type_name_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002762 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002763 :py:obj:`PKCS7Type.get_type_name` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002764 arguments.
2765 """
Jean-Paul Calderone97b28ca2010-07-30 10:56:07 -04002766 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2767 self.assertRaises(TypeError, pkcs7.get_type_name, None)
2768
2769
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002770 def test_get_type_name(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002771 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002772 :py:obj:`PKCS7Type.get_type_name` returns a :py:obj:`str` giving the type name.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002773 """
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002774 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
Jean-Paul Calderone07640f12010-08-22 17:14:43 -04002775 self.assertEquals(pkcs7.get_type_name(), b('pkcs7-signedData'))
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002776
2777
2778 def test_attribute(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002779 """
2780 If an attribute other than one of the methods tested here is accessed on
Jonathan Ballet648875f2011-07-16 14:14:58 +09002781 an instance of :py:obj:`PKCS7Type`, :py:obj:`AttributeError` is raised.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002782 """
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002783 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2784 self.assertRaises(AttributeError, getattr, pkcs7, "foo")
2785
2786
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002787
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002788class NetscapeSPKITests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002789 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002790 Tests for :py:obj:`OpenSSL.crypto.NetscapeSPKI`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002791 """
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002792 def signable(self):
2793 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002794 Return a new :py:obj:`NetscapeSPKI` for use with signing tests.
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002795 """
2796 return NetscapeSPKI()
2797
2798
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002799 def test_type(self):
2800 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002801 :py:obj:`NetscapeSPKI` and :py:obj:`NetscapeSPKIType` refer to the same type object
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002802 and can be used to create instances of that type.
2803 """
2804 self.assertIdentical(NetscapeSPKI, NetscapeSPKIType)
2805 self.assertConsistentType(NetscapeSPKI, 'NetscapeSPKI')
2806
2807
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002808 def test_construction(self):
2809 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002810 :py:obj:`NetscapeSPKI` returns an instance of :py:obj:`NetscapeSPKIType`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002811 """
2812 nspki = NetscapeSPKI()
2813 self.assertTrue(isinstance(nspki, NetscapeSPKIType))
2814
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002815
Jean-Paul Calderone969efaa2010-08-03 18:19:19 -04002816 def test_invalid_attribute(self):
2817 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002818 Accessing a non-existent attribute of a :py:obj:`NetscapeSPKI` instance causes
2819 an :py:obj:`AttributeError` to be raised.
Jean-Paul Calderone969efaa2010-08-03 18:19:19 -04002820 """
2821 nspki = NetscapeSPKI()
2822 self.assertRaises(AttributeError, lambda: nspki.foo)
2823
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002824
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002825 def test_b64_encode(self):
2826 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002827 :py:obj:`NetscapeSPKI.b64_encode` encodes the certificate to a base64 blob.
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002828 """
2829 nspki = NetscapeSPKI()
2830 blob = nspki.b64_encode()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002831 self.assertTrue(isinstance(blob, binary_type))
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002832
2833
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002834
Rick Dean536ba022009-07-24 23:57:27 -05002835class RevokedTests(TestCase):
2836 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002837 Tests for :py:obj:`OpenSSL.crypto.Revoked`
Rick Dean536ba022009-07-24 23:57:27 -05002838 """
2839 def test_construction(self):
2840 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002841 Confirm we can create :py:obj:`OpenSSL.crypto.Revoked`. Check
Rick Dean536ba022009-07-24 23:57:27 -05002842 that it is empty.
2843 """
2844 revoked = Revoked()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002845 self.assertTrue(isinstance(revoked, Revoked))
2846 self.assertEquals(type(revoked), Revoked)
2847 self.assertEquals(revoked.get_serial(), b('00'))
2848 self.assertEquals(revoked.get_rev_date(), None)
2849 self.assertEquals(revoked.get_reason(), None)
Rick Dean536ba022009-07-24 23:57:27 -05002850
2851
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002852 def test_construction_wrong_args(self):
2853 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002854 Calling :py:obj:`OpenSSL.crypto.Revoked` with any arguments results
2855 in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002856 """
2857 self.assertRaises(TypeError, Revoked, None)
2858 self.assertRaises(TypeError, Revoked, 1)
2859 self.assertRaises(TypeError, Revoked, "foo")
2860
2861
Rick Dean536ba022009-07-24 23:57:27 -05002862 def test_serial(self):
2863 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002864 Confirm we can set and get serial numbers from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002865 :py:obj:`OpenSSL.crypto.Revoked`. Confirm errors are handled
Rick Dean536ba022009-07-24 23:57:27 -05002866 with grace.
2867 """
2868 revoked = Revoked()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002869 ret = revoked.set_serial(b('10b'))
2870 self.assertEquals(ret, None)
Rick Dean536ba022009-07-24 23:57:27 -05002871 ser = revoked.get_serial()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002872 self.assertEquals(ser, b('010B'))
Rick Dean536ba022009-07-24 23:57:27 -05002873
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002874 revoked.set_serial(b('31ppp')) # a type error would be nice
Rick Dean536ba022009-07-24 23:57:27 -05002875 ser = revoked.get_serial()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002876 self.assertEquals(ser, b('31'))
Rick Dean536ba022009-07-24 23:57:27 -05002877
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002878 self.assertRaises(ValueError, revoked.set_serial, b('pqrst'))
Rick Dean536ba022009-07-24 23:57:27 -05002879 self.assertRaises(TypeError, revoked.set_serial, 100)
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002880 self.assertRaises(TypeError, revoked.get_serial, 1)
2881 self.assertRaises(TypeError, revoked.get_serial, None)
2882 self.assertRaises(TypeError, revoked.get_serial, "")
Rick Dean536ba022009-07-24 23:57:27 -05002883
2884
2885 def test_date(self):
2886 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002887 Confirm we can set and get revocation dates from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002888 :py:obj:`OpenSSL.crypto.Revoked`. Confirm errors are handled
Rick Dean536ba022009-07-24 23:57:27 -05002889 with grace.
2890 """
2891 revoked = Revoked()
2892 date = revoked.get_rev_date()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002893 self.assertEquals(date, None)
Rick Dean536ba022009-07-24 23:57:27 -05002894
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002895 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05002896 ret = revoked.set_rev_date(now)
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002897 self.assertEqual(ret, None)
Rick Dean536ba022009-07-24 23:57:27 -05002898 date = revoked.get_rev_date()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002899 self.assertEqual(date, now)
Rick Dean536ba022009-07-24 23:57:27 -05002900
2901
Rick Dean6385faf2009-07-26 00:07:47 -05002902 def test_reason(self):
2903 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002904 Confirm we can set and get revocation reasons from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002905 :py:obj:`OpenSSL.crypto.Revoked`. The "get" need to work
Rick Dean6385faf2009-07-26 00:07:47 -05002906 as "set". Likewise, each reason of all_reasons() must work.
2907 """
2908 revoked = Revoked()
2909 for r in revoked.all_reasons():
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002910 for x in range(2):
Rick Dean6385faf2009-07-26 00:07:47 -05002911 ret = revoked.set_reason(r)
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002912 self.assertEquals(ret, None)
Rick Dean6385faf2009-07-26 00:07:47 -05002913 reason = revoked.get_reason()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002914 self.assertEquals(
2915 reason.lower().replace(b(' '), b('')),
2916 r.lower().replace(b(' '), b('')))
Rick Dean6385faf2009-07-26 00:07:47 -05002917 r = reason # again with the resp of get
2918
2919 revoked.set_reason(None)
2920 self.assertEqual(revoked.get_reason(), None)
2921
2922
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002923 def test_set_reason_wrong_arguments(self):
Rick Dean6385faf2009-07-26 00:07:47 -05002924 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002925 Calling :py:obj:`OpenSSL.crypto.Revoked.set_reason` with other than
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002926 one argument, or an argument which isn't a valid reason,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002927 results in :py:obj:`TypeError` or :py:obj:`ValueError` being raised.
Rick Dean6385faf2009-07-26 00:07:47 -05002928 """
2929 revoked = Revoked()
2930 self.assertRaises(TypeError, revoked.set_reason, 100)
Jean-Paul Calderone281b62b2010-08-28 14:22:29 -04002931 self.assertRaises(ValueError, revoked.set_reason, b('blue'))
Rick Dean6385faf2009-07-26 00:07:47 -05002932
Rick Dean536ba022009-07-24 23:57:27 -05002933
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002934 def test_get_reason_wrong_arguments(self):
2935 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002936 Calling :py:obj:`OpenSSL.crypto.Revoked.get_reason` with any
2937 arguments results in :py:obj:`TypeError` being raised.
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002938 """
2939 revoked = Revoked()
2940 self.assertRaises(TypeError, revoked.get_reason, None)
2941 self.assertRaises(TypeError, revoked.get_reason, 1)
2942 self.assertRaises(TypeError, revoked.get_reason, "foo")
2943
2944
2945
Rick Dean536ba022009-07-24 23:57:27 -05002946class CRLTests(TestCase):
2947 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002948 Tests for :py:obj:`OpenSSL.crypto.CRL`
Rick Dean536ba022009-07-24 23:57:27 -05002949 """
2950 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
2951 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2952
2953 def test_construction(self):
2954 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002955 Confirm we can create :py:obj:`OpenSSL.crypto.CRL`. Check
Rick Dean536ba022009-07-24 23:57:27 -05002956 that it is empty
2957 """
2958 crl = CRL()
2959 self.assertTrue( isinstance(crl, CRL) )
2960 self.assertEqual(crl.get_revoked(), None)
2961
2962
Jean-Paul Calderone2efd03e2010-01-30 13:59:55 -05002963 def test_construction_wrong_args(self):
2964 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002965 Calling :py:obj:`OpenSSL.crypto.CRL` with any number of arguments
2966 results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone2efd03e2010-01-30 13:59:55 -05002967 """
2968 self.assertRaises(TypeError, CRL, 1)
2969 self.assertRaises(TypeError, CRL, "")
2970 self.assertRaises(TypeError, CRL, None)
2971
2972
Rick Dean536ba022009-07-24 23:57:27 -05002973 def test_export(self):
2974 """
2975 Use python to create a simple CRL with a revocation, and export
2976 the CRL in formats of PEM, DER and text. Those outputs are verified
2977 with the openssl program.
2978 """
2979 crl = CRL()
2980 revoked = Revoked()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002981 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05002982 revoked.set_rev_date(now)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002983 revoked.set_serial(b('3ab'))
2984 revoked.set_reason(b('sUpErSeDEd'))
Rick Dean536ba022009-07-24 23:57:27 -05002985 crl.add_revoked(revoked)
2986
2987 # PEM format
2988 dumped_crl = crl.export(self.cert, self.pkey, days=20)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002989 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002990 text.index(b('Serial Number: 03AB'))
2991 text.index(b('Superseded'))
2992 text.index(b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA'))
Rick Dean536ba022009-07-24 23:57:27 -05002993
2994 # DER format
2995 dumped_crl = crl.export(self.cert, self.pkey, FILETYPE_ASN1)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002996 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text", b"-inform", b"DER")
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002997 text.index(b('Serial Number: 03AB'))
2998 text.index(b('Superseded'))
2999 text.index(b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA'))
Rick Dean536ba022009-07-24 23:57:27 -05003000
3001 # text format
3002 dumped_text = crl.export(self.cert, self.pkey, type=FILETYPE_TEXT)
3003 self.assertEqual(text, dumped_text)
3004
3005
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -04003006 def test_export_invalid(self):
3007 """
3008 If :py:obj:`CRL.export` is used with an uninitialized :py:obj:`X509`
Jean-Paul Calderoneb5871072012-03-09 14:58:00 -08003009 instance, :py:obj:`OpenSSL.crypto.Error` is raised.
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -04003010 """
3011 crl = CRL()
3012 self.assertRaises(Error, crl.export, X509(), PKey())
3013
3014
Jean-Paul Calderone56515342010-01-30 13:49:38 -05003015 def test_add_revoked_keyword(self):
3016 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003017 :py:obj:`OpenSSL.CRL.add_revoked` accepts its single argument as the
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003018 ``revoked`` keyword argument.
Jean-Paul Calderone56515342010-01-30 13:49:38 -05003019 """
3020 crl = CRL()
3021 revoked = Revoked()
3022 crl.add_revoked(revoked=revoked)
3023 self.assertTrue(isinstance(crl.get_revoked()[0], Revoked))
3024
Rick Dean6385faf2009-07-26 00:07:47 -05003025
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05003026 def test_export_wrong_args(self):
3027 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003028 Calling :py:obj:`OpenSSL.CRL.export` with fewer than two or more than
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05003029 four arguments, or with arguments other than the certificate,
3030 private key, integer file type, and integer number of days it
Jonathan Ballet648875f2011-07-16 14:14:58 +09003031 expects, results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05003032 """
3033 crl = CRL()
3034 self.assertRaises(TypeError, crl.export)
3035 self.assertRaises(TypeError, crl.export, self.cert)
3036 self.assertRaises(TypeError, crl.export, self.cert, self.pkey, FILETYPE_PEM, 10, "foo")
3037
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05003038 self.assertRaises(TypeError, crl.export, None, self.pkey, FILETYPE_PEM, 10)
3039 self.assertRaises(TypeError, crl.export, self.cert, None, FILETYPE_PEM, 10)
3040 self.assertRaises(TypeError, crl.export, self.cert, self.pkey, None, 10)
3041 self.assertRaises(TypeError, crl.export, self.cert, FILETYPE_PEM, None)
3042
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05003043
Jean-Paul Calderoneea198422010-01-30 13:58:23 -05003044 def test_export_unknown_filetype(self):
3045 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003046 Calling :py:obj:`OpenSSL.CRL.export` with a file type other than
3047 :py:obj:`FILETYPE_PEM`, :py:obj:`FILETYPE_ASN1`, or :py:obj:`FILETYPE_TEXT` results
3048 in a :py:obj:`ValueError` being raised.
Jean-Paul Calderoneea198422010-01-30 13:58:23 -05003049 """
3050 crl = CRL()
3051 self.assertRaises(ValueError, crl.export, self.cert, self.pkey, 100, 10)
3052
3053
Rick Dean536ba022009-07-24 23:57:27 -05003054 def test_get_revoked(self):
3055 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05003056 Use python to create a simple CRL with two revocations.
Jonathan Ballet648875f2011-07-16 14:14:58 +09003057 Get back the :py:obj:`Revoked` using :py:obj:`OpenSSL.CRL.get_revoked` and
Rick Dean536ba022009-07-24 23:57:27 -05003058 verify them.
3059 """
3060 crl = CRL()
3061
3062 revoked = Revoked()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003063 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05003064 revoked.set_rev_date(now)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003065 revoked.set_serial(b('3ab'))
Rick Dean536ba022009-07-24 23:57:27 -05003066 crl.add_revoked(revoked)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003067 revoked.set_serial(b('100'))
3068 revoked.set_reason(b('sUpErSeDEd'))
Rick Dean536ba022009-07-24 23:57:27 -05003069 crl.add_revoked(revoked)
3070
3071 revs = crl.get_revoked()
3072 self.assertEqual(len(revs), 2)
3073 self.assertEqual(type(revs[0]), Revoked)
3074 self.assertEqual(type(revs[1]), Revoked)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003075 self.assertEqual(revs[0].get_serial(), b('03AB'))
3076 self.assertEqual(revs[1].get_serial(), b('0100'))
Rick Dean536ba022009-07-24 23:57:27 -05003077 self.assertEqual(revs[0].get_rev_date(), now)
3078 self.assertEqual(revs[1].get_rev_date(), now)
3079
3080
Jean-Paul Calderone46bdce42010-01-30 13:44:16 -05003081 def test_get_revoked_wrong_args(self):
3082 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003083 Calling :py:obj:`OpenSSL.CRL.get_revoked` with any arguments results
3084 in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone46bdce42010-01-30 13:44:16 -05003085 """
3086 crl = CRL()
3087 self.assertRaises(TypeError, crl.get_revoked, None)
3088 self.assertRaises(TypeError, crl.get_revoked, 1)
3089 self.assertRaises(TypeError, crl.get_revoked, "")
3090 self.assertRaises(TypeError, crl.get_revoked, "", 1, None)
3091
3092
Jean-Paul Calderoneecef6fa2010-01-30 13:47:18 -05003093 def test_add_revoked_wrong_args(self):
3094 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003095 Calling :py:obj:`OpenSSL.CRL.add_revoked` with other than one
3096 argument results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderoneecef6fa2010-01-30 13:47:18 -05003097 """
3098 crl = CRL()
3099 self.assertRaises(TypeError, crl.add_revoked)
3100 self.assertRaises(TypeError, crl.add_revoked, 1, 2)
3101 self.assertRaises(TypeError, crl.add_revoked, "foo", "bar")
3102
3103
Rick Dean536ba022009-07-24 23:57:27 -05003104 def test_load_crl(self):
3105 """
3106 Load a known CRL and inspect its revocations. Both
3107 PEM and DER formats are loaded.
3108 """
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003109 crl = load_crl(FILETYPE_PEM, crlData)
Rick Dean536ba022009-07-24 23:57:27 -05003110 revs = crl.get_revoked()
3111 self.assertEqual(len(revs), 2)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003112 self.assertEqual(revs[0].get_serial(), b('03AB'))
Rick Dean6385faf2009-07-26 00:07:47 -05003113 self.assertEqual(revs[0].get_reason(), None)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003114 self.assertEqual(revs[1].get_serial(), b('0100'))
3115 self.assertEqual(revs[1].get_reason(), b('Superseded'))
Rick Dean536ba022009-07-24 23:57:27 -05003116
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003117 der = _runopenssl(crlData, b"crl", b"-outform", b"DER")
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05003118 crl = load_crl(FILETYPE_ASN1, der)
Rick Dean536ba022009-07-24 23:57:27 -05003119 revs = crl.get_revoked()
3120 self.assertEqual(len(revs), 2)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003121 self.assertEqual(revs[0].get_serial(), b('03AB'))
Rick Dean6385faf2009-07-26 00:07:47 -05003122 self.assertEqual(revs[0].get_reason(), None)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003123 self.assertEqual(revs[1].get_serial(), b('0100'))
3124 self.assertEqual(revs[1].get_reason(), b('Superseded'))
Rick Dean536ba022009-07-24 23:57:27 -05003125
3126
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003127 def test_load_crl_wrong_args(self):
3128 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003129 Calling :py:obj:`OpenSSL.crypto.load_crl` with other than two
3130 arguments results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003131 """
3132 self.assertRaises(TypeError, load_crl)
3133 self.assertRaises(TypeError, load_crl, FILETYPE_PEM)
3134 self.assertRaises(TypeError, load_crl, FILETYPE_PEM, crlData, None)
3135
3136
3137 def test_load_crl_bad_filetype(self):
3138 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003139 Calling :py:obj:`OpenSSL.crypto.load_crl` with an unknown file type
3140 raises a :py:obj:`ValueError`.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003141 """
3142 self.assertRaises(ValueError, load_crl, 100, crlData)
3143
3144
3145 def test_load_crl_bad_data(self):
3146 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003147 Calling :py:obj:`OpenSSL.crypto.load_crl` with file data which can't
3148 be loaded raises a :py:obj:`OpenSSL.crypto.Error`.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003149 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003150 self.assertRaises(Error, load_crl, FILETYPE_PEM, b"hello, world")
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003151
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04003152
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -05003153
James Yonan7c2e5d32010-02-27 05:45:50 -07003154class SignVerifyTests(TestCase):
3155 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003156 Tests for :py:obj:`OpenSSL.crypto.sign` and :py:obj:`OpenSSL.crypto.verify`.
James Yonan7c2e5d32010-02-27 05:45:50 -07003157 """
3158 def test_sign_verify(self):
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04003159 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003160 :py:obj:`sign` generates a cryptographic signature which :py:obj:`verify` can check.
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04003161 """
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003162 content = b(
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04003163 "It was a bright cold day in April, and the clocks were striking "
3164 "thirteen. Winston Smith, his chin nuzzled into his breast in an "
3165 "effort to escape the vile wind, slipped quickly through the "
3166 "glass doors of Victory Mansions, though not quickly enough to "
3167 "prevent a swirl of gritty dust from entering along with him.")
3168
3169 # sign the content with this private key
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04003170 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04003171 # verify the content with this cert
3172 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3173 # certificate unrelated to priv_key, used to trigger an error
3174 bad_cert = load_certificate(FILETYPE_PEM, server_cert_pem)
James Yonan7c2e5d32010-02-27 05:45:50 -07003175
Jean-Paul Calderoned08feb02010-10-12 21:53:24 -04003176 for digest in ['md5', 'sha1']:
James Yonan7c2e5d32010-02-27 05:45:50 -07003177 sig = sign(priv_key, content, digest)
3178
3179 # Verify the signature of content, will throw an exception if error.
3180 verify(good_cert, sig, content, digest)
3181
3182 # This should fail because the certificate doesn't match the
3183 # private key that was used to sign the content.
3184 self.assertRaises(Error, verify, bad_cert, sig, content, digest)
3185
3186 # This should fail because we've "tainted" the content after
3187 # signing it.
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003188 self.assertRaises(
3189 Error, verify,
3190 good_cert, sig, content + b("tainted"), digest)
James Yonan7c2e5d32010-02-27 05:45:50 -07003191
3192 # test that unknown digest types fail
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003193 self.assertRaises(
Jean-Paul Calderone9538f142010-10-13 22:13:40 -04003194 ValueError, sign, priv_key, content, "strange-digest")
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003195 self.assertRaises(
Jean-Paul Calderone9538f142010-10-13 22:13:40 -04003196 ValueError, verify, good_cert, sig, content, "strange-digest")
James Yonan7c2e5d32010-02-27 05:45:50 -07003197
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04003198
Abraham Martinc5484ba2015-03-25 15:33:05 +00003199 def test_sign_verify_with_text(self):
3200 """
3201 :py:obj:`sign` generates a cryptographic signature which :py:obj:`verify` can check.
3202 Deprecation warnings raised because using text instead of bytes as content
3203 """
3204 if not PY3:
3205 content = unicode(
3206 "It was a bright cold day in April, and the clocks were striking "
3207 "thirteen. Winston Smith, his chin nuzzled into his breast in an "
3208 "effort to escape the vile wind, slipped quickly through the "
3209 "glass doors of Victory Mansions, though not quickly enough to "
3210 "prevent a swirl of gritty dust from entering along with him.")
3211 else:
3212 content = b(
3213 "It was a bright cold day in April, and the clocks were striking "
3214 "thirteen. Winston Smith, his chin nuzzled into his breast in an "
3215 "effort to escape the vile wind, slipped quickly through the "
3216 "glass doors of Victory Mansions, though not quickly enough to "
3217 "prevent a swirl of gritty dust from entering along with him.").decode()
3218
3219 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
3220 cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3221 for digest in ['md5', 'sha1']:
3222 with catch_warnings(record=True) as w:
3223 simplefilter("always")
3224 sig = sign(priv_key, content, digest)
3225 if not PY3:
3226 self.assertTrue("unicode in data is no longer accepted, "
3227 "use bytes" in str(w[-1].message))
3228 else:
3229 self.assertTrue("str in data is no longer accepted, "
3230 "use bytes" in str(w[-1].message))
3231 with catch_warnings(record=True) as w:
3232 simplefilter("always")
3233 verify(cert, sig, content, digest)
3234 if not PY3:
3235 self.assertTrue("unicode in data is no longer accepted, "
3236 "use bytes" in str(w[-1].message))
3237 else:
3238 self.assertTrue("str in data is no longer accepted, "
3239 "use bytes" in str(w[-1].message))
3240
3241
Jean-Paul Calderone9828f662010-12-08 22:57:26 -05003242 def test_sign_nulls(self):
3243 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003244 :py:obj:`sign` produces a signature for a string with embedded nulls.
Jean-Paul Calderone9828f662010-12-08 22:57:26 -05003245 """
3246 content = b("Watch out! \0 Did you see it?")
3247 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
3248 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3249 sig = sign(priv_key, content, "sha1")
3250 verify(good_cert, sig, content, "sha1")
3251
3252
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003253
3254class EllipticCurveTests(TestCase):
3255 """
3256 Tests for :py:class:`_EllipticCurve`, :py:obj:`get_elliptic_curve`, and
3257 :py:obj:`get_elliptic_curves`.
3258 """
3259 def test_set(self):
3260 """
3261 :py:obj:`get_elliptic_curves` returns a :py:obj:`set`.
3262 """
3263 self.assertIsInstance(get_elliptic_curves(), set)
3264
3265
3266 def test_some_curves(self):
3267 """
3268 If :py:mod:`cryptography` has elliptic curve support then the set
3269 returned by :py:obj:`get_elliptic_curves` has some elliptic curves in
3270 it.
3271
3272 There could be an OpenSSL that violates this assumption. If so, this
3273 test will fail and we'll find out.
3274 """
3275 curves = get_elliptic_curves()
3276 if lib.Cryptography_HAS_EC:
3277 self.assertTrue(curves)
3278 else:
3279 self.assertFalse(curves)
3280
3281
3282 def test_a_curve(self):
3283 """
3284 :py:obj:`get_elliptic_curve` can be used to retrieve a particular
3285 supported curve.
3286 """
3287 curves = get_elliptic_curves()
3288 if curves:
3289 curve = next(iter(curves))
3290 self.assertEqual(curve.name, get_elliptic_curve(curve.name).name)
3291 else:
Jean-Paul Calderoneeb86f3a2014-04-19 09:45:57 -04003292 self.assertRaises(ValueError, get_elliptic_curve, u("prime256v1"))
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003293
3294
3295 def test_not_a_curve(self):
3296 """
3297 :py:obj:`get_elliptic_curve` raises :py:class:`ValueError` if called
3298 with a name which does not identify a supported curve.
3299 """
3300 self.assertRaises(
Jean-Paul Calderone5a82db92014-04-19 09:51:29 -04003301 ValueError, get_elliptic_curve, u("this curve was just invented"))
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003302
3303
3304 def test_repr(self):
3305 """
3306 The string representation of a curve object includes simply states the
3307 object is a curve and what its name is.
3308 """
3309 curves = get_elliptic_curves()
3310 if curves:
3311 curve = next(iter(curves))
3312 self.assertEqual("<Curve %r>" % (curve.name,), repr(curve))
3313
3314
3315 def test_to_EC_KEY(self):
3316 """
3317 The curve object can export a version of itself as an EC_KEY* via the
3318 private :py:meth:`_EllipticCurve._to_EC_KEY`.
3319 """
3320 curves = get_elliptic_curves()
3321 if curves:
3322 curve = next(iter(curves))
3323 # It's not easy to assert anything about this object. However, see
3324 # leakcheck/crypto.py for a test that demonstrates it at least does
3325 # not leak memory.
3326 curve._to_EC_KEY()
3327
3328
Jean-Paul Calderone1be77082014-04-30 18:17:41 -04003329
3330class EllipticCurveFactory(object):
3331 """
3332 A helper to get the names of two curves.
3333 """
3334 def __init__(self):
3335 curves = iter(get_elliptic_curves())
3336 try:
3337 self.curve_name = next(curves).name
3338 self.another_curve_name = next(curves).name
3339 except StopIteration:
3340 self.curve_name = self.another_curve_name = None
3341
3342
3343
3344class EllipticCurveEqualityTests(TestCase, EqualityTestsMixin):
3345 """
3346 Tests :py:type:`_EllipticCurve`\ 's implementation of ``==`` and ``!=``.
3347 """
3348 curve_factory = EllipticCurveFactory()
3349
3350 if curve_factory.curve_name is None:
3351 skip = "There are no curves available there can be no curve objects."
3352
3353
3354 def anInstance(self):
3355 """
3356 Get the curve object for an arbitrary curve supported by the system.
3357 """
3358 return get_elliptic_curve(self.curve_factory.curve_name)
3359
3360
3361 def anotherInstance(self):
3362 """
3363 Get the curve object for an arbitrary curve supported by the system -
3364 but not the one returned by C{anInstance}.
3365 """
3366 return get_elliptic_curve(self.curve_factory.another_curve_name)
3367
3368
3369
Jean-Paul Calderone22c31242014-05-01 07:49:47 -04003370class EllipticCurveHashTests(TestCase):
3371 """
3372 Tests for :py:type:`_EllipticCurve`\ 's implementation of hashing (thus use
3373 as an item in a :py:type:`dict` or :py:type:`set`).
3374 """
3375 curve_factory = EllipticCurveFactory()
3376
3377 if curve_factory.curve_name is None:
3378 skip = "There are no curves available there can be no curve objects."
3379
3380
3381 def test_contains(self):
3382 """
3383 The ``in`` operator reports that a :py:type:`set` containing a curve
3384 does contain that curve.
3385 """
3386 curve = get_elliptic_curve(self.curve_factory.curve_name)
3387 curves = set([curve])
3388 self.assertIn(curve, curves)
3389
3390
3391 def test_does_not_contain(self):
3392 """
3393 The ``in`` operator reports that a :py:type:`set` not containing a
3394 curve does not contain that curve.
3395 """
3396 curve = get_elliptic_curve(self.curve_factory.curve_name)
3397 curves = set([get_elliptic_curve(self.curve_factory.another_curve_name)])
3398 self.assertNotIn(curve, curves)
3399
3400
3401
Rick Dean5b7b6372009-04-01 11:34:06 -05003402if __name__ == '__main__':
3403 main()