blob: 409410a35cd94bf88cf0b4132967debb57a46d39 [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
Jean-Paul Calderone60432792015-04-13 12:26:07 -04009from warnings import catch_warnings, simplefilter
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -040010
Alex Gaynor4b9c96a2014-08-14 09:51:48 -070011import base64
12import os
13import re
Jean-Paul Calderone62ca8da2010-08-11 19:58:08 -040014from subprocess import PIPE, Popen
Rick Dean47262da2009-07-08 16:17:17 -050015from datetime import datetime, timedelta
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -050016
Alex Gaynorb8e38992015-09-04 08:14:04 -040017from six import u, b, binary_type
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050018
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -050019from OpenSSL.crypto import TYPE_RSA, TYPE_DSA, Error, PKey, PKeyType
Jean-Paul Calderone78381d22008-03-06 23:35:22 -050020from OpenSSL.crypto import X509, X509Type, X509Name, X509NameType
Stephen Holsapple08ffaa62015-01-30 17:18:40 -080021from OpenSSL.crypto import X509Store, X509StoreType, X509StoreContext, X509StoreContextError
Stephen Holsapple0d9815f2014-08-27 19:36:53 -070022from OpenSSL.crypto import 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 Calderone6462b072015-03-29 07:03:11 -040034from OpenSSL.test.util import (
35 EqualityTestsMixin, TestCase, WARNING_TYPE_EXPECTED
36)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040037from OpenSSL._util import native, lib
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040038
Alex Gaynoraceb3e22015-09-05 12:00:22 -040039
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -040040def normalize_certificate_pem(pem):
41 return dump_certificate(FILETYPE_PEM, load_certificate(FILETYPE_PEM, pem))
42
43
44def normalize_privatekey_pem(pem):
45 return dump_privatekey(FILETYPE_PEM, load_privatekey(FILETYPE_PEM, pem))
46
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040047
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050048GOOD_CIPHER = "blowfish"
49BAD_CIPHER = "zippers"
50
51GOOD_DIGEST = "MD5"
52BAD_DIGEST = "monkeys"
53
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040054root_cert_pem = b("""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -050055MIIC7TCCAlagAwIBAgIIPQzE4MbeufQwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE
56BhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdU
57ZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwIhgPMjAwOTAzMjUxMjM2
58NThaGA8yMDE3MDYxMTEyMzY1OFowWDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklM
59MRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9U
60ZXN0aW5nIFJvb3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPmaQumL
61urpE527uSEHdL1pqcDRmWzu+98Y6YHzT/J7KWEamyMCNZ6fRW1JCR782UQ8a07fy
622xXsKy4WdKaxyG8CcatwmXvpvRQ44dSANMihHELpANTdyVp6DCysED6wkQFurHlF
631dshEaJw8b/ypDhmbVIo6Ci1xvCJqivbLFnbAgMBAAGjgbswgbgwHQYDVR0OBBYE
64FINVdy1eIfFJDAkk51QJEo3IfgSuMIGIBgNVHSMEgYAwfoAUg1V3LV4h8UkMCSTn
65VAkSjch+BK6hXKRaMFgxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UE
66BxMHQ2hpY2FnbzEQMA4GA1UEChMHVGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBS
67b290IENBggg9DMTgxt659DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB
68AGGCDazMJGoWNBpc03u6+smc95dEead2KlZXBATOdFT1VesY3+nUOqZhEhTGlDMi
69hkgaZnzoIq/Uamidegk4hirsCT/R+6vsKAAxNTcBjUeZjlykCJWy5ojShGftXIKY
70w/njVbKMXrvc83qmTdGl3TAM0fxQIpqgcglFLveEBgzn
71-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040072""")
Rick Dean94e46fd2009-07-18 14:51:24 -050073
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040074root_key_pem = b("""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -050075MIICXQIBAAKBgQD5mkLpi7q6ROdu7khB3S9aanA0Zls7vvfGOmB80/yeylhGpsjA
76jWen0VtSQke/NlEPGtO38tsV7CsuFnSmschvAnGrcJl76b0UOOHUgDTIoRxC6QDU
773claegwsrBA+sJEBbqx5RdXbIRGicPG/8qQ4Zm1SKOgotcbwiaor2yxZ2wIDAQAB
78AoGBAPCgMpmLxzwDaUmcFbTJUvlLW1hoxNNYSu2jIZm1k/hRAcE60JYwvBkgz3UB
79yMEh0AtLxYe0bFk6EHah11tMUPgscbCq73snJ++8koUw+csk22G65hOs51bVb7Aa
806JBe67oLzdtvgCUFAA2qfrKzWRZzAdhUirQUZgySZk+Xq1pBAkEA/kZG0A6roTSM
81BVnx7LnPfsycKUsTumorpXiylZJjTi9XtmzxhrYN6wgZlDOOwOLgSQhszGpxVoMD
82u3gByT1b2QJBAPtL3mSKdvwRu/+40zaZLwvSJRxaj0mcE4BJOS6Oqs/hS1xRlrNk
83PpQ7WJ4yM6ZOLnXzm2mKyxm50Mv64109FtMCQQDOqS2KkjHaLowTGVxwC0DijMfr
84I9Lf8sSQk32J5VWCySWf5gGTfEnpmUa41gKTMJIbqZZLucNuDcOtzUaeWZlZAkA8
85ttXigLnCqR486JDPTi9ZscoZkZ+w7y6e/hH8t6d5Vjt48JVyfjPIaJY+km58LcN3
866AWSeGAdtRFHVzR7oHjVAkB4hutvxiOeiIVQNBhM6RSI9aBPMI21DoX2JRoxvNW2
87cbvAhow217X9V0dVerEOKxnNYspXRrh36h7k4mQA+sDq
88-----END RSA PRIVATE KEY-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040089""")
Rick Dean94e46fd2009-07-18 14:51:24 -050090
Stephen Holsapple0d9815f2014-08-27 19:36:53 -070091intermediate_cert_pem = b("""-----BEGIN CERTIFICATE-----
92MIICVzCCAcCgAwIBAgIRAMPzhm6//0Y/g2pmnHR2C4cwDQYJKoZIhvcNAQENBQAw
93WDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAw
94DgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwHhcNMTQw
95ODI4MDIwNDA4WhcNMjQwODI1MDIwNDA4WjBmMRUwEwYDVQQDEwxpbnRlcm1lZGlh
96dGUxDDAKBgNVBAoTA29yZzERMA8GA1UECxMIb3JnLXVuaXQxCzAJBgNVBAYTAlVT
97MQswCQYDVQQIEwJDQTESMBAGA1UEBxMJU2FuIERpZWdvMIGfMA0GCSqGSIb3DQEB
98AQUAA4GNADCBiQKBgQDYcEQw5lfbEQRjr5Yy4yxAHGV0b9Al+Lmu7wLHMkZ/ZMmK
99FGIbljbviiD1Nz97Oh2cpB91YwOXOTN2vXHq26S+A5xe8z/QJbBsyghMur88CjdT
10021H2qwMa+r5dCQwEhuGIiZ3KbzB/n4DTMYI5zy4IYPv0pjxShZn4aZTCCK2IUwID
101AQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBDQUAA4GBAPIWSkLX
102QRMApOjjyC+tMxumT5e2pMqChHmxobQK4NMdrf2VCx+cRT6EmY8sK3/Xl/X8UBQ+
1039n5zXb1ZwhW/sTWgUvmOceJ4/XVs9FkdWOOn1J0XBch9ZIiFe/s5ASIgG7fUdcUF
1049mAWS6FK2ca3xIh5kIupCXOFa0dPvlw/YUFT
105-----END CERTIFICATE-----
106""")
107
108intermediate_key_pem = b("""-----BEGIN RSA PRIVATE KEY-----
109MIICWwIBAAKBgQDYcEQw5lfbEQRjr5Yy4yxAHGV0b9Al+Lmu7wLHMkZ/ZMmKFGIb
110ljbviiD1Nz97Oh2cpB91YwOXOTN2vXHq26S+A5xe8z/QJbBsyghMur88CjdT21H2
111qwMa+r5dCQwEhuGIiZ3KbzB/n4DTMYI5zy4IYPv0pjxShZn4aZTCCK2IUwIDAQAB
112AoGAfSZVV80pSeOKHTYfbGdNY/jHdU9eFUa/33YWriXU+77EhpIItJjkRRgivIfo
113rhFJpBSGmDLblaqepm8emsXMeH4+2QzOYIf0QGGP6E6scjTt1PLqdqKfVJ1a2REN
114147cujNcmFJb/5VQHHMpaPTgttEjlzuww4+BCDPsVRABWrkCQQD3loH36nLoQTtf
115+kQq0T6Bs9/UWkTAGo0ND81ALj0F8Ie1oeZg6RNT96RxZ3aVuFTESTv6/TbjWywO
116wdzlmV1vAkEA38rTJ6PTwaJlw5OttdDzAXGPB9tDmzh9oSi7cHwQQXizYd8MBYx4
117sjHUKD3dCQnb1dxJFhd3BT5HsnkRMbVZXQJAbXduH17ZTzcIOXc9jHDXYiFVZV5D
11852vV0WCbLzVCZc3jMrtSUKa8lPN5EWrdU3UchWybyG0MR5mX8S5lrF4SoQJAIyUD
119DBKaSqpqONCUUx1BTFS9FYrFjzbL4+c1qHCTTPTblt8kUCrDOZjBrKAqeiTmNSum
120/qUot9YUBF8m6BuGsQJATHHmdFy/fG1VLkyBp49CAa8tN3Z5r/CgTznI4DfMTf4C
121NbRHn2UmYlwQBa+L5lg9phewNe8aEwpPyPLoV85U8Q==
122-----END RSA PRIVATE KEY-----
123""")
124
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400125server_cert_pem = b("""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500126MIICKDCCAZGgAwIBAgIJAJn/HpR21r/8MA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
127BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
128VGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBSb290IENBMCIYDzIwMDkwMzI1MTIz
129NzUzWhgPMjAxNzA2MTExMjM3NTNaMBgxFjAUBgNVBAMTDWxvdmVseSBzZXJ2ZXIw
130gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAL6m+G653V0tpBC/OKl22VxOi2Cv
131lK4TYu9LHSDP9uDVTe7V5D5Tl6qzFoRRx5pfmnkqT5B+W9byp2NU3FC5hLm5zSAr
132b45meUhjEJ/ifkZgbNUjHdBIGP9MAQUHZa5WKdkGIJvGAvs8UzUqlr4TBWQIB24+
133lJ+Ukk/CRgasrYwdAgMBAAGjNjA0MB0GA1UdDgQWBBS4kC7Ij0W1TZXZqXQFAM2e
134gKEG2DATBgNVHSUEDDAKBggrBgEFBQcDATANBgkqhkiG9w0BAQUFAAOBgQBh30Li
135dJ+NlxIOx5343WqIBka3UbsOb2kxWrbkVCrvRapCMLCASO4FqiKWM+L0VDBprqIp
1362mgpFQ6FHpoIENGvJhdEKpptQ5i7KaGhnDNTfdy3x1+h852G99f1iyj0RmbuFcM8
137uzujnS8YXWvM7DM1Ilozk4MzPug8jzFp5uhKCQ==
138-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400139""")
Rick Dean94e46fd2009-07-18 14:51:24 -0500140
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -0400141server_key_pem = normalize_privatekey_pem(b("""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500142MIICWwIBAAKBgQC+pvhuud1dLaQQvzipdtlcTotgr5SuE2LvSx0gz/bg1U3u1eQ+
143U5eqsxaEUceaX5p5Kk+QflvW8qdjVNxQuYS5uc0gK2+OZnlIYxCf4n5GYGzVIx3Q
144SBj/TAEFB2WuVinZBiCbxgL7PFM1Kpa+EwVkCAduPpSflJJPwkYGrK2MHQIDAQAB
145AoGAbwuZ0AR6JveahBaczjfnSpiFHf+mve2UxoQdpyr6ROJ4zg/PLW5K/KXrC48G
146j6f3tXMrfKHcpEoZrQWUfYBRCUsGD5DCazEhD8zlxEHahIsqpwA0WWssJA2VOLEN
147j6DuV2pCFbw67rfTBkTSo32ahfXxEKev5KswZk0JIzH3ooECQQDgzS9AI89h0gs8
148Dt+1m11Rzqo3vZML7ZIyGApUzVan+a7hbc33nbGRkAXjHaUBJO31it/H6dTO+uwX
149msWwNG5ZAkEA2RyFKs5xR5USTFaKLWCgpH/ydV96KPOpBND7TKQx62snDenFNNbn
150FwwOhpahld+vqhYk+pfuWWUpQciE+Bu7ZQJASjfT4sQv4qbbKK/scePicnDdx9th
1514e1EeB9xwb+tXXXUo/6Bor/AcUNwfiQ6Zt9PZOK9sR3lMZSsP7rMi7kzuQJABie6
1521sXXjFH7nNJvRG4S39cIxq8YRYTy68II/dlB2QzGpKxV/POCxbJ/zu0CU79tuYK7
153NaeNCFfH3aeTrX0LyQJAMBWjWmeKM2G2sCExheeQK0ROnaBC8itCECD4Jsve4nqf
154r50+LF74iLXFwqysVCebPKMOpDWp/qQ1BbJQIPs7/A==
155-----END RSA PRIVATE KEY-----
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -0400156"""))
Rick Dean94e46fd2009-07-18 14:51:24 -0500157
Stephen Holsapple0d9815f2014-08-27 19:36:53 -0700158intermediate_server_cert_pem = b("""-----BEGIN CERTIFICATE-----
159MIICWDCCAcGgAwIBAgIRAPQFY9jfskSihdiNSNdt6GswDQYJKoZIhvcNAQENBQAw
160ZjEVMBMGA1UEAxMMaW50ZXJtZWRpYXRlMQwwCgYDVQQKEwNvcmcxETAPBgNVBAsT
161CG9yZy11bml0MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVNh
162biBEaWVnbzAeFw0xNDA4MjgwMjEwNDhaFw0yNDA4MjUwMjEwNDhaMG4xHTAbBgNV
163BAMTFGludGVybWVkaWF0ZS1zZXJ2aWNlMQwwCgYDVQQKEwNvcmcxETAPBgNVBAsT
164CG9yZy11bml0MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVNh
165biBEaWVnbzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqpJZygd+w1faLOr1
166iOAmbBhx5SZWcTCZ/ZjHQTJM7GuPT624QkqsixFghRKdDROwpwnAP7gMRukLqiy4
167+kRuGT5OfyGggL95i2xqA+zehjj08lSTlvGHpePJgCyTavIy5+Ljsj4DKnKyuhxm
168biXTRrH83NDgixVkObTEmh/OVK0CAwEAATANBgkqhkiG9w0BAQ0FAAOBgQBa0Npw
169UkzjaYEo1OUE1sTI6Mm4riTIHMak4/nswKh9hYup//WVOlr/RBSBtZ7Q/BwbjobN
1703bfAtV7eSAqBsfxYXyof7G1ALANQERkq3+oyLP1iVt08W1WOUlIMPhdCF/QuCwy6
171x9MJLhUCGLJPM+O2rAPWVD9wCmvq10ALsiH3yA==
172-----END CERTIFICATE-----
173""")
174
175intermediate_server_key_pem = b("""-----BEGIN RSA PRIVATE KEY-----
176MIICXAIBAAKBgQCqklnKB37DV9os6vWI4CZsGHHlJlZxMJn9mMdBMkzsa49PrbhC
177SqyLEWCFEp0NE7CnCcA/uAxG6QuqLLj6RG4ZPk5/IaCAv3mLbGoD7N6GOPTyVJOW
1788Yel48mALJNq8jLn4uOyPgMqcrK6HGZuJdNGsfzc0OCLFWQ5tMSaH85UrQIDAQAB
179AoGAIQ594j5zna3/9WaPsTgnmhlesVctt4AAx/n827DA4ayyuHFlXUuVhtoWR5Pk
1805ezj9mtYW8DyeCegABnsu2vZni/CdvU6uiS1Hv6qM1GyYDm9KWgovIP9rQCDSGaz
181d57IWVGxx7ODFkm3gN5nxnSBOFVHytuW1J7FBRnEsehRroECQQDXHFOv82JuXDcz
182z3+4c74IEURdOHcbycxlppmK9kFqm5lsUdydnnGW+mvwDk0APOB7Wg7vyFyr393e
183dpmBDCzNAkEAyv6tVbTKUYhSjW+QhabJo896/EqQEYUmtMXxk4cQnKeR/Ao84Rkf
184EqD5IykMUfUI0jJU4DGX+gWZ10a7kNbHYQJAVFCuHNFxS4Cpwo0aqtnzKoZaHY/8
185X9ABZfafSHCtw3Op92M+7ikkrOELXdS9KdKyyqbKJAKNEHF3LbOfB44WIQJAA2N4
1869UNNVUsXRbElEnYUS529CdUczo4QdVgQjkvk5RiPAUwSdBd9Q0xYnFOlFwEmIowg
187ipWJWe0aAlP18ZcEQQJBAL+5lekZ/GUdQoZ4HAsN5a9syrzavJ9VvU1KOOPorPZK
188nMRZbbQgP+aSB7yl6K0gaLaZ8XaK0pjxNBh6ASqg9f4=
189-----END RSA PRIVATE KEY-----
190""")
191
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400192client_cert_pem = b("""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500193MIICJjCCAY+gAwIBAgIJAKxpFI5lODkjMA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
194BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
195VGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBSb290IENBMCIYDzIwMDkwMzI1MTIz
196ODA1WhgPMjAxNzA2MTExMjM4MDVaMBYxFDASBgNVBAMTC3VnbHkgY2xpZW50MIGf
197MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDAZh/SRtNm5ntMT4qb6YzEpTroMlq2
198rn+GrRHRiZ+xkCw/CGNhbtPir7/QxaUj26BSmQrHw1bGKEbPsWiW7bdXSespl+xK
199iku4G/KvnnmWdeJHqsiXeUZtqurMELcPQAw9xPHEuhqqUJvvEoMTsnCEqGM+7Dtb
200oCRajYyHfluARQIDAQABozYwNDAdBgNVHQ4EFgQUNQB+qkaOaEVecf1J3TTUtAff
2010fAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQEFBQADgYEAyv/Jh7gM
202Q3OHvmsFEEvRI+hsW8y66zK4K5de239Y44iZrFYkt7Q5nBPMEWDj4F2hLYWL/qtI
2039Zdr0U4UDCU9SmmGYh4o7R4TZ5pGFvBYvjhHbkSFYFQXZxKUi+WUxplP6I0wr2KJ
204PSTJCjJOn3xo2NTKRgV1gaoTf2EhL+RG8TQ=
205-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400206""")
Rick Dean94e46fd2009-07-18 14:51:24 -0500207
Jean-Paul Calderone22cbe502011-05-04 17:01:43 -0400208client_key_pem = normalize_privatekey_pem(b("""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500209MIICXgIBAAKBgQDAZh/SRtNm5ntMT4qb6YzEpTroMlq2rn+GrRHRiZ+xkCw/CGNh
210btPir7/QxaUj26BSmQrHw1bGKEbPsWiW7bdXSespl+xKiku4G/KvnnmWdeJHqsiX
211eUZtqurMELcPQAw9xPHEuhqqUJvvEoMTsnCEqGM+7DtboCRajYyHfluARQIDAQAB
212AoGATkZ+NceY5Glqyl4mD06SdcKfV65814vg2EL7V9t8+/mi9rYL8KztSXGlQWPX
213zuHgtRoMl78yQ4ZJYOBVo+nsx8KZNRCEBlE19bamSbQLCeQMenWnpeYyQUZ908gF
214h6L9qsFVJepgA9RDgAjyDoS5CaWCdCCPCH2lDkdcqC54SVUCQQDseuduc4wi8h4t
215V8AahUn9fn9gYfhoNuM0gdguTA0nPLVWz4hy1yJiWYQe0H7NLNNTmCKiLQaJpAbb
216TC6vE8C7AkEA0Ee8CMJUc20BnGEmxwgWcVuqFWaKCo8jTH1X38FlATUsyR3krjW2
217dL3yDD9NwHxsYP7nTKp/U8MV7U9IBn4y/wJBAJl7H0/BcLeRmuJk7IqJ7b635iYB
218D/9beFUw3MUXmQXZUfyYz39xf6CDZsu1GEdEC5haykeln3Of4M9d/4Kj+FcCQQCY
219si6xwT7GzMDkk/ko684AV3KPc/h6G0yGtFIrMg7J3uExpR/VdH2KgwMkZXisSMvw
220JJEQjOMCVsEJlRk54WWjAkEAzoZNH6UhDdBK5F38rVt/y4SEHgbSfJHIAmPS32Kq
221f6GGcfNpip0Uk7q7udTKuX7Q/buZi/C4YW7u3VKAquv9NA==
222-----END RSA PRIVATE KEY-----
Jean-Paul Calderone22cbe502011-05-04 17:01:43 -0400223"""))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400224
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400225cleartextCertificatePEM = b("""-----BEGIN CERTIFICATE-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400226MIIC7TCCAlagAwIBAgIIPQzE4MbeufQwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE
227BhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdU
228ZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwIhgPMjAwOTAzMjUxMjM2
229NThaGA8yMDE3MDYxMTEyMzY1OFowWDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklM
230MRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9U
231ZXN0aW5nIFJvb3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPmaQumL
232urpE527uSEHdL1pqcDRmWzu+98Y6YHzT/J7KWEamyMCNZ6fRW1JCR782UQ8a07fy
2332xXsKy4WdKaxyG8CcatwmXvpvRQ44dSANMihHELpANTdyVp6DCysED6wkQFurHlF
2341dshEaJw8b/ypDhmbVIo6Ci1xvCJqivbLFnbAgMBAAGjgbswgbgwHQYDVR0OBBYE
235FINVdy1eIfFJDAkk51QJEo3IfgSuMIGIBgNVHSMEgYAwfoAUg1V3LV4h8UkMCSTn
236VAkSjch+BK6hXKRaMFgxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UE
237BxMHQ2hpY2FnbzEQMA4GA1UEChMHVGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBS
238b290IENBggg9DMTgxt659DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB
239AGGCDazMJGoWNBpc03u6+smc95dEead2KlZXBATOdFT1VesY3+nUOqZhEhTGlDMi
240hkgaZnzoIq/Uamidegk4hirsCT/R+6vsKAAxNTcBjUeZjlykCJWy5ojShGftXIKY
241w/njVbKMXrvc83qmTdGl3TAM0fxQIpqgcglFLveEBgzn
242-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400243""")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400244
Jean-Paul Calderoned50d2042011-05-04 17:00:49 -0400245cleartextPrivateKeyPEM = normalize_privatekey_pem(b("""\
246-----BEGIN RSA PRIVATE KEY-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400247MIICXQIBAAKBgQD5mkLpi7q6ROdu7khB3S9aanA0Zls7vvfGOmB80/yeylhGpsjA
248jWen0VtSQke/NlEPGtO38tsV7CsuFnSmschvAnGrcJl76b0UOOHUgDTIoRxC6QDU
2493claegwsrBA+sJEBbqx5RdXbIRGicPG/8qQ4Zm1SKOgotcbwiaor2yxZ2wIDAQAB
250AoGBAPCgMpmLxzwDaUmcFbTJUvlLW1hoxNNYSu2jIZm1k/hRAcE60JYwvBkgz3UB
251yMEh0AtLxYe0bFk6EHah11tMUPgscbCq73snJ++8koUw+csk22G65hOs51bVb7Aa
2526JBe67oLzdtvgCUFAA2qfrKzWRZzAdhUirQUZgySZk+Xq1pBAkEA/kZG0A6roTSM
253BVnx7LnPfsycKUsTumorpXiylZJjTi9XtmzxhrYN6wgZlDOOwOLgSQhszGpxVoMD
254u3gByT1b2QJBAPtL3mSKdvwRu/+40zaZLwvSJRxaj0mcE4BJOS6Oqs/hS1xRlrNk
255PpQ7WJ4yM6ZOLnXzm2mKyxm50Mv64109FtMCQQDOqS2KkjHaLowTGVxwC0DijMfr
256I9Lf8sSQk32J5VWCySWf5gGTfEnpmUa41gKTMJIbqZZLucNuDcOtzUaeWZlZAkA8
257ttXigLnCqR486JDPTi9ZscoZkZ+w7y6e/hH8t6d5Vjt48JVyfjPIaJY+km58LcN3
2586AWSeGAdtRFHVzR7oHjVAkB4hutvxiOeiIVQNBhM6RSI9aBPMI21DoX2JRoxvNW2
259cbvAhow217X9V0dVerEOKxnNYspXRrh36h7k4mQA+sDq
260-----END RSA PRIVATE KEY-----
Jean-Paul Calderoned50d2042011-05-04 17:00:49 -0400261"""))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400262
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400263cleartextCertificateRequestPEM = b("""-----BEGIN CERTIFICATE REQUEST-----
264MIIBnjCCAQcCAQAwXjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQH
265EwdDaGljYWdvMRcwFQYDVQQKEw5NeSBDb21wYW55IEx0ZDEXMBUGA1UEAxMORnJl
266ZGVyaWNrIERlYW4wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANp6Y17WzKSw
267BsUWkXdqg6tnXy8H8hA1msCMWpc+/2KJ4mbv5NyD6UD+/SqagQqulPbF/DFea9nA
268E0zhmHJELcM8gUTIlXv/cgDWnmK4xj8YkjVUiCdqKRAKeuzLG1pGmwwF5lGeJpXN
269xQn5ecR0UYSOWj6TTGXB9VyUMQzCClcBAgMBAAGgADANBgkqhkiG9w0BAQUFAAOB
270gQAAJGuF/R/GGbeC7FbFW+aJgr9ee0Xbl6nlhu7pTe67k+iiKT2dsl2ti68MVTnu
271Vrb3HUNqOkiwsJf6kCtq5oPn3QVYzTa76Dt2y3Rtzv6boRSlmlfrgS92GNma8JfR
272oICQk3nAudi6zl1Dix3BCv1pUp5KMtGn3MeDEi6QFGy2rA==
273-----END CERTIFICATE REQUEST-----
274""")
Rick Dean5b7b6372009-04-01 11:34:06 -0500275
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400276encryptedPrivateKeyPEM = b("""-----BEGIN RSA PRIVATE KEY-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400277Proc-Type: 4,ENCRYPTED
278DEK-Info: DES-EDE3-CBC,9573604A18579E9E
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400279
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400280SHOho56WxDkT0ht10UTeKc0F5u8cqIa01kzFAmETw0MAs8ezYtK15NPdCXUm3X/2
281a17G7LSF5bkxOgZ7vpXyMzun/owrj7CzvLxyncyEFZWvtvzaAhPhvTJtTIB3kf8B
2828+qRcpTGK7NgXEgYBW5bj1y4qZkD4zCL9o9NQzsKI3Ie8i0239jsDOWR38AxjXBH
283mGwAQ4Z6ZN5dnmM4fhMIWsmFf19sNyAML4gHenQCHhmXbjXeVq47aC2ProInJbrm
284+00TcisbAQ40V9aehVbcDKtS4ZbMVDwncAjpXpcncC54G76N6j7F7wL7L/FuXa3A
285fvSVy9n2VfF/pJ3kYSflLHH2G/DFxjF7dl0GxhKPxJjp3IJi9VtuvmN9R2jZWLQF
286tfC8dXgy/P9CfFQhlinqBTEwgH0oZ/d4k4NVFDSdEMaSdmBAjlHpc+Vfdty3HVnV
287rKXj//wslsFNm9kIwJGIgKUa/n2jsOiydrsk1mgH7SmNCb3YHgZhbbnq0qLat/HC
288gHDt3FHpNQ31QzzL3yrenFB2L9osIsnRsDTPFNi4RX4SpDgNroxOQmyzCCV6H+d4
289o1mcnNiZSdxLZxVKccq0AfRpHqpPAFnJcQHP6xyT9MZp6fBa0XkxDnt9kNU8H3Qw
2907SJWZ69VXjBUzMlQViLuaWMgTnL+ZVyFZf9hTF7U/ef4HMLMAVNdiaGG+G+AjCV/
291MbzjS007Oe4qqBnCWaFPSnJX6uLApeTbqAxAeyCql56ULW5x6vDMNC3dwjvS/CEh
29211n8RkgFIQA0AhuKSIg3CbuartRsJnWOLwgLTzsrKYL4yRog1RJrtw==
293-----END RSA PRIVATE KEY-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400294""")
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400295
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400296encryptedPrivateKeyPEMPassphrase = b("foobar")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400297
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400298# Some PKCS#7 stuff. Generated with the openssl command line:
299#
300# openssl crl2pkcs7 -inform pem -outform pem -certfile s.pem -nocrl
301#
302# with a certificate and key (but the key should be irrelevant) in s.pem
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400303pkcs7Data = b("""\
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400304-----BEGIN PKCS7-----
305MIIDNwYJKoZIhvcNAQcCoIIDKDCCAyQCAQExADALBgkqhkiG9w0BBwGgggMKMIID
306BjCCAm+gAwIBAgIBATANBgkqhkiG9w0BAQQFADB7MQswCQYDVQQGEwJTRzERMA8G
307A1UEChMITTJDcnlwdG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtN
308MkNyeXB0byBDZXJ0aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNA
309cG9zdDEuY29tMB4XDTAwMDkxMDA5NTEzMFoXDTAyMDkxMDA5NTEzMFowUzELMAkG
310A1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwlsb2NhbGhvc3Qx
311HTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tMFwwDQYJKoZIhvcNAQEBBQAD
312SwAwSAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh5kwI
313zOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEAAaOCAQQwggEAMAkGA1UdEwQCMAAw
314LAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0G
315A1UdDgQWBBTPhIKSvnsmYsBVNWjj0m3M2z0qVTCBpQYDVR0jBIGdMIGagBT7hyNp
31665w6kxXlxb8pUU/+7Sg4AaF/pH0wezELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0y
317Q3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlwdG8g
318Q2VydGlmaWNhdGUgTWFzdGVyMR0wGwYJKoZIhvcNAQkBFg5uZ3BzQHBvc3QxLmNv
319bYIBADANBgkqhkiG9w0BAQQFAAOBgQA7/CqT6PoHycTdhEStWNZde7M/2Yc6BoJu
320VwnW8YxGO8Sn6UJ4FeffZNcYZddSDKosw8LtPOeWoK3JINjAk5jiPQ2cww++7QGG
321/g5NDjxFZNDJP1dGiLAxPW6JXwov4v0FmdzfLOZ01jDcgQQZqEpYlgpuI5JEWUQ9
322Ho4EzbYCOaEAMQA=
323-----END PKCS7-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400324""")
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400325
Alex Gaynor8fa1dd62014-08-14 09:57:51 -0700326pkcs7DataASN1 = base64.b64decode(b"""
Alex Gaynor4b9c96a2014-08-14 09:51:48 -0700327MIIDNwYJKoZIhvcNAQcCoIIDKDCCAyQCAQExADALBgkqhkiG9w0BBwGgggMKMIID
328BjCCAm+gAwIBAgIBATANBgkqhkiG9w0BAQQFADB7MQswCQYDVQQGEwJTRzERMA8G
329A1UEChMITTJDcnlwdG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtN
330MkNyeXB0byBDZXJ0aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNA
331cG9zdDEuY29tMB4XDTAwMDkxMDA5NTEzMFoXDTAyMDkxMDA5NTEzMFowUzELMAkG
332A1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwlsb2NhbGhvc3Qx
333HTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tMFwwDQYJKoZIhvcNAQEBBQAD
334SwAwSAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh5kwI
335zOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEAAaOCAQQwggEAMAkGA1UdEwQCMAAw
336LAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0G
337A1UdDgQWBBTPhIKSvnsmYsBVNWjj0m3M2z0qVTCBpQYDVR0jBIGdMIGagBT7hyNp
33865w6kxXlxb8pUU/+7Sg4AaF/pH0wezELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0y
339Q3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlwdG8g
340Q2VydGlmaWNhdGUgTWFzdGVyMR0wGwYJKoZIhvcNAQkBFg5uZ3BzQHBvc3QxLmNv
341bYIBADANBgkqhkiG9w0BAQQFAAOBgQA7/CqT6PoHycTdhEStWNZde7M/2Yc6BoJu
342VwnW8YxGO8Sn6UJ4FeffZNcYZddSDKosw8LtPOeWoK3JINjAk5jiPQ2cww++7QGG
343/g5NDjxFZNDJP1dGiLAxPW6JXwov4v0FmdzfLOZ01jDcgQQZqEpYlgpuI5JEWUQ9
344Ho4EzbYCOaEAMQA=
Alex Gaynor8fa1dd62014-08-14 09:57:51 -0700345""")
Alex Gaynor4b9c96a2014-08-14 09:51:48 -0700346
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400347crlData = b("""\
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -0500348-----BEGIN X509 CRL-----
349MIIBWzCBxTANBgkqhkiG9w0BAQQFADBYMQswCQYDVQQGEwJVUzELMAkGA1UECBMC
350SUwxEDAOBgNVBAcTB0NoaWNhZ28xEDAOBgNVBAoTB1Rlc3RpbmcxGDAWBgNVBAMT
351D1Rlc3RpbmcgUm9vdCBDQRcNMDkwNzI2MDQzNDU2WhcNMTIwOTI3MDI0MTUyWjA8
352MBUCAgOrGA8yMDA5MDcyNTIzMzQ1NlowIwICAQAYDzIwMDkwNzI1MjMzNDU2WjAM
353MAoGA1UdFQQDCgEEMA0GCSqGSIb3DQEBBAUAA4GBAEBt7xTs2htdD3d4ErrcGAw1
3544dKcVnIWTutoI7xxen26Wwvh8VCsT7i/UeP+rBl9rC/kfjWjzQk3/zleaarGTpBT
3550yp4HXRFFoRhhSE/hP+eteaPXRgrsNRLHe9ZDd69wmh7J1wMDb0m81RG7kqcbsid
356vrzEeLDRiiPl92dyyWmu
357-----END X509 CRL-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400358""")
Jean-Paul Calderonee890db32010-08-22 16:55:15 -0400359
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400360
361# A broken RSA private key which can be used to test the error path through
362# PKey.check.
363inconsistentPrivateKeyPEM = b("""-----BEGIN RSA PRIVATE KEY-----
364MIIBPAIBAAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh
3655kwIzOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEaAQJBAIqm/bz4NA1H++Vx5Ewx
366OcKp3w19QSaZAwlGRtsUxrP7436QjnREM3Bm8ygU11BjkPVmtrKm6AayQfCHqJoT
367zIECIQDW0BoMoL0HOYM/mrTLhaykYAVqgIeJsPjvkEhTFXWBuQIhAM3deFAvWNu4
368nklUQ37XsCT2c9tmNt1LAT+slG2JOTTRAiAuXDtC/m3NYVwyHfFm+zKHRzHkClk2
369HjubeEgjpj32AQIhAJqMGTaZVOwevTXvvHwNeH+vRWsAYU/gbx+OQB+7VOcBAiEA
370oolb6NMg/R3enNPvS1O4UU1H8wpaF77L4yiSWlE0p4w=
371-----END RSA PRIVATE KEY-----
372""")
373
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -0400374# certificate with NULL bytes in subjectAltName and common name
375
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400376nulbyteSubjectAltNamePEM = b("""-----BEGIN CERTIFICATE-----
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -0400377MIIE2DCCA8CgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBxTELMAkGA1UEBhMCVVMx
378DzANBgNVBAgMBk9yZWdvbjESMBAGA1UEBwwJQmVhdmVydG9uMSMwIQYDVQQKDBpQ
379eXRob24gU29mdHdhcmUgRm91bmRhdGlvbjEgMB4GA1UECwwXUHl0aG9uIENvcmUg
380RGV2ZWxvcG1lbnQxJDAiBgNVBAMMG251bGwucHl0aG9uLm9yZwBleGFtcGxlLm9y
381ZzEkMCIGCSqGSIb3DQEJARYVcHl0aG9uLWRldkBweXRob24ub3JnMB4XDTEzMDgw
382NzEzMTE1MloXDTEzMDgwNzEzMTI1MlowgcUxCzAJBgNVBAYTAlVTMQ8wDQYDVQQI
383DAZPcmVnb24xEjAQBgNVBAcMCUJlYXZlcnRvbjEjMCEGA1UECgwaUHl0aG9uIFNv
384ZnR3YXJlIEZvdW5kYXRpb24xIDAeBgNVBAsMF1B5dGhvbiBDb3JlIERldmVsb3Bt
385ZW50MSQwIgYDVQQDDBtudWxsLnB5dGhvbi5vcmcAZXhhbXBsZS5vcmcxJDAiBgkq
386hkiG9w0BCQEWFXB5dGhvbi1kZXZAcHl0aG9uLm9yZzCCASIwDQYJKoZIhvcNAQEB
387BQADggEPADCCAQoCggEBALXq7cn7Rn1vO3aA3TrzA5QLp6bb7B3f/yN0CJ2XFj+j
388pHs+Gw6WWSUDpybiiKnPec33BFawq3kyblnBMjBU61ioy5HwQqVkJ8vUVjGIUq3P
389vX/wBmQfzCe4o4uM89gpHyUL9UYGG8oCRa17dgqcv7u5rg0Wq2B1rgY+nHwx3JIv
390KRrgSwyRkGzpN8WQ1yrXlxWjgI9de0mPVDDUlywcWze1q2kwaEPTM3hLAmD1PESA
391oY/n8A/RXoeeRs9i/Pm/DGUS8ZPINXk/yOzsR/XvvkTVroIeLZqfmFpnZeF0cHzL
39208LODkVJJ9zjLdT7SA4vnne4FEbAxDbKAq5qkYzaL4UCAwEAAaOB0DCBzTAMBgNV
393HRMBAf8EAjAAMB0GA1UdDgQWBBSIWlXAUv9hzVKjNQ/qWpwkOCL3XDALBgNVHQ8E
394BAMCBeAwgZAGA1UdEQSBiDCBhYIeYWx0bnVsbC5weXRob24ub3JnAGV4YW1wbGUu
395Y29tgSBudWxsQHB5dGhvbi5vcmcAdXNlckBleGFtcGxlLm9yZ4YpaHR0cDovL251
396bGwucHl0aG9uLm9yZwBodHRwOi8vZXhhbXBsZS5vcmeHBMAAAgGHECABDbgAAAAA
397AAAAAAAAAAEwDQYJKoZIhvcNAQEFBQADggEBAKxPRe99SaghcI6IWT7UNkJw9aO9
398i9eo0Fj2MUqxpKbdb9noRDy2CnHWf7EIYZ1gznXPdwzSN4YCjV5d+Q9xtBaowT0j
399HPERs1ZuytCNNJTmhyqZ8q6uzMLoht4IqH/FBfpvgaeC5tBTnTT0rD5A/olXeimk
400kX4LxlEx5RAvpGB2zZVRGr6LobD9rVK91xuHYNIxxxfEGE8tCCWjp0+3ksri9SXx
401VHWBnbM9YaL32u3hxm8sYB/Yb8WSBavJCWJJqRStVRHM1koZlJmXNx2BX4vPo6iW
402RFEIPQsFZRLrtnCAiEhyT8bC2s/Njlu6ly9gtJZWSV46Q3ZjBL4q9sHKqZQ=
403-----END CERTIFICATE-----""")
404
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400405
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400406class X509ExtTests(TestCase):
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400407 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900408 Tests for :py:class:`OpenSSL.crypto.X509Extension`.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400409 """
410
411 def setUp(self):
412 """
413 Create a new private key and start a certificate request (for a test
414 method to finish in one way or another).
415 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -0800416 super(X509ExtTests, self).setUp()
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400417 # Basic setup stuff to generate a certificate
418 self.pkey = PKey()
419 self.pkey.generate_key(TYPE_RSA, 384)
420 self.req = X509Req()
421 self.req.set_pubkey(self.pkey)
422 # Authority good you have.
423 self.req.get_subject().commonName = "Yoda root CA"
424 self.x509 = X509()
425 self.subject = self.x509.get_subject()
426 self.subject.commonName = self.req.get_subject().commonName
427 self.x509.set_issuer(self.subject)
428 self.x509.set_pubkey(self.pkey)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400429 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Alex Gaynor7f636492015-09-04 13:26:52 -0400430 expire = b((datetime.now() + timedelta(days=100)).strftime("%Y%m%d%H%M%SZ"))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400431 self.x509.set_notBefore(now)
432 self.x509.set_notAfter(expire)
433
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -0800434 def tearDown(self):
435 """
436 Forget all of the pyOpenSSL objects so they can be garbage collected,
437 their memory released, and not interfere with the leak detection code.
438 """
439 self.pkey = self.req = self.x509 = self.subject = None
440 super(X509ExtTests, self).tearDown()
441
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400442 def test_str(self):
443 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900444 The string representation of :py:class:`X509Extension` instances as returned by
445 :py:data:`str` includes stuff.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400446 """
447 # This isn't necessarily the best string representation. Perhaps it
448 # will be changed/improved in the future.
449 self.assertEquals(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400450 str(X509Extension(b('basicConstraints'), True, b('CA:false'))),
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400451 'CA:FALSE')
452
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400453 def test_type(self):
454 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900455 :py:class:`X509Extension` and :py:class:`X509ExtensionType` refer to the same type object
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400456 and can be used to create instances of that type.
457 """
458 self.assertIdentical(X509Extension, X509ExtensionType)
459 self.assertConsistentType(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400460 X509Extension,
461 'X509Extension', b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400462
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500463 def test_construction(self):
464 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900465 :py:class:`X509Extension` accepts an extension type name, a critical flag,
466 and an extension value and returns an :py:class:`X509ExtensionType` instance.
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500467 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400468 basic = X509Extension(b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500469 self.assertTrue(
470 isinstance(basic, X509ExtensionType),
471 "%r is of type %r, should be %r" % (
472 basic, type(basic), X509ExtensionType))
473
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400474 comment = X509Extension(
475 b('nsComment'), False, b('pyOpenSSL unit test'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500476 self.assertTrue(
477 isinstance(comment, X509ExtensionType),
478 "%r is of type %r, should be %r" % (
479 comment, type(comment), X509ExtensionType))
480
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500481 def test_invalid_extension(self):
482 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900483 :py:class:`X509Extension` raises something if it is passed a bad extension
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500484 name or value.
485 """
486 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400487 Error, X509Extension, b('thisIsMadeUp'), False, b('hi'))
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500488 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400489 Error, X509Extension, b('basicConstraints'), False, b('blah blah'))
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500490
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500491 # Exercise a weird one (an extension which uses the r2i method). This
492 # exercises the codepath that requires a non-NULL ctx to be passed to
493 # X509V3_EXT_nconf. It can't work now because we provide no
494 # configuration database. It might be made to work in the future.
495 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400496 Error, X509Extension, b('proxyCertInfo'), True,
497 b('language:id-ppl-anyLanguage,pathlen:1,policy:text:AB'))
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500498
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500499 def test_get_critical(self):
500 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900501 :py:meth:`X509ExtensionType.get_critical` returns the value of the
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500502 extension's critical flag.
503 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400504 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500505 self.assertTrue(ext.get_critical())
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400506 ext = X509Extension(b('basicConstraints'), False, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500507 self.assertFalse(ext.get_critical())
508
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500509 def test_get_short_name(self):
510 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900511 :py:meth:`X509ExtensionType.get_short_name` returns a string giving the short
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500512 type name of the extension.
513 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400514 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
515 self.assertEqual(ext.get_short_name(), b('basicConstraints'))
516 ext = X509Extension(b('nsComment'), True, b('foo bar'))
517 self.assertEqual(ext.get_short_name(), b('nsComment'))
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500518
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400519 def test_get_data(self):
520 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900521 :py:meth:`X509Extension.get_data` returns a string giving the data of the
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400522 extension.
523 """
524 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
525 # Expect to get back the DER encoded form of CA:true.
526 self.assertEqual(ext.get_data(), b('0\x03\x01\x01\xff'))
527
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400528 def test_get_data_wrong_args(self):
529 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900530 :py:meth:`X509Extension.get_data` raises :py:exc:`TypeError` if passed any arguments.
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400531 """
532 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
533 self.assertRaises(TypeError, ext.get_data, None)
534 self.assertRaises(TypeError, ext.get_data, "foo")
535 self.assertRaises(TypeError, ext.get_data, 7)
536
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400537 def test_unused_subject(self):
Rick Dean47262da2009-07-08 16:17:17 -0500538 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900539 The :py:data:`subject` parameter to :py:class:`X509Extension` may be provided for an
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400540 extension which does not use it and is ignored in this case.
Rick Dean47262da2009-07-08 16:17:17 -0500541 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400542 ext1 = X509Extension(
543 b('basicConstraints'), False, b('CA:TRUE'), subject=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400544 self.x509.add_extensions([ext1])
545 self.x509.sign(self.pkey, 'sha1')
546 # This is a little lame. Can we think of a better way?
547 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400548 self.assertTrue(b('X509v3 Basic Constraints:') in text)
549 self.assertTrue(b('CA:TRUE') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400550
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400551 def test_subject(self):
552 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900553 If an extension requires a subject, the :py:data:`subject` parameter to
554 :py:class:`X509Extension` provides its value.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400555 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400556 ext3 = X509Extension(
557 b('subjectKeyIdentifier'), False, b('hash'), subject=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400558 self.x509.add_extensions([ext3])
559 self.x509.sign(self.pkey, 'sha1')
560 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400561 self.assertTrue(b('X509v3 Subject Key Identifier:') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400562
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400563 def test_missing_subject(self):
564 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900565 If an extension requires a subject and the :py:data:`subject` parameter is
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400566 given no value, something happens.
567 """
568 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400569 Error, X509Extension, b('subjectKeyIdentifier'), False, b('hash'))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400570
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400571 def test_invalid_subject(self):
572 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900573 If the :py:data:`subject` parameter is given a value which is not an
574 :py:class:`X509` instance, :py:exc:`TypeError` is raised.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400575 """
576 for badObj in [True, object(), "hello", [], self]:
577 self.assertRaises(
578 TypeError,
579 X509Extension,
580 'basicConstraints', False, 'CA:TRUE', subject=badObj)
581
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400582 def test_unused_issuer(self):
583 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900584 The :py:data:`issuer` parameter to :py:class:`X509Extension` may be provided for an
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400585 extension which does not use it and is ignored in this case.
586 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400587 ext1 = X509Extension(
588 b('basicConstraints'), False, b('CA:TRUE'), issuer=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400589 self.x509.add_extensions([ext1])
590 self.x509.sign(self.pkey, 'sha1')
591 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400592 self.assertTrue(b('X509v3 Basic Constraints:') in text)
593 self.assertTrue(b('CA:TRUE') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400594
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400595 def test_issuer(self):
596 """
Alex Gaynor3b0ee972014-11-15 09:17:33 -0800597 If an extension requires an issuer, the :py:data:`issuer` parameter to
Jonathan Ballet648875f2011-07-16 14:14:58 +0900598 :py:class:`X509Extension` provides its value.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400599 """
600 ext2 = X509Extension(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400601 b('authorityKeyIdentifier'), False, b('issuer:always'),
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400602 issuer=self.x509)
603 self.x509.add_extensions([ext2])
604 self.x509.sign(self.pkey, 'sha1')
605 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400606 self.assertTrue(b('X509v3 Authority Key Identifier:') in text)
607 self.assertTrue(b('DirName:/CN=Yoda root CA') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400608
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400609 def test_missing_issuer(self):
610 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900611 If an extension requires an issue and the :py:data:`issuer` parameter is given
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400612 no value, something happens.
613 """
614 self.assertRaises(
615 Error,
616 X509Extension,
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400617 b('authorityKeyIdentifier'), False,
618 b('keyid:always,issuer:always'))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400619
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400620 def test_invalid_issuer(self):
621 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900622 If the :py:data:`issuer` parameter is given a value which is not an
623 :py:class:`X509` instance, :py:exc:`TypeError` is raised.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400624 """
625 for badObj in [True, object(), "hello", [], self]:
626 self.assertRaises(
627 TypeError,
628 X509Extension,
629 'authorityKeyIdentifier', False, 'keyid:always,issuer:always',
630 issuer=badObj)
Rick Dean47262da2009-07-08 16:17:17 -0500631
632
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400633class PKeyTests(TestCase):
Jean-Paul Calderoneac930e12008-03-06 18:50:51 -0500634 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900635 Unit tests for :py:class:`OpenSSL.crypto.PKey`.
Jean-Paul Calderoneac930e12008-03-06 18:50:51 -0500636 """
Alex Gaynoraceb3e22015-09-05 12:00:22 -0400637
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400638 def test_type(self):
639 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900640 :py:class:`PKey` and :py:class:`PKeyType` refer to the same type object
641 and can be used to create instances of that type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400642 """
643 self.assertIdentical(PKey, PKeyType)
644 self.assertConsistentType(PKey, 'PKey')
645
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500646 def test_construction(self):
647 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900648 :py:class:`PKey` takes no arguments and returns a new :py:class:`PKey` instance.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500649 """
650 self.assertRaises(TypeError, PKey, None)
651 key = PKey()
652 self.assertTrue(
653 isinstance(key, PKeyType),
654 "%r is of type %r, should be %r" % (key, type(key), PKeyType))
655
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500656 def test_pregeneration(self):
657 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900658 :py:attr:`PKeyType.bits` and :py:attr:`PKeyType.type` return :py:data:`0` before the key is
659 generated. :py:attr:`PKeyType.check` raises :py:exc:`TypeError` before the key is
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500660 generated.
661 """
662 key = PKey()
663 self.assertEqual(key.type(), 0)
664 self.assertEqual(key.bits(), 0)
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400665 self.assertRaises(TypeError, key.check)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500666
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500667 def test_failedGeneration(self):
668 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900669 :py:meth:`PKeyType.generate_key` takes two arguments, the first giving the key
670 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 -0500671 number of bits to generate. If an invalid type is specified or
Jonathan Ballet648875f2011-07-16 14:14:58 +0900672 generation fails, :py:exc:`Error` is raised. If an invalid number of bits is
673 specified, :py:exc:`ValueError` or :py:exc:`Error` is raised.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500674 """
675 key = PKey()
676 self.assertRaises(TypeError, key.generate_key)
677 self.assertRaises(TypeError, key.generate_key, 1, 2, 3)
678 self.assertRaises(TypeError, key.generate_key, "foo", "bar")
679 self.assertRaises(Error, key.generate_key, -1, 0)
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500680
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500681 self.assertRaises(ValueError, key.generate_key, TYPE_RSA, -1)
682 self.assertRaises(ValueError, key.generate_key, TYPE_RSA, 0)
Jean-Paul Calderoned71fe982008-03-06 00:31:50 -0500683
684 # XXX RSA generation for small values of bits is fairly buggy in a wide
685 # range of OpenSSL versions. I need to figure out what the safe lower
686 # bound for a reasonable number of OpenSSL versions is and explicitly
687 # check for that in the wrapper. The failure behavior is typically an
688 # infinite loop inside OpenSSL.
689
690 # self.assertRaises(Error, key.generate_key, TYPE_RSA, 2)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500691
692 # XXX DSA generation seems happy with any number of bits. The DSS
693 # says bits must be between 512 and 1024 inclusive. OpenSSL's DSA
694 # generator doesn't seem to care about the upper limit at all. For
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500695 # the lower limit, it uses 512 if anything smaller is specified.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500696 # So, it doesn't seem possible to make generate_key fail for
697 # TYPE_DSA with a bits argument which is at least an int.
698
699 # self.assertRaises(Error, key.generate_key, TYPE_DSA, -7)
700
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500701 def test_rsaGeneration(self):
702 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900703 :py:meth:`PKeyType.generate_key` generates an RSA key when passed
704 :py:data:`TYPE_RSA` as a type and a reasonable number of bits.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500705 """
706 bits = 128
707 key = PKey()
708 key.generate_key(TYPE_RSA, bits)
709 self.assertEqual(key.type(), TYPE_RSA)
710 self.assertEqual(key.bits(), bits)
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -0400711 self.assertTrue(key.check())
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500712
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500713 def test_dsaGeneration(self):
714 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900715 :py:meth:`PKeyType.generate_key` generates a DSA key when passed
716 :py:data:`TYPE_DSA` as a type and a reasonable number of bits.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500717 """
718 # 512 is a magic number. The DSS (Digital Signature Standard)
719 # allows a minimum of 512 bits for DSA. DSA_generate_parameters
720 # will silently promote any value below 512 to 512.
721 bits = 512
722 key = PKey()
723 key.generate_key(TYPE_DSA, bits)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800724 # self.assertEqual(key.type(), TYPE_DSA)
725 # self.assertEqual(key.bits(), bits)
726 # self.assertRaises(TypeError, key.check)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500727
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500728 def test_regeneration(self):
729 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900730 :py:meth:`PKeyType.generate_key` can be called multiple times on the same
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500731 key to generate new keys.
732 """
733 key = PKey()
734 for type, bits in [(TYPE_RSA, 512), (TYPE_DSA, 576)]:
Alex Gaynor7f636492015-09-04 13:26:52 -0400735 key.generate_key(type, bits)
736 self.assertEqual(key.type(), type)
737 self.assertEqual(key.bits(), bits)
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500738
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400739 def test_inconsistentKey(self):
740 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900741 :py:`PKeyType.check` returns :py:exc:`Error` if the key is not consistent.
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400742 """
743 key = load_privatekey(FILETYPE_PEM, inconsistentPrivateKeyPEM)
Jean-Paul Calderoned338e4e2009-05-13 15:45:07 -0400744 self.assertRaises(Error, key.check)
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400745
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400746 def test_check_wrong_args(self):
747 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900748 :py:meth:`PKeyType.check` raises :py:exc:`TypeError` if called with any arguments.
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400749 """
750 self.assertRaises(TypeError, PKey().check, None)
751 self.assertRaises(TypeError, PKey().check, object())
752 self.assertRaises(TypeError, PKey().check, 1)
753
Jean-Paul Calderone02d01972011-10-31 10:39:29 -0400754 def test_check_public_key(self):
755 """
756 :py:meth:`PKeyType.check` raises :py:exc:`TypeError` if only the public
757 part of the key is available.
758 """
759 # A trick to get a public-only key
760 key = PKey()
761 key.generate_key(TYPE_RSA, 512)
762 cert = X509()
763 cert.set_pubkey(key)
764 pub = cert.get_pubkey()
765 self.assertRaises(TypeError, pub.check)
766
767
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400768class X509NameTests(TestCase):
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500769 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900770 Unit tests for :py:class:`OpenSSL.crypto.X509Name`.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500771 """
Alex Gaynoraceb3e22015-09-05 12:00:22 -0400772
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500773 def _x509name(self, **attrs):
774 # XXX There's no other way to get a new X509Name yet.
775 name = X509().get_subject()
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400776 attrs = list(attrs.items())
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500777 # Make the order stable - order matters!
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400778 def key(attr):
779 return attr[1]
780 attrs.sort(key=key)
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500781 for k, v in attrs:
782 setattr(name, k, v)
783 return name
784
Rick Deane15b1472009-07-09 15:53:42 -0500785 def test_type(self):
786 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900787 The type of X509Name objects is :py:class:`X509NameType`.
Rick Deane15b1472009-07-09 15:53:42 -0500788 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400789 self.assertIdentical(X509Name, X509NameType)
790 self.assertEqual(X509NameType.__name__, 'X509Name')
791 self.assertTrue(isinstance(X509NameType, type))
792
Rick Deane15b1472009-07-09 15:53:42 -0500793 name = self._x509name()
794 self.assertTrue(
795 isinstance(name, X509NameType),
796 "%r is of type %r, should be %r" % (
797 name, type(name), X509NameType))
Rick Deane15b1472009-07-09 15:53:42 -0500798
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400799 def test_onlyStringAttributes(self):
800 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900801 Attempting to set a non-:py:data:`str` attribute name on an :py:class:`X509NameType`
802 instance causes :py:exc:`TypeError` to be raised.
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400803 """
804 name = self._x509name()
805 # Beyond these cases, you may also think that unicode should be
806 # rejected. Sorry, you're wrong. unicode is automatically converted to
807 # str outside of the control of X509Name, so there's no way to reject
808 # it.
Jean-Paul Calderoneff363be2013-03-03 10:21:23 -0800809
810 # Also, this used to test str subclasses, but that test is less relevant
811 # now that the implementation is in Python instead of C. Also PyPy
812 # automatically converts str subclasses to str when they are passed to
813 # setattr, so we can't test it on PyPy. Apparently CPython does this
814 # sometimes as well.
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400815 self.assertRaises(TypeError, setattr, name, None, "hello")
816 self.assertRaises(TypeError, setattr, name, 30, "hello")
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400817
818 def test_setInvalidAttribute(self):
819 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900820 Attempting to set any attribute name on an :py:class:`X509NameType` instance for
821 which no corresponding NID is defined causes :py:exc:`AttributeError` to be
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400822 raised.
823 """
824 name = self._x509name()
825 self.assertRaises(AttributeError, setattr, name, "no such thing", None)
826
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500827 def test_attributes(self):
828 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900829 :py:class:`X509NameType` instances have attributes for each standard (?)
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500830 X509Name field.
831 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500832 name = self._x509name()
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500833 name.commonName = "foo"
834 self.assertEqual(name.commonName, "foo")
835 self.assertEqual(name.CN, "foo")
836 name.CN = "baz"
837 self.assertEqual(name.commonName, "baz")
838 self.assertEqual(name.CN, "baz")
839 name.commonName = "bar"
840 self.assertEqual(name.commonName, "bar")
841 self.assertEqual(name.CN, "bar")
842 name.CN = "quux"
843 self.assertEqual(name.commonName, "quux")
844 self.assertEqual(name.CN, "quux")
845
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500846 def test_copy(self):
847 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900848 :py:class:`X509Name` creates a new :py:class:`X509NameType` instance with all the same
849 attributes as an existing :py:class:`X509NameType` instance when called with
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500850 one.
851 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500852 name = self._x509name(commonName="foo", emailAddress="bar@example.com")
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500853
854 copy = X509Name(name)
855 self.assertEqual(copy.commonName, "foo")
856 self.assertEqual(copy.emailAddress, "bar@example.com")
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500857
858 # Mutate the copy and ensure the original is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500859 copy.commonName = "baz"
860 self.assertEqual(name.commonName, "foo")
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500861
862 # Mutate the original and ensure the copy is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500863 name.emailAddress = "quux@example.com"
864 self.assertEqual(copy.emailAddress, "bar@example.com")
865
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500866 def test_repr(self):
867 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900868 :py:func:`repr` passed an :py:class:`X509NameType` instance should return a string
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500869 containing a description of the type and the NIDs which have been set
870 on it.
871 """
872 name = self._x509name(commonName="foo", emailAddress="bar")
873 self.assertEqual(
874 repr(name),
875 "<X509Name object '/emailAddress=bar/CN=foo'>")
876
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500877 def test_comparison(self):
878 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900879 :py:class:`X509NameType` instances should compare based on their NIDs.
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500880 """
881 def _equality(a, b, assertTrue, assertFalse):
882 assertTrue(a == b, "(%r == %r) --> False" % (a, b))
883 assertFalse(a != b)
884 assertTrue(b == a)
885 assertFalse(b != a)
886
887 def assertEqual(a, b):
888 _equality(a, b, self.assertTrue, self.assertFalse)
889
890 # Instances compare equal to themselves.
891 name = self._x509name()
892 assertEqual(name, name)
893
894 # Empty instances should compare equal to each other.
895 assertEqual(self._x509name(), self._x509name())
896
897 # Instances with equal NIDs should compare equal to each other.
898 assertEqual(self._x509name(commonName="foo"),
899 self._x509name(commonName="foo"))
900
901 # Instance with equal NIDs set using different aliases should compare
902 # equal to each other.
903 assertEqual(self._x509name(commonName="foo"),
904 self._x509name(CN="foo"))
905
906 # Instances with more than one NID with the same values should compare
907 # equal to each other.
908 assertEqual(self._x509name(CN="foo", organizationalUnitName="bar"),
909 self._x509name(commonName="foo", OU="bar"))
910
911 def assertNotEqual(a, b):
912 _equality(a, b, self.assertFalse, self.assertTrue)
913
914 # Instances with different values for the same NID should not compare
915 # equal to each other.
916 assertNotEqual(self._x509name(CN="foo"),
917 self._x509name(CN="bar"))
918
919 # Instances with different NIDs should not compare equal to each other.
920 assertNotEqual(self._x509name(CN="foo"),
921 self._x509name(OU="foo"))
922
923 def _inequality(a, b, assertTrue, assertFalse):
924 assertTrue(a < b)
925 assertTrue(a <= b)
926 assertTrue(b > a)
927 assertTrue(b >= a)
928 assertFalse(a > b)
929 assertFalse(a >= b)
930 assertFalse(b < a)
931 assertFalse(b <= a)
932
933 def assertLessThan(a, b):
934 _inequality(a, b, self.assertTrue, self.assertFalse)
935
936 # An X509Name with a NID with a value which sorts less than the value
937 # of the same NID on another X509Name compares less than the other
938 # X509Name.
939 assertLessThan(self._x509name(CN="abc"),
940 self._x509name(CN="def"))
941
942 def assertGreaterThan(a, b):
943 _inequality(a, b, self.assertFalse, self.assertTrue)
944
945 # An X509Name with a NID with a value which sorts greater than the
946 # value of the same NID on another X509Name compares greater than the
947 # other X509Name.
948 assertGreaterThan(self._x509name(CN="def"),
949 self._x509name(CN="abc"))
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -0500950
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400951 def test_hash(self):
952 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900953 :py:meth:`X509Name.hash` returns an integer hash based on the value of the
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400954 name.
955 """
956 a = self._x509name(CN="foo")
957 b = self._x509name(CN="foo")
958 self.assertEqual(a.hash(), b.hash())
959 a.CN = "bar"
960 self.assertNotEqual(a.hash(), b.hash())
961
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400962 def test_der(self):
963 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900964 :py:meth:`X509Name.der` returns the DER encoded form of the name.
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400965 """
966 a = self._x509name(CN="foo", C="US")
967 self.assertEqual(
968 a.der(),
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -0400969 b('0\x1b1\x0b0\t\x06\x03U\x04\x06\x13\x02US'
D.S. Ljungmark5533e252014-05-31 13:18:41 +0200970 '1\x0c0\n\x06\x03U\x04\x03\x0c\x03foo'))
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400971
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400972 def test_get_components(self):
973 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900974 :py:meth:`X509Name.get_components` returns a :py:data:`list` of
975 two-tuples of :py:data:`str`
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400976 giving the NIDs and associated values which make up the name.
977 """
978 a = self._x509name()
979 self.assertEqual(a.get_components(), [])
980 a.CN = "foo"
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -0400981 self.assertEqual(a.get_components(), [(b("CN"), b("foo"))])
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400982 a.organizationalUnitName = "bar"
983 self.assertEqual(
984 a.get_components(),
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -0400985 [(b("CN"), b("foo")), (b("OU"), b("bar"))])
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400986
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400987 def test_load_nul_byte_attribute(self):
988 """
Jean-Paul Calderone9af07b02013-08-23 16:07:31 -0400989 An :py:class:`OpenSSL.crypto.X509Name` from an
990 :py:class:`OpenSSL.crypto.X509` instance loaded from a file can have a
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400991 NUL byte in the value of one of its attributes.
992 """
993 cert = load_certificate(FILETYPE_PEM, nulbyteSubjectAltNamePEM)
994 subject = cert.get_subject()
995 self.assertEqual(
Jean-Paul Calderone06754fc2013-08-23 15:47:47 -0400996 "null.python.org\x00example.org", subject.commonName)
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400997
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -0500998 def test_setAttributeFailure(self):
999 """
1000 If the value of an attribute cannot be set for some reason then
1001 :py:class:`OpenSSL.crypto.Error` is raised.
1002 """
1003 name = self._x509name()
1004 # This value is too long
1005 self.assertRaises(Error, setattr, name, "O", b"x" * 512)
1006
1007
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001008class _PKeyInteractionTestsMixin:
1009 """
1010 Tests which involve another thing and a PKey.
1011 """
Alex Gaynoraceb3e22015-09-05 12:00:22 -04001012
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001013 def signable(self):
1014 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001015 Return something with a :py:meth:`set_pubkey`, :py:meth:`set_pubkey`,
1016 and :py:meth:`sign` method.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001017 """
1018 raise NotImplementedError()
1019
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001020 def test_signWithUngenerated(self):
1021 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001022 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when pass a
1023 :py:class:`PKey` with no parts.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001024 """
1025 request = self.signable()
1026 key = PKey()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001027 self.assertRaises(ValueError, request.sign, key, GOOD_DIGEST)
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001028
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001029 def test_signWithPublicKey(self):
1030 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001031 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when pass a
1032 :py:class:`PKey` with no private part as the signing key.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001033 """
1034 request = self.signable()
1035 key = PKey()
1036 key.generate_key(TYPE_RSA, 512)
1037 request.set_pubkey(key)
1038 pub = request.get_pubkey()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001039 self.assertRaises(ValueError, request.sign, pub, GOOD_DIGEST)
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001040
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -04001041 def test_signWithUnknownDigest(self):
1042 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001043 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when passed a digest name which is
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -04001044 not known.
1045 """
1046 request = self.signable()
1047 key = PKey()
1048 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001049 self.assertRaises(ValueError, request.sign, key, BAD_DIGEST)
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -04001050
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04001051 def test_sign(self):
1052 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001053 :py:meth:`X509Req.sign` succeeds when passed a private key object and a valid
1054 digest function. :py:meth:`X509Req.verify` can be used to check the signature.
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04001055 """
1056 request = self.signable()
1057 key = PKey()
1058 key.generate_key(TYPE_RSA, 512)
1059 request.set_pubkey(key)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001060 request.sign(key, GOOD_DIGEST)
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04001061 # If the type has a verify method, cover that too.
1062 if getattr(request, 'verify', None) is not None:
1063 pub = request.get_pubkey()
1064 self.assertTrue(request.verify(pub))
1065 # Make another key that won't verify.
1066 key = PKey()
1067 key.generate_key(TYPE_RSA, 512)
1068 self.assertRaises(Error, request.verify, key)
1069
1070
Jean-Paul Calderone18808652009-07-05 12:54:05 -04001071class X509ReqTests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001072 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001073 Tests for :py:class:`OpenSSL.crypto.X509Req`.
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001074 """
Alex Gaynoraceb3e22015-09-05 12:00:22 -04001075
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001076 def signable(self):
1077 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001078 Create and return a new :py:class:`X509Req`.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001079 """
1080 return X509Req()
1081
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001082 def test_type(self):
1083 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001084 :py:obj:`X509Req` and :py:obj:`X509ReqType` refer to the same type object and can be
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001085 used to create instances of that type.
1086 """
1087 self.assertIdentical(X509Req, X509ReqType)
1088 self.assertConsistentType(X509Req, 'X509Req')
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001089
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001090 def test_construction(self):
1091 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001092 :py:obj:`X509Req` takes no arguments and returns an :py:obj:`X509ReqType` instance.
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001093 """
1094 request = X509Req()
1095 self.assertTrue(
1096 isinstance(request, X509ReqType),
1097 "%r is of type %r, should be %r" % (request, type(request), X509ReqType))
1098
Jean-Paul Calderone8dd19b82008-12-28 20:41:16 -05001099 def test_version(self):
1100 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001101 :py:obj:`X509ReqType.set_version` sets the X.509 version of the certificate
1102 request. :py:obj:`X509ReqType.get_version` returns the X.509 version of
Jean-Paul Calderone8dd19b82008-12-28 20:41:16 -05001103 the certificate request. The initial value of the version is 0.
1104 """
1105 request = X509Req()
1106 self.assertEqual(request.get_version(), 0)
1107 request.set_version(1)
1108 self.assertEqual(request.get_version(), 1)
1109 request.set_version(3)
1110 self.assertEqual(request.get_version(), 3)
1111
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001112 def test_version_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001113 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001114 :py:obj:`X509ReqType.set_version` raises :py:obj:`TypeError` if called with the wrong
1115 number of arguments or with a non-:py:obj:`int` argument.
1116 :py:obj:`X509ReqType.get_version` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001117 arguments.
1118 """
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001119 request = X509Req()
1120 self.assertRaises(TypeError, request.set_version)
1121 self.assertRaises(TypeError, request.set_version, "foo")
1122 self.assertRaises(TypeError, request.set_version, 1, 2)
1123 self.assertRaises(TypeError, request.get_version, None)
1124
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001125 def test_get_subject(self):
1126 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001127 :py:obj:`X509ReqType.get_subject` returns an :py:obj:`X509Name` for the subject of
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001128 the request and which is valid even after the request object is
1129 otherwise dead.
1130 """
1131 request = X509Req()
1132 subject = request.get_subject()
1133 self.assertTrue(
1134 isinstance(subject, X509NameType),
1135 "%r is of type %r, should be %r" % (subject, type(subject), X509NameType))
1136 subject.commonName = "foo"
1137 self.assertEqual(request.get_subject().commonName, "foo")
1138 del request
1139 subject.commonName = "bar"
1140 self.assertEqual(subject.commonName, "bar")
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001141
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001142 def test_get_subject_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001143 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001144 :py:obj:`X509ReqType.get_subject` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001145 arguments.
1146 """
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001147 request = X509Req()
1148 self.assertRaises(TypeError, request.get_subject, None)
1149
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001150 def test_add_extensions(self):
1151 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001152 :py:obj:`X509Req.add_extensions` accepts a :py:obj:`list` of :py:obj:`X509Extension`
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001153 instances and adds them to the X509 request.
1154 """
1155 request = X509Req()
1156 request.add_extensions([
Alex Gaynoraceb3e22015-09-05 12:00:22 -04001157 X509Extension(b('basicConstraints'), True, b('CA:false'))])
Stephen Holsappleca545b72014-01-28 21:43:25 -08001158 exts = request.get_extensions()
Stephen Holsapple7fbdf642014-03-01 20:05:47 -08001159 self.assertEqual(len(exts), 1)
1160 self.assertEqual(exts[0].get_short_name(), b('basicConstraints'))
1161 self.assertEqual(exts[0].get_critical(), 1)
1162 self.assertEqual(exts[0].get_data(), b('0\x00'))
1163
Stephen Holsapple7fbdf642014-03-01 20:05:47 -08001164 def test_get_extensions(self):
1165 """
1166 :py:obj:`X509Req.get_extensions` returns a :py:obj:`list` of
1167 extensions added to this X509 request.
1168 """
1169 request = X509Req()
1170 exts = request.get_extensions()
1171 self.assertEqual(exts, [])
1172 request.add_extensions([
Alex Gaynoraceb3e22015-09-05 12:00:22 -04001173 X509Extension(b('basicConstraints'), True, b('CA:true')),
1174 X509Extension(b('keyUsage'), False, b('digitalSignature'))])
Stephen Holsapple7fbdf642014-03-01 20:05:47 -08001175 exts = request.get_extensions()
1176 self.assertEqual(len(exts), 2)
1177 self.assertEqual(exts[0].get_short_name(), b('basicConstraints'))
1178 self.assertEqual(exts[0].get_critical(), 1)
1179 self.assertEqual(exts[0].get_data(), b('0\x03\x01\x01\xff'))
1180 self.assertEqual(exts[1].get_short_name(), b('keyUsage'))
1181 self.assertEqual(exts[1].get_critical(), 0)
1182 self.assertEqual(exts[1].get_data(), b('\x03\x02\x07\x80'))
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001183
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001184 def test_add_extensions_wrong_args(self):
1185 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001186 :py:obj:`X509Req.add_extensions` raises :py:obj:`TypeError` if called with the wrong
1187 number of arguments or with a non-:py:obj:`list`. Or it raises :py:obj:`ValueError`
1188 if called with a :py:obj:`list` containing objects other than :py:obj:`X509Extension`
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001189 instances.
1190 """
1191 request = X509Req()
1192 self.assertRaises(TypeError, request.add_extensions)
1193 self.assertRaises(TypeError, request.add_extensions, object())
1194 self.assertRaises(ValueError, request.add_extensions, [object()])
1195 self.assertRaises(TypeError, request.add_extensions, [], None)
1196
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001197 def test_verify_wrong_args(self):
1198 """
1199 :py:obj:`X509Req.verify` raises :py:obj:`TypeError` if called with zero
1200 arguments or more than one argument or if passed anything other than a
1201 :py:obj:`PKey` instance as its single argument.
1202 """
1203 request = X509Req()
1204 self.assertRaises(TypeError, request.verify)
1205 self.assertRaises(TypeError, request.verify, object())
1206 self.assertRaises(TypeError, request.verify, PKey(), object())
1207
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001208 def test_verify_uninitialized_key(self):
1209 """
1210 :py:obj:`X509Req.verify` raises :py:obj:`OpenSSL.crypto.Error` if called
1211 with a :py:obj:`OpenSSL.crypto.PKey` which contains no key data.
1212 """
1213 request = X509Req()
1214 pkey = PKey()
1215 self.assertRaises(Error, request.verify, pkey)
1216
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001217 def test_verify_wrong_key(self):
1218 """
1219 :py:obj:`X509Req.verify` raises :py:obj:`OpenSSL.crypto.Error` if called
1220 with a :py:obj:`OpenSSL.crypto.PKey` which does not represent the public
1221 part of the key which signed the request.
1222 """
1223 request = X509Req()
1224 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001225 request.sign(pkey, GOOD_DIGEST)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001226 another_pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
1227 self.assertRaises(Error, request.verify, another_pkey)
1228
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001229 def test_verify_success(self):
1230 """
1231 :py:obj:`X509Req.verify` returns :py:obj:`True` if called with a
Alex Gaynor3b0ee972014-11-15 09:17:33 -08001232 :py:obj:`OpenSSL.crypto.PKey` which represents the public part of the key
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001233 which signed the request.
1234 """
1235 request = X509Req()
1236 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001237 request.sign(pkey, GOOD_DIGEST)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001238 self.assertEqual(True, request.verify(pkey))
1239
1240
Jean-Paul Calderone18808652009-07-05 12:54:05 -04001241class X509Tests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001242 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001243 Tests for :py:obj:`OpenSSL.crypto.X509`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001244 """
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001245 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
Jean-Paul Calderone8114b452008-03-25 15:27:59 -04001246
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001247 extpem = """
1248-----BEGIN CERTIFICATE-----
1249MIIC3jCCAkegAwIBAgIJAJHFjlcCgnQzMA0GCSqGSIb3DQEBBQUAMEcxCzAJBgNV
1250BAYTAlNFMRUwEwYDVQQIEwxXZXN0ZXJib3R0b20xEjAQBgNVBAoTCUNhdGFsb2dp
1251eDENMAsGA1UEAxMEUm9vdDAeFw0wODA0MjIxNDQ1MzhaFw0wOTA0MjIxNDQ1Mzha
1252MFQxCzAJBgNVBAYTAlNFMQswCQYDVQQIEwJXQjEUMBIGA1UEChMLT3Blbk1ldGFk
1253aXIxIjAgBgNVBAMTGW5vZGUxLm9tMi5vcGVubWV0YWRpci5vcmcwgZ8wDQYJKoZI
1254hvcNAQEBBQADgY0AMIGJAoGBAPIcQMrwbk2nESF/0JKibj9i1x95XYAOwP+LarwT
1255Op4EQbdlI9SY+uqYqlERhF19w7CS+S6oyqx0DRZSk4Y9dZ9j9/xgm2u/f136YS1u
1256zgYFPvfUs6PqYLPSM8Bw+SjJ+7+2+TN+Tkiof9WP1cMjodQwOmdsiRbR0/J7+b1B
1257hec1AgMBAAGjgcQwgcEwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNT
1258TCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFIdHsBcMVVMbAO7j6NCj
125903HgLnHaMB8GA1UdIwQYMBaAFL2h9Bf9Mre4vTdOiHTGAt7BRY/8MEYGA1UdEQQ/
1260MD2CDSouZXhhbXBsZS5vcmeCESoub20yLmV4bWFwbGUuY29thwSC7wgKgRNvbTJA
1261b3Blbm1ldGFkaXIub3JnMA0GCSqGSIb3DQEBBQUAA4GBALd7WdXkp2KvZ7/PuWZA
1262MPlIxyjS+Ly11+BNE0xGQRp9Wz+2lABtpgNqssvU156+HkKd02rGheb2tj7MX9hG
1263uZzbwDAZzJPjzDQDD7d3cWsrVcfIdqVU7epHqIadnOF+X0ghJ39pAm6VVadnSXCt
1264WpOdIpB8KksUTCzV591Nr1wd
1265-----END CERTIFICATE-----
1266 """
Alex Gaynoraceb3e22015-09-05 12:00:22 -04001267
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001268 def signable(self):
1269 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001270 Create and return a new :py:obj:`X509`.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001271 """
1272 return X509()
1273
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001274 def test_type(self):
1275 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001276 :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 -04001277 to create instances of that type.
1278 """
1279 self.assertIdentical(X509, X509Type)
1280 self.assertConsistentType(X509, 'X509')
1281
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001282 def test_construction(self):
1283 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001284 :py:obj:`X509` takes no arguments and returns an instance of :py:obj:`X509Type`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001285 """
1286 certificate = X509()
1287 self.assertTrue(
1288 isinstance(certificate, X509Type),
1289 "%r is of type %r, should be %r" % (certificate,
1290 type(certificate),
1291 X509Type))
Rick Deane15b1472009-07-09 15:53:42 -05001292 self.assertEqual(type(X509Type).__name__, 'type')
1293 self.assertEqual(type(certificate).__name__, 'X509')
1294 self.assertEqual(type(certificate), X509Type)
Rick Dean04113e72009-07-16 12:06:35 -05001295 self.assertEqual(type(certificate), X509)
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001296
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001297 def test_get_version_wrong_args(self):
1298 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001299 :py:obj:`X509.get_version` raises :py:obj:`TypeError` if invoked with any arguments.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001300 """
1301 cert = X509()
1302 self.assertRaises(TypeError, cert.get_version, None)
1303
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001304 def test_set_version_wrong_args(self):
1305 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001306 :py:obj:`X509.set_version` raises :py:obj:`TypeError` if invoked with the wrong number
1307 of arguments or an argument not of type :py:obj:`int`.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001308 """
1309 cert = X509()
1310 self.assertRaises(TypeError, cert.set_version)
1311 self.assertRaises(TypeError, cert.set_version, None)
1312 self.assertRaises(TypeError, cert.set_version, 1, None)
1313
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001314 def test_version(self):
1315 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001316 :py:obj:`X509.set_version` sets the certificate version number.
1317 :py:obj:`X509.get_version` retrieves it.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001318 """
1319 cert = X509()
1320 cert.set_version(1234)
1321 self.assertEquals(cert.get_version(), 1234)
1322
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001323 def test_get_serial_number_wrong_args(self):
1324 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001325 :py:obj:`X509.get_serial_number` raises :py:obj:`TypeError` if invoked with any
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001326 arguments.
1327 """
1328 cert = X509()
1329 self.assertRaises(TypeError, cert.get_serial_number, None)
1330
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001331 def test_serial_number(self):
1332 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001333 The serial number of an :py:obj:`X509Type` can be retrieved and modified with
1334 :py:obj:`X509Type.get_serial_number` and :py:obj:`X509Type.set_serial_number`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001335 """
1336 certificate = X509()
1337 self.assertRaises(TypeError, certificate.set_serial_number)
1338 self.assertRaises(TypeError, certificate.set_serial_number, 1, 2)
1339 self.assertRaises(TypeError, certificate.set_serial_number, "1")
1340 self.assertRaises(TypeError, certificate.set_serial_number, 5.5)
1341 self.assertEqual(certificate.get_serial_number(), 0)
1342 certificate.set_serial_number(1)
1343 self.assertEqual(certificate.get_serial_number(), 1)
1344 certificate.set_serial_number(2 ** 32 + 1)
1345 self.assertEqual(certificate.get_serial_number(), 2 ** 32 + 1)
1346 certificate.set_serial_number(2 ** 64 + 1)
1347 self.assertEqual(certificate.get_serial_number(), 2 ** 64 + 1)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001348 certificate.set_serial_number(2 ** 128 + 1)
1349 self.assertEqual(certificate.get_serial_number(), 2 ** 128 + 1)
1350
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001351 def _setBoundTest(self, which):
1352 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001353 :py:obj:`X509Type.set_notBefore` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001354 GENERALIZEDTIME and sets the beginning of the certificate's validity
1355 period to it.
1356 """
1357 certificate = X509()
1358 set = getattr(certificate, 'set_not' + which)
1359 get = getattr(certificate, 'get_not' + which)
1360
Jean-Paul Calderonee0615b52008-03-09 21:44:46 -04001361 # Starts with no value.
1362 self.assertEqual(get(), None)
1363
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001364 # GMT (Or is it UTC?) -exarkun
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001365 when = b("20040203040506Z")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001366 set(when)
1367 self.assertEqual(get(), when)
1368
1369 # A plus two hours and thirty minutes offset
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001370 when = b("20040203040506+0530")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001371 set(when)
1372 self.assertEqual(get(), when)
1373
1374 # A minus one hour fifteen minutes offset
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001375 when = b("20040203040506-0115")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001376 set(when)
1377 self.assertEqual(get(), when)
1378
1379 # An invalid string results in a ValueError
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001380 self.assertRaises(ValueError, set, b("foo bar"))
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001381
Jean-Paul Calderone31ca2002010-01-30 15:14:43 -05001382 # The wrong number of arguments results in a TypeError.
1383 self.assertRaises(TypeError, set)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001384 self.assertRaises(TypeError, set, b("20040203040506Z"), b("20040203040506Z"))
1385 self.assertRaises(TypeError, get, b("foo bar"))
1386
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001387 # XXX ASN1_TIME (not GENERALIZEDTIME)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001388
1389 def test_set_notBefore(self):
1390 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001391 :py:obj:`X509Type.set_notBefore` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001392 GENERALIZEDTIME and sets the beginning of the certificate's validity
1393 period to it.
1394 """
1395 self._setBoundTest("Before")
1396
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001397 def test_set_notAfter(self):
1398 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001399 :py:obj:`X509Type.set_notAfter` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001400 GENERALIZEDTIME and sets the end of the certificate's validity period
1401 to it.
1402 """
1403 self._setBoundTest("After")
Jean-Paul Calderone76576d52008-03-24 16:04:46 -04001404
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001405 def test_get_notBefore(self):
1406 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001407 :py:obj:`X509Type.get_notBefore` returns a string in the format of an ASN1
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001408 GENERALIZEDTIME even for certificates which store it as UTCTIME
1409 internally.
1410 """
Jean-Paul Calderone8114b452008-03-25 15:27:59 -04001411 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001412 self.assertEqual(cert.get_notBefore(), b("20090325123658Z"))
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001413
Rick Dean38a05c82009-07-18 01:41:30 -05001414 def test_get_notAfter(self):
1415 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001416 :py:obj:`X509Type.get_notAfter` returns a string in the format of an ASN1
Rick Dean38a05c82009-07-18 01:41:30 -05001417 GENERALIZEDTIME even for certificates which store it as UTCTIME
1418 internally.
1419 """
1420 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001421 self.assertEqual(cert.get_notAfter(), b("20170611123658Z"))
Rick Dean38a05c82009-07-18 01:41:30 -05001422
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001423 def test_gmtime_adj_notBefore_wrong_args(self):
1424 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001425 :py:obj:`X509Type.gmtime_adj_notBefore` raises :py:obj:`TypeError` if called with the
1426 wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001427 """
1428 cert = X509()
1429 self.assertRaises(TypeError, cert.gmtime_adj_notBefore)
1430 self.assertRaises(TypeError, cert.gmtime_adj_notBefore, None)
1431 self.assertRaises(TypeError, cert.gmtime_adj_notBefore, 123, None)
1432
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001433 def test_gmtime_adj_notBefore(self):
1434 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001435 :py:obj:`X509Type.gmtime_adj_notBefore` changes the not-before timestamp to be
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001436 the current time plus the number of seconds passed in.
1437 """
1438 cert = load_certificate(FILETYPE_PEM, self.pemData)
Maximilian Hilsbed25c92015-07-25 12:58:07 +02001439 not_before_min = datetime.utcnow().replace(microsecond=0) + timedelta(seconds=100)
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001440 cert.gmtime_adj_notBefore(100)
Maximilian Hilsbed25c92015-07-25 12:58:07 +02001441 not_before = datetime.strptime(cert.get_notBefore().decode(), "%Y%m%d%H%M%SZ")
1442 not_before_max = datetime.utcnow() + timedelta(seconds=100)
1443 self.assertTrue(not_before_min <= not_before <= not_before_max)
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001444
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001445 def test_gmtime_adj_notAfter_wrong_args(self):
1446 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001447 :py:obj:`X509Type.gmtime_adj_notAfter` raises :py:obj:`TypeError` if called with the
1448 wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001449 """
1450 cert = X509()
1451 self.assertRaises(TypeError, cert.gmtime_adj_notAfter)
1452 self.assertRaises(TypeError, cert.gmtime_adj_notAfter, None)
1453 self.assertRaises(TypeError, cert.gmtime_adj_notAfter, 123, None)
1454
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001455 def test_gmtime_adj_notAfter(self):
1456 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001457 :py:obj:`X509Type.gmtime_adj_notAfter` changes the not-after timestamp to be
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001458 the current time plus the number of seconds passed in.
1459 """
1460 cert = load_certificate(FILETYPE_PEM, self.pemData)
Maximilian Hilsbed25c92015-07-25 12:58:07 +02001461 not_after_min = datetime.utcnow().replace(microsecond=0) + timedelta(seconds=100)
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001462 cert.gmtime_adj_notAfter(100)
Maximilian Hilsbed25c92015-07-25 12:58:07 +02001463 not_after = datetime.strptime(cert.get_notAfter().decode(), "%Y%m%d%H%M%SZ")
1464 not_after_max = datetime.utcnow() + timedelta(seconds=100)
1465 self.assertTrue(not_after_min <= not_after <= not_after_max)
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001466
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001467 def test_has_expired_wrong_args(self):
1468 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001469 :py:obj:`X509Type.has_expired` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001470 arguments.
1471 """
1472 cert = X509()
1473 self.assertRaises(TypeError, cert.has_expired, None)
1474
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001475 def test_has_expired(self):
1476 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001477 :py:obj:`X509Type.has_expired` returns :py:obj:`True` if the certificate's not-after
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001478 time is in the past.
1479 """
1480 cert = X509()
1481 cert.gmtime_adj_notAfter(-1)
1482 self.assertTrue(cert.has_expired())
1483
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001484 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
Jeff Tangfc18f7b2015-04-15 17:42:33 -04001493 def test_root_has_not_expired(self):
1494 """
1495 :py:obj:`X509Type.has_expired` returns :py:obj:`False` if the certificate's not-after
1496 time is in the future.
1497 """
1498 cert = load_certificate(FILETYPE_PEM, root_cert_pem)
1499 self.assertFalse(cert.has_expired())
1500
Rick Dean38a05c82009-07-18 01:41:30 -05001501 def test_digest(self):
1502 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001503 :py:obj:`X509.digest` returns a string giving ":"-separated hex-encoded words
Rick Dean38a05c82009-07-18 01:41:30 -05001504 of the digest of the certificate.
1505 """
Jeff Tangfc18f7b2015-04-15 17:42:33 -04001506 cert = load_certificate(FILETYPE_PEM, root_cert_pem)
Rick Dean38a05c82009-07-18 01:41:30 -05001507 self.assertEqual(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001508 # This is MD5 instead of GOOD_DIGEST because the digest algorithm
1509 # actually matters to the assertion (ie, another arbitrary, good
1510 # digest will not product the same digest).
Jeff Tangfc18f7b2015-04-15 17:42:33 -04001511 # Digest verified with the command:
1512 # openssl x509 -in root_cert.pem -noout -fingerprint -md5
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001513 cert.digest("MD5"),
Jeff Tangfc18f7b2015-04-15 17:42:33 -04001514 b("19:B3:05:26:2B:F8:F2:FF:0B:8F:21:07:A8:28:B8:75"))
Rick Dean38a05c82009-07-18 01:41:30 -05001515
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001516 def _extcert(self, pkey, extensions):
1517 cert = X509()
1518 cert.set_pubkey(pkey)
1519 cert.get_subject().commonName = "Unit Tests"
1520 cert.get_issuer().commonName = "Unit Tests"
1521 when = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
1522 cert.set_notBefore(when)
1523 cert.set_notAfter(when)
1524
1525 cert.add_extensions(extensions)
Jeff Tangfc18f7b2015-04-15 17:42:33 -04001526 cert.sign(pkey, 'sha1')
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001527 return load_certificate(
1528 FILETYPE_PEM, dump_certificate(FILETYPE_PEM, cert))
1529
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001530 def test_extension_count(self):
1531 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001532 :py:obj:`X509.get_extension_count` returns the number of extensions that are
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001533 present in the certificate.
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001534 """
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001535 pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001536 ca = X509Extension(b('basicConstraints'), True, b('CA:FALSE'))
1537 key = X509Extension(b('keyUsage'), True, b('digitalSignature'))
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001538 subjectAltName = X509Extension(
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001539 b('subjectAltName'), True, b('DNS:example.com'))
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001540
1541 # Try a certificate with no extensions at all.
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001542 c = self._extcert(pkey, [])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001543 self.assertEqual(c.get_extension_count(), 0)
1544
1545 # And a certificate with one
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001546 c = self._extcert(pkey, [ca])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001547 self.assertEqual(c.get_extension_count(), 1)
1548
1549 # And a certificate with several
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001550 c = self._extcert(pkey, [ca, key, subjectAltName])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001551 self.assertEqual(c.get_extension_count(), 3)
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001552
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001553 def test_get_extension(self):
1554 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001555 :py:obj:`X509.get_extension` takes an integer and returns an :py:obj:`X509Extension`
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001556 corresponding to the extension at that index.
1557 """
1558 pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001559 ca = X509Extension(b('basicConstraints'), True, b('CA:FALSE'))
1560 key = X509Extension(b('keyUsage'), True, b('digitalSignature'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001561 subjectAltName = X509Extension(
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001562 b('subjectAltName'), False, b('DNS:example.com'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001563
1564 cert = self._extcert(pkey, [ca, key, subjectAltName])
1565
1566 ext = cert.get_extension(0)
1567 self.assertTrue(isinstance(ext, X509Extension))
1568 self.assertTrue(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001569 self.assertEqual(ext.get_short_name(), b('basicConstraints'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001570
1571 ext = cert.get_extension(1)
1572 self.assertTrue(isinstance(ext, X509Extension))
1573 self.assertTrue(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001574 self.assertEqual(ext.get_short_name(), b('keyUsage'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001575
1576 ext = cert.get_extension(2)
1577 self.assertTrue(isinstance(ext, X509Extension))
1578 self.assertFalse(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001579 self.assertEqual(ext.get_short_name(), b('subjectAltName'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001580
1581 self.assertRaises(IndexError, cert.get_extension, -1)
1582 self.assertRaises(IndexError, cert.get_extension, 4)
1583 self.assertRaises(TypeError, cert.get_extension, "hello")
1584
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001585 def test_nullbyte_subjectAltName(self):
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001586 """
Jean-Paul Calderone9af07b02013-08-23 16:07:31 -04001587 The fields of a `subjectAltName` extension on an X509 may contain NUL
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001588 bytes and this value is reflected in the string representation of the
1589 extension object.
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001590 """
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001591 cert = load_certificate(FILETYPE_PEM, nulbyteSubjectAltNamePEM)
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001592
1593 ext = cert.get_extension(3)
1594 self.assertEqual(ext.get_short_name(), b('subjectAltName'))
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001595 self.assertEqual(
1596 b("DNS:altnull.python.org\x00example.com, "
1597 "email:null@python.org\x00user@example.org, "
1598 "URI:http://null.python.org\x00http://example.org, "
1599 "IP Address:192.0.2.1, IP Address:2001:DB8:0:0:0:0:0:1\n"),
1600 b(str(ext)))
1601
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001602 def test_invalid_digest_algorithm(self):
1603 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001604 :py:obj:`X509.digest` raises :py:obj:`ValueError` if called with an unrecognized hash
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001605 algorithm.
1606 """
1607 cert = X509()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001608 self.assertRaises(ValueError, cert.digest, BAD_DIGEST)
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001609
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001610 def test_get_subject_wrong_args(self):
1611 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001612 :py:obj:`X509.get_subject` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001613 """
1614 cert = X509()
1615 self.assertRaises(TypeError, cert.get_subject, None)
1616
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001617 def test_get_subject(self):
1618 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001619 :py:obj:`X509.get_subject` returns an :py:obj:`X509Name` instance.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001620 """
1621 cert = load_certificate(FILETYPE_PEM, self.pemData)
1622 subj = cert.get_subject()
1623 self.assertTrue(isinstance(subj, X509Name))
1624 self.assertEquals(
1625 subj.get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001626 [(b('C'), b('US')), (b('ST'), b('IL')), (b('L'), b('Chicago')),
1627 (b('O'), b('Testing')), (b('CN'), b('Testing Root CA'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001628
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001629 def test_set_subject_wrong_args(self):
1630 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001631 :py:obj:`X509.set_subject` raises a :py:obj:`TypeError` if called with the wrong
1632 number of arguments or an argument not of type :py:obj:`X509Name`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001633 """
1634 cert = X509()
1635 self.assertRaises(TypeError, cert.set_subject)
1636 self.assertRaises(TypeError, cert.set_subject, None)
1637 self.assertRaises(TypeError, cert.set_subject, cert.get_subject(), None)
1638
1639
1640 def test_set_subject(self):
1641 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001642 :py:obj:`X509.set_subject` changes the subject of the certificate to the one
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001643 passed in.
1644 """
1645 cert = X509()
1646 name = cert.get_subject()
1647 name.C = 'AU'
1648 name.O = 'Unit Tests'
1649 cert.set_subject(name)
1650 self.assertEquals(
1651 cert.get_subject().get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001652 [(b('C'), b('AU')), (b('O'), b('Unit Tests'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001653
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001654 def test_get_issuer_wrong_args(self):
1655 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001656 :py:obj:`X509.get_issuer` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001657 """
1658 cert = X509()
1659 self.assertRaises(TypeError, cert.get_issuer, None)
1660
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001661 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
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001674 def test_set_issuer_wrong_args(self):
1675 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001676 :py:obj:`X509.set_issuer` raises a :py:obj:`TypeError` if called with the wrong
1677 number of arguments or an argument not of type :py:obj:`X509Name`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001678 """
1679 cert = X509()
1680 self.assertRaises(TypeError, cert.set_issuer)
1681 self.assertRaises(TypeError, cert.set_issuer, None)
1682 self.assertRaises(TypeError, cert.set_issuer, cert.get_issuer(), None)
1683
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001684 def test_set_issuer(self):
1685 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001686 :py:obj:`X509.set_issuer` changes the issuer of the certificate to the one
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001687 passed in.
1688 """
1689 cert = X509()
1690 name = cert.get_issuer()
1691 name.C = 'AU'
1692 name.O = 'Unit Tests'
1693 cert.set_issuer(name)
1694 self.assertEquals(
1695 cert.get_issuer().get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001696 [(b('C'), b('AU')), (b('O'), b('Unit Tests'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001697
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001698 def test_get_pubkey_uninitialized(self):
1699 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001700 When called on a certificate with no public key, :py:obj:`X509.get_pubkey`
1701 raises :py:obj:`OpenSSL.crypto.Error`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001702 """
1703 cert = X509()
1704 self.assertRaises(Error, cert.get_pubkey)
1705
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001706 def test_subject_name_hash_wrong_args(self):
1707 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001708 :py:obj:`X509.subject_name_hash` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001709 arguments.
1710 """
1711 cert = X509()
1712 self.assertRaises(TypeError, cert.subject_name_hash, None)
1713
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001714 def test_subject_name_hash(self):
1715 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001716 :py:obj:`X509.subject_name_hash` returns the hash of the certificate's subject
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001717 name.
1718 """
1719 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -04001720 self.assertIn(
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001721 cert.subject_name_hash(),
Alex Gaynoraceb3e22015-09-05 12:00:22 -04001722 [3350047874, # OpenSSL 0.9.8, MD5
1723 3278919224, # OpenSSL 1.0.0, SHA1
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -04001724 ])
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001725
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001726 def test_get_signature_algorithm(self):
1727 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001728 :py:obj:`X509Type.get_signature_algorithm` returns a string which means
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001729 the algorithm used to sign the certificate.
1730 """
1731 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001732 self.assertEqual(
1733 b("sha1WithRSAEncryption"), cert.get_signature_algorithm())
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001734
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001735 def test_get_undefined_signature_algorithm(self):
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001736 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001737 :py:obj:`X509Type.get_signature_algorithm` raises :py:obj:`ValueError` if the
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001738 signature algorithm is undefined or unknown.
1739 """
1740 # This certificate has been modified to indicate a bogus OID in the
1741 # signature algorithm field so that OpenSSL does not recognize it.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001742 certPEM = b("""\
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001743-----BEGIN CERTIFICATE-----
1744MIIC/zCCAmigAwIBAgIBATAGBgJ8BQUAMHsxCzAJBgNVBAYTAlNHMREwDwYDVQQK
1745EwhNMkNyeXB0bzEUMBIGA1UECxMLTTJDcnlwdG8gQ0ExJDAiBgNVBAMTG00yQ3J5
1746cHRvIENlcnRpZmljYXRlIE1hc3RlcjEdMBsGCSqGSIb3DQEJARYObmdwc0Bwb3N0
1747MS5jb20wHhcNMDAwOTEwMDk1MTMwWhcNMDIwOTEwMDk1MTMwWjBTMQswCQYDVQQG
1748EwJTRzERMA8GA1UEChMITTJDcnlwdG8xEjAQBgNVBAMTCWxvY2FsaG9zdDEdMBsG
1749CSqGSIb3DQEJARYObmdwc0Bwb3N0MS5jb20wXDANBgkqhkiG9w0BAQEFAANLADBI
1750AkEArL57d26W9fNXvOhNlZzlPOACmvwOZ5AdNgLzJ1/MfsQQJ7hHVeHmTAjM664V
1751+fXvwUGJLziCeBo1ysWLRnl8CQIDAQABo4IBBDCCAQAwCQYDVR0TBAIwADAsBglg
1752hkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0O
1753BBYEFM+EgpK+eyZiwFU1aOPSbczbPSpVMIGlBgNVHSMEgZ0wgZqAFPuHI2nrnDqT
1754FeXFvylRT/7tKDgBoX+kfTB7MQswCQYDVQQGEwJTRzERMA8GA1UEChMITTJDcnlw
1755dG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtNMkNyeXB0byBDZXJ0
1756aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tggEA
1757MA0GCSqGSIb3DQEBBAUAA4GBADv8KpPo+gfJxN2ERK1Y1l17sz/ZhzoGgm5XCdbx
1758jEY7xKfpQngV599k1xhl11IMqizDwu0855agrckg2MCTmOI9DZzDD77tAYb+Dk0O
1759PEVk0Mk/V0aIsDE9bolfCi/i/QWZ3N8s5nTWMNyBBBmoSliWCm4jkkRZRD0ejgTN
1760tgI5
1761-----END CERTIFICATE-----
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001762""")
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001763 cert = load_certificate(FILETYPE_PEM, certPEM)
1764 self.assertRaises(ValueError, cert.get_signature_algorithm)
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001765
1766
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001767class X509StoreTests(TestCase):
1768 """
1769 Test for :py:obj:`OpenSSL.crypto.X509Store`.
1770 """
Alex Gaynoraceb3e22015-09-05 12:00:22 -04001771
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001772 def test_type(self):
1773 """
1774 :py:obj:`X509StoreType` is a type object.
1775 """
1776 self.assertIdentical(X509Store, X509StoreType)
1777 self.assertConsistentType(X509Store, 'X509Store')
1778
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001779 def test_add_cert_wrong_args(self):
1780 store = X509Store()
1781 self.assertRaises(TypeError, store.add_cert)
1782 self.assertRaises(TypeError, store.add_cert, object())
1783 self.assertRaises(TypeError, store.add_cert, X509(), object())
1784
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001785 def test_add_cert(self):
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001786 """
1787 :py:obj:`X509Store.add_cert` adds a :py:obj:`X509` instance to the
1788 certificate store.
1789 """
1790 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001791 store = X509Store()
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001792 store.add_cert(cert)
1793
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001794 def test_add_cert_rejects_duplicate(self):
1795 """
1796 :py:obj:`X509Store.add_cert` raises :py:obj:`OpenSSL.crypto.Error` if an
1797 attempt is made to add the same certificate to the store more than once.
1798 """
1799 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
1800 store = X509Store()
1801 store.add_cert(cert)
1802 self.assertRaises(Error, store.add_cert, cert)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001803
1804
Rick Dean623ee362009-07-17 12:22:16 -05001805class PKCS12Tests(TestCase):
1806 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001807 Test for :py:obj:`OpenSSL.crypto.PKCS12` and :py:obj:`OpenSSL.crypto.load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001808 """
1809 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
1810
Jean-Paul Calderonec3a41f72009-07-25 12:36:02 -04001811 def test_type(self):
1812 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001813 :py:obj:`PKCS12Type` is a type object.
Jean-Paul Calderonec3a41f72009-07-25 12:36:02 -04001814 """
1815 self.assertIdentical(PKCS12, PKCS12Type)
1816 self.assertConsistentType(PKCS12, 'PKCS12')
1817
Rick Deanf94096c2009-07-18 14:23:06 -05001818 def test_empty_construction(self):
Rick Dean38a05c82009-07-18 01:41:30 -05001819 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001820 :py:obj:`PKCS12` returns a new instance of :py:obj:`PKCS12` with no certificate,
Jean-Paul Calderonedc857b52009-07-25 12:25:07 -04001821 private key, CA certificates, or friendly name.
Rick Dean38a05c82009-07-18 01:41:30 -05001822 """
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001823 p12 = PKCS12()
Rick Dean623ee362009-07-17 12:22:16 -05001824 self.assertEqual(None, p12.get_certificate())
1825 self.assertEqual(None, p12.get_privatekey())
1826 self.assertEqual(None, p12.get_ca_certificates())
Rick Dean42d69e12009-07-20 11:36:08 -05001827 self.assertEqual(None, p12.get_friendlyname())
Rick Dean623ee362009-07-17 12:22:16 -05001828
1829 def test_type_errors(self):
Rick Dean38a05c82009-07-18 01:41:30 -05001830 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001831 The :py:obj:`PKCS12` setter functions (:py:obj:`set_certificate`, :py:obj:`set_privatekey`,
1832 :py:obj:`set_ca_certificates`, and :py:obj:`set_friendlyname`) raise :py:obj:`TypeError`
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001833 when passed objects of types other than those expected.
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.assertRaises(TypeError, p12.set_certificate, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05001837 self.assertRaises(TypeError, p12.set_certificate, PKey())
1838 self.assertRaises(TypeError, p12.set_certificate, X509)
Rick Dean623ee362009-07-17 12:22:16 -05001839 self.assertRaises(TypeError, p12.set_privatekey, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05001840 self.assertRaises(TypeError, p12.set_privatekey, 'legbone')
1841 self.assertRaises(TypeError, p12.set_privatekey, X509())
Rick Dean623ee362009-07-17 12:22:16 -05001842 self.assertRaises(TypeError, p12.set_ca_certificates, 3)
1843 self.assertRaises(TypeError, p12.set_ca_certificates, X509())
1844 self.assertRaises(TypeError, p12.set_ca_certificates, (3, 4))
Alex Gaynor7f636492015-09-04 13:26:52 -04001845 self.assertRaises(TypeError, p12.set_ca_certificates, (PKey(),))
Rick Dean42d69e12009-07-20 11:36:08 -05001846 self.assertRaises(TypeError, p12.set_friendlyname, 6)
1847 self.assertRaises(TypeError, p12.set_friendlyname, ('foo', 'bar'))
Rick Dean623ee362009-07-17 12:22:16 -05001848
1849 def test_key_only(self):
1850 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001851 A :py:obj:`PKCS12` with only a private key can be exported using
1852 :py:obj:`PKCS12.export` and loaded again using :py:obj:`load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001853 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001854 passwd = b"blah"
Rick Dean623ee362009-07-17 12:22:16 -05001855 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001856 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001857 p12.set_privatekey(pkey)
Rick Dean623ee362009-07-17 12:22:16 -05001858 self.assertEqual(None, p12.get_certificate())
1859 self.assertEqual(pkey, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05001860 try:
1861 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
1862 except Error:
1863 # Some versions of OpenSSL will throw an exception
1864 # for this nearly useless PKCS12 we tried to generate:
1865 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
1866 return
Rick Dean623ee362009-07-17 12:22:16 -05001867 p12 = load_pkcs12(dumped_p12, passwd)
1868 self.assertEqual(None, p12.get_ca_certificates())
1869 self.assertEqual(None, p12.get_certificate())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001870
1871 # OpenSSL fails to bring the key back to us. So sad. Perhaps in the
1872 # future this will be improved.
1873 self.assertTrue(isinstance(p12.get_privatekey(), (PKey, type(None))))
Rick Dean623ee362009-07-17 12:22:16 -05001874
1875 def test_cert_only(self):
1876 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001877 A :py:obj:`PKCS12` with only a certificate can be exported using
1878 :py:obj:`PKCS12.export` and loaded again using :py:obj:`load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001879 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001880 passwd = b"blah"
Rick Dean623ee362009-07-17 12:22:16 -05001881 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001882 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001883 p12.set_certificate(cert)
Rick Dean623ee362009-07-17 12:22:16 -05001884 self.assertEqual(cert, p12.get_certificate())
1885 self.assertEqual(None, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05001886 try:
1887 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
1888 except Error:
1889 # Some versions of OpenSSL will throw an exception
1890 # for this nearly useless PKCS12 we tried to generate:
1891 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
1892 return
Rick Dean623ee362009-07-17 12:22:16 -05001893 p12 = load_pkcs12(dumped_p12, passwd)
1894 self.assertEqual(None, p12.get_privatekey())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001895
1896 # OpenSSL fails to bring the cert back to us. Groany mcgroan.
1897 self.assertTrue(isinstance(p12.get_certificate(), (X509, type(None))))
1898
1899 # Oh ho. It puts the certificate into the ca certificates list, in
1900 # fact. Totally bogus, I would think. Nevertheless, let's exploit
1901 # that to check to see if it reconstructed the certificate we expected
1902 # it to. At some point, hopefully this will change so that
1903 # p12.get_certificate() is actually what returns the loaded
1904 # certificate.
1905 self.assertEqual(
1906 cleartextCertificatePEM,
1907 dump_certificate(FILETYPE_PEM, p12.get_ca_certificates()[0]))
Rick Dean623ee362009-07-17 12:22:16 -05001908
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001909 def gen_pkcs12(self, cert_pem=None, key_pem=None, ca_pem=None, friendly_name=None):
Rick Dean623ee362009-07-17 12:22:16 -05001910 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001911 Generate a PKCS12 object with components from PEM. Verify that the set
1912 functions return None.
Rick Dean623ee362009-07-17 12:22:16 -05001913 """
Rick Deanf94096c2009-07-18 14:23:06 -05001914 p12 = PKCS12()
1915 if cert_pem:
1916 ret = p12.set_certificate(load_certificate(FILETYPE_PEM, cert_pem))
1917 self.assertEqual(ret, None)
1918 if key_pem:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001919 ret = p12.set_privatekey(load_privatekey(FILETYPE_PEM, key_pem))
Rick Deanf94096c2009-07-18 14:23:06 -05001920 self.assertEqual(ret, None)
1921 if ca_pem:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001922 ret = p12.set_ca_certificates((load_certificate(FILETYPE_PEM, ca_pem),))
Rick Deanf94096c2009-07-18 14:23:06 -05001923 self.assertEqual(ret, None)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001924 if friendly_name:
1925 ret = p12.set_friendlyname(friendly_name)
Rick Dean42d69e12009-07-20 11:36:08 -05001926 self.assertEqual(ret, None)
Rick Deanf94096c2009-07-18 14:23:06 -05001927 return p12
1928
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001929 def check_recovery(self, p12_str, key=None, cert=None, ca=None, passwd=b"",
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001930 extra=()):
Rick Deanf94096c2009-07-18 14:23:06 -05001931 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001932 Use openssl program to confirm three components are recoverable from a
1933 PKCS12 string.
Rick Deanf94096c2009-07-18 14:23:06 -05001934 """
1935 if key:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001936 recovered_key = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001937 p12_str, b"pkcs12", b"-nocerts", b"-nodes", b"-passin",
1938 b"pass:" + passwd, *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001939 self.assertEqual(recovered_key[-len(key):], key)
1940 if cert:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001941 recovered_cert = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001942 p12_str, b"pkcs12", b"-clcerts", b"-nodes", b"-passin",
1943 b"pass:" + passwd, b"-nokeys", *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001944 self.assertEqual(recovered_cert[-len(cert):], cert)
1945 if ca:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001946 recovered_cert = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001947 p12_str, b"pkcs12", b"-cacerts", b"-nodes", b"-passin",
1948 b"pass:" + passwd, b"-nokeys", *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001949 self.assertEqual(recovered_cert[-len(ca):], ca)
1950
Stephen Holsapple38482622014-04-05 20:29:34 -07001951 def verify_pkcs12_container(self, p12):
1952 """
1953 Verify that the PKCS#12 container contains the correct client
1954 certificate and private key.
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04001955
1956 :param p12: The PKCS12 instance to verify.
1957 :type p12: :py:class:`PKCS12`
Stephen Holsapple38482622014-04-05 20:29:34 -07001958 """
1959 cert_pem = dump_certificate(FILETYPE_PEM, p12.get_certificate())
1960 key_pem = dump_privatekey(FILETYPE_PEM, p12.get_privatekey())
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04001961 self.assertEqual(
1962 (client_cert_pem, client_key_pem, None),
1963 (cert_pem, key_pem, p12.get_ca_certificates()))
Stephen Holsapple38482622014-04-05 20:29:34 -07001964
Rick Deanf94096c2009-07-18 14:23:06 -05001965 def test_load_pkcs12(self):
1966 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001967 A PKCS12 string generated using the openssl command line can be loaded
Jonathan Ballet648875f2011-07-16 14:14:58 +09001968 with :py:obj:`load_pkcs12` and its components extracted and examined.
Rick Deanf94096c2009-07-18 14:23:06 -05001969 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001970 passwd = b"whatever"
Rick Dean623ee362009-07-17 12:22:16 -05001971 pem = client_key_pem + client_cert_pem
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001972 p12_str = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001973 pem, b"pkcs12", b"-export", b"-clcerts", b"-passout", b"pass:" + passwd)
Stephen Holsapple38482622014-04-05 20:29:34 -07001974 p12 = load_pkcs12(p12_str, passphrase=passwd)
1975 self.verify_pkcs12_container(p12)
1976
Abraham Martinc5484ba2015-03-25 15:33:05 +00001977 def test_load_pkcs12_text_passphrase(self):
1978 """
1979 A PKCS12 string generated using the openssl command line can be loaded
1980 with :py:obj:`load_pkcs12` and its components extracted and examined.
1981 Using text as passphrase instead of bytes. DeprecationWarning expected.
1982 """
1983 pem = client_key_pem + client_cert_pem
1984 passwd = b"whatever"
1985 p12_str = _runopenssl(pem, b"pkcs12", b"-export", b"-clcerts",
1986 b"-passout", b"pass:" + passwd)
1987 with catch_warnings(record=True) as w:
1988 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04001989 p12 = load_pkcs12(p12_str, passphrase=b"whatever".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04001990
1991 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04001992 "{0} for passphrase is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04001993 WARNING_TYPE_EXPECTED
1994 ),
1995 str(w[-1].message)
1996 )
1997 self.assertIs(w[-1].category, DeprecationWarning)
1998
Abraham Martinc5484ba2015-03-25 15:33:05 +00001999 self.verify_pkcs12_container(p12)
2000
Stephen Holsapple38482622014-04-05 20:29:34 -07002001 def test_load_pkcs12_no_passphrase(self):
2002 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002003 A PKCS12 string generated using openssl command line can be loaded with
2004 :py:obj:`load_pkcs12` without a passphrase and its components extracted
2005 and examined.
Stephen Holsapple38482622014-04-05 20:29:34 -07002006 """
2007 pem = client_key_pem + client_cert_pem
2008 p12_str = _runopenssl(
2009 pem, b"pkcs12", b"-export", b"-clcerts", b"-passout", b"pass:")
2010 p12 = load_pkcs12(p12_str)
2011 self.verify_pkcs12_container(p12)
2012
Stephen Holsapple38482622014-04-05 20:29:34 -07002013 def _dump_and_load(self, dump_passphrase, load_passphrase):
2014 """
2015 A helper method to dump and load a PKCS12 object.
2016 """
2017 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem)
2018 dumped_p12 = p12.export(passphrase=dump_passphrase, iter=2, maciter=3)
2019 return load_pkcs12(dumped_p12, passphrase=load_passphrase)
2020
Stephen Holsapple38482622014-04-05 20:29:34 -07002021 def test_load_pkcs12_null_passphrase_load_empty(self):
2022 """
2023 A PKCS12 string can be dumped with a null passphrase, loaded with an
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002024 empty passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002025 extracted and examined.
2026 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002027 self.verify_pkcs12_container(
2028 self._dump_and_load(dump_passphrase=None, load_passphrase=b''))
Stephen Holsapple38482622014-04-05 20:29:34 -07002029
Stephen Holsapple38482622014-04-05 20:29:34 -07002030 def test_load_pkcs12_null_passphrase_load_null(self):
2031 """
2032 A PKCS12 string can be dumped with a null passphrase, loaded with a
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002033 null passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002034 extracted and examined.
2035 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002036 self.verify_pkcs12_container(
2037 self._dump_and_load(dump_passphrase=None, load_passphrase=None))
Stephen Holsapple38482622014-04-05 20:29:34 -07002038
Stephen Holsapple38482622014-04-05 20:29:34 -07002039 def test_load_pkcs12_empty_passphrase_load_empty(self):
2040 """
2041 A PKCS12 string can be dumped with an empty passphrase, loaded with an
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002042 empty passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002043 extracted and examined.
2044 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002045 self.verify_pkcs12_container(
2046 self._dump_and_load(dump_passphrase=b'', load_passphrase=b''))
Stephen Holsapple38482622014-04-05 20:29:34 -07002047
Stephen Holsapple38482622014-04-05 20:29:34 -07002048 def test_load_pkcs12_empty_passphrase_load_null(self):
2049 """
2050 A PKCS12 string can be dumped with an empty passphrase, loaded with a
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002051 null passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002052 extracted and examined.
2053 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002054 self.verify_pkcs12_container(
2055 self._dump_and_load(dump_passphrase=b'', load_passphrase=None))
Rick Deanf94096c2009-07-18 14:23:06 -05002056
Rick Deanee568302009-07-24 09:56:29 -05002057 def test_load_pkcs12_garbage(self):
2058 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002059 :py:obj:`load_pkcs12` raises :py:obj:`OpenSSL.crypto.Error` when passed a string
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002060 which is not a PKCS12 dump.
Rick Deanee568302009-07-24 09:56:29 -05002061 """
2062 passwd = 'whatever'
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002063 e = self.assertRaises(Error, load_pkcs12, b'fruit loops', passwd)
Alex Gaynor7f636492015-09-04 13:26:52 -04002064 self.assertEqual(e.args[0][0][0], 'asn1 encoding routines')
2065 self.assertEqual(len(e.args[0][0]), 3)
Rick Deanee568302009-07-24 09:56:29 -05002066
Rick Deanf94096c2009-07-18 14:23:06 -05002067 def test_replace(self):
2068 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002069 :py:obj:`PKCS12.set_certificate` replaces the certificate in a PKCS12 cluster.
2070 :py:obj:`PKCS12.set_privatekey` replaces the private key.
2071 :py:obj:`PKCS12.set_ca_certificates` replaces the CA certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05002072 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002073 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
2074 p12.set_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2075 p12.set_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002076 root_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05002077 client_cert = load_certificate(FILETYPE_PEM, client_cert_pem)
Alex Gaynoraceb3e22015-09-05 12:00:22 -04002078 p12.set_ca_certificates([root_cert]) # not a tuple
Rick Dean623ee362009-07-17 12:22:16 -05002079 self.assertEqual(1, len(p12.get_ca_certificates()))
2080 self.assertEqual(root_cert, p12.get_ca_certificates()[0])
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002081 p12.set_ca_certificates([client_cert, root_cert])
Rick Deanf94096c2009-07-18 14:23:06 -05002082 self.assertEqual(2, len(p12.get_ca_certificates()))
2083 self.assertEqual(client_cert, p12.get_ca_certificates()[0])
2084 self.assertEqual(root_cert, p12.get_ca_certificates()[1])
2085
Rick Deanf94096c2009-07-18 14:23:06 -05002086 def test_friendly_name(self):
2087 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002088 The *friendlyName* of a PKCS12 can be set and retrieved via
Jonathan Ballet648875f2011-07-16 14:14:58 +09002089 :py:obj:`PKCS12.get_friendlyname` and :py:obj:`PKCS12_set_friendlyname`, and a
2090 :py:obj:`PKCS12` with a friendly name set can be dumped with :py:obj:`PKCS12.export`.
Rick Deanf94096c2009-07-18 14:23:06 -05002091 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002092 passwd = b'Dogmeat[]{}!@#$%^&*()~`?/.,<>-_+=";:'
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002093 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -04002094 for friendly_name in [b('Serverlicious'), None, b('###')]:
Rick Dean42d69e12009-07-20 11:36:08 -05002095 p12.set_friendlyname(friendly_name)
2096 self.assertEqual(p12.get_friendlyname(), friendly_name)
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002097 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
Rick Dean42d69e12009-07-20 11:36:08 -05002098 reloaded_p12 = load_pkcs12(dumped_p12, passwd)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002099 self.assertEqual(
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -04002100 p12.get_friendlyname(), reloaded_p12.get_friendlyname())
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002101 # We would use the openssl program to confirm the friendly
2102 # name, but it is not possible. The pkcs12 command
2103 # does not store the friendly name in the cert's
Rick Dean42d69e12009-07-20 11:36:08 -05002104 # alias, which we could then extract.
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002105 self.check_recovery(
2106 dumped_p12, key=server_key_pem, cert=server_cert_pem,
2107 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05002108
Rick Deanf94096c2009-07-18 14:23:06 -05002109 def test_various_empty_passphrases(self):
2110 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002111 Test that missing, None, and '' passphrases are identical for PKCS12
2112 export.
Rick Deanf94096c2009-07-18 14:23:06 -05002113 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002114 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002115 passwd = b""
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002116 dumped_p12_empty = p12.export(iter=2, maciter=0, passphrase=passwd)
2117 dumped_p12_none = p12.export(iter=3, maciter=2, passphrase=None)
2118 dumped_p12_nopw = p12.export(iter=9, maciter=4)
2119 for dumped_p12 in [dumped_p12_empty, dumped_p12_none, dumped_p12_nopw]:
2120 self.check_recovery(
2121 dumped_p12, key=client_key_pem, cert=client_cert_pem,
2122 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05002123
Rick Deanf94096c2009-07-18 14:23:06 -05002124 def test_removing_ca_cert(self):
2125 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002126 Passing :py:obj:`None` to :py:obj:`PKCS12.set_ca_certificates` removes all CA
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002127 certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05002128 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002129 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
2130 p12.set_ca_certificates(None)
Rick Dean623ee362009-07-17 12:22:16 -05002131 self.assertEqual(None, p12.get_ca_certificates())
Rick Deanf94096c2009-07-18 14:23:06 -05002132
Rick Deanf94096c2009-07-18 14:23:06 -05002133 def test_export_without_mac(self):
2134 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002135 Exporting a PKCS12 with a :py:obj:`maciter` of ``-1`` excludes the MAC
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002136 entirely.
Rick Deanf94096c2009-07-18 14:23:06 -05002137 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002138 passwd = b"Lake Michigan"
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002139 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Dean623ee362009-07-17 12:22:16 -05002140 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002141 self.check_recovery(
2142 dumped_p12, key=server_key_pem, cert=server_cert_pem,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002143 passwd=passwd, extra=(b"-nomacver",))
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002144
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002145 def test_load_without_mac(self):
2146 """
2147 Loading a PKCS12 without a MAC does something other than crash.
2148 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002149 passwd = b"Lake Michigan"
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002150 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
2151 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Rick Dean321a0512009-08-13 17:21:29 -05002152 try:
2153 recovered_p12 = load_pkcs12(dumped_p12, passwd)
2154 # The person who generated this PCKS12 should be flogged,
2155 # or better yet we should have a means to determine
2156 # whether a PCKS12 had a MAC that was verified.
2157 # Anyway, libopenssl chooses to allow it, so the
2158 # pyopenssl binding does as well.
2159 self.assertTrue(isinstance(recovered_p12, PKCS12))
2160 except Error:
2161 # Failing here with an exception is preferred as some openssl
2162 # versions do.
2163 pass
Rick Dean623ee362009-07-17 12:22:16 -05002164
Rick Dean25bcc1f2009-07-20 11:53:13 -05002165 def test_zero_len_list_for_ca(self):
2166 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002167 A PKCS12 with an empty CA certificates list can be exported.
Rick Dean25bcc1f2009-07-20 11:53:13 -05002168 """
2169 passwd = 'Hobie 18'
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002170 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002171 # p12.set_ca_certificates([])
2172 # self.assertEqual((), p12.get_ca_certificates())
2173 # dumped_p12 = p12.export(passphrase=passwd, iter=3)
2174 # self.check_recovery(
2175 # dumped_p12, key=server_key_pem, cert=server_cert_pem,
2176 # passwd=passwd)
Rick Dean25bcc1f2009-07-20 11:53:13 -05002177
Rick Deanf94096c2009-07-18 14:23:06 -05002178 def test_export_without_args(self):
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002179 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002180 All the arguments to :py:obj:`PKCS12.export` are optional.
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002181 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002182 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05002183 dumped_p12 = p12.export() # no args
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002184 self.check_recovery(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002185 dumped_p12, key=server_key_pem, cert=server_cert_pem, passwd=b"")
Rick Deanf94096c2009-07-18 14:23:06 -05002186
Abraham Martinc5484ba2015-03-25 15:33:05 +00002187 def test_export_without_bytes(self):
2188 """
2189 Test :py:obj:`PKCS12.export` with text not bytes as passphrase
2190 """
2191 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
2192
2193 with catch_warnings(record=True) as w:
2194 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002195 dumped_p12 = p12.export(passphrase=b"randomtext".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002196 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002197 "{0} for passphrase is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002198 WARNING_TYPE_EXPECTED
2199 ),
2200 str(w[-1].message)
2201 )
2202 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinc5484ba2015-03-25 15:33:05 +00002203 self.check_recovery(
2204 dumped_p12, key=server_key_pem, cert=server_cert_pem, passwd=b"randomtext")
2205
Rick Deanf94096c2009-07-18 14:23:06 -05002206 def test_key_cert_mismatch(self):
2207 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002208 :py:obj:`PKCS12.export` raises an exception when a key and certificate
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002209 mismatch.
Rick Deanf94096c2009-07-18 14:23:06 -05002210 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002211 p12 = self.gen_pkcs12(server_cert_pem, client_key_pem, root_cert_pem)
2212 self.assertRaises(Error, p12.export)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002213
2214
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002215# These quoting functions taken directly from Twisted's twisted.python.win32.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002216_cmdLineQuoteRe = re.compile(br'(\\*)"')
2217_cmdLineQuoteRe2 = re.compile(br'(\\+)\Z')
Alex Gaynoraceb3e22015-09-05 12:00:22 -04002218
2219
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002220def cmdLineQuote(s):
2221 """
2222 Internal method for quoting a single command-line argument.
2223
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002224 See http://www.perlmonks.org/?node_id=764004
2225
Jonathan Ballet648875f2011-07-16 14:14:58 +09002226 :type: :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002227 :param s: A single unquoted string to quote for something that is expecting
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002228 cmd.exe-style quoting
2229
Jonathan Ballet648875f2011-07-16 14:14:58 +09002230 :rtype: :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002231 :return: A cmd.exe-style quoted string
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002232 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002233 s = _cmdLineQuoteRe2.sub(br"\1\1", _cmdLineQuoteRe.sub(br'\1\1\\"', s))
2234 return b'"' + s + b'"'
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002235
2236
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002237def quoteArguments(arguments):
2238 """
2239 Quote an iterable of command-line arguments for passing to CreateProcess or
Jonathan Ballet648875f2011-07-16 14:14:58 +09002240 a similar API. This allows the list passed to :py:obj:`reactor.spawnProcess` to
2241 match the child process's :py:obj:`sys.argv` properly.
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002242
Jonathan Ballet648875f2011-07-16 14:14:58 +09002243 :type arguments: :py:obj:`iterable` of :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002244 :param arguments: An iterable of unquoted arguments to quote
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002245
Jonathan Ballet648875f2011-07-16 14:14:58 +09002246 :rtype: :py:obj:`str`
2247 :return: A space-delimited string containing quoted versions of :py:obj:`arguments`
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002248 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002249 return b' '.join(map(cmdLineQuote, arguments))
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002250
2251
Rick Dean4c9ad612009-07-17 15:05:22 -05002252def _runopenssl(pem, *args):
2253 """
2254 Run the command line openssl tool with the given arguments and write
Rick Dean55d1ce62009-08-13 17:40:24 -05002255 the given PEM to its stdin. Not safe for quotes.
Rick Dean4c9ad612009-07-17 15:05:22 -05002256 """
Jean-Paul Calderone038de952009-08-21 12:16:06 -04002257 if os.name == 'posix':
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002258 command = b"openssl " + b" ".join([
2259 (b"'" + arg.replace(b"'", b"'\\''") + b"'")
2260 for arg in args])
Rick Dean55d1ce62009-08-13 17:40:24 -05002261 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002262 command = b"openssl " + quoteArguments(args)
2263 proc = Popen(native(command), shell=True, stdin=PIPE, stdout=PIPE)
Jean-Paul Calderone62ca8da2010-08-11 19:58:08 -04002264 proc.stdin.write(pem)
2265 proc.stdin.close()
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002266 output = proc.stdout.read()
2267 proc.stdout.close()
2268 proc.wait()
2269 return output
Rick Dean4c9ad612009-07-17 15:05:22 -05002270
2271
Jean-Paul Calderone18808652009-07-05 12:54:05 -04002272class FunctionTests(TestCase):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002273 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002274 Tests for free-functions in the :py:obj:`OpenSSL.crypto` module.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002275 """
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002276
2277 def test_load_privatekey_invalid_format(self):
2278 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002279 :py:obj:`load_privatekey` raises :py:obj:`ValueError` if passed an unknown filetype.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002280 """
2281 self.assertRaises(ValueError, load_privatekey, 100, root_key_pem)
2282
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002283 def test_load_privatekey_invalid_passphrase_type(self):
2284 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002285 :py:obj:`load_privatekey` raises :py:obj:`TypeError` if passed a passphrase that is
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002286 neither a :py:obj:`str` nor a callable.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002287 """
2288 self.assertRaises(
2289 TypeError,
2290 load_privatekey,
2291 FILETYPE_PEM, encryptedPrivateKeyPEMPassphrase, object())
2292
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002293 def test_load_privatekey_wrong_args(self):
2294 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002295 :py:obj:`load_privatekey` raises :py:obj:`TypeError` if called with the wrong number
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002296 of arguments.
2297 """
2298 self.assertRaises(TypeError, load_privatekey)
2299
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002300 def test_load_privatekey_wrongPassphrase(self):
2301 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002302 :py:obj:`load_privatekey` raises :py:obj:`OpenSSL.crypto.Error` when it is passed an
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002303 encrypted PEM and an incorrect passphrase.
2304 """
2305 self.assertRaises(
2306 Error,
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002307 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, b("quack"))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002308
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002309 def test_load_privatekey_passphraseWrongType(self):
2310 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002311 :py:obj:`load_privatekey` raises :py:obj:`ValueError` when it is passed a passphrase
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002312 with a private key encoded in a format, that doesn't support
2313 encryption.
2314 """
2315 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2316 blob = dump_privatekey(FILETYPE_ASN1, key)
2317 self.assertRaises(ValueError,
2318 load_privatekey, FILETYPE_ASN1, blob, "secret")
2319
2320
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002321 def test_load_privatekey_passphrase(self):
2322 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002323 :py:obj:`load_privatekey` can create a :py:obj:`PKey` object from an encrypted PEM
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002324 string if given the passphrase.
2325 """
2326 key = load_privatekey(
2327 FILETYPE_PEM, encryptedPrivateKeyPEM,
2328 encryptedPrivateKeyPEMPassphrase)
2329 self.assertTrue(isinstance(key, PKeyType))
2330
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002331 def test_load_privatekey_passphrase_exception(self):
2332 """
2333 If the passphrase callback raises an exception, that exception is raised
2334 by :py:obj:`load_privatekey`.
2335 """
2336 def cb(ignored):
2337 raise ArithmeticError
2338
2339 self.assertRaises(ArithmeticError,
2340 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2341
2342
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002343 def test_load_privatekey_wrongPassphraseCallback(self):
2344 """
Jean-Paul Calderoned440a082011-09-14 11:02:05 -04002345 :py:obj:`load_privatekey` raises :py:obj:`OpenSSL.crypto.Error` when it
2346 is passed an encrypted PEM and a passphrase callback which returns an
2347 incorrect passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002348 """
2349 called = []
Alex Gaynoraceb3e22015-09-05 12:00:22 -04002350
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002351 def cb(*a):
2352 called.append(None)
Jean-Paul Calderoned440a082011-09-14 11:02:05 -04002353 return b("quack")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002354 self.assertRaises(
2355 Error,
2356 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2357 self.assertTrue(called)
2358
2359 def test_load_privatekey_passphraseCallback(self):
2360 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002361 :py:obj:`load_privatekey` can create a :py:obj:`PKey` object from an encrypted PEM
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002362 string if given a passphrase callback which returns the correct
2363 password.
2364 """
2365 called = []
Alex Gaynoraceb3e22015-09-05 12:00:22 -04002366
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002367 def cb(writing):
2368 called.append(writing)
2369 return encryptedPrivateKeyPEMPassphrase
2370 key = load_privatekey(FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2371 self.assertTrue(isinstance(key, PKeyType))
2372 self.assertEqual(called, [False])
2373
Jean-Paul Calderone105cb952011-09-14 10:16:46 -04002374 def test_load_privatekey_passphrase_wrong_return_type(self):
2375 """
2376 :py:obj:`load_privatekey` raises :py:obj:`ValueError` if the passphrase
2377 callback returns something other than a byte string.
2378 """
2379 self.assertRaises(
2380 ValueError,
2381 load_privatekey,
2382 FILETYPE_PEM, encryptedPrivateKeyPEM, lambda *args: 3)
2383
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002384 def test_dump_privatekey_wrong_args(self):
2385 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002386 :py:obj:`dump_privatekey` raises :py:obj:`TypeError` if called with the wrong number
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002387 of arguments.
2388 """
2389 self.assertRaises(TypeError, dump_privatekey)
Jean-Paul Calderone1eeccd82011-09-14 10:18:52 -04002390 # If cipher name is given, password is required.
2391 self.assertRaises(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002392 TypeError, dump_privatekey, FILETYPE_PEM, PKey(), GOOD_CIPHER)
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002393
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002394 def test_dump_privatekey_unknown_cipher(self):
2395 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002396 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` if called with an unrecognized
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002397 cipher name.
2398 """
2399 key = PKey()
2400 key.generate_key(TYPE_RSA, 512)
2401 self.assertRaises(
2402 ValueError, dump_privatekey,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002403 FILETYPE_PEM, key, BAD_CIPHER, "passphrase")
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002404
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002405 def test_dump_privatekey_invalid_passphrase_type(self):
2406 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002407 :py:obj:`dump_privatekey` raises :py:obj:`TypeError` if called with a passphrase which
2408 is neither a :py:obj:`str` nor a callable.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002409 """
2410 key = PKey()
2411 key.generate_key(TYPE_RSA, 512)
2412 self.assertRaises(
2413 TypeError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002414 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, object())
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002415
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002416 def test_dump_privatekey_invalid_filetype(self):
2417 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002418 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` if called with an unrecognized
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002419 filetype.
2420 """
2421 key = PKey()
2422 key.generate_key(TYPE_RSA, 512)
2423 self.assertRaises(ValueError, dump_privatekey, 100, key)
2424
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002425 def test_load_privatekey_passphraseCallbackLength(self):
2426 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002427 :py:obj:`crypto.load_privatekey` should raise an error when the passphrase
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002428 provided by the callback is too long, not silently truncate it.
2429 """
2430 def cb(ignored):
2431 return "a" * 1025
2432
2433 self.assertRaises(ValueError,
2434 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2435
2436
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002437 def test_dump_privatekey_passphrase(self):
2438 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002439 :py:obj:`dump_privatekey` writes an encrypted PEM when given a passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002440 """
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002441 passphrase = b("foo")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002442 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002443 pem = dump_privatekey(FILETYPE_PEM, key, GOOD_CIPHER, passphrase)
2444 self.assertTrue(isinstance(pem, binary_type))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002445 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
2446 self.assertTrue(isinstance(loadedKey, PKeyType))
2447 self.assertEqual(loadedKey.type(), key.type())
2448 self.assertEqual(loadedKey.bits(), key.bits())
2449
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002450 def test_dump_privatekey_passphraseWrongType(self):
2451 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002452 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` when it is passed a passphrase
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002453 with a private key encoded in a format, that doesn't support
2454 encryption.
2455 """
2456 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2457 self.assertRaises(ValueError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002458 dump_privatekey, FILETYPE_ASN1, key, GOOD_CIPHER, "secret")
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002459
2460
Rick Dean5b7b6372009-04-01 11:34:06 -05002461 def test_dump_certificate(self):
2462 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002463 :py:obj:`dump_certificate` writes PEM, DER, and text.
Rick Dean5b7b6372009-04-01 11:34:06 -05002464 """
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002465 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
Rick Dean5b7b6372009-04-01 11:34:06 -05002466 cert = load_certificate(FILETYPE_PEM, pemData)
2467 dumped_pem = dump_certificate(FILETYPE_PEM, cert)
2468 self.assertEqual(dumped_pem, cleartextCertificatePEM)
2469 dumped_der = dump_certificate(FILETYPE_ASN1, cert)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002470 good_der = _runopenssl(dumped_pem, b"x509", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002471 self.assertEqual(dumped_der, good_der)
2472 cert2 = load_certificate(FILETYPE_ASN1, dumped_der)
2473 dumped_pem2 = dump_certificate(FILETYPE_PEM, cert2)
2474 self.assertEqual(dumped_pem2, cleartextCertificatePEM)
2475 dumped_text = dump_certificate(FILETYPE_TEXT, cert)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002476 good_text = _runopenssl(dumped_pem, b"x509", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002477 self.assertEqual(dumped_text, good_text)
2478
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002479 def test_dump_privatekey_pem(self):
Rick Dean5b7b6372009-04-01 11:34:06 -05002480 """
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002481 :py:obj:`dump_privatekey` writes a PEM
Rick Dean5b7b6372009-04-01 11:34:06 -05002482 """
2483 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -04002484 self.assertTrue(key.check())
Rick Dean5b7b6372009-04-01 11:34:06 -05002485 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2486 self.assertEqual(dumped_pem, cleartextPrivateKeyPEM)
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002487
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002488 def test_dump_privatekey_asn1(self):
2489 """
2490 :py:obj:`dump_privatekey` writes a DER
2491 """
2492 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2493 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2494
Rick Dean5b7b6372009-04-01 11:34:06 -05002495 dumped_der = dump_privatekey(FILETYPE_ASN1, key)
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002496 # XXX This OpenSSL call writes "writing RSA key" to standard out. Sad.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002497 good_der = _runopenssl(dumped_pem, b"rsa", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002498 self.assertEqual(dumped_der, good_der)
2499 key2 = load_privatekey(FILETYPE_ASN1, dumped_der)
2500 dumped_pem2 = dump_privatekey(FILETYPE_PEM, key2)
2501 self.assertEqual(dumped_pem2, cleartextPrivateKeyPEM)
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002502
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002503 def test_dump_privatekey_text(self):
2504 """
2505 :py:obj:`dump_privatekey` writes a text
2506 """
2507 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2508 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2509
Rick Dean5b7b6372009-04-01 11:34:06 -05002510 dumped_text = dump_privatekey(FILETYPE_TEXT, key)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002511 good_text = _runopenssl(dumped_pem, b"rsa", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002512 self.assertEqual(dumped_text, good_text)
2513
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002514
Rick Dean5b7b6372009-04-01 11:34:06 -05002515 def test_dump_certificate_request(self):
2516 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002517 :py:obj:`dump_certificate_request` writes a PEM, DER, and text.
Rick Dean5b7b6372009-04-01 11:34:06 -05002518 """
2519 req = load_certificate_request(FILETYPE_PEM, cleartextCertificateRequestPEM)
2520 dumped_pem = dump_certificate_request(FILETYPE_PEM, req)
2521 self.assertEqual(dumped_pem, cleartextCertificateRequestPEM)
2522 dumped_der = dump_certificate_request(FILETYPE_ASN1, req)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002523 good_der = _runopenssl(dumped_pem, b"req", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002524 self.assertEqual(dumped_der, good_der)
2525 req2 = load_certificate_request(FILETYPE_ASN1, dumped_der)
2526 dumped_pem2 = dump_certificate_request(FILETYPE_PEM, req2)
2527 self.assertEqual(dumped_pem2, cleartextCertificateRequestPEM)
2528 dumped_text = dump_certificate_request(FILETYPE_TEXT, req)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002529 good_text = _runopenssl(dumped_pem, b"req", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002530 self.assertEqual(dumped_text, good_text)
Jean-Paul Calderoneaf43cdf2010-08-03 18:40:52 -04002531 self.assertRaises(ValueError, dump_certificate_request, 100, req)
Rick Dean5b7b6372009-04-01 11:34:06 -05002532
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002533 def test_dump_privatekey_passphraseCallback(self):
2534 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002535 :py:obj:`dump_privatekey` writes an encrypted PEM when given a callback which
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002536 returns the correct passphrase.
2537 """
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002538 passphrase = b("foo")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002539 called = []
Alex Gaynoraceb3e22015-09-05 12:00:22 -04002540
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002541 def cb(writing):
2542 called.append(writing)
2543 return passphrase
2544 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002545 pem = dump_privatekey(FILETYPE_PEM, key, GOOD_CIPHER, cb)
2546 self.assertTrue(isinstance(pem, binary_type))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002547 self.assertEqual(called, [True])
2548 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
2549 self.assertTrue(isinstance(loadedKey, PKeyType))
2550 self.assertEqual(loadedKey.type(), key.type())
2551 self.assertEqual(loadedKey.bits(), key.bits())
Rick Dean5b7b6372009-04-01 11:34:06 -05002552
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002553 def test_dump_privatekey_passphrase_exception(self):
2554 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002555 :py:obj:`dump_privatekey` should not overwrite the exception raised
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002556 by the passphrase callback.
2557 """
2558 def cb(ignored):
2559 raise ArithmeticError
2560
2561 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2562 self.assertRaises(ArithmeticError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002563 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, cb)
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002564
2565
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002566 def test_dump_privatekey_passphraseCallbackLength(self):
2567 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002568 :py:obj:`crypto.dump_privatekey` should raise an error when the passphrase
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002569 provided by the callback is too long, not silently truncate it.
2570 """
2571 def cb(ignored):
2572 return "a" * 1025
2573
2574 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2575 self.assertRaises(ValueError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002576 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, cb)
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002577
2578
Alex Gaynor4b9c96a2014-08-14 09:51:48 -07002579 def test_load_pkcs7_data_pem(self):
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002580 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002581 :py:obj:`load_pkcs7_data` accepts a PKCS#7 string and returns an instance of
2582 :py:obj:`PKCS7Type`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002583 """
2584 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2585 self.assertTrue(isinstance(pkcs7, PKCS7Type))
2586
Alex Gaynor4b9c96a2014-08-14 09:51:48 -07002587 def test_load_pkcs7_data_asn1(self):
Alex Gaynor9875a912014-08-14 13:35:05 -07002588 """
2589 :py:obj:`load_pkcs7_data` accepts a bytes containing ASN1 data
2590 representing PKCS#7 and returns an instance of :py:obj`PKCS7Type`.
2591 """
Alex Gaynor4b9c96a2014-08-14 09:51:48 -07002592 pkcs7 = load_pkcs7_data(FILETYPE_ASN1, pkcs7DataASN1)
2593 self.assertTrue(isinstance(pkcs7, PKCS7Type))
2594
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002595 def test_load_pkcs7_data_invalid(self):
2596 """
2597 If the data passed to :py:obj:`load_pkcs7_data` is invalid,
2598 :py:obj:`Error` is raised.
2599 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002600 self.assertRaises(Error, load_pkcs7_data, FILETYPE_PEM, b"foo")
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002601
2602
Jean-Paul Calderone4a68b402013-12-29 16:54:58 -05002603class LoadCertificateTests(TestCase):
2604 """
2605 Tests for :py:obj:`load_certificate_request`.
2606 """
Alex Gaynoraceb3e22015-09-05 12:00:22 -04002607
Jean-Paul Calderone4a68b402013-12-29 16:54:58 -05002608 def test_badFileType(self):
2609 """
2610 If the file type passed to :py:obj:`load_certificate_request` is
2611 neither :py:obj:`FILETYPE_PEM` nor :py:obj:`FILETYPE_ASN1` then
2612 :py:class:`ValueError` is raised.
2613 """
2614 self.assertRaises(ValueError, load_certificate_request, object(), b"")
2615
2616
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002617class PKCS7Tests(TestCase):
2618 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002619 Tests for :py:obj:`PKCS7Type`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002620 """
Alex Gaynoraceb3e22015-09-05 12:00:22 -04002621
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002622 def test_type(self):
2623 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002624 :py:obj:`PKCS7Type` is a type object.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002625 """
2626 self.assertTrue(isinstance(PKCS7Type, type))
2627 self.assertEqual(PKCS7Type.__name__, 'PKCS7')
2628
2629 # XXX This doesn't currently work.
2630 # self.assertIdentical(PKCS7, PKCS7Type)
2631
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002632 # XXX Opposite results for all these following methods
2633
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002634 def test_type_is_signed_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002635 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002636 :py:obj:`PKCS7Type.type_is_signed` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002637 arguments.
2638 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002639 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2640 self.assertRaises(TypeError, pkcs7.type_is_signed, None)
2641
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002642 def test_type_is_signed(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002643 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002644 :py:obj:`PKCS7Type.type_is_signed` returns :py:obj:`True` if the PKCS7 object is of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002645 the type *signed*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002646 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002647 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2648 self.assertTrue(pkcs7.type_is_signed())
2649
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002650 def test_type_is_enveloped_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002651 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002652 :py:obj:`PKCS7Type.type_is_enveloped` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002653 arguments.
2654 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002655 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2656 self.assertRaises(TypeError, pkcs7.type_is_enveloped, None)
2657
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002658 def test_type_is_enveloped(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002659 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002660 :py:obj:`PKCS7Type.type_is_enveloped` returns :py:obj:`False` if the PKCS7 object is
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002661 not of the type *enveloped*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002662 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002663 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2664 self.assertFalse(pkcs7.type_is_enveloped())
2665
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002666 def test_type_is_signedAndEnveloped_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002667 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002668 :py:obj:`PKCS7Type.type_is_signedAndEnveloped` raises :py:obj:`TypeError` if called
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002669 with any arguments.
2670 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002671 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2672 self.assertRaises(TypeError, pkcs7.type_is_signedAndEnveloped, None)
2673
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002674 def test_type_is_signedAndEnveloped(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002675 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002676 :py:obj:`PKCS7Type.type_is_signedAndEnveloped` returns :py:obj:`False` if the PKCS7
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002677 object is not of the type *signed and enveloped*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002678 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002679 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2680 self.assertFalse(pkcs7.type_is_signedAndEnveloped())
2681
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002682 def test_type_is_data(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002683 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002684 :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 -04002685 the type data.
2686 """
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002687 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2688 self.assertFalse(pkcs7.type_is_data())
2689
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002690 def test_type_is_data_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002691 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002692 :py:obj:`PKCS7Type.type_is_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002693 arguments.
2694 """
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002695 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2696 self.assertRaises(TypeError, pkcs7.type_is_data, None)
2697
Jean-Paul Calderone97b28ca2010-07-30 10:56:07 -04002698 def test_get_type_name_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002699 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002700 :py:obj:`PKCS7Type.get_type_name` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002701 arguments.
2702 """
Jean-Paul Calderone97b28ca2010-07-30 10:56:07 -04002703 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2704 self.assertRaises(TypeError, pkcs7.get_type_name, None)
2705
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002706 def test_get_type_name(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002707 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002708 :py:obj:`PKCS7Type.get_type_name` returns a :py:obj:`str` giving the type name.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002709 """
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002710 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
Jean-Paul Calderone07640f12010-08-22 17:14:43 -04002711 self.assertEquals(pkcs7.get_type_name(), b('pkcs7-signedData'))
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002712
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002713 def test_attribute(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002714 """
2715 If an attribute other than one of the methods tested here is accessed on
Jonathan Ballet648875f2011-07-16 14:14:58 +09002716 an instance of :py:obj:`PKCS7Type`, :py:obj:`AttributeError` is raised.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002717 """
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002718 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2719 self.assertRaises(AttributeError, getattr, pkcs7, "foo")
2720
2721
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002722class NetscapeSPKITests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002723 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002724 Tests for :py:obj:`OpenSSL.crypto.NetscapeSPKI`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002725 """
Alex Gaynoraceb3e22015-09-05 12:00:22 -04002726
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002727 def signable(self):
2728 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002729 Return a new :py:obj:`NetscapeSPKI` for use with signing tests.
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002730 """
2731 return NetscapeSPKI()
2732
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002733 def test_type(self):
2734 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002735 :py:obj:`NetscapeSPKI` and :py:obj:`NetscapeSPKIType` refer to the same type object
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002736 and can be used to create instances of that type.
2737 """
2738 self.assertIdentical(NetscapeSPKI, NetscapeSPKIType)
2739 self.assertConsistentType(NetscapeSPKI, 'NetscapeSPKI')
2740
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002741 def test_construction(self):
2742 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002743 :py:obj:`NetscapeSPKI` returns an instance of :py:obj:`NetscapeSPKIType`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002744 """
2745 nspki = NetscapeSPKI()
2746 self.assertTrue(isinstance(nspki, NetscapeSPKIType))
2747
Jean-Paul Calderone969efaa2010-08-03 18:19:19 -04002748 def test_invalid_attribute(self):
2749 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002750 Accessing a non-existent attribute of a :py:obj:`NetscapeSPKI` instance causes
2751 an :py:obj:`AttributeError` to be raised.
Jean-Paul Calderone969efaa2010-08-03 18:19:19 -04002752 """
2753 nspki = NetscapeSPKI()
2754 self.assertRaises(AttributeError, lambda: nspki.foo)
2755
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002756 def test_b64_encode(self):
2757 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002758 :py:obj:`NetscapeSPKI.b64_encode` encodes the certificate to a base64 blob.
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002759 """
2760 nspki = NetscapeSPKI()
2761 blob = nspki.b64_encode()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002762 self.assertTrue(isinstance(blob, binary_type))
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002763
2764
Rick Dean536ba022009-07-24 23:57:27 -05002765class RevokedTests(TestCase):
2766 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002767 Tests for :py:obj:`OpenSSL.crypto.Revoked`
Rick Dean536ba022009-07-24 23:57:27 -05002768 """
Alex Gaynoraceb3e22015-09-05 12:00:22 -04002769
Rick Dean536ba022009-07-24 23:57:27 -05002770 def test_construction(self):
2771 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002772 Confirm we can create :py:obj:`OpenSSL.crypto.Revoked`. Check
Rick Dean536ba022009-07-24 23:57:27 -05002773 that it is empty.
2774 """
2775 revoked = Revoked()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002776 self.assertTrue(isinstance(revoked, Revoked))
2777 self.assertEquals(type(revoked), Revoked)
2778 self.assertEquals(revoked.get_serial(), b('00'))
2779 self.assertEquals(revoked.get_rev_date(), None)
2780 self.assertEquals(revoked.get_reason(), None)
Rick Dean536ba022009-07-24 23:57:27 -05002781
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002782 def test_construction_wrong_args(self):
2783 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002784 Calling :py:obj:`OpenSSL.crypto.Revoked` with any arguments results
2785 in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002786 """
2787 self.assertRaises(TypeError, Revoked, None)
2788 self.assertRaises(TypeError, Revoked, 1)
2789 self.assertRaises(TypeError, Revoked, "foo")
2790
Rick Dean536ba022009-07-24 23:57:27 -05002791 def test_serial(self):
2792 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002793 Confirm we can set and get serial numbers from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002794 :py:obj:`OpenSSL.crypto.Revoked`. Confirm errors are handled
Rick Dean536ba022009-07-24 23:57:27 -05002795 with grace.
2796 """
2797 revoked = Revoked()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002798 ret = revoked.set_serial(b('10b'))
2799 self.assertEquals(ret, None)
Rick Dean536ba022009-07-24 23:57:27 -05002800 ser = revoked.get_serial()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002801 self.assertEquals(ser, b('010B'))
Rick Dean536ba022009-07-24 23:57:27 -05002802
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002803 revoked.set_serial(b('31ppp')) # a type error would be nice
Rick Dean536ba022009-07-24 23:57:27 -05002804 ser = revoked.get_serial()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002805 self.assertEquals(ser, b('31'))
Rick Dean536ba022009-07-24 23:57:27 -05002806
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002807 self.assertRaises(ValueError, revoked.set_serial, b('pqrst'))
Rick Dean536ba022009-07-24 23:57:27 -05002808 self.assertRaises(TypeError, revoked.set_serial, 100)
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002809 self.assertRaises(TypeError, revoked.get_serial, 1)
2810 self.assertRaises(TypeError, revoked.get_serial, None)
2811 self.assertRaises(TypeError, revoked.get_serial, "")
Rick Dean536ba022009-07-24 23:57:27 -05002812
Rick Dean536ba022009-07-24 23:57:27 -05002813 def test_date(self):
2814 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002815 Confirm we can set and get revocation dates from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002816 :py:obj:`OpenSSL.crypto.Revoked`. Confirm errors are handled
Rick Dean536ba022009-07-24 23:57:27 -05002817 with grace.
2818 """
2819 revoked = Revoked()
2820 date = revoked.get_rev_date()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002821 self.assertEquals(date, None)
Rick Dean536ba022009-07-24 23:57:27 -05002822
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002823 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05002824 ret = revoked.set_rev_date(now)
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002825 self.assertEqual(ret, None)
Rick Dean536ba022009-07-24 23:57:27 -05002826 date = revoked.get_rev_date()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002827 self.assertEqual(date, now)
Rick Dean536ba022009-07-24 23:57:27 -05002828
Rick Dean6385faf2009-07-26 00:07:47 -05002829 def test_reason(self):
2830 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002831 Confirm we can set and get revocation reasons from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002832 :py:obj:`OpenSSL.crypto.Revoked`. The "get" need to work
Rick Dean6385faf2009-07-26 00:07:47 -05002833 as "set". Likewise, each reason of all_reasons() must work.
2834 """
2835 revoked = Revoked()
2836 for r in revoked.all_reasons():
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002837 for x in range(2):
Rick Dean6385faf2009-07-26 00:07:47 -05002838 ret = revoked.set_reason(r)
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002839 self.assertEquals(ret, None)
Rick Dean6385faf2009-07-26 00:07:47 -05002840 reason = revoked.get_reason()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002841 self.assertEquals(
2842 reason.lower().replace(b(' '), b('')),
2843 r.lower().replace(b(' '), b('')))
Alex Gaynoraceb3e22015-09-05 12:00:22 -04002844 r = reason # again with the resp of get
Rick Dean6385faf2009-07-26 00:07:47 -05002845
2846 revoked.set_reason(None)
2847 self.assertEqual(revoked.get_reason(), None)
2848
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002849 def test_set_reason_wrong_arguments(self):
Rick Dean6385faf2009-07-26 00:07:47 -05002850 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002851 Calling :py:obj:`OpenSSL.crypto.Revoked.set_reason` with other than
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002852 one argument, or an argument which isn't a valid reason,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002853 results in :py:obj:`TypeError` or :py:obj:`ValueError` being raised.
Rick Dean6385faf2009-07-26 00:07:47 -05002854 """
2855 revoked = Revoked()
2856 self.assertRaises(TypeError, revoked.set_reason, 100)
Jean-Paul Calderone281b62b2010-08-28 14:22:29 -04002857 self.assertRaises(ValueError, revoked.set_reason, b('blue'))
Rick Dean6385faf2009-07-26 00:07:47 -05002858
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002859 def test_get_reason_wrong_arguments(self):
2860 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002861 Calling :py:obj:`OpenSSL.crypto.Revoked.get_reason` with any
2862 arguments results in :py:obj:`TypeError` being raised.
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002863 """
2864 revoked = Revoked()
2865 self.assertRaises(TypeError, revoked.get_reason, None)
2866 self.assertRaises(TypeError, revoked.get_reason, 1)
2867 self.assertRaises(TypeError, revoked.get_reason, "foo")
2868
2869
Rick Dean536ba022009-07-24 23:57:27 -05002870class CRLTests(TestCase):
2871 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002872 Tests for :py:obj:`OpenSSL.crypto.CRL`
Rick Dean536ba022009-07-24 23:57:27 -05002873 """
2874 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
2875 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2876
2877 def test_construction(self):
2878 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002879 Confirm we can create :py:obj:`OpenSSL.crypto.CRL`. Check
Rick Dean536ba022009-07-24 23:57:27 -05002880 that it is empty
2881 """
2882 crl = CRL()
Alex Gaynor7f636492015-09-04 13:26:52 -04002883 self.assertTrue(isinstance(crl, CRL))
Rick Dean536ba022009-07-24 23:57:27 -05002884 self.assertEqual(crl.get_revoked(), None)
2885
Jean-Paul Calderone2efd03e2010-01-30 13:59:55 -05002886 def test_construction_wrong_args(self):
2887 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002888 Calling :py:obj:`OpenSSL.crypto.CRL` with any number of arguments
2889 results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone2efd03e2010-01-30 13:59:55 -05002890 """
2891 self.assertRaises(TypeError, CRL, 1)
2892 self.assertRaises(TypeError, CRL, "")
2893 self.assertRaises(TypeError, CRL, None)
2894
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002895 def _get_crl(self):
Rick Dean536ba022009-07-24 23:57:27 -05002896 """
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002897 Get a new ``CRL`` with a revocation.
Rick Dean536ba022009-07-24 23:57:27 -05002898 """
2899 crl = CRL()
2900 revoked = Revoked()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002901 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05002902 revoked.set_rev_date(now)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002903 revoked.set_serial(b('3ab'))
2904 revoked.set_reason(b('sUpErSeDEd'))
Rick Dean536ba022009-07-24 23:57:27 -05002905 crl.add_revoked(revoked)
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002906 return crl
Rick Dean536ba022009-07-24 23:57:27 -05002907
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002908 def test_export_pem(self):
2909 """
2910 If not passed a format, ``CRL.export`` returns a "PEM" format string
2911 representing a serial number, a revoked reason, and certificate issuer
2912 information.
2913 """
2914 crl = self._get_crl()
Rick Dean536ba022009-07-24 23:57:27 -05002915 # PEM format
2916 dumped_crl = crl.export(self.cert, self.pkey, days=20)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002917 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002918
2919 # These magic values are based on the way the CRL above was constructed
2920 # and with what certificate it was exported.
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002921 text.index(b('Serial Number: 03AB'))
2922 text.index(b('Superseded'))
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002923 text.index(
2924 b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA')
2925 )
2926
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002927 def test_export_der(self):
2928 """
2929 If passed ``FILETYPE_ASN1`` for the format, ``CRL.export`` returns a
2930 "DER" format string representing a serial number, a revoked reason, and
2931 certificate issuer information.
2932 """
2933 crl = self._get_crl()
Rick Dean536ba022009-07-24 23:57:27 -05002934
2935 # DER format
2936 dumped_crl = crl.export(self.cert, self.pkey, FILETYPE_ASN1)
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002937 text = _runopenssl(
2938 dumped_crl, b"crl", b"-noout", b"-text", b"-inform", b"DER"
2939 )
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002940 text.index(b('Serial Number: 03AB'))
2941 text.index(b('Superseded'))
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002942 text.index(
2943 b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA')
2944 )
2945
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002946 def test_export_text(self):
2947 """
2948 If passed ``FILETYPE_TEXT`` for the format, ``CRL.export`` returns a
2949 text format string like the one produced by the openssl command line
2950 tool.
2951 """
2952 crl = self._get_crl()
2953
2954 dumped_crl = crl.export(self.cert, self.pkey, FILETYPE_ASN1)
2955 text = _runopenssl(
2956 dumped_crl, b"crl", b"-noout", b"-text", b"-inform", b"DER"
2957 )
Rick Dean536ba022009-07-24 23:57:27 -05002958
2959 # text format
2960 dumped_text = crl.export(self.cert, self.pkey, type=FILETYPE_TEXT)
2961 self.assertEqual(text, dumped_text)
2962
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002963 def test_export_custom_digest(self):
2964 """
2965 If passed the name of a digest function, ``CRL.export`` uses a
2966 signature algorithm based on that digest function.
2967 """
2968 crl = self._get_crl()
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002969 dumped_crl = crl.export(self.cert, self.pkey, digest=b"sha1")
Bulat Gaifullin1966c972014-09-22 09:47:20 +04002970 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
2971 text.index(b('Signature Algorithm: sha1'))
2972
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002973 def test_export_md5_digest(self):
2974 """
2975 If passed md5 as the digest function, ``CRL.export`` uses md5 and does
2976 not emit a deprecation warning.
2977 """
2978 crl = self._get_crl()
2979 with catch_warnings(record=True) as catcher:
2980 simplefilter("always")
2981 self.assertEqual(0, len(catcher))
2982 dumped_crl = crl.export(self.cert, self.pkey, digest=b"md5")
2983 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
2984 text.index(b('Signature Algorithm: md5'))
2985
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002986 def test_export_default_digest(self):
2987 """
2988 If not passed the name of a digest function, ``CRL.export`` uses a
2989 signature algorithm based on MD5 and emits a deprecation warning.
2990 """
2991 crl = self._get_crl()
2992 with catch_warnings(record=True) as catcher:
2993 simplefilter("always")
2994 dumped_crl = crl.export(self.cert, self.pkey)
2995 self.assertEqual(
2996 "The default message digest (md5) is deprecated. "
2997 "Pass the name of a message digest explicitly.",
2998 str(catcher[0].message),
2999 )
Bulat Gaifullin1966c972014-09-22 09:47:20 +04003000 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
3001 text.index(b('Signature Algorithm: md5'))
3002
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -04003003 def test_export_invalid(self):
3004 """
3005 If :py:obj:`CRL.export` is used with an uninitialized :py:obj:`X509`
Jean-Paul Calderoneb5871072012-03-09 14:58:00 -08003006 instance, :py:obj:`OpenSSL.crypto.Error` is raised.
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -04003007 """
3008 crl = CRL()
3009 self.assertRaises(Error, crl.export, X509(), PKey())
3010
Jean-Paul Calderone56515342010-01-30 13:49:38 -05003011 def test_add_revoked_keyword(self):
3012 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003013 :py:obj:`OpenSSL.CRL.add_revoked` accepts its single argument as the
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003014 ``revoked`` keyword argument.
Jean-Paul Calderone56515342010-01-30 13:49:38 -05003015 """
3016 crl = CRL()
3017 revoked = Revoked()
3018 crl.add_revoked(revoked=revoked)
3019 self.assertTrue(isinstance(crl.get_revoked()[0], Revoked))
3020
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05003021 def test_export_wrong_args(self):
3022 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003023 Calling :py:obj:`OpenSSL.CRL.export` with fewer than two or more than
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05003024 four arguments, or with arguments other than the certificate,
3025 private key, integer file type, and integer number of days it
Jonathan Ballet648875f2011-07-16 14:14:58 +09003026 expects, results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05003027 """
3028 crl = CRL()
3029 self.assertRaises(TypeError, crl.export)
3030 self.assertRaises(TypeError, crl.export, self.cert)
Bulat Gaifullin925f7862014-09-22 10:10:44 +04003031 self.assertRaises(TypeError, crl.export, self.cert, self.pkey, FILETYPE_PEM, 10, "md5", "foo")
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05003032
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05003033 self.assertRaises(TypeError, crl.export, None, self.pkey, FILETYPE_PEM, 10)
3034 self.assertRaises(TypeError, crl.export, self.cert, None, FILETYPE_PEM, 10)
3035 self.assertRaises(TypeError, crl.export, self.cert, self.pkey, None, 10)
3036 self.assertRaises(TypeError, crl.export, self.cert, FILETYPE_PEM, None)
3037
Jean-Paul Calderoneea198422010-01-30 13:58:23 -05003038 def test_export_unknown_filetype(self):
3039 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003040 Calling :py:obj:`OpenSSL.CRL.export` with a file type other than
3041 :py:obj:`FILETYPE_PEM`, :py:obj:`FILETYPE_ASN1`, or :py:obj:`FILETYPE_TEXT` results
3042 in a :py:obj:`ValueError` being raised.
Jean-Paul Calderoneea198422010-01-30 13:58:23 -05003043 """
3044 crl = CRL()
3045 self.assertRaises(ValueError, crl.export, self.cert, self.pkey, 100, 10)
3046
3047
Bulat Gaifullin925f7862014-09-22 10:10:44 +04003048 def test_export_unknown_digest(self):
Bulat Gaifullin5f9eea42014-09-23 19:35:15 +04003049 """
Alex Gaynorca87ff62015-09-04 23:31:03 -04003050 Calling :py:obj:`OpenSSL.CRL.export` with an unsupported digest results
Bulat Gaifullin5f9eea42014-09-23 19:35:15 +04003051 in a :py:obj:`ValueError` being raised.
3052 """
Bulat Gaifullin925f7862014-09-22 10:10:44 +04003053 crl = CRL()
Jean-Paul Calderone9be85192015-04-13 21:20:51 -04003054 self.assertRaises(
3055 ValueError,
3056 crl.export,
3057 self.cert, self.pkey, FILETYPE_PEM, 10, b"strange-digest"
3058 )
Bulat Gaifullin925f7862014-09-22 10:10:44 +04003059
Rick Dean536ba022009-07-24 23:57:27 -05003060 def test_get_revoked(self):
3061 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05003062 Use python to create a simple CRL with two revocations.
Jonathan Ballet648875f2011-07-16 14:14:58 +09003063 Get back the :py:obj:`Revoked` using :py:obj:`OpenSSL.CRL.get_revoked` and
Rick Dean536ba022009-07-24 23:57:27 -05003064 verify them.
3065 """
3066 crl = CRL()
3067
3068 revoked = Revoked()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003069 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05003070 revoked.set_rev_date(now)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003071 revoked.set_serial(b('3ab'))
Rick Dean536ba022009-07-24 23:57:27 -05003072 crl.add_revoked(revoked)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003073 revoked.set_serial(b('100'))
3074 revoked.set_reason(b('sUpErSeDEd'))
Rick Dean536ba022009-07-24 23:57:27 -05003075 crl.add_revoked(revoked)
3076
3077 revs = crl.get_revoked()
3078 self.assertEqual(len(revs), 2)
3079 self.assertEqual(type(revs[0]), Revoked)
3080 self.assertEqual(type(revs[1]), Revoked)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003081 self.assertEqual(revs[0].get_serial(), b('03AB'))
3082 self.assertEqual(revs[1].get_serial(), b('0100'))
Rick Dean536ba022009-07-24 23:57:27 -05003083 self.assertEqual(revs[0].get_rev_date(), now)
3084 self.assertEqual(revs[1].get_rev_date(), now)
3085
Jean-Paul Calderone46bdce42010-01-30 13:44:16 -05003086 def test_get_revoked_wrong_args(self):
3087 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003088 Calling :py:obj:`OpenSSL.CRL.get_revoked` with any arguments results
3089 in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone46bdce42010-01-30 13:44:16 -05003090 """
3091 crl = CRL()
3092 self.assertRaises(TypeError, crl.get_revoked, None)
3093 self.assertRaises(TypeError, crl.get_revoked, 1)
3094 self.assertRaises(TypeError, crl.get_revoked, "")
3095 self.assertRaises(TypeError, crl.get_revoked, "", 1, None)
3096
Jean-Paul Calderoneecef6fa2010-01-30 13:47:18 -05003097 def test_add_revoked_wrong_args(self):
3098 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003099 Calling :py:obj:`OpenSSL.CRL.add_revoked` with other than one
3100 argument results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderoneecef6fa2010-01-30 13:47:18 -05003101 """
3102 crl = CRL()
3103 self.assertRaises(TypeError, crl.add_revoked)
3104 self.assertRaises(TypeError, crl.add_revoked, 1, 2)
3105 self.assertRaises(TypeError, crl.add_revoked, "foo", "bar")
3106
Rick Dean536ba022009-07-24 23:57:27 -05003107 def test_load_crl(self):
3108 """
3109 Load a known CRL and inspect its revocations. Both
3110 PEM and DER formats are loaded.
3111 """
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003112 crl = load_crl(FILETYPE_PEM, crlData)
Rick Dean536ba022009-07-24 23:57:27 -05003113 revs = crl.get_revoked()
3114 self.assertEqual(len(revs), 2)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003115 self.assertEqual(revs[0].get_serial(), b('03AB'))
Rick Dean6385faf2009-07-26 00:07:47 -05003116 self.assertEqual(revs[0].get_reason(), None)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003117 self.assertEqual(revs[1].get_serial(), b('0100'))
3118 self.assertEqual(revs[1].get_reason(), b('Superseded'))
Rick Dean536ba022009-07-24 23:57:27 -05003119
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003120 der = _runopenssl(crlData, b"crl", b"-outform", b"DER")
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05003121 crl = load_crl(FILETYPE_ASN1, der)
Rick Dean536ba022009-07-24 23:57:27 -05003122 revs = crl.get_revoked()
3123 self.assertEqual(len(revs), 2)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003124 self.assertEqual(revs[0].get_serial(), b('03AB'))
Rick Dean6385faf2009-07-26 00:07:47 -05003125 self.assertEqual(revs[0].get_reason(), None)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003126 self.assertEqual(revs[1].get_serial(), b('0100'))
3127 self.assertEqual(revs[1].get_reason(), b('Superseded'))
Rick Dean536ba022009-07-24 23:57:27 -05003128
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003129 def test_load_crl_wrong_args(self):
3130 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003131 Calling :py:obj:`OpenSSL.crypto.load_crl` with other than two
3132 arguments results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003133 """
3134 self.assertRaises(TypeError, load_crl)
3135 self.assertRaises(TypeError, load_crl, FILETYPE_PEM)
3136 self.assertRaises(TypeError, load_crl, FILETYPE_PEM, crlData, None)
3137
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003138 def test_load_crl_bad_filetype(self):
3139 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003140 Calling :py:obj:`OpenSSL.crypto.load_crl` with an unknown file type
3141 raises a :py:obj:`ValueError`.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003142 """
3143 self.assertRaises(ValueError, load_crl, 100, crlData)
3144
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003145 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
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003154class X509StoreContextTests(TestCase):
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003155 """
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003156 Tests for :py:obj:`OpenSSL.crypto.X509StoreContext`.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003157 """
3158 root_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3159 intermediate_cert = load_certificate(FILETYPE_PEM, intermediate_cert_pem)
3160 intermediate_server_cert = load_certificate(FILETYPE_PEM, intermediate_server_cert_pem)
3161
3162 def test_valid(self):
3163 """
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003164 :py:obj:`verify_certificate` returns ``None`` when called with a certificate
Jean-Paul Calderone06e01b92015-01-18 15:43:13 -05003165 and valid chain.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003166 """
3167 store = X509Store()
3168 store.add_cert(self.root_cert)
3169 store.add_cert(self.intermediate_cert)
3170 store_ctx = X509StoreContext(store, self.intermediate_server_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003171 self.assertEqual(store_ctx.verify_certificate(), None)
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003172
3173 def test_reuse(self):
3174 """
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003175 :py:obj:`verify_certificate` can be called multiple times with the same
Jean-Paul Calderone06e01b92015-01-18 15:43:13 -05003176 ``X509StoreContext`` instance to produce the same result.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003177 """
3178 store = X509Store()
3179 store.add_cert(self.root_cert)
3180 store.add_cert(self.intermediate_cert)
3181 store_ctx = X509StoreContext(store, self.intermediate_server_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003182 self.assertEqual(store_ctx.verify_certificate(), None)
3183 self.assertEqual(store_ctx.verify_certificate(), None)
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003184
3185 def test_trusted_self_signed(self):
3186 """
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003187 :py:obj:`verify_certificate` returns ``None`` when called with a self-signed
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003188 certificate and itself in the chain.
3189 """
3190 store = X509Store()
3191 store.add_cert(self.root_cert)
3192 store_ctx = X509StoreContext(store, self.root_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003193 self.assertEqual(store_ctx.verify_certificate(), None)
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003194
3195 def test_untrusted_self_signed(self):
3196 """
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003197 :py:obj:`verify_certificate` raises error when a self-signed certificate is
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003198 verified without itself in the chain.
3199 """
3200 store = X509Store()
3201 store_ctx = X509StoreContext(store, self.root_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003202 e = self.assertRaises(X509StoreContextError, store_ctx.verify_certificate)
Jean-Paul Calderone4c10a1e2015-01-18 16:31:27 -05003203 self.assertEqual(e.args[0][2], 'self signed certificate')
Jean-Paul Calderone06e01b92015-01-18 15:43:13 -05003204 self.assertEqual(e.certificate.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003205
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003206 def test_invalid_chain_no_root(self):
3207 """
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003208 :py:obj:`verify_certificate` raises error when a root certificate is missing
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003209 from the chain.
3210 """
3211 store = X509Store()
3212 store.add_cert(self.intermediate_cert)
3213 store_ctx = X509StoreContext(store, self.intermediate_server_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003214 e = self.assertRaises(X509StoreContextError, store_ctx.verify_certificate)
Jean-Paul Calderone4c10a1e2015-01-18 16:31:27 -05003215 self.assertEqual(e.args[0][2], 'unable to get issuer certificate')
Jean-Paul Calderone06e01b92015-01-18 15:43:13 -05003216 self.assertEqual(e.certificate.get_subject().CN, 'intermediate')
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003217
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003218 def test_invalid_chain_no_intermediate(self):
3219 """
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003220 :py:obj:`verify_certificate` raises error when an intermediate certificate is
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003221 missing from the chain.
3222 """
3223 store = X509Store()
3224 store.add_cert(self.root_cert)
3225 store_ctx = X509StoreContext(store, self.intermediate_server_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003226 e = self.assertRaises(X509StoreContextError, store_ctx.verify_certificate)
Jean-Paul Calderone4c10a1e2015-01-18 16:31:27 -05003227 self.assertEqual(e.args[0][2], 'unable to get local issuer certificate')
Jean-Paul Calderone06e01b92015-01-18 15:43:13 -05003228 self.assertEqual(e.certificate.get_subject().CN, 'intermediate-service')
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003229
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003230
Stephen Holsapple46a09252015-02-12 14:45:43 -08003231 def test_modification_pre_verify(self):
3232 """
3233 :py:obj:`verify_certificate` can use a store context modified after
3234 instantiation.
3235 """
3236 store_bad = X509Store()
3237 store_bad.add_cert(self.intermediate_cert)
3238 store_good = X509Store()
3239 store_good.add_cert(self.root_cert)
3240 store_good.add_cert(self.intermediate_cert)
3241 store_ctx = X509StoreContext(store_bad, self.intermediate_server_cert)
3242 e = self.assertRaises(X509StoreContextError, store_ctx.verify_certificate)
3243 self.assertEqual(e.args[0][2], 'unable to get issuer certificate')
3244 self.assertEqual(e.certificate.get_subject().CN, 'intermediate')
3245 store_ctx.set_store(store_good)
3246 self.assertEqual(store_ctx.verify_certificate(), None)
3247
3248
James Yonan7c2e5d32010-02-27 05:45:50 -07003249class SignVerifyTests(TestCase):
3250 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003251 Tests for :py:obj:`OpenSSL.crypto.sign` and :py:obj:`OpenSSL.crypto.verify`.
James Yonan7c2e5d32010-02-27 05:45:50 -07003252 """
Alex Gaynoraceb3e22015-09-05 12:00:22 -04003253
James Yonan7c2e5d32010-02-27 05:45:50 -07003254 def test_sign_verify(self):
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04003255 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003256 :py:obj:`sign` generates a cryptographic signature which :py:obj:`verify` can check.
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04003257 """
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003258 content = b(
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04003259 "It was a bright cold day in April, and the clocks were striking "
3260 "thirteen. Winston Smith, his chin nuzzled into his breast in an "
3261 "effort to escape the vile wind, slipped quickly through the "
3262 "glass doors of Victory Mansions, though not quickly enough to "
3263 "prevent a swirl of gritty dust from entering along with him.")
3264
3265 # sign the content with this private key
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04003266 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04003267 # verify the content with this cert
3268 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3269 # certificate unrelated to priv_key, used to trigger an error
3270 bad_cert = load_certificate(FILETYPE_PEM, server_cert_pem)
James Yonan7c2e5d32010-02-27 05:45:50 -07003271
Jean-Paul Calderoned08feb02010-10-12 21:53:24 -04003272 for digest in ['md5', 'sha1']:
James Yonan7c2e5d32010-02-27 05:45:50 -07003273 sig = sign(priv_key, content, digest)
3274
Alex Gaynoraceb3e22015-09-05 12:00:22 -04003275 # Verify the signature of content, will throw an exception if
3276 # error.
James Yonan7c2e5d32010-02-27 05:45:50 -07003277 verify(good_cert, sig, content, digest)
3278
3279 # This should fail because the certificate doesn't match the
3280 # private key that was used to sign the content.
3281 self.assertRaises(Error, verify, bad_cert, sig, content, digest)
3282
3283 # This should fail because we've "tainted" the content after
3284 # signing it.
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003285 self.assertRaises(
3286 Error, verify,
3287 good_cert, sig, content + b("tainted"), digest)
James Yonan7c2e5d32010-02-27 05:45:50 -07003288
3289 # test that unknown digest types fail
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003290 self.assertRaises(
Jean-Paul Calderone9538f142010-10-13 22:13:40 -04003291 ValueError, sign, priv_key, content, "strange-digest")
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003292 self.assertRaises(
Jean-Paul Calderone9538f142010-10-13 22:13:40 -04003293 ValueError, verify, good_cert, sig, content, "strange-digest")
James Yonan7c2e5d32010-02-27 05:45:50 -07003294
Abraham Martinc5484ba2015-03-25 15:33:05 +00003295 def test_sign_verify_with_text(self):
3296 """
3297 :py:obj:`sign` generates a cryptographic signature which :py:obj:`verify` can check.
3298 Deprecation warnings raised because using text instead of bytes as content
3299 """
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003300 content = (
Jean-Paul Calderone362c1f52015-03-29 08:01:39 -04003301 b"It was a bright cold day in April, and the clocks were striking "
3302 b"thirteen. Winston Smith, his chin nuzzled into his breast in an "
3303 b"effort to escape the vile wind, slipped quickly through the "
3304 b"glass doors of Victory Mansions, though not quickly enough to "
3305 b"prevent a swirl of gritty dust from entering along with him."
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003306 ).decode("ascii")
Abraham Martinc5484ba2015-03-25 15:33:05 +00003307
3308 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
3309 cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3310 for digest in ['md5', 'sha1']:
3311 with catch_warnings(record=True) as w:
3312 simplefilter("always")
3313 sig = sign(priv_key, content, digest)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003314
3315 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003316 "{0} for data is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003317 WARNING_TYPE_EXPECTED
3318 ),
3319 str(w[-1].message)
3320 )
3321 self.assertIs(w[-1].category, DeprecationWarning)
3322
Abraham Martinc5484ba2015-03-25 15:33:05 +00003323 with catch_warnings(record=True) as w:
3324 simplefilter("always")
3325 verify(cert, sig, content, digest)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003326
3327 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003328 "{0} for data is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003329 WARNING_TYPE_EXPECTED
3330 ),
3331 str(w[-1].message)
3332 )
3333 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinc5484ba2015-03-25 15:33:05 +00003334
Jean-Paul Calderone9828f662010-12-08 22:57:26 -05003335 def test_sign_nulls(self):
3336 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003337 :py:obj:`sign` produces a signature for a string with embedded nulls.
Jean-Paul Calderone9828f662010-12-08 22:57:26 -05003338 """
3339 content = b("Watch out! \0 Did you see it?")
3340 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
3341 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3342 sig = sign(priv_key, content, "sha1")
3343 verify(good_cert, sig, content, "sha1")
3344
3345
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003346class EllipticCurveTests(TestCase):
3347 """
3348 Tests for :py:class:`_EllipticCurve`, :py:obj:`get_elliptic_curve`, and
3349 :py:obj:`get_elliptic_curves`.
3350 """
Alex Gaynoraceb3e22015-09-05 12:00:22 -04003351
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003352 def test_set(self):
3353 """
3354 :py:obj:`get_elliptic_curves` returns a :py:obj:`set`.
3355 """
3356 self.assertIsInstance(get_elliptic_curves(), set)
3357
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003358 def test_some_curves(self):
3359 """
3360 If :py:mod:`cryptography` has elliptic curve support then the set
3361 returned by :py:obj:`get_elliptic_curves` has some elliptic curves in
3362 it.
3363
3364 There could be an OpenSSL that violates this assumption. If so, this
3365 test will fail and we'll find out.
3366 """
3367 curves = get_elliptic_curves()
3368 if lib.Cryptography_HAS_EC:
3369 self.assertTrue(curves)
3370 else:
3371 self.assertFalse(curves)
3372
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003373 def test_a_curve(self):
3374 """
3375 :py:obj:`get_elliptic_curve` can be used to retrieve a particular
3376 supported curve.
3377 """
3378 curves = get_elliptic_curves()
3379 if curves:
3380 curve = next(iter(curves))
3381 self.assertEqual(curve.name, get_elliptic_curve(curve.name).name)
3382 else:
Jean-Paul Calderoneeb86f3a2014-04-19 09:45:57 -04003383 self.assertRaises(ValueError, get_elliptic_curve, u("prime256v1"))
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003384
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003385 def test_not_a_curve(self):
3386 """
3387 :py:obj:`get_elliptic_curve` raises :py:class:`ValueError` if called
3388 with a name which does not identify a supported curve.
3389 """
3390 self.assertRaises(
Jean-Paul Calderone5a82db92014-04-19 09:51:29 -04003391 ValueError, get_elliptic_curve, u("this curve was just invented"))
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003392
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003393 def test_repr(self):
3394 """
3395 The string representation of a curve object includes simply states the
3396 object is a curve and what its name is.
3397 """
3398 curves = get_elliptic_curves()
3399 if curves:
3400 curve = next(iter(curves))
3401 self.assertEqual("<Curve %r>" % (curve.name,), repr(curve))
3402
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003403 def test_to_EC_KEY(self):
3404 """
3405 The curve object can export a version of itself as an EC_KEY* via the
3406 private :py:meth:`_EllipticCurve._to_EC_KEY`.
3407 """
3408 curves = get_elliptic_curves()
3409 if curves:
3410 curve = next(iter(curves))
3411 # It's not easy to assert anything about this object. However, see
3412 # leakcheck/crypto.py for a test that demonstrates it at least does
3413 # not leak memory.
3414 curve._to_EC_KEY()
3415
3416
Jean-Paul Calderone1be77082014-04-30 18:17:41 -04003417class EllipticCurveFactory(object):
3418 """
3419 A helper to get the names of two curves.
3420 """
Alex Gaynoraceb3e22015-09-05 12:00:22 -04003421
Jean-Paul Calderone1be77082014-04-30 18:17:41 -04003422 def __init__(self):
3423 curves = iter(get_elliptic_curves())
3424 try:
3425 self.curve_name = next(curves).name
3426 self.another_curve_name = next(curves).name
3427 except StopIteration:
3428 self.curve_name = self.another_curve_name = None
3429
3430
Jean-Paul Calderone1be77082014-04-30 18:17:41 -04003431class EllipticCurveEqualityTests(TestCase, EqualityTestsMixin):
3432 """
3433 Tests :py:type:`_EllipticCurve`\ 's implementation of ``==`` and ``!=``.
3434 """
3435 curve_factory = EllipticCurveFactory()
3436
3437 if curve_factory.curve_name is None:
3438 skip = "There are no curves available there can be no curve objects."
3439
Jean-Paul Calderone1be77082014-04-30 18:17:41 -04003440 def anInstance(self):
3441 """
3442 Get the curve object for an arbitrary curve supported by the system.
3443 """
3444 return get_elliptic_curve(self.curve_factory.curve_name)
3445
Jean-Paul Calderone1be77082014-04-30 18:17:41 -04003446 def anotherInstance(self):
3447 """
3448 Get the curve object for an arbitrary curve supported by the system -
3449 but not the one returned by C{anInstance}.
3450 """
3451 return get_elliptic_curve(self.curve_factory.another_curve_name)
3452
3453
Jean-Paul Calderone22c31242014-05-01 07:49:47 -04003454class EllipticCurveHashTests(TestCase):
3455 """
3456 Tests for :py:type:`_EllipticCurve`\ 's implementation of hashing (thus use
3457 as an item in a :py:type:`dict` or :py:type:`set`).
3458 """
3459 curve_factory = EllipticCurveFactory()
3460
3461 if curve_factory.curve_name is None:
3462 skip = "There are no curves available there can be no curve objects."
3463
Jean-Paul Calderone22c31242014-05-01 07:49:47 -04003464 def test_contains(self):
3465 """
3466 The ``in`` operator reports that a :py:type:`set` containing a curve
3467 does contain that curve.
3468 """
3469 curve = get_elliptic_curve(self.curve_factory.curve_name)
3470 curves = set([curve])
3471 self.assertIn(curve, curves)
3472
Jean-Paul Calderone22c31242014-05-01 07:49:47 -04003473 def test_does_not_contain(self):
3474 """
3475 The ``in`` operator reports that a :py:type:`set` not containing a
3476 curve does not contain that curve.
3477 """
3478 curve = get_elliptic_curve(self.curve_factory.curve_name)
3479 curves = set([get_elliptic_curve(self.curve_factory.another_curve_name)])
3480 self.assertNotIn(curve, curves)
3481
3482
Rick Dean5b7b6372009-04-01 11:34:06 -05003483if __name__ == '__main__':
3484 main()