blob: b82728108a97935548a1ca7514784891f5a5a776 [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
Jean-Paul Calderoneeb86f3a2014-04-19 09:45:57 -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 Calderone1be77082014-04-30 18:17:41 -040034from OpenSSL.test.util import EqualityTestsMixin, TestCase
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040035from OpenSSL._util import native, lib
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040036
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -040037def normalize_certificate_pem(pem):
38 return dump_certificate(FILETYPE_PEM, load_certificate(FILETYPE_PEM, pem))
39
40
41def normalize_privatekey_pem(pem):
42 return dump_privatekey(FILETYPE_PEM, load_privatekey(FILETYPE_PEM, pem))
43
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040044
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050045GOOD_CIPHER = "blowfish"
46BAD_CIPHER = "zippers"
47
48GOOD_DIGEST = "MD5"
49BAD_DIGEST = "monkeys"
50
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040051root_cert_pem = b("""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -050052MIIC7TCCAlagAwIBAgIIPQzE4MbeufQwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE
53BhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdU
54ZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwIhgPMjAwOTAzMjUxMjM2
55NThaGA8yMDE3MDYxMTEyMzY1OFowWDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklM
56MRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9U
57ZXN0aW5nIFJvb3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPmaQumL
58urpE527uSEHdL1pqcDRmWzu+98Y6YHzT/J7KWEamyMCNZ6fRW1JCR782UQ8a07fy
592xXsKy4WdKaxyG8CcatwmXvpvRQ44dSANMihHELpANTdyVp6DCysED6wkQFurHlF
601dshEaJw8b/ypDhmbVIo6Ci1xvCJqivbLFnbAgMBAAGjgbswgbgwHQYDVR0OBBYE
61FINVdy1eIfFJDAkk51QJEo3IfgSuMIGIBgNVHSMEgYAwfoAUg1V3LV4h8UkMCSTn
62VAkSjch+BK6hXKRaMFgxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UE
63BxMHQ2hpY2FnbzEQMA4GA1UEChMHVGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBS
64b290IENBggg9DMTgxt659DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB
65AGGCDazMJGoWNBpc03u6+smc95dEead2KlZXBATOdFT1VesY3+nUOqZhEhTGlDMi
66hkgaZnzoIq/Uamidegk4hirsCT/R+6vsKAAxNTcBjUeZjlykCJWy5ojShGftXIKY
67w/njVbKMXrvc83qmTdGl3TAM0fxQIpqgcglFLveEBgzn
68-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040069""")
Rick Dean94e46fd2009-07-18 14:51:24 -050070
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040071root_key_pem = b("""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -050072MIICXQIBAAKBgQD5mkLpi7q6ROdu7khB3S9aanA0Zls7vvfGOmB80/yeylhGpsjA
73jWen0VtSQke/NlEPGtO38tsV7CsuFnSmschvAnGrcJl76b0UOOHUgDTIoRxC6QDU
743claegwsrBA+sJEBbqx5RdXbIRGicPG/8qQ4Zm1SKOgotcbwiaor2yxZ2wIDAQAB
75AoGBAPCgMpmLxzwDaUmcFbTJUvlLW1hoxNNYSu2jIZm1k/hRAcE60JYwvBkgz3UB
76yMEh0AtLxYe0bFk6EHah11tMUPgscbCq73snJ++8koUw+csk22G65hOs51bVb7Aa
776JBe67oLzdtvgCUFAA2qfrKzWRZzAdhUirQUZgySZk+Xq1pBAkEA/kZG0A6roTSM
78BVnx7LnPfsycKUsTumorpXiylZJjTi9XtmzxhrYN6wgZlDOOwOLgSQhszGpxVoMD
79u3gByT1b2QJBAPtL3mSKdvwRu/+40zaZLwvSJRxaj0mcE4BJOS6Oqs/hS1xRlrNk
80PpQ7WJ4yM6ZOLnXzm2mKyxm50Mv64109FtMCQQDOqS2KkjHaLowTGVxwC0DijMfr
81I9Lf8sSQk32J5VWCySWf5gGTfEnpmUa41gKTMJIbqZZLucNuDcOtzUaeWZlZAkA8
82ttXigLnCqR486JDPTi9ZscoZkZ+w7y6e/hH8t6d5Vjt48JVyfjPIaJY+km58LcN3
836AWSeGAdtRFHVzR7oHjVAkB4hutvxiOeiIVQNBhM6RSI9aBPMI21DoX2JRoxvNW2
84cbvAhow217X9V0dVerEOKxnNYspXRrh36h7k4mQA+sDq
85-----END RSA PRIVATE KEY-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040086""")
Rick Dean94e46fd2009-07-18 14:51:24 -050087
Stephen Holsapple0d9815f2014-08-27 19:36:53 -070088intermediate_cert_pem = b("""-----BEGIN CERTIFICATE-----
89MIICVzCCAcCgAwIBAgIRAMPzhm6//0Y/g2pmnHR2C4cwDQYJKoZIhvcNAQENBQAw
90WDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAw
91DgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwHhcNMTQw
92ODI4MDIwNDA4WhcNMjQwODI1MDIwNDA4WjBmMRUwEwYDVQQDEwxpbnRlcm1lZGlh
93dGUxDDAKBgNVBAoTA29yZzERMA8GA1UECxMIb3JnLXVuaXQxCzAJBgNVBAYTAlVT
94MQswCQYDVQQIEwJDQTESMBAGA1UEBxMJU2FuIERpZWdvMIGfMA0GCSqGSIb3DQEB
95AQUAA4GNADCBiQKBgQDYcEQw5lfbEQRjr5Yy4yxAHGV0b9Al+Lmu7wLHMkZ/ZMmK
96FGIbljbviiD1Nz97Oh2cpB91YwOXOTN2vXHq26S+A5xe8z/QJbBsyghMur88CjdT
9721H2qwMa+r5dCQwEhuGIiZ3KbzB/n4DTMYI5zy4IYPv0pjxShZn4aZTCCK2IUwID
98AQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBDQUAA4GBAPIWSkLX
99QRMApOjjyC+tMxumT5e2pMqChHmxobQK4NMdrf2VCx+cRT6EmY8sK3/Xl/X8UBQ+
1009n5zXb1ZwhW/sTWgUvmOceJ4/XVs9FkdWOOn1J0XBch9ZIiFe/s5ASIgG7fUdcUF
1019mAWS6FK2ca3xIh5kIupCXOFa0dPvlw/YUFT
102-----END CERTIFICATE-----
103""")
104
105intermediate_key_pem = b("""-----BEGIN RSA PRIVATE KEY-----
106MIICWwIBAAKBgQDYcEQw5lfbEQRjr5Yy4yxAHGV0b9Al+Lmu7wLHMkZ/ZMmKFGIb
107ljbviiD1Nz97Oh2cpB91YwOXOTN2vXHq26S+A5xe8z/QJbBsyghMur88CjdT21H2
108qwMa+r5dCQwEhuGIiZ3KbzB/n4DTMYI5zy4IYPv0pjxShZn4aZTCCK2IUwIDAQAB
109AoGAfSZVV80pSeOKHTYfbGdNY/jHdU9eFUa/33YWriXU+77EhpIItJjkRRgivIfo
110rhFJpBSGmDLblaqepm8emsXMeH4+2QzOYIf0QGGP6E6scjTt1PLqdqKfVJ1a2REN
111147cujNcmFJb/5VQHHMpaPTgttEjlzuww4+BCDPsVRABWrkCQQD3loH36nLoQTtf
112+kQq0T6Bs9/UWkTAGo0ND81ALj0F8Ie1oeZg6RNT96RxZ3aVuFTESTv6/TbjWywO
113wdzlmV1vAkEA38rTJ6PTwaJlw5OttdDzAXGPB9tDmzh9oSi7cHwQQXizYd8MBYx4
114sjHUKD3dCQnb1dxJFhd3BT5HsnkRMbVZXQJAbXduH17ZTzcIOXc9jHDXYiFVZV5D
11552vV0WCbLzVCZc3jMrtSUKa8lPN5EWrdU3UchWybyG0MR5mX8S5lrF4SoQJAIyUD
116DBKaSqpqONCUUx1BTFS9FYrFjzbL4+c1qHCTTPTblt8kUCrDOZjBrKAqeiTmNSum
117/qUot9YUBF8m6BuGsQJATHHmdFy/fG1VLkyBp49CAa8tN3Z5r/CgTznI4DfMTf4C
118NbRHn2UmYlwQBa+L5lg9phewNe8aEwpPyPLoV85U8Q==
119-----END RSA PRIVATE KEY-----
120""")
121
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400122server_cert_pem = b("""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500123MIICKDCCAZGgAwIBAgIJAJn/HpR21r/8MA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
124BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
125VGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBSb290IENBMCIYDzIwMDkwMzI1MTIz
126NzUzWhgPMjAxNzA2MTExMjM3NTNaMBgxFjAUBgNVBAMTDWxvdmVseSBzZXJ2ZXIw
127gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAL6m+G653V0tpBC/OKl22VxOi2Cv
128lK4TYu9LHSDP9uDVTe7V5D5Tl6qzFoRRx5pfmnkqT5B+W9byp2NU3FC5hLm5zSAr
129b45meUhjEJ/ifkZgbNUjHdBIGP9MAQUHZa5WKdkGIJvGAvs8UzUqlr4TBWQIB24+
130lJ+Ukk/CRgasrYwdAgMBAAGjNjA0MB0GA1UdDgQWBBS4kC7Ij0W1TZXZqXQFAM2e
131gKEG2DATBgNVHSUEDDAKBggrBgEFBQcDATANBgkqhkiG9w0BAQUFAAOBgQBh30Li
132dJ+NlxIOx5343WqIBka3UbsOb2kxWrbkVCrvRapCMLCASO4FqiKWM+L0VDBprqIp
1332mgpFQ6FHpoIENGvJhdEKpptQ5i7KaGhnDNTfdy3x1+h852G99f1iyj0RmbuFcM8
134uzujnS8YXWvM7DM1Ilozk4MzPug8jzFp5uhKCQ==
135-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400136""")
Rick Dean94e46fd2009-07-18 14:51:24 -0500137
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -0400138server_key_pem = normalize_privatekey_pem(b("""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500139MIICWwIBAAKBgQC+pvhuud1dLaQQvzipdtlcTotgr5SuE2LvSx0gz/bg1U3u1eQ+
140U5eqsxaEUceaX5p5Kk+QflvW8qdjVNxQuYS5uc0gK2+OZnlIYxCf4n5GYGzVIx3Q
141SBj/TAEFB2WuVinZBiCbxgL7PFM1Kpa+EwVkCAduPpSflJJPwkYGrK2MHQIDAQAB
142AoGAbwuZ0AR6JveahBaczjfnSpiFHf+mve2UxoQdpyr6ROJ4zg/PLW5K/KXrC48G
143j6f3tXMrfKHcpEoZrQWUfYBRCUsGD5DCazEhD8zlxEHahIsqpwA0WWssJA2VOLEN
144j6DuV2pCFbw67rfTBkTSo32ahfXxEKev5KswZk0JIzH3ooECQQDgzS9AI89h0gs8
145Dt+1m11Rzqo3vZML7ZIyGApUzVan+a7hbc33nbGRkAXjHaUBJO31it/H6dTO+uwX
146msWwNG5ZAkEA2RyFKs5xR5USTFaKLWCgpH/ydV96KPOpBND7TKQx62snDenFNNbn
147FwwOhpahld+vqhYk+pfuWWUpQciE+Bu7ZQJASjfT4sQv4qbbKK/scePicnDdx9th
1484e1EeB9xwb+tXXXUo/6Bor/AcUNwfiQ6Zt9PZOK9sR3lMZSsP7rMi7kzuQJABie6
1491sXXjFH7nNJvRG4S39cIxq8YRYTy68II/dlB2QzGpKxV/POCxbJ/zu0CU79tuYK7
150NaeNCFfH3aeTrX0LyQJAMBWjWmeKM2G2sCExheeQK0ROnaBC8itCECD4Jsve4nqf
151r50+LF74iLXFwqysVCebPKMOpDWp/qQ1BbJQIPs7/A==
152-----END RSA PRIVATE KEY-----
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -0400153"""))
Rick Dean94e46fd2009-07-18 14:51:24 -0500154
Stephen Holsapple0d9815f2014-08-27 19:36:53 -0700155intermediate_server_cert_pem = b("""-----BEGIN CERTIFICATE-----
156MIICWDCCAcGgAwIBAgIRAPQFY9jfskSihdiNSNdt6GswDQYJKoZIhvcNAQENBQAw
157ZjEVMBMGA1UEAxMMaW50ZXJtZWRpYXRlMQwwCgYDVQQKEwNvcmcxETAPBgNVBAsT
158CG9yZy11bml0MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVNh
159biBEaWVnbzAeFw0xNDA4MjgwMjEwNDhaFw0yNDA4MjUwMjEwNDhaMG4xHTAbBgNV
160BAMTFGludGVybWVkaWF0ZS1zZXJ2aWNlMQwwCgYDVQQKEwNvcmcxETAPBgNVBAsT
161CG9yZy11bml0MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVNh
162biBEaWVnbzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqpJZygd+w1faLOr1
163iOAmbBhx5SZWcTCZ/ZjHQTJM7GuPT624QkqsixFghRKdDROwpwnAP7gMRukLqiy4
164+kRuGT5OfyGggL95i2xqA+zehjj08lSTlvGHpePJgCyTavIy5+Ljsj4DKnKyuhxm
165biXTRrH83NDgixVkObTEmh/OVK0CAwEAATANBgkqhkiG9w0BAQ0FAAOBgQBa0Npw
166UkzjaYEo1OUE1sTI6Mm4riTIHMak4/nswKh9hYup//WVOlr/RBSBtZ7Q/BwbjobN
1673bfAtV7eSAqBsfxYXyof7G1ALANQERkq3+oyLP1iVt08W1WOUlIMPhdCF/QuCwy6
168x9MJLhUCGLJPM+O2rAPWVD9wCmvq10ALsiH3yA==
169-----END CERTIFICATE-----
170""")
171
172intermediate_server_key_pem = b("""-----BEGIN RSA PRIVATE KEY-----
173MIICXAIBAAKBgQCqklnKB37DV9os6vWI4CZsGHHlJlZxMJn9mMdBMkzsa49PrbhC
174SqyLEWCFEp0NE7CnCcA/uAxG6QuqLLj6RG4ZPk5/IaCAv3mLbGoD7N6GOPTyVJOW
1758Yel48mALJNq8jLn4uOyPgMqcrK6HGZuJdNGsfzc0OCLFWQ5tMSaH85UrQIDAQAB
176AoGAIQ594j5zna3/9WaPsTgnmhlesVctt4AAx/n827DA4ayyuHFlXUuVhtoWR5Pk
1775ezj9mtYW8DyeCegABnsu2vZni/CdvU6uiS1Hv6qM1GyYDm9KWgovIP9rQCDSGaz
178d57IWVGxx7ODFkm3gN5nxnSBOFVHytuW1J7FBRnEsehRroECQQDXHFOv82JuXDcz
179z3+4c74IEURdOHcbycxlppmK9kFqm5lsUdydnnGW+mvwDk0APOB7Wg7vyFyr393e
180dpmBDCzNAkEAyv6tVbTKUYhSjW+QhabJo896/EqQEYUmtMXxk4cQnKeR/Ao84Rkf
181EqD5IykMUfUI0jJU4DGX+gWZ10a7kNbHYQJAVFCuHNFxS4Cpwo0aqtnzKoZaHY/8
182X9ABZfafSHCtw3Op92M+7ikkrOELXdS9KdKyyqbKJAKNEHF3LbOfB44WIQJAA2N4
1839UNNVUsXRbElEnYUS529CdUczo4QdVgQjkvk5RiPAUwSdBd9Q0xYnFOlFwEmIowg
184ipWJWe0aAlP18ZcEQQJBAL+5lekZ/GUdQoZ4HAsN5a9syrzavJ9VvU1KOOPorPZK
185nMRZbbQgP+aSB7yl6K0gaLaZ8XaK0pjxNBh6ASqg9f4=
186-----END RSA PRIVATE KEY-----
187""")
188
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400189client_cert_pem = b("""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500190MIICJjCCAY+gAwIBAgIJAKxpFI5lODkjMA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
191BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
192VGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBSb290IENBMCIYDzIwMDkwMzI1MTIz
193ODA1WhgPMjAxNzA2MTExMjM4MDVaMBYxFDASBgNVBAMTC3VnbHkgY2xpZW50MIGf
194MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDAZh/SRtNm5ntMT4qb6YzEpTroMlq2
195rn+GrRHRiZ+xkCw/CGNhbtPir7/QxaUj26BSmQrHw1bGKEbPsWiW7bdXSespl+xK
196iku4G/KvnnmWdeJHqsiXeUZtqurMELcPQAw9xPHEuhqqUJvvEoMTsnCEqGM+7Dtb
197oCRajYyHfluARQIDAQABozYwNDAdBgNVHQ4EFgQUNQB+qkaOaEVecf1J3TTUtAff
1980fAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQEFBQADgYEAyv/Jh7gM
199Q3OHvmsFEEvRI+hsW8y66zK4K5de239Y44iZrFYkt7Q5nBPMEWDj4F2hLYWL/qtI
2009Zdr0U4UDCU9SmmGYh4o7R4TZ5pGFvBYvjhHbkSFYFQXZxKUi+WUxplP6I0wr2KJ
201PSTJCjJOn3xo2NTKRgV1gaoTf2EhL+RG8TQ=
202-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400203""")
Rick Dean94e46fd2009-07-18 14:51:24 -0500204
Jean-Paul Calderone22cbe502011-05-04 17:01:43 -0400205client_key_pem = normalize_privatekey_pem(b("""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500206MIICXgIBAAKBgQDAZh/SRtNm5ntMT4qb6YzEpTroMlq2rn+GrRHRiZ+xkCw/CGNh
207btPir7/QxaUj26BSmQrHw1bGKEbPsWiW7bdXSespl+xKiku4G/KvnnmWdeJHqsiX
208eUZtqurMELcPQAw9xPHEuhqqUJvvEoMTsnCEqGM+7DtboCRajYyHfluARQIDAQAB
209AoGATkZ+NceY5Glqyl4mD06SdcKfV65814vg2EL7V9t8+/mi9rYL8KztSXGlQWPX
210zuHgtRoMl78yQ4ZJYOBVo+nsx8KZNRCEBlE19bamSbQLCeQMenWnpeYyQUZ908gF
211h6L9qsFVJepgA9RDgAjyDoS5CaWCdCCPCH2lDkdcqC54SVUCQQDseuduc4wi8h4t
212V8AahUn9fn9gYfhoNuM0gdguTA0nPLVWz4hy1yJiWYQe0H7NLNNTmCKiLQaJpAbb
213TC6vE8C7AkEA0Ee8CMJUc20BnGEmxwgWcVuqFWaKCo8jTH1X38FlATUsyR3krjW2
214dL3yDD9NwHxsYP7nTKp/U8MV7U9IBn4y/wJBAJl7H0/BcLeRmuJk7IqJ7b635iYB
215D/9beFUw3MUXmQXZUfyYz39xf6CDZsu1GEdEC5haykeln3Of4M9d/4Kj+FcCQQCY
216si6xwT7GzMDkk/ko684AV3KPc/h6G0yGtFIrMg7J3uExpR/VdH2KgwMkZXisSMvw
217JJEQjOMCVsEJlRk54WWjAkEAzoZNH6UhDdBK5F38rVt/y4SEHgbSfJHIAmPS32Kq
218f6GGcfNpip0Uk7q7udTKuX7Q/buZi/C4YW7u3VKAquv9NA==
219-----END RSA PRIVATE KEY-----
Jean-Paul Calderone22cbe502011-05-04 17:01:43 -0400220"""))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400221
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400222cleartextCertificatePEM = b("""-----BEGIN CERTIFICATE-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400223MIIC7TCCAlagAwIBAgIIPQzE4MbeufQwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE
224BhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdU
225ZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwIhgPMjAwOTAzMjUxMjM2
226NThaGA8yMDE3MDYxMTEyMzY1OFowWDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklM
227MRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9U
228ZXN0aW5nIFJvb3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPmaQumL
229urpE527uSEHdL1pqcDRmWzu+98Y6YHzT/J7KWEamyMCNZ6fRW1JCR782UQ8a07fy
2302xXsKy4WdKaxyG8CcatwmXvpvRQ44dSANMihHELpANTdyVp6DCysED6wkQFurHlF
2311dshEaJw8b/ypDhmbVIo6Ci1xvCJqivbLFnbAgMBAAGjgbswgbgwHQYDVR0OBBYE
232FINVdy1eIfFJDAkk51QJEo3IfgSuMIGIBgNVHSMEgYAwfoAUg1V3LV4h8UkMCSTn
233VAkSjch+BK6hXKRaMFgxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UE
234BxMHQ2hpY2FnbzEQMA4GA1UEChMHVGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBS
235b290IENBggg9DMTgxt659DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB
236AGGCDazMJGoWNBpc03u6+smc95dEead2KlZXBATOdFT1VesY3+nUOqZhEhTGlDMi
237hkgaZnzoIq/Uamidegk4hirsCT/R+6vsKAAxNTcBjUeZjlykCJWy5ojShGftXIKY
238w/njVbKMXrvc83qmTdGl3TAM0fxQIpqgcglFLveEBgzn
239-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400240""")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400241
Jean-Paul Calderoned50d2042011-05-04 17:00:49 -0400242cleartextPrivateKeyPEM = normalize_privatekey_pem(b("""\
243-----BEGIN RSA PRIVATE KEY-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400244MIICXQIBAAKBgQD5mkLpi7q6ROdu7khB3S9aanA0Zls7vvfGOmB80/yeylhGpsjA
245jWen0VtSQke/NlEPGtO38tsV7CsuFnSmschvAnGrcJl76b0UOOHUgDTIoRxC6QDU
2463claegwsrBA+sJEBbqx5RdXbIRGicPG/8qQ4Zm1SKOgotcbwiaor2yxZ2wIDAQAB
247AoGBAPCgMpmLxzwDaUmcFbTJUvlLW1hoxNNYSu2jIZm1k/hRAcE60JYwvBkgz3UB
248yMEh0AtLxYe0bFk6EHah11tMUPgscbCq73snJ++8koUw+csk22G65hOs51bVb7Aa
2496JBe67oLzdtvgCUFAA2qfrKzWRZzAdhUirQUZgySZk+Xq1pBAkEA/kZG0A6roTSM
250BVnx7LnPfsycKUsTumorpXiylZJjTi9XtmzxhrYN6wgZlDOOwOLgSQhszGpxVoMD
251u3gByT1b2QJBAPtL3mSKdvwRu/+40zaZLwvSJRxaj0mcE4BJOS6Oqs/hS1xRlrNk
252PpQ7WJ4yM6ZOLnXzm2mKyxm50Mv64109FtMCQQDOqS2KkjHaLowTGVxwC0DijMfr
253I9Lf8sSQk32J5VWCySWf5gGTfEnpmUa41gKTMJIbqZZLucNuDcOtzUaeWZlZAkA8
254ttXigLnCqR486JDPTi9ZscoZkZ+w7y6e/hH8t6d5Vjt48JVyfjPIaJY+km58LcN3
2556AWSeGAdtRFHVzR7oHjVAkB4hutvxiOeiIVQNBhM6RSI9aBPMI21DoX2JRoxvNW2
256cbvAhow217X9V0dVerEOKxnNYspXRrh36h7k4mQA+sDq
257-----END RSA PRIVATE KEY-----
Jean-Paul Calderoned50d2042011-05-04 17:00:49 -0400258"""))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400259
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400260cleartextCertificateRequestPEM = b("""-----BEGIN CERTIFICATE REQUEST-----
261MIIBnjCCAQcCAQAwXjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQH
262EwdDaGljYWdvMRcwFQYDVQQKEw5NeSBDb21wYW55IEx0ZDEXMBUGA1UEAxMORnJl
263ZGVyaWNrIERlYW4wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANp6Y17WzKSw
264BsUWkXdqg6tnXy8H8hA1msCMWpc+/2KJ4mbv5NyD6UD+/SqagQqulPbF/DFea9nA
265E0zhmHJELcM8gUTIlXv/cgDWnmK4xj8YkjVUiCdqKRAKeuzLG1pGmwwF5lGeJpXN
266xQn5ecR0UYSOWj6TTGXB9VyUMQzCClcBAgMBAAGgADANBgkqhkiG9w0BAQUFAAOB
267gQAAJGuF/R/GGbeC7FbFW+aJgr9ee0Xbl6nlhu7pTe67k+iiKT2dsl2ti68MVTnu
268Vrb3HUNqOkiwsJf6kCtq5oPn3QVYzTa76Dt2y3Rtzv6boRSlmlfrgS92GNma8JfR
269oICQk3nAudi6zl1Dix3BCv1pUp5KMtGn3MeDEi6QFGy2rA==
270-----END CERTIFICATE REQUEST-----
271""")
Rick Dean5b7b6372009-04-01 11:34:06 -0500272
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400273encryptedPrivateKeyPEM = b("""-----BEGIN RSA PRIVATE KEY-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400274Proc-Type: 4,ENCRYPTED
275DEK-Info: DES-EDE3-CBC,9573604A18579E9E
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400276
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400277SHOho56WxDkT0ht10UTeKc0F5u8cqIa01kzFAmETw0MAs8ezYtK15NPdCXUm3X/2
278a17G7LSF5bkxOgZ7vpXyMzun/owrj7CzvLxyncyEFZWvtvzaAhPhvTJtTIB3kf8B
2798+qRcpTGK7NgXEgYBW5bj1y4qZkD4zCL9o9NQzsKI3Ie8i0239jsDOWR38AxjXBH
280mGwAQ4Z6ZN5dnmM4fhMIWsmFf19sNyAML4gHenQCHhmXbjXeVq47aC2ProInJbrm
281+00TcisbAQ40V9aehVbcDKtS4ZbMVDwncAjpXpcncC54G76N6j7F7wL7L/FuXa3A
282fvSVy9n2VfF/pJ3kYSflLHH2G/DFxjF7dl0GxhKPxJjp3IJi9VtuvmN9R2jZWLQF
283tfC8dXgy/P9CfFQhlinqBTEwgH0oZ/d4k4NVFDSdEMaSdmBAjlHpc+Vfdty3HVnV
284rKXj//wslsFNm9kIwJGIgKUa/n2jsOiydrsk1mgH7SmNCb3YHgZhbbnq0qLat/HC
285gHDt3FHpNQ31QzzL3yrenFB2L9osIsnRsDTPFNi4RX4SpDgNroxOQmyzCCV6H+d4
286o1mcnNiZSdxLZxVKccq0AfRpHqpPAFnJcQHP6xyT9MZp6fBa0XkxDnt9kNU8H3Qw
2877SJWZ69VXjBUzMlQViLuaWMgTnL+ZVyFZf9hTF7U/ef4HMLMAVNdiaGG+G+AjCV/
288MbzjS007Oe4qqBnCWaFPSnJX6uLApeTbqAxAeyCql56ULW5x6vDMNC3dwjvS/CEh
28911n8RkgFIQA0AhuKSIg3CbuartRsJnWOLwgLTzsrKYL4yRog1RJrtw==
290-----END RSA PRIVATE KEY-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400291""")
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400292
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400293encryptedPrivateKeyPEMPassphrase = b("foobar")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400294
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400295# Some PKCS#7 stuff. Generated with the openssl command line:
296#
297# openssl crl2pkcs7 -inform pem -outform pem -certfile s.pem -nocrl
298#
299# with a certificate and key (but the key should be irrelevant) in s.pem
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400300pkcs7Data = b("""\
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400301-----BEGIN PKCS7-----
302MIIDNwYJKoZIhvcNAQcCoIIDKDCCAyQCAQExADALBgkqhkiG9w0BBwGgggMKMIID
303BjCCAm+gAwIBAgIBATANBgkqhkiG9w0BAQQFADB7MQswCQYDVQQGEwJTRzERMA8G
304A1UEChMITTJDcnlwdG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtN
305MkNyeXB0byBDZXJ0aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNA
306cG9zdDEuY29tMB4XDTAwMDkxMDA5NTEzMFoXDTAyMDkxMDA5NTEzMFowUzELMAkG
307A1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwlsb2NhbGhvc3Qx
308HTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tMFwwDQYJKoZIhvcNAQEBBQAD
309SwAwSAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh5kwI
310zOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEAAaOCAQQwggEAMAkGA1UdEwQCMAAw
311LAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0G
312A1UdDgQWBBTPhIKSvnsmYsBVNWjj0m3M2z0qVTCBpQYDVR0jBIGdMIGagBT7hyNp
31365w6kxXlxb8pUU/+7Sg4AaF/pH0wezELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0y
314Q3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlwdG8g
315Q2VydGlmaWNhdGUgTWFzdGVyMR0wGwYJKoZIhvcNAQkBFg5uZ3BzQHBvc3QxLmNv
316bYIBADANBgkqhkiG9w0BAQQFAAOBgQA7/CqT6PoHycTdhEStWNZde7M/2Yc6BoJu
317VwnW8YxGO8Sn6UJ4FeffZNcYZddSDKosw8LtPOeWoK3JINjAk5jiPQ2cww++7QGG
318/g5NDjxFZNDJP1dGiLAxPW6JXwov4v0FmdzfLOZ01jDcgQQZqEpYlgpuI5JEWUQ9
319Ho4EzbYCOaEAMQA=
320-----END PKCS7-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400321""")
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400322
Alex Gaynor8fa1dd62014-08-14 09:57:51 -0700323pkcs7DataASN1 = base64.b64decode(b"""
Alex Gaynor4b9c96a2014-08-14 09:51:48 -0700324MIIDNwYJKoZIhvcNAQcCoIIDKDCCAyQCAQExADALBgkqhkiG9w0BBwGgggMKMIID
325BjCCAm+gAwIBAgIBATANBgkqhkiG9w0BAQQFADB7MQswCQYDVQQGEwJTRzERMA8G
326A1UEChMITTJDcnlwdG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtN
327MkNyeXB0byBDZXJ0aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNA
328cG9zdDEuY29tMB4XDTAwMDkxMDA5NTEzMFoXDTAyMDkxMDA5NTEzMFowUzELMAkG
329A1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwlsb2NhbGhvc3Qx
330HTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tMFwwDQYJKoZIhvcNAQEBBQAD
331SwAwSAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh5kwI
332zOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEAAaOCAQQwggEAMAkGA1UdEwQCMAAw
333LAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0G
334A1UdDgQWBBTPhIKSvnsmYsBVNWjj0m3M2z0qVTCBpQYDVR0jBIGdMIGagBT7hyNp
33565w6kxXlxb8pUU/+7Sg4AaF/pH0wezELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0y
336Q3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlwdG8g
337Q2VydGlmaWNhdGUgTWFzdGVyMR0wGwYJKoZIhvcNAQkBFg5uZ3BzQHBvc3QxLmNv
338bYIBADANBgkqhkiG9w0BAQQFAAOBgQA7/CqT6PoHycTdhEStWNZde7M/2Yc6BoJu
339VwnW8YxGO8Sn6UJ4FeffZNcYZddSDKosw8LtPOeWoK3JINjAk5jiPQ2cww++7QGG
340/g5NDjxFZNDJP1dGiLAxPW6JXwov4v0FmdzfLOZ01jDcgQQZqEpYlgpuI5JEWUQ9
341Ho4EzbYCOaEAMQA=
Alex Gaynor8fa1dd62014-08-14 09:57:51 -0700342""")
Alex Gaynor4b9c96a2014-08-14 09:51:48 -0700343
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400344crlData = b("""\
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -0500345-----BEGIN X509 CRL-----
346MIIBWzCBxTANBgkqhkiG9w0BAQQFADBYMQswCQYDVQQGEwJVUzELMAkGA1UECBMC
347SUwxEDAOBgNVBAcTB0NoaWNhZ28xEDAOBgNVBAoTB1Rlc3RpbmcxGDAWBgNVBAMT
348D1Rlc3RpbmcgUm9vdCBDQRcNMDkwNzI2MDQzNDU2WhcNMTIwOTI3MDI0MTUyWjA8
349MBUCAgOrGA8yMDA5MDcyNTIzMzQ1NlowIwICAQAYDzIwMDkwNzI1MjMzNDU2WjAM
350MAoGA1UdFQQDCgEEMA0GCSqGSIb3DQEBBAUAA4GBAEBt7xTs2htdD3d4ErrcGAw1
3514dKcVnIWTutoI7xxen26Wwvh8VCsT7i/UeP+rBl9rC/kfjWjzQk3/zleaarGTpBT
3520yp4HXRFFoRhhSE/hP+eteaPXRgrsNRLHe9ZDd69wmh7J1wMDb0m81RG7kqcbsid
353vrzEeLDRiiPl92dyyWmu
354-----END X509 CRL-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400355""")
Jean-Paul Calderonee890db32010-08-22 16:55:15 -0400356
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400357
358# A broken RSA private key which can be used to test the error path through
359# PKey.check.
360inconsistentPrivateKeyPEM = b("""-----BEGIN RSA PRIVATE KEY-----
361MIIBPAIBAAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh
3625kwIzOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEaAQJBAIqm/bz4NA1H++Vx5Ewx
363OcKp3w19QSaZAwlGRtsUxrP7436QjnREM3Bm8ygU11BjkPVmtrKm6AayQfCHqJoT
364zIECIQDW0BoMoL0HOYM/mrTLhaykYAVqgIeJsPjvkEhTFXWBuQIhAM3deFAvWNu4
365nklUQ37XsCT2c9tmNt1LAT+slG2JOTTRAiAuXDtC/m3NYVwyHfFm+zKHRzHkClk2
366HjubeEgjpj32AQIhAJqMGTaZVOwevTXvvHwNeH+vRWsAYU/gbx+OQB+7VOcBAiEA
367oolb6NMg/R3enNPvS1O4UU1H8wpaF77L4yiSWlE0p4w=
368-----END RSA PRIVATE KEY-----
369""")
370
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -0400371# certificate with NULL bytes in subjectAltName and common name
372
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400373nulbyteSubjectAltNamePEM = b("""-----BEGIN CERTIFICATE-----
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -0400374MIIE2DCCA8CgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBxTELMAkGA1UEBhMCVVMx
375DzANBgNVBAgMBk9yZWdvbjESMBAGA1UEBwwJQmVhdmVydG9uMSMwIQYDVQQKDBpQ
376eXRob24gU29mdHdhcmUgRm91bmRhdGlvbjEgMB4GA1UECwwXUHl0aG9uIENvcmUg
377RGV2ZWxvcG1lbnQxJDAiBgNVBAMMG251bGwucHl0aG9uLm9yZwBleGFtcGxlLm9y
378ZzEkMCIGCSqGSIb3DQEJARYVcHl0aG9uLWRldkBweXRob24ub3JnMB4XDTEzMDgw
379NzEzMTE1MloXDTEzMDgwNzEzMTI1MlowgcUxCzAJBgNVBAYTAlVTMQ8wDQYDVQQI
380DAZPcmVnb24xEjAQBgNVBAcMCUJlYXZlcnRvbjEjMCEGA1UECgwaUHl0aG9uIFNv
381ZnR3YXJlIEZvdW5kYXRpb24xIDAeBgNVBAsMF1B5dGhvbiBDb3JlIERldmVsb3Bt
382ZW50MSQwIgYDVQQDDBtudWxsLnB5dGhvbi5vcmcAZXhhbXBsZS5vcmcxJDAiBgkq
383hkiG9w0BCQEWFXB5dGhvbi1kZXZAcHl0aG9uLm9yZzCCASIwDQYJKoZIhvcNAQEB
384BQADggEPADCCAQoCggEBALXq7cn7Rn1vO3aA3TrzA5QLp6bb7B3f/yN0CJ2XFj+j
385pHs+Gw6WWSUDpybiiKnPec33BFawq3kyblnBMjBU61ioy5HwQqVkJ8vUVjGIUq3P
386vX/wBmQfzCe4o4uM89gpHyUL9UYGG8oCRa17dgqcv7u5rg0Wq2B1rgY+nHwx3JIv
387KRrgSwyRkGzpN8WQ1yrXlxWjgI9de0mPVDDUlywcWze1q2kwaEPTM3hLAmD1PESA
388oY/n8A/RXoeeRs9i/Pm/DGUS8ZPINXk/yOzsR/XvvkTVroIeLZqfmFpnZeF0cHzL
38908LODkVJJ9zjLdT7SA4vnne4FEbAxDbKAq5qkYzaL4UCAwEAAaOB0DCBzTAMBgNV
390HRMBAf8EAjAAMB0GA1UdDgQWBBSIWlXAUv9hzVKjNQ/qWpwkOCL3XDALBgNVHQ8E
391BAMCBeAwgZAGA1UdEQSBiDCBhYIeYWx0bnVsbC5weXRob24ub3JnAGV4YW1wbGUu
392Y29tgSBudWxsQHB5dGhvbi5vcmcAdXNlckBleGFtcGxlLm9yZ4YpaHR0cDovL251
393bGwucHl0aG9uLm9yZwBodHRwOi8vZXhhbXBsZS5vcmeHBMAAAgGHECABDbgAAAAA
394AAAAAAAAAAEwDQYJKoZIhvcNAQEFBQADggEBAKxPRe99SaghcI6IWT7UNkJw9aO9
395i9eo0Fj2MUqxpKbdb9noRDy2CnHWf7EIYZ1gznXPdwzSN4YCjV5d+Q9xtBaowT0j
396HPERs1ZuytCNNJTmhyqZ8q6uzMLoht4IqH/FBfpvgaeC5tBTnTT0rD5A/olXeimk
397kX4LxlEx5RAvpGB2zZVRGr6LobD9rVK91xuHYNIxxxfEGE8tCCWjp0+3ksri9SXx
398VHWBnbM9YaL32u3hxm8sYB/Yb8WSBavJCWJJqRStVRHM1koZlJmXNx2BX4vPo6iW
399RFEIPQsFZRLrtnCAiEhyT8bC2s/Njlu6ly9gtJZWSV46Q3ZjBL4q9sHKqZQ=
400-----END CERTIFICATE-----""")
401
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400402
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400403class X509ExtTests(TestCase):
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400404 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900405 Tests for :py:class:`OpenSSL.crypto.X509Extension`.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400406 """
407
408 def setUp(self):
409 """
410 Create a new private key and start a certificate request (for a test
411 method to finish in one way or another).
412 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -0800413 super(X509ExtTests, self).setUp()
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400414 # Basic setup stuff to generate a certificate
415 self.pkey = PKey()
416 self.pkey.generate_key(TYPE_RSA, 384)
417 self.req = X509Req()
418 self.req.set_pubkey(self.pkey)
419 # Authority good you have.
420 self.req.get_subject().commonName = "Yoda root CA"
421 self.x509 = X509()
422 self.subject = self.x509.get_subject()
423 self.subject.commonName = self.req.get_subject().commonName
424 self.x509.set_issuer(self.subject)
425 self.x509.set_pubkey(self.pkey)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400426 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
427 expire = b((datetime.now() + timedelta(days=100)).strftime("%Y%m%d%H%M%SZ"))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400428 self.x509.set_notBefore(now)
429 self.x509.set_notAfter(expire)
430
431
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -0800432 def tearDown(self):
433 """
434 Forget all of the pyOpenSSL objects so they can be garbage collected,
435 their memory released, and not interfere with the leak detection code.
436 """
437 self.pkey = self.req = self.x509 = self.subject = None
438 super(X509ExtTests, self).tearDown()
439
440
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400441 def test_str(self):
442 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900443 The string representation of :py:class:`X509Extension` instances as returned by
444 :py:data:`str` includes stuff.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400445 """
446 # This isn't necessarily the best string representation. Perhaps it
447 # will be changed/improved in the future.
448 self.assertEquals(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400449 str(X509Extension(b('basicConstraints'), True, b('CA:false'))),
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400450 'CA:FALSE')
451
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
463
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500464 def test_construction(self):
465 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900466 :py:class:`X509Extension` accepts an extension type name, a critical flag,
467 and an extension value and returns an :py:class:`X509ExtensionType` instance.
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500468 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400469 basic = X509Extension(b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500470 self.assertTrue(
471 isinstance(basic, X509ExtensionType),
472 "%r is of type %r, should be %r" % (
473 basic, type(basic), X509ExtensionType))
474
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400475 comment = X509Extension(
476 b('nsComment'), False, b('pyOpenSSL unit test'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500477 self.assertTrue(
478 isinstance(comment, X509ExtensionType),
479 "%r is of type %r, should be %r" % (
480 comment, type(comment), X509ExtensionType))
481
482
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500483 def test_invalid_extension(self):
484 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900485 :py:class:`X509Extension` raises something if it is passed a bad extension
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500486 name or value.
487 """
488 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400489 Error, X509Extension, b('thisIsMadeUp'), False, b('hi'))
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500490 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400491 Error, X509Extension, b('basicConstraints'), False, b('blah blah'))
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500492
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500493 # Exercise a weird one (an extension which uses the r2i method). This
494 # exercises the codepath that requires a non-NULL ctx to be passed to
495 # X509V3_EXT_nconf. It can't work now because we provide no
496 # configuration database. It might be made to work in the future.
497 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400498 Error, X509Extension, b('proxyCertInfo'), True,
499 b('language:id-ppl-anyLanguage,pathlen:1,policy:text:AB'))
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500500
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500501
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500502 def test_get_critical(self):
503 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900504 :py:meth:`X509ExtensionType.get_critical` returns the value of the
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500505 extension's critical flag.
506 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400507 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500508 self.assertTrue(ext.get_critical())
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400509 ext = X509Extension(b('basicConstraints'), False, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500510 self.assertFalse(ext.get_critical())
511
Jean-Paul Calderone7535dab2008-03-06 18:53:11 -0500512
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500513 def test_get_short_name(self):
514 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900515 :py:meth:`X509ExtensionType.get_short_name` returns a string giving the short
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500516 type name of the extension.
517 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400518 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
519 self.assertEqual(ext.get_short_name(), b('basicConstraints'))
520 ext = X509Extension(b('nsComment'), True, b('foo bar'))
521 self.assertEqual(ext.get_short_name(), b('nsComment'))
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500522
523
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400524 def test_get_data(self):
525 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900526 :py:meth:`X509Extension.get_data` returns a string giving the data of the
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400527 extension.
528 """
529 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
530 # Expect to get back the DER encoded form of CA:true.
531 self.assertEqual(ext.get_data(), b('0\x03\x01\x01\xff'))
532
533
534 def test_get_data_wrong_args(self):
535 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900536 :py:meth:`X509Extension.get_data` raises :py:exc:`TypeError` if passed any arguments.
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400537 """
538 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
539 self.assertRaises(TypeError, ext.get_data, None)
540 self.assertRaises(TypeError, ext.get_data, "foo")
541 self.assertRaises(TypeError, ext.get_data, 7)
542
543
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400544 def test_unused_subject(self):
Rick Dean47262da2009-07-08 16:17:17 -0500545 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900546 The :py:data:`subject` parameter to :py:class:`X509Extension` may be provided for an
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400547 extension which does not use it and is ignored in this case.
Rick Dean47262da2009-07-08 16:17:17 -0500548 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400549 ext1 = X509Extension(
550 b('basicConstraints'), False, b('CA:TRUE'), subject=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400551 self.x509.add_extensions([ext1])
552 self.x509.sign(self.pkey, 'sha1')
553 # This is a little lame. Can we think of a better way?
554 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400555 self.assertTrue(b('X509v3 Basic Constraints:') in text)
556 self.assertTrue(b('CA:TRUE') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400557
558
559 def test_subject(self):
560 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900561 If an extension requires a subject, the :py:data:`subject` parameter to
562 :py:class:`X509Extension` provides its value.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400563 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400564 ext3 = X509Extension(
565 b('subjectKeyIdentifier'), False, b('hash'), subject=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400566 self.x509.add_extensions([ext3])
567 self.x509.sign(self.pkey, 'sha1')
568 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400569 self.assertTrue(b('X509v3 Subject Key Identifier:') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400570
571
572 def test_missing_subject(self):
573 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900574 If an extension requires a subject and the :py:data:`subject` parameter is
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400575 given no value, something happens.
576 """
577 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400578 Error, X509Extension, b('subjectKeyIdentifier'), False, b('hash'))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400579
580
581 def test_invalid_subject(self):
582 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900583 If the :py:data:`subject` parameter is given a value which is not an
584 :py:class:`X509` instance, :py:exc:`TypeError` is raised.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400585 """
586 for badObj in [True, object(), "hello", [], self]:
587 self.assertRaises(
588 TypeError,
589 X509Extension,
590 'basicConstraints', False, 'CA:TRUE', subject=badObj)
591
592
593 def test_unused_issuer(self):
594 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900595 The :py:data:`issuer` parameter to :py:class:`X509Extension` may be provided for an
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400596 extension which does not use it and is ignored in this case.
597 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400598 ext1 = X509Extension(
599 b('basicConstraints'), False, b('CA:TRUE'), issuer=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400600 self.x509.add_extensions([ext1])
601 self.x509.sign(self.pkey, 'sha1')
602 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400603 self.assertTrue(b('X509v3 Basic Constraints:') in text)
604 self.assertTrue(b('CA:TRUE') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400605
606
607 def test_issuer(self):
608 """
Alex Gaynor3b0ee972014-11-15 09:17:33 -0800609 If an extension requires an issuer, the :py:data:`issuer` parameter to
Jonathan Ballet648875f2011-07-16 14:14:58 +0900610 :py:class:`X509Extension` provides its value.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400611 """
612 ext2 = X509Extension(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400613 b('authorityKeyIdentifier'), False, b('issuer:always'),
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400614 issuer=self.x509)
615 self.x509.add_extensions([ext2])
616 self.x509.sign(self.pkey, 'sha1')
617 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400618 self.assertTrue(b('X509v3 Authority Key Identifier:') in text)
619 self.assertTrue(b('DirName:/CN=Yoda root CA') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400620
621
622 def test_missing_issuer(self):
623 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900624 If an extension requires an issue and the :py:data:`issuer` parameter is given
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400625 no value, something happens.
626 """
627 self.assertRaises(
628 Error,
629 X509Extension,
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400630 b('authorityKeyIdentifier'), False,
631 b('keyid:always,issuer:always'))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400632
633
634 def test_invalid_issuer(self):
635 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900636 If the :py:data:`issuer` parameter is given a value which is not an
637 :py:class:`X509` instance, :py:exc:`TypeError` is raised.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400638 """
639 for badObj in [True, object(), "hello", [], self]:
640 self.assertRaises(
641 TypeError,
642 X509Extension,
643 'authorityKeyIdentifier', False, 'keyid:always,issuer:always',
644 issuer=badObj)
Rick Dean47262da2009-07-08 16:17:17 -0500645
646
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500647
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400648class PKeyTests(TestCase):
Jean-Paul Calderoneac930e12008-03-06 18:50:51 -0500649 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900650 Unit tests for :py:class:`OpenSSL.crypto.PKey`.
Jean-Paul Calderoneac930e12008-03-06 18:50:51 -0500651 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400652 def test_type(self):
653 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900654 :py:class:`PKey` and :py:class:`PKeyType` refer to the same type object
655 and can be used to create instances of that type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400656 """
657 self.assertIdentical(PKey, PKeyType)
658 self.assertConsistentType(PKey, 'PKey')
659
660
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500661 def test_construction(self):
662 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900663 :py:class:`PKey` takes no arguments and returns a new :py:class:`PKey` instance.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500664 """
665 self.assertRaises(TypeError, PKey, None)
666 key = PKey()
667 self.assertTrue(
668 isinstance(key, PKeyType),
669 "%r is of type %r, should be %r" % (key, type(key), PKeyType))
670
671
672 def test_pregeneration(self):
673 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900674 :py:attr:`PKeyType.bits` and :py:attr:`PKeyType.type` return :py:data:`0` before the key is
675 generated. :py:attr:`PKeyType.check` raises :py:exc:`TypeError` before the key is
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500676 generated.
677 """
678 key = PKey()
679 self.assertEqual(key.type(), 0)
680 self.assertEqual(key.bits(), 0)
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400681 self.assertRaises(TypeError, key.check)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500682
683
684 def test_failedGeneration(self):
685 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900686 :py:meth:`PKeyType.generate_key` takes two arguments, the first giving the key
687 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 -0500688 number of bits to generate. If an invalid type is specified or
Jonathan Ballet648875f2011-07-16 14:14:58 +0900689 generation fails, :py:exc:`Error` is raised. If an invalid number of bits is
690 specified, :py:exc:`ValueError` or :py:exc:`Error` is raised.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500691 """
692 key = PKey()
693 self.assertRaises(TypeError, key.generate_key)
694 self.assertRaises(TypeError, key.generate_key, 1, 2, 3)
695 self.assertRaises(TypeError, key.generate_key, "foo", "bar")
696 self.assertRaises(Error, key.generate_key, -1, 0)
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500697
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500698 self.assertRaises(ValueError, key.generate_key, TYPE_RSA, -1)
699 self.assertRaises(ValueError, key.generate_key, TYPE_RSA, 0)
Jean-Paul Calderoned71fe982008-03-06 00:31:50 -0500700
701 # XXX RSA generation for small values of bits is fairly buggy in a wide
702 # range of OpenSSL versions. I need to figure out what the safe lower
703 # bound for a reasonable number of OpenSSL versions is and explicitly
704 # check for that in the wrapper. The failure behavior is typically an
705 # infinite loop inside OpenSSL.
706
707 # self.assertRaises(Error, key.generate_key, TYPE_RSA, 2)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500708
709 # XXX DSA generation seems happy with any number of bits. The DSS
710 # says bits must be between 512 and 1024 inclusive. OpenSSL's DSA
711 # generator doesn't seem to care about the upper limit at all. For
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500712 # the lower limit, it uses 512 if anything smaller is specified.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500713 # So, it doesn't seem possible to make generate_key fail for
714 # TYPE_DSA with a bits argument which is at least an int.
715
716 # self.assertRaises(Error, key.generate_key, TYPE_DSA, -7)
717
718
719 def test_rsaGeneration(self):
720 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900721 :py:meth:`PKeyType.generate_key` generates an RSA key when passed
722 :py:data:`TYPE_RSA` as a type and a reasonable number of bits.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500723 """
724 bits = 128
725 key = PKey()
726 key.generate_key(TYPE_RSA, bits)
727 self.assertEqual(key.type(), TYPE_RSA)
728 self.assertEqual(key.bits(), bits)
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -0400729 self.assertTrue(key.check())
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500730
731
732 def test_dsaGeneration(self):
733 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900734 :py:meth:`PKeyType.generate_key` generates a DSA key when passed
735 :py:data:`TYPE_DSA` as a type and a reasonable number of bits.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500736 """
737 # 512 is a magic number. The DSS (Digital Signature Standard)
738 # allows a minimum of 512 bits for DSA. DSA_generate_parameters
739 # will silently promote any value below 512 to 512.
740 bits = 512
741 key = PKey()
742 key.generate_key(TYPE_DSA, bits)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800743 # self.assertEqual(key.type(), TYPE_DSA)
744 # self.assertEqual(key.bits(), bits)
745 # self.assertRaises(TypeError, key.check)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500746
747
748 def test_regeneration(self):
749 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900750 :py:meth:`PKeyType.generate_key` can be called multiple times on the same
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500751 key to generate new keys.
752 """
753 key = PKey()
754 for type, bits in [(TYPE_RSA, 512), (TYPE_DSA, 576)]:
755 key.generate_key(type, bits)
756 self.assertEqual(key.type(), type)
757 self.assertEqual(key.bits(), bits)
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500758
759
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400760 def test_inconsistentKey(self):
761 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900762 :py:`PKeyType.check` returns :py:exc:`Error` if the key is not consistent.
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400763 """
764 key = load_privatekey(FILETYPE_PEM, inconsistentPrivateKeyPEM)
Jean-Paul Calderoned338e4e2009-05-13 15:45:07 -0400765 self.assertRaises(Error, key.check)
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400766
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500767
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400768 def test_check_wrong_args(self):
769 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900770 :py:meth:`PKeyType.check` raises :py:exc:`TypeError` if called with any arguments.
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400771 """
772 self.assertRaises(TypeError, PKey().check, None)
773 self.assertRaises(TypeError, PKey().check, object())
774 self.assertRaises(TypeError, PKey().check, 1)
775
776
Jean-Paul Calderone02d01972011-10-31 10:39:29 -0400777 def test_check_public_key(self):
778 """
779 :py:meth:`PKeyType.check` raises :py:exc:`TypeError` if only the public
780 part of the key is available.
781 """
782 # A trick to get a public-only key
783 key = PKey()
784 key.generate_key(TYPE_RSA, 512)
785 cert = X509()
786 cert.set_pubkey(key)
787 pub = cert.get_pubkey()
788 self.assertRaises(TypeError, pub.check)
789
790
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400791
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400792class X509NameTests(TestCase):
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500793 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900794 Unit tests for :py:class:`OpenSSL.crypto.X509Name`.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500795 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500796 def _x509name(self, **attrs):
797 # XXX There's no other way to get a new X509Name yet.
798 name = X509().get_subject()
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400799 attrs = list(attrs.items())
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500800 # Make the order stable - order matters!
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400801 def key(attr):
802 return attr[1]
803 attrs.sort(key=key)
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500804 for k, v in attrs:
805 setattr(name, k, v)
806 return name
807
808
Rick Deane15b1472009-07-09 15:53:42 -0500809 def test_type(self):
810 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900811 The type of X509Name objects is :py:class:`X509NameType`.
Rick Deane15b1472009-07-09 15:53:42 -0500812 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400813 self.assertIdentical(X509Name, X509NameType)
814 self.assertEqual(X509NameType.__name__, 'X509Name')
815 self.assertTrue(isinstance(X509NameType, type))
816
Rick Deane15b1472009-07-09 15:53:42 -0500817 name = self._x509name()
818 self.assertTrue(
819 isinstance(name, X509NameType),
820 "%r is of type %r, should be %r" % (
821 name, type(name), X509NameType))
Rick Deane15b1472009-07-09 15:53:42 -0500822
823
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400824 def test_onlyStringAttributes(self):
825 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900826 Attempting to set a non-:py:data:`str` attribute name on an :py:class:`X509NameType`
827 instance causes :py:exc:`TypeError` to be raised.
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400828 """
829 name = self._x509name()
830 # Beyond these cases, you may also think that unicode should be
831 # rejected. Sorry, you're wrong. unicode is automatically converted to
832 # str outside of the control of X509Name, so there's no way to reject
833 # it.
Jean-Paul Calderoneff363be2013-03-03 10:21:23 -0800834
835 # Also, this used to test str subclasses, but that test is less relevant
836 # now that the implementation is in Python instead of C. Also PyPy
837 # automatically converts str subclasses to str when they are passed to
838 # setattr, so we can't test it on PyPy. Apparently CPython does this
839 # sometimes as well.
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400840 self.assertRaises(TypeError, setattr, name, None, "hello")
841 self.assertRaises(TypeError, setattr, name, 30, "hello")
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400842
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -0500843
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400844 def test_setInvalidAttribute(self):
845 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900846 Attempting to set any attribute name on an :py:class:`X509NameType` instance for
847 which no corresponding NID is defined causes :py:exc:`AttributeError` to be
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400848 raised.
849 """
850 name = self._x509name()
851 self.assertRaises(AttributeError, setattr, name, "no such thing", None)
852
853
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500854 def test_attributes(self):
855 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900856 :py:class:`X509NameType` instances have attributes for each standard (?)
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500857 X509Name field.
858 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500859 name = self._x509name()
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500860 name.commonName = "foo"
861 self.assertEqual(name.commonName, "foo")
862 self.assertEqual(name.CN, "foo")
863 name.CN = "baz"
864 self.assertEqual(name.commonName, "baz")
865 self.assertEqual(name.CN, "baz")
866 name.commonName = "bar"
867 self.assertEqual(name.commonName, "bar")
868 self.assertEqual(name.CN, "bar")
869 name.CN = "quux"
870 self.assertEqual(name.commonName, "quux")
871 self.assertEqual(name.CN, "quux")
872
873
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500874 def test_copy(self):
875 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900876 :py:class:`X509Name` creates a new :py:class:`X509NameType` instance with all the same
877 attributes as an existing :py:class:`X509NameType` instance when called with
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500878 one.
879 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500880 name = self._x509name(commonName="foo", emailAddress="bar@example.com")
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500881
882 copy = X509Name(name)
883 self.assertEqual(copy.commonName, "foo")
884 self.assertEqual(copy.emailAddress, "bar@example.com")
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500885
886 # Mutate the copy and ensure the original is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500887 copy.commonName = "baz"
888 self.assertEqual(name.commonName, "foo")
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500889
890 # Mutate the original and ensure the copy is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500891 name.emailAddress = "quux@example.com"
892 self.assertEqual(copy.emailAddress, "bar@example.com")
893
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500894
895 def test_repr(self):
896 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900897 :py:func:`repr` passed an :py:class:`X509NameType` instance should return a string
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500898 containing a description of the type and the NIDs which have been set
899 on it.
900 """
901 name = self._x509name(commonName="foo", emailAddress="bar")
902 self.assertEqual(
903 repr(name),
904 "<X509Name object '/emailAddress=bar/CN=foo'>")
905
906
907 def test_comparison(self):
908 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900909 :py:class:`X509NameType` instances should compare based on their NIDs.
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500910 """
911 def _equality(a, b, assertTrue, assertFalse):
912 assertTrue(a == b, "(%r == %r) --> False" % (a, b))
913 assertFalse(a != b)
914 assertTrue(b == a)
915 assertFalse(b != a)
916
917 def assertEqual(a, b):
918 _equality(a, b, self.assertTrue, self.assertFalse)
919
920 # Instances compare equal to themselves.
921 name = self._x509name()
922 assertEqual(name, name)
923
924 # Empty instances should compare equal to each other.
925 assertEqual(self._x509name(), self._x509name())
926
927 # Instances with equal NIDs should compare equal to each other.
928 assertEqual(self._x509name(commonName="foo"),
929 self._x509name(commonName="foo"))
930
931 # Instance with equal NIDs set using different aliases should compare
932 # equal to each other.
933 assertEqual(self._x509name(commonName="foo"),
934 self._x509name(CN="foo"))
935
936 # Instances with more than one NID with the same values should compare
937 # equal to each other.
938 assertEqual(self._x509name(CN="foo", organizationalUnitName="bar"),
939 self._x509name(commonName="foo", OU="bar"))
940
941 def assertNotEqual(a, b):
942 _equality(a, b, self.assertFalse, self.assertTrue)
943
944 # Instances with different values for the same NID should not compare
945 # equal to each other.
946 assertNotEqual(self._x509name(CN="foo"),
947 self._x509name(CN="bar"))
948
949 # Instances with different NIDs should not compare equal to each other.
950 assertNotEqual(self._x509name(CN="foo"),
951 self._x509name(OU="foo"))
952
953 def _inequality(a, b, assertTrue, assertFalse):
954 assertTrue(a < b)
955 assertTrue(a <= b)
956 assertTrue(b > a)
957 assertTrue(b >= a)
958 assertFalse(a > b)
959 assertFalse(a >= b)
960 assertFalse(b < a)
961 assertFalse(b <= a)
962
963 def assertLessThan(a, b):
964 _inequality(a, b, self.assertTrue, self.assertFalse)
965
966 # An X509Name with a NID with a value which sorts less than the value
967 # of the same NID on another X509Name compares less than the other
968 # X509Name.
969 assertLessThan(self._x509name(CN="abc"),
970 self._x509name(CN="def"))
971
972 def assertGreaterThan(a, b):
973 _inequality(a, b, self.assertFalse, self.assertTrue)
974
975 # An X509Name with a NID with a value which sorts greater than the
976 # value of the same NID on another X509Name compares greater than the
977 # other X509Name.
978 assertGreaterThan(self._x509name(CN="def"),
979 self._x509name(CN="abc"))
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -0500980
981
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400982 def test_hash(self):
983 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900984 :py:meth:`X509Name.hash` returns an integer hash based on the value of the
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400985 name.
986 """
987 a = self._x509name(CN="foo")
988 b = self._x509name(CN="foo")
989 self.assertEqual(a.hash(), b.hash())
990 a.CN = "bar"
991 self.assertNotEqual(a.hash(), b.hash())
992
993
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400994 def test_der(self):
995 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900996 :py:meth:`X509Name.der` returns the DER encoded form of the name.
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400997 """
998 a = self._x509name(CN="foo", C="US")
999 self.assertEqual(
1000 a.der(),
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -04001001 b('0\x1b1\x0b0\t\x06\x03U\x04\x06\x13\x02US'
1002 '1\x0c0\n\x06\x03U\x04\x03\x13\x03foo'))
Jean-Paul Calderonee957a002008-03-25 15:16:51 -04001003
1004
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -04001005 def test_get_components(self):
1006 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001007 :py:meth:`X509Name.get_components` returns a :py:data:`list` of
1008 two-tuples of :py:data:`str`
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -04001009 giving the NIDs and associated values which make up the name.
1010 """
1011 a = self._x509name()
1012 self.assertEqual(a.get_components(), [])
1013 a.CN = "foo"
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -04001014 self.assertEqual(a.get_components(), [(b("CN"), b("foo"))])
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -04001015 a.organizationalUnitName = "bar"
1016 self.assertEqual(
1017 a.get_components(),
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -04001018 [(b("CN"), b("foo")), (b("OU"), b("bar"))])
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -04001019
Jean-Paul Calderone110cd092008-03-24 17:27:42 -04001020
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001021 def test_load_nul_byte_attribute(self):
1022 """
Jean-Paul Calderone9af07b02013-08-23 16:07:31 -04001023 An :py:class:`OpenSSL.crypto.X509Name` from an
1024 :py:class:`OpenSSL.crypto.X509` instance loaded from a file can have a
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001025 NUL byte in the value of one of its attributes.
1026 """
1027 cert = load_certificate(FILETYPE_PEM, nulbyteSubjectAltNamePEM)
1028 subject = cert.get_subject()
1029 self.assertEqual(
Jean-Paul Calderone06754fc2013-08-23 15:47:47 -04001030 "null.python.org\x00example.org", subject.commonName)
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001031
1032
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -05001033 def test_setAttributeFailure(self):
1034 """
1035 If the value of an attribute cannot be set for some reason then
1036 :py:class:`OpenSSL.crypto.Error` is raised.
1037 """
1038 name = self._x509name()
1039 # This value is too long
1040 self.assertRaises(Error, setattr, name, "O", b"x" * 512)
1041
1042
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001043
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001044class _PKeyInteractionTestsMixin:
1045 """
1046 Tests which involve another thing and a PKey.
1047 """
1048 def signable(self):
1049 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001050 Return something with a :py:meth:`set_pubkey`, :py:meth:`set_pubkey`,
1051 and :py:meth:`sign` method.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001052 """
1053 raise NotImplementedError()
1054
1055
1056 def test_signWithUngenerated(self):
1057 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001058 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when pass a
1059 :py:class:`PKey` with no parts.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001060 """
1061 request = self.signable()
1062 key = PKey()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001063 self.assertRaises(ValueError, request.sign, key, GOOD_DIGEST)
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001064
1065
1066 def test_signWithPublicKey(self):
1067 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001068 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when pass a
1069 :py:class:`PKey` with no private part as the signing key.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001070 """
1071 request = self.signable()
1072 key = PKey()
1073 key.generate_key(TYPE_RSA, 512)
1074 request.set_pubkey(key)
1075 pub = request.get_pubkey()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001076 self.assertRaises(ValueError, request.sign, pub, GOOD_DIGEST)
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001077
1078
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -04001079 def test_signWithUnknownDigest(self):
1080 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001081 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when passed a digest name which is
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -04001082 not known.
1083 """
1084 request = self.signable()
1085 key = PKey()
1086 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001087 self.assertRaises(ValueError, request.sign, key, BAD_DIGEST)
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -04001088
1089
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04001090 def test_sign(self):
1091 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001092 :py:meth:`X509Req.sign` succeeds when passed a private key object and a valid
1093 digest function. :py:meth:`X509Req.verify` can be used to check the signature.
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04001094 """
1095 request = self.signable()
1096 key = PKey()
1097 key.generate_key(TYPE_RSA, 512)
1098 request.set_pubkey(key)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001099 request.sign(key, GOOD_DIGEST)
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04001100 # If the type has a verify method, cover that too.
1101 if getattr(request, 'verify', None) is not None:
1102 pub = request.get_pubkey()
1103 self.assertTrue(request.verify(pub))
1104 # Make another key that won't verify.
1105 key = PKey()
1106 key.generate_key(TYPE_RSA, 512)
1107 self.assertRaises(Error, request.verify, key)
1108
1109
1110
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001111
Jean-Paul Calderone18808652009-07-05 12:54:05 -04001112class X509ReqTests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001113 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001114 Tests for :py:class:`OpenSSL.crypto.X509Req`.
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001115 """
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001116 def signable(self):
1117 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001118 Create and return a new :py:class:`X509Req`.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001119 """
1120 return X509Req()
1121
1122
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001123 def test_type(self):
1124 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001125 :py:obj:`X509Req` and :py:obj:`X509ReqType` refer to the same type object and can be
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001126 used to create instances of that type.
1127 """
1128 self.assertIdentical(X509Req, X509ReqType)
1129 self.assertConsistentType(X509Req, 'X509Req')
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001130
1131
1132 def test_construction(self):
1133 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001134 :py:obj:`X509Req` takes no arguments and returns an :py:obj:`X509ReqType` instance.
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001135 """
1136 request = X509Req()
1137 self.assertTrue(
1138 isinstance(request, X509ReqType),
1139 "%r is of type %r, should be %r" % (request, type(request), X509ReqType))
1140
1141
Jean-Paul Calderone8dd19b82008-12-28 20:41:16 -05001142 def test_version(self):
1143 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001144 :py:obj:`X509ReqType.set_version` sets the X.509 version of the certificate
1145 request. :py:obj:`X509ReqType.get_version` returns the X.509 version of
Jean-Paul Calderone8dd19b82008-12-28 20:41:16 -05001146 the certificate request. The initial value of the version is 0.
1147 """
1148 request = X509Req()
1149 self.assertEqual(request.get_version(), 0)
1150 request.set_version(1)
1151 self.assertEqual(request.get_version(), 1)
1152 request.set_version(3)
1153 self.assertEqual(request.get_version(), 3)
1154
1155
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001156 def test_version_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001157 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001158 :py:obj:`X509ReqType.set_version` raises :py:obj:`TypeError` if called with the wrong
1159 number of arguments or with a non-:py:obj:`int` argument.
1160 :py:obj:`X509ReqType.get_version` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001161 arguments.
1162 """
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001163 request = X509Req()
1164 self.assertRaises(TypeError, request.set_version)
1165 self.assertRaises(TypeError, request.set_version, "foo")
1166 self.assertRaises(TypeError, request.set_version, 1, 2)
1167 self.assertRaises(TypeError, request.get_version, None)
1168
1169
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001170 def test_get_subject(self):
1171 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001172 :py:obj:`X509ReqType.get_subject` returns an :py:obj:`X509Name` for the subject of
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001173 the request and which is valid even after the request object is
1174 otherwise dead.
1175 """
1176 request = X509Req()
1177 subject = request.get_subject()
1178 self.assertTrue(
1179 isinstance(subject, X509NameType),
1180 "%r is of type %r, should be %r" % (subject, type(subject), X509NameType))
1181 subject.commonName = "foo"
1182 self.assertEqual(request.get_subject().commonName, "foo")
1183 del request
1184 subject.commonName = "bar"
1185 self.assertEqual(subject.commonName, "bar")
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001186
1187
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001188 def test_get_subject_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001189 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001190 :py:obj:`X509ReqType.get_subject` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001191 arguments.
1192 """
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001193 request = X509Req()
1194 self.assertRaises(TypeError, request.get_subject, None)
1195
1196
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001197 def test_add_extensions(self):
1198 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001199 :py:obj:`X509Req.add_extensions` accepts a :py:obj:`list` of :py:obj:`X509Extension`
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001200 instances and adds them to the X509 request.
1201 """
1202 request = X509Req()
1203 request.add_extensions([
Jean-Paul Calderonee16f9f32010-08-22 19:20:37 -04001204 X509Extension(b('basicConstraints'), True, b('CA:false'))])
Stephen Holsappleca545b72014-01-28 21:43:25 -08001205 exts = request.get_extensions()
Stephen Holsapple7fbdf642014-03-01 20:05:47 -08001206 self.assertEqual(len(exts), 1)
1207 self.assertEqual(exts[0].get_short_name(), b('basicConstraints'))
1208 self.assertEqual(exts[0].get_critical(), 1)
1209 self.assertEqual(exts[0].get_data(), b('0\x00'))
1210
1211
1212 def test_get_extensions(self):
1213 """
1214 :py:obj:`X509Req.get_extensions` returns a :py:obj:`list` of
1215 extensions added to this X509 request.
1216 """
1217 request = X509Req()
1218 exts = request.get_extensions()
1219 self.assertEqual(exts, [])
1220 request.add_extensions([
1221 X509Extension(b('basicConstraints'), True, b('CA:true')),
1222 X509Extension(b('keyUsage'), False, b('digitalSignature'))])
1223 exts = request.get_extensions()
1224 self.assertEqual(len(exts), 2)
1225 self.assertEqual(exts[0].get_short_name(), b('basicConstraints'))
1226 self.assertEqual(exts[0].get_critical(), 1)
1227 self.assertEqual(exts[0].get_data(), b('0\x03\x01\x01\xff'))
1228 self.assertEqual(exts[1].get_short_name(), b('keyUsage'))
1229 self.assertEqual(exts[1].get_critical(), 0)
1230 self.assertEqual(exts[1].get_data(), b('\x03\x02\x07\x80'))
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001231
1232
1233 def test_add_extensions_wrong_args(self):
1234 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001235 :py:obj:`X509Req.add_extensions` raises :py:obj:`TypeError` if called with the wrong
1236 number of arguments or with a non-:py:obj:`list`. Or it raises :py:obj:`ValueError`
1237 if called with a :py:obj:`list` containing objects other than :py:obj:`X509Extension`
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001238 instances.
1239 """
1240 request = X509Req()
1241 self.assertRaises(TypeError, request.add_extensions)
1242 self.assertRaises(TypeError, request.add_extensions, object())
1243 self.assertRaises(ValueError, request.add_extensions, [object()])
1244 self.assertRaises(TypeError, request.add_extensions, [], None)
1245
1246
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001247 def test_verify_wrong_args(self):
1248 """
1249 :py:obj:`X509Req.verify` raises :py:obj:`TypeError` if called with zero
1250 arguments or more than one argument or if passed anything other than a
1251 :py:obj:`PKey` instance as its single argument.
1252 """
1253 request = X509Req()
1254 self.assertRaises(TypeError, request.verify)
1255 self.assertRaises(TypeError, request.verify, object())
1256 self.assertRaises(TypeError, request.verify, PKey(), object())
1257
1258
1259 def test_verify_uninitialized_key(self):
1260 """
1261 :py:obj:`X509Req.verify` raises :py:obj:`OpenSSL.crypto.Error` if called
1262 with a :py:obj:`OpenSSL.crypto.PKey` which contains no key data.
1263 """
1264 request = X509Req()
1265 pkey = PKey()
1266 self.assertRaises(Error, request.verify, pkey)
1267
1268
1269 def test_verify_wrong_key(self):
1270 """
1271 :py:obj:`X509Req.verify` raises :py:obj:`OpenSSL.crypto.Error` if called
1272 with a :py:obj:`OpenSSL.crypto.PKey` which does not represent the public
1273 part of the key which signed the request.
1274 """
1275 request = X509Req()
1276 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001277 request.sign(pkey, GOOD_DIGEST)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001278 another_pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
1279 self.assertRaises(Error, request.verify, another_pkey)
1280
1281
1282 def test_verify_success(self):
1283 """
1284 :py:obj:`X509Req.verify` returns :py:obj:`True` if called with a
Alex Gaynor3b0ee972014-11-15 09:17:33 -08001285 :py:obj:`OpenSSL.crypto.PKey` which represents the public part of the key
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001286 which signed the request.
1287 """
1288 request = X509Req()
1289 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001290 request.sign(pkey, GOOD_DIGEST)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001291 self.assertEqual(True, request.verify(pkey))
1292
1293
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001294
Jean-Paul Calderone18808652009-07-05 12:54:05 -04001295class X509Tests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001296 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001297 Tests for :py:obj:`OpenSSL.crypto.X509`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001298 """
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001299 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
Jean-Paul Calderone8114b452008-03-25 15:27:59 -04001300
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001301 extpem = """
1302-----BEGIN CERTIFICATE-----
1303MIIC3jCCAkegAwIBAgIJAJHFjlcCgnQzMA0GCSqGSIb3DQEBBQUAMEcxCzAJBgNV
1304BAYTAlNFMRUwEwYDVQQIEwxXZXN0ZXJib3R0b20xEjAQBgNVBAoTCUNhdGFsb2dp
1305eDENMAsGA1UEAxMEUm9vdDAeFw0wODA0MjIxNDQ1MzhaFw0wOTA0MjIxNDQ1Mzha
1306MFQxCzAJBgNVBAYTAlNFMQswCQYDVQQIEwJXQjEUMBIGA1UEChMLT3Blbk1ldGFk
1307aXIxIjAgBgNVBAMTGW5vZGUxLm9tMi5vcGVubWV0YWRpci5vcmcwgZ8wDQYJKoZI
1308hvcNAQEBBQADgY0AMIGJAoGBAPIcQMrwbk2nESF/0JKibj9i1x95XYAOwP+LarwT
1309Op4EQbdlI9SY+uqYqlERhF19w7CS+S6oyqx0DRZSk4Y9dZ9j9/xgm2u/f136YS1u
1310zgYFPvfUs6PqYLPSM8Bw+SjJ+7+2+TN+Tkiof9WP1cMjodQwOmdsiRbR0/J7+b1B
1311hec1AgMBAAGjgcQwgcEwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNT
1312TCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFIdHsBcMVVMbAO7j6NCj
131303HgLnHaMB8GA1UdIwQYMBaAFL2h9Bf9Mre4vTdOiHTGAt7BRY/8MEYGA1UdEQQ/
1314MD2CDSouZXhhbXBsZS5vcmeCESoub20yLmV4bWFwbGUuY29thwSC7wgKgRNvbTJA
1315b3Blbm1ldGFkaXIub3JnMA0GCSqGSIb3DQEBBQUAA4GBALd7WdXkp2KvZ7/PuWZA
1316MPlIxyjS+Ly11+BNE0xGQRp9Wz+2lABtpgNqssvU156+HkKd02rGheb2tj7MX9hG
1317uZzbwDAZzJPjzDQDD7d3cWsrVcfIdqVU7epHqIadnOF+X0ghJ39pAm6VVadnSXCt
1318WpOdIpB8KksUTCzV591Nr1wd
1319-----END CERTIFICATE-----
1320 """
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001321 def signable(self):
1322 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001323 Create and return a new :py:obj:`X509`.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001324 """
1325 return X509()
1326
1327
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001328 def test_type(self):
1329 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001330 :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 -04001331 to create instances of that type.
1332 """
1333 self.assertIdentical(X509, X509Type)
1334 self.assertConsistentType(X509, 'X509')
1335
1336
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001337 def test_construction(self):
1338 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001339 :py:obj:`X509` takes no arguments and returns an instance of :py:obj:`X509Type`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001340 """
1341 certificate = X509()
1342 self.assertTrue(
1343 isinstance(certificate, X509Type),
1344 "%r is of type %r, should be %r" % (certificate,
1345 type(certificate),
1346 X509Type))
Rick Deane15b1472009-07-09 15:53:42 -05001347 self.assertEqual(type(X509Type).__name__, 'type')
1348 self.assertEqual(type(certificate).__name__, 'X509')
1349 self.assertEqual(type(certificate), X509Type)
Rick Dean04113e72009-07-16 12:06:35 -05001350 self.assertEqual(type(certificate), X509)
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001351
1352
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001353 def test_get_version_wrong_args(self):
1354 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001355 :py:obj:`X509.get_version` raises :py:obj:`TypeError` if invoked with any arguments.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001356 """
1357 cert = X509()
1358 self.assertRaises(TypeError, cert.get_version, None)
1359
1360
1361 def test_set_version_wrong_args(self):
1362 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001363 :py:obj:`X509.set_version` raises :py:obj:`TypeError` if invoked with the wrong number
1364 of arguments or an argument not of type :py:obj:`int`.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001365 """
1366 cert = X509()
1367 self.assertRaises(TypeError, cert.set_version)
1368 self.assertRaises(TypeError, cert.set_version, None)
1369 self.assertRaises(TypeError, cert.set_version, 1, None)
1370
1371
1372 def test_version(self):
1373 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001374 :py:obj:`X509.set_version` sets the certificate version number.
1375 :py:obj:`X509.get_version` retrieves it.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001376 """
1377 cert = X509()
1378 cert.set_version(1234)
1379 self.assertEquals(cert.get_version(), 1234)
1380
1381
1382 def test_get_serial_number_wrong_args(self):
1383 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001384 :py:obj:`X509.get_serial_number` raises :py:obj:`TypeError` if invoked with any
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001385 arguments.
1386 """
1387 cert = X509()
1388 self.assertRaises(TypeError, cert.get_serial_number, None)
1389
1390
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001391 def test_serial_number(self):
1392 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001393 The serial number of an :py:obj:`X509Type` can be retrieved and modified with
1394 :py:obj:`X509Type.get_serial_number` and :py:obj:`X509Type.set_serial_number`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001395 """
1396 certificate = X509()
1397 self.assertRaises(TypeError, certificate.set_serial_number)
1398 self.assertRaises(TypeError, certificate.set_serial_number, 1, 2)
1399 self.assertRaises(TypeError, certificate.set_serial_number, "1")
1400 self.assertRaises(TypeError, certificate.set_serial_number, 5.5)
1401 self.assertEqual(certificate.get_serial_number(), 0)
1402 certificate.set_serial_number(1)
1403 self.assertEqual(certificate.get_serial_number(), 1)
1404 certificate.set_serial_number(2 ** 32 + 1)
1405 self.assertEqual(certificate.get_serial_number(), 2 ** 32 + 1)
1406 certificate.set_serial_number(2 ** 64 + 1)
1407 self.assertEqual(certificate.get_serial_number(), 2 ** 64 + 1)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001408 certificate.set_serial_number(2 ** 128 + 1)
1409 self.assertEqual(certificate.get_serial_number(), 2 ** 128 + 1)
1410
1411
1412 def _setBoundTest(self, which):
1413 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001414 :py:obj:`X509Type.set_notBefore` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001415 GENERALIZEDTIME and sets the beginning of the certificate's validity
1416 period to it.
1417 """
1418 certificate = X509()
1419 set = getattr(certificate, 'set_not' + which)
1420 get = getattr(certificate, 'get_not' + which)
1421
Jean-Paul Calderonee0615b52008-03-09 21:44:46 -04001422 # Starts with no value.
1423 self.assertEqual(get(), None)
1424
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001425 # GMT (Or is it UTC?) -exarkun
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001426 when = b("20040203040506Z")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001427 set(when)
1428 self.assertEqual(get(), when)
1429
1430 # A plus two hours and thirty minutes offset
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001431 when = b("20040203040506+0530")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001432 set(when)
1433 self.assertEqual(get(), when)
1434
1435 # A minus one hour fifteen minutes offset
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001436 when = b("20040203040506-0115")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001437 set(when)
1438 self.assertEqual(get(), when)
1439
1440 # An invalid string results in a ValueError
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001441 self.assertRaises(ValueError, set, b("foo bar"))
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001442
Jean-Paul Calderone31ca2002010-01-30 15:14:43 -05001443 # The wrong number of arguments results in a TypeError.
1444 self.assertRaises(TypeError, set)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001445 self.assertRaises(TypeError, set, b("20040203040506Z"), b("20040203040506Z"))
1446 self.assertRaises(TypeError, get, b("foo bar"))
1447
Jean-Paul Calderone31ca2002010-01-30 15:14:43 -05001448
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001449 # XXX ASN1_TIME (not GENERALIZEDTIME)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001450
1451 def test_set_notBefore(self):
1452 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001453 :py:obj:`X509Type.set_notBefore` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001454 GENERALIZEDTIME and sets the beginning of the certificate's validity
1455 period to it.
1456 """
1457 self._setBoundTest("Before")
1458
1459
1460 def test_set_notAfter(self):
1461 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001462 :py:obj:`X509Type.set_notAfter` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001463 GENERALIZEDTIME and sets the end of the certificate's validity period
1464 to it.
1465 """
1466 self._setBoundTest("After")
Jean-Paul Calderone76576d52008-03-24 16:04:46 -04001467
1468
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001469 def test_get_notBefore(self):
1470 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001471 :py:obj:`X509Type.get_notBefore` returns a string in the format of an ASN1
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001472 GENERALIZEDTIME even for certificates which store it as UTCTIME
1473 internally.
1474 """
Jean-Paul Calderone8114b452008-03-25 15:27:59 -04001475 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001476 self.assertEqual(cert.get_notBefore(), b("20090325123658Z"))
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001477
Rick Dean38a05c82009-07-18 01:41:30 -05001478
1479 def test_get_notAfter(self):
1480 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001481 :py:obj:`X509Type.get_notAfter` returns a string in the format of an ASN1
Rick Dean38a05c82009-07-18 01:41:30 -05001482 GENERALIZEDTIME even for certificates which store it as UTCTIME
1483 internally.
1484 """
1485 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001486 self.assertEqual(cert.get_notAfter(), b("20170611123658Z"))
Rick Dean38a05c82009-07-18 01:41:30 -05001487
1488
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001489 def test_gmtime_adj_notBefore_wrong_args(self):
1490 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001491 :py:obj:`X509Type.gmtime_adj_notBefore` raises :py:obj:`TypeError` if called with the
1492 wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001493 """
1494 cert = X509()
1495 self.assertRaises(TypeError, cert.gmtime_adj_notBefore)
1496 self.assertRaises(TypeError, cert.gmtime_adj_notBefore, None)
1497 self.assertRaises(TypeError, cert.gmtime_adj_notBefore, 123, None)
1498
1499
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001500 def test_gmtime_adj_notBefore(self):
1501 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001502 :py:obj:`X509Type.gmtime_adj_notBefore` changes the not-before timestamp to be
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001503 the current time plus the number of seconds passed in.
1504 """
1505 cert = load_certificate(FILETYPE_PEM, self.pemData)
1506 now = datetime.utcnow() + timedelta(seconds=100)
1507 cert.gmtime_adj_notBefore(100)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001508 self.assertEqual(cert.get_notBefore(), b(now.strftime("%Y%m%d%H%M%SZ")))
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001509
1510
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001511 def test_gmtime_adj_notAfter_wrong_args(self):
1512 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001513 :py:obj:`X509Type.gmtime_adj_notAfter` raises :py:obj:`TypeError` if called with the
1514 wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001515 """
1516 cert = X509()
1517 self.assertRaises(TypeError, cert.gmtime_adj_notAfter)
1518 self.assertRaises(TypeError, cert.gmtime_adj_notAfter, None)
1519 self.assertRaises(TypeError, cert.gmtime_adj_notAfter, 123, None)
1520
1521
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001522 def test_gmtime_adj_notAfter(self):
1523 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001524 :py:obj:`X509Type.gmtime_adj_notAfter` changes the not-after timestamp to be
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001525 the current time plus the number of seconds passed in.
1526 """
1527 cert = load_certificate(FILETYPE_PEM, self.pemData)
1528 now = datetime.utcnow() + timedelta(seconds=100)
1529 cert.gmtime_adj_notAfter(100)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001530 self.assertEqual(cert.get_notAfter(), b(now.strftime("%Y%m%d%H%M%SZ")))
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001531
1532
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001533 def test_has_expired_wrong_args(self):
1534 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001535 :py:obj:`X509Type.has_expired` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001536 arguments.
1537 """
1538 cert = X509()
1539 self.assertRaises(TypeError, cert.has_expired, None)
1540
1541
1542 def test_has_expired(self):
1543 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001544 :py:obj:`X509Type.has_expired` returns :py:obj:`True` if the certificate's not-after
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001545 time is in the past.
1546 """
1547 cert = X509()
1548 cert.gmtime_adj_notAfter(-1)
1549 self.assertTrue(cert.has_expired())
1550
1551
1552 def test_has_not_expired(self):
1553 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001554 :py:obj:`X509Type.has_expired` returns :py:obj:`False` if the certificate's not-after
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001555 time is in the future.
1556 """
1557 cert = X509()
1558 cert.gmtime_adj_notAfter(2)
1559 self.assertFalse(cert.has_expired())
1560
1561
Rick Dean38a05c82009-07-18 01:41:30 -05001562 def test_digest(self):
1563 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001564 :py:obj:`X509.digest` returns a string giving ":"-separated hex-encoded words
Rick Dean38a05c82009-07-18 01:41:30 -05001565 of the digest of the certificate.
1566 """
1567 cert = X509()
1568 self.assertEqual(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001569 # This is MD5 instead of GOOD_DIGEST because the digest algorithm
1570 # actually matters to the assertion (ie, another arbitrary, good
1571 # digest will not product the same digest).
1572 cert.digest("MD5"),
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001573 b("A8:EB:07:F8:53:25:0A:F2:56:05:C5:A5:C4:C4:C7:15"))
Rick Dean38a05c82009-07-18 01:41:30 -05001574
1575
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001576 def _extcert(self, pkey, extensions):
1577 cert = X509()
1578 cert.set_pubkey(pkey)
1579 cert.get_subject().commonName = "Unit Tests"
1580 cert.get_issuer().commonName = "Unit Tests"
1581 when = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
1582 cert.set_notBefore(when)
1583 cert.set_notAfter(when)
1584
1585 cert.add_extensions(extensions)
1586 return load_certificate(
1587 FILETYPE_PEM, dump_certificate(FILETYPE_PEM, cert))
1588
1589
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001590 def test_extension_count(self):
1591 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001592 :py:obj:`X509.get_extension_count` returns the number of extensions that are
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001593 present in the certificate.
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001594 """
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001595 pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001596 ca = X509Extension(b('basicConstraints'), True, b('CA:FALSE'))
1597 key = X509Extension(b('keyUsage'), True, b('digitalSignature'))
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001598 subjectAltName = X509Extension(
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001599 b('subjectAltName'), True, b('DNS:example.com'))
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001600
1601 # Try a certificate with no extensions at all.
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001602 c = self._extcert(pkey, [])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001603 self.assertEqual(c.get_extension_count(), 0)
1604
1605 # And a certificate with one
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001606 c = self._extcert(pkey, [ca])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001607 self.assertEqual(c.get_extension_count(), 1)
1608
1609 # And a certificate with several
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001610 c = self._extcert(pkey, [ca, key, subjectAltName])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001611 self.assertEqual(c.get_extension_count(), 3)
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001612
1613
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001614 def test_get_extension(self):
1615 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001616 :py:obj:`X509.get_extension` takes an integer and returns an :py:obj:`X509Extension`
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001617 corresponding to the extension at that index.
1618 """
1619 pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001620 ca = X509Extension(b('basicConstraints'), True, b('CA:FALSE'))
1621 key = X509Extension(b('keyUsage'), True, b('digitalSignature'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001622 subjectAltName = X509Extension(
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001623 b('subjectAltName'), False, b('DNS:example.com'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001624
1625 cert = self._extcert(pkey, [ca, key, subjectAltName])
1626
1627 ext = cert.get_extension(0)
1628 self.assertTrue(isinstance(ext, X509Extension))
1629 self.assertTrue(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001630 self.assertEqual(ext.get_short_name(), b('basicConstraints'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001631
1632 ext = cert.get_extension(1)
1633 self.assertTrue(isinstance(ext, X509Extension))
1634 self.assertTrue(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001635 self.assertEqual(ext.get_short_name(), b('keyUsage'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001636
1637 ext = cert.get_extension(2)
1638 self.assertTrue(isinstance(ext, X509Extension))
1639 self.assertFalse(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001640 self.assertEqual(ext.get_short_name(), b('subjectAltName'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001641
1642 self.assertRaises(IndexError, cert.get_extension, -1)
1643 self.assertRaises(IndexError, cert.get_extension, 4)
1644 self.assertRaises(TypeError, cert.get_extension, "hello")
1645
1646
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001647 def test_nullbyte_subjectAltName(self):
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001648 """
Jean-Paul Calderone9af07b02013-08-23 16:07:31 -04001649 The fields of a `subjectAltName` extension on an X509 may contain NUL
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001650 bytes and this value is reflected in the string representation of the
1651 extension object.
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001652 """
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001653 cert = load_certificate(FILETYPE_PEM, nulbyteSubjectAltNamePEM)
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001654
1655 ext = cert.get_extension(3)
1656 self.assertEqual(ext.get_short_name(), b('subjectAltName'))
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001657 self.assertEqual(
1658 b("DNS:altnull.python.org\x00example.com, "
1659 "email:null@python.org\x00user@example.org, "
1660 "URI:http://null.python.org\x00http://example.org, "
1661 "IP Address:192.0.2.1, IP Address:2001:DB8:0:0:0:0:0:1\n"),
1662 b(str(ext)))
1663
Rick Dean38a05c82009-07-18 01:41:30 -05001664
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001665 def test_invalid_digest_algorithm(self):
1666 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001667 :py:obj:`X509.digest` raises :py:obj:`ValueError` if called with an unrecognized hash
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001668 algorithm.
1669 """
1670 cert = X509()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001671 self.assertRaises(ValueError, cert.digest, BAD_DIGEST)
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001672
1673
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001674 def test_get_subject_wrong_args(self):
1675 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001676 :py:obj:`X509.get_subject` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001677 """
1678 cert = X509()
1679 self.assertRaises(TypeError, cert.get_subject, None)
1680
1681
1682 def test_get_subject(self):
1683 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001684 :py:obj:`X509.get_subject` returns an :py:obj:`X509Name` instance.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001685 """
1686 cert = load_certificate(FILETYPE_PEM, self.pemData)
1687 subj = cert.get_subject()
1688 self.assertTrue(isinstance(subj, X509Name))
1689 self.assertEquals(
1690 subj.get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001691 [(b('C'), b('US')), (b('ST'), b('IL')), (b('L'), b('Chicago')),
1692 (b('O'), b('Testing')), (b('CN'), b('Testing Root CA'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001693
1694
1695 def test_set_subject_wrong_args(self):
1696 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001697 :py:obj:`X509.set_subject` raises a :py:obj:`TypeError` if called with the wrong
1698 number of arguments or an argument not of type :py:obj:`X509Name`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001699 """
1700 cert = X509()
1701 self.assertRaises(TypeError, cert.set_subject)
1702 self.assertRaises(TypeError, cert.set_subject, None)
1703 self.assertRaises(TypeError, cert.set_subject, cert.get_subject(), None)
1704
1705
1706 def test_set_subject(self):
1707 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001708 :py:obj:`X509.set_subject` changes the subject of the certificate to the one
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001709 passed in.
1710 """
1711 cert = X509()
1712 name = cert.get_subject()
1713 name.C = 'AU'
1714 name.O = 'Unit Tests'
1715 cert.set_subject(name)
1716 self.assertEquals(
1717 cert.get_subject().get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001718 [(b('C'), b('AU')), (b('O'), b('Unit Tests'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001719
1720
1721 def test_get_issuer_wrong_args(self):
1722 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001723 :py:obj:`X509.get_issuer` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001724 """
1725 cert = X509()
1726 self.assertRaises(TypeError, cert.get_issuer, None)
1727
1728
1729 def test_get_issuer(self):
1730 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001731 :py:obj:`X509.get_issuer` returns an :py:obj:`X509Name` instance.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001732 """
1733 cert = load_certificate(FILETYPE_PEM, self.pemData)
1734 subj = cert.get_issuer()
1735 self.assertTrue(isinstance(subj, X509Name))
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001736 comp = subj.get_components()
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001737 self.assertEquals(
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001738 comp,
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001739 [(b('C'), b('US')), (b('ST'), b('IL')), (b('L'), b('Chicago')),
1740 (b('O'), b('Testing')), (b('CN'), b('Testing Root CA'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001741
1742
1743 def test_set_issuer_wrong_args(self):
1744 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001745 :py:obj:`X509.set_issuer` raises a :py:obj:`TypeError` if called with the wrong
1746 number of arguments or an argument not of type :py:obj:`X509Name`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001747 """
1748 cert = X509()
1749 self.assertRaises(TypeError, cert.set_issuer)
1750 self.assertRaises(TypeError, cert.set_issuer, None)
1751 self.assertRaises(TypeError, cert.set_issuer, cert.get_issuer(), None)
1752
1753
1754 def test_set_issuer(self):
1755 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001756 :py:obj:`X509.set_issuer` changes the issuer of the certificate to the one
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001757 passed in.
1758 """
1759 cert = X509()
1760 name = cert.get_issuer()
1761 name.C = 'AU'
1762 name.O = 'Unit Tests'
1763 cert.set_issuer(name)
1764 self.assertEquals(
1765 cert.get_issuer().get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001766 [(b('C'), b('AU')), (b('O'), b('Unit Tests'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001767
1768
1769 def test_get_pubkey_uninitialized(self):
1770 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001771 When called on a certificate with no public key, :py:obj:`X509.get_pubkey`
1772 raises :py:obj:`OpenSSL.crypto.Error`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001773 """
1774 cert = X509()
1775 self.assertRaises(Error, cert.get_pubkey)
1776
1777
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001778 def test_subject_name_hash_wrong_args(self):
1779 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001780 :py:obj:`X509.subject_name_hash` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001781 arguments.
1782 """
1783 cert = X509()
1784 self.assertRaises(TypeError, cert.subject_name_hash, None)
1785
1786
1787 def test_subject_name_hash(self):
1788 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001789 :py:obj:`X509.subject_name_hash` returns the hash of the certificate's subject
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001790 name.
1791 """
1792 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -04001793 self.assertIn(
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001794 cert.subject_name_hash(),
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -04001795 [3350047874, # OpenSSL 0.9.8, MD5
1796 3278919224, # OpenSSL 1.0.0, SHA1
1797 ])
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001798
1799
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001800 def test_get_signature_algorithm(self):
1801 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001802 :py:obj:`X509Type.get_signature_algorithm` returns a string which means
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001803 the algorithm used to sign the certificate.
1804 """
1805 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001806 self.assertEqual(
1807 b("sha1WithRSAEncryption"), cert.get_signature_algorithm())
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001808
1809
1810 def test_get_undefined_signature_algorithm(self):
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001811 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001812 :py:obj:`X509Type.get_signature_algorithm` raises :py:obj:`ValueError` if the
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001813 signature algorithm is undefined or unknown.
1814 """
1815 # This certificate has been modified to indicate a bogus OID in the
1816 # signature algorithm field so that OpenSSL does not recognize it.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001817 certPEM = b("""\
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001818-----BEGIN CERTIFICATE-----
1819MIIC/zCCAmigAwIBAgIBATAGBgJ8BQUAMHsxCzAJBgNVBAYTAlNHMREwDwYDVQQK
1820EwhNMkNyeXB0bzEUMBIGA1UECxMLTTJDcnlwdG8gQ0ExJDAiBgNVBAMTG00yQ3J5
1821cHRvIENlcnRpZmljYXRlIE1hc3RlcjEdMBsGCSqGSIb3DQEJARYObmdwc0Bwb3N0
1822MS5jb20wHhcNMDAwOTEwMDk1MTMwWhcNMDIwOTEwMDk1MTMwWjBTMQswCQYDVQQG
1823EwJTRzERMA8GA1UEChMITTJDcnlwdG8xEjAQBgNVBAMTCWxvY2FsaG9zdDEdMBsG
1824CSqGSIb3DQEJARYObmdwc0Bwb3N0MS5jb20wXDANBgkqhkiG9w0BAQEFAANLADBI
1825AkEArL57d26W9fNXvOhNlZzlPOACmvwOZ5AdNgLzJ1/MfsQQJ7hHVeHmTAjM664V
1826+fXvwUGJLziCeBo1ysWLRnl8CQIDAQABo4IBBDCCAQAwCQYDVR0TBAIwADAsBglg
1827hkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0O
1828BBYEFM+EgpK+eyZiwFU1aOPSbczbPSpVMIGlBgNVHSMEgZ0wgZqAFPuHI2nrnDqT
1829FeXFvylRT/7tKDgBoX+kfTB7MQswCQYDVQQGEwJTRzERMA8GA1UEChMITTJDcnlw
1830dG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtNMkNyeXB0byBDZXJ0
1831aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tggEA
1832MA0GCSqGSIb3DQEBBAUAA4GBADv8KpPo+gfJxN2ERK1Y1l17sz/ZhzoGgm5XCdbx
1833jEY7xKfpQngV599k1xhl11IMqizDwu0855agrckg2MCTmOI9DZzDD77tAYb+Dk0O
1834PEVk0Mk/V0aIsDE9bolfCi/i/QWZ3N8s5nTWMNyBBBmoSliWCm4jkkRZRD0ejgTN
1835tgI5
1836-----END CERTIFICATE-----
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001837""")
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001838 cert = load_certificate(FILETYPE_PEM, certPEM)
1839 self.assertRaises(ValueError, cert.get_signature_algorithm)
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001840
1841
Rick Dean38a05c82009-07-18 01:41:30 -05001842
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001843class X509StoreTests(TestCase):
1844 """
1845 Test for :py:obj:`OpenSSL.crypto.X509Store`.
1846 """
1847 def test_type(self):
1848 """
1849 :py:obj:`X509StoreType` is a type object.
1850 """
1851 self.assertIdentical(X509Store, X509StoreType)
1852 self.assertConsistentType(X509Store, 'X509Store')
1853
1854
1855 def test_add_cert_wrong_args(self):
1856 store = X509Store()
1857 self.assertRaises(TypeError, store.add_cert)
1858 self.assertRaises(TypeError, store.add_cert, object())
1859 self.assertRaises(TypeError, store.add_cert, X509(), object())
1860
1861
1862 def test_add_cert(self):
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001863 """
1864 :py:obj:`X509Store.add_cert` adds a :py:obj:`X509` instance to the
1865 certificate store.
1866 """
1867 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001868 store = X509Store()
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001869 store.add_cert(cert)
1870
1871
1872 def test_add_cert_rejects_duplicate(self):
1873 """
1874 :py:obj:`X509Store.add_cert` raises :py:obj:`OpenSSL.crypto.Error` if an
1875 attempt is made to add the same certificate to the store more than once.
1876 """
1877 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
1878 store = X509Store()
1879 store.add_cert(cert)
1880 self.assertRaises(Error, store.add_cert, cert)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001881
1882
1883
Rick Dean623ee362009-07-17 12:22:16 -05001884class PKCS12Tests(TestCase):
1885 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001886 Test for :py:obj:`OpenSSL.crypto.PKCS12` and :py:obj:`OpenSSL.crypto.load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001887 """
1888 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
1889
Jean-Paul Calderonec3a41f72009-07-25 12:36:02 -04001890 def test_type(self):
1891 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001892 :py:obj:`PKCS12Type` is a type object.
Jean-Paul Calderonec3a41f72009-07-25 12:36:02 -04001893 """
1894 self.assertIdentical(PKCS12, PKCS12Type)
1895 self.assertConsistentType(PKCS12, 'PKCS12')
1896
1897
Rick Deanf94096c2009-07-18 14:23:06 -05001898 def test_empty_construction(self):
Rick Dean38a05c82009-07-18 01:41:30 -05001899 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001900 :py:obj:`PKCS12` returns a new instance of :py:obj:`PKCS12` with no certificate,
Jean-Paul Calderonedc857b52009-07-25 12:25:07 -04001901 private key, CA certificates, or friendly name.
Rick Dean38a05c82009-07-18 01:41:30 -05001902 """
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001903 p12 = PKCS12()
Rick Dean623ee362009-07-17 12:22:16 -05001904 self.assertEqual(None, p12.get_certificate())
1905 self.assertEqual(None, p12.get_privatekey())
1906 self.assertEqual(None, p12.get_ca_certificates())
Rick Dean42d69e12009-07-20 11:36:08 -05001907 self.assertEqual(None, p12.get_friendlyname())
Rick Dean623ee362009-07-17 12:22:16 -05001908
Rick Dean38a05c82009-07-18 01:41:30 -05001909
Rick Dean623ee362009-07-17 12:22:16 -05001910 def test_type_errors(self):
Rick Dean38a05c82009-07-18 01:41:30 -05001911 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001912 The :py:obj:`PKCS12` setter functions (:py:obj:`set_certificate`, :py:obj:`set_privatekey`,
1913 :py:obj:`set_ca_certificates`, and :py:obj:`set_friendlyname`) raise :py:obj:`TypeError`
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001914 when passed objects of types other than those expected.
Rick Dean38a05c82009-07-18 01:41:30 -05001915 """
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001916 p12 = PKCS12()
Rick Dean623ee362009-07-17 12:22:16 -05001917 self.assertRaises(TypeError, p12.set_certificate, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05001918 self.assertRaises(TypeError, p12.set_certificate, PKey())
1919 self.assertRaises(TypeError, p12.set_certificate, X509)
Rick Dean623ee362009-07-17 12:22:16 -05001920 self.assertRaises(TypeError, p12.set_privatekey, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05001921 self.assertRaises(TypeError, p12.set_privatekey, 'legbone')
1922 self.assertRaises(TypeError, p12.set_privatekey, X509())
Rick Dean623ee362009-07-17 12:22:16 -05001923 self.assertRaises(TypeError, p12.set_ca_certificates, 3)
1924 self.assertRaises(TypeError, p12.set_ca_certificates, X509())
1925 self.assertRaises(TypeError, p12.set_ca_certificates, (3, 4))
Rick Deanf94096c2009-07-18 14:23:06 -05001926 self.assertRaises(TypeError, p12.set_ca_certificates, ( PKey(), ))
Rick Dean42d69e12009-07-20 11:36:08 -05001927 self.assertRaises(TypeError, p12.set_friendlyname, 6)
1928 self.assertRaises(TypeError, p12.set_friendlyname, ('foo', 'bar'))
Rick Dean623ee362009-07-17 12:22:16 -05001929
Rick Dean38a05c82009-07-18 01:41:30 -05001930
Rick Dean623ee362009-07-17 12:22:16 -05001931 def test_key_only(self):
1932 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001933 A :py:obj:`PKCS12` with only a private key can be exported using
1934 :py:obj:`PKCS12.export` and loaded again using :py:obj:`load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001935 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001936 passwd = b"blah"
Rick Dean623ee362009-07-17 12:22:16 -05001937 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001938 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001939 p12.set_privatekey(pkey)
Rick Dean623ee362009-07-17 12:22:16 -05001940 self.assertEqual(None, p12.get_certificate())
1941 self.assertEqual(pkey, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05001942 try:
1943 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
1944 except Error:
1945 # Some versions of OpenSSL will throw an exception
1946 # for this nearly useless PKCS12 we tried to generate:
1947 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
1948 return
Rick Dean623ee362009-07-17 12:22:16 -05001949 p12 = load_pkcs12(dumped_p12, passwd)
1950 self.assertEqual(None, p12.get_ca_certificates())
1951 self.assertEqual(None, p12.get_certificate())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001952
1953 # OpenSSL fails to bring the key back to us. So sad. Perhaps in the
1954 # future this will be improved.
1955 self.assertTrue(isinstance(p12.get_privatekey(), (PKey, type(None))))
Rick Dean623ee362009-07-17 12:22:16 -05001956
Rick Dean38a05c82009-07-18 01:41:30 -05001957
Rick Dean623ee362009-07-17 12:22:16 -05001958 def test_cert_only(self):
1959 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001960 A :py:obj:`PKCS12` with only a certificate can be exported using
1961 :py:obj:`PKCS12.export` and loaded again using :py:obj:`load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001962 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001963 passwd = b"blah"
Rick Dean623ee362009-07-17 12:22:16 -05001964 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001965 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001966 p12.set_certificate(cert)
Rick Dean623ee362009-07-17 12:22:16 -05001967 self.assertEqual(cert, p12.get_certificate())
1968 self.assertEqual(None, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05001969 try:
1970 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
1971 except Error:
1972 # Some versions of OpenSSL will throw an exception
1973 # for this nearly useless PKCS12 we tried to generate:
1974 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
1975 return
Rick Dean623ee362009-07-17 12:22:16 -05001976 p12 = load_pkcs12(dumped_p12, passwd)
1977 self.assertEqual(None, p12.get_privatekey())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001978
1979 # OpenSSL fails to bring the cert back to us. Groany mcgroan.
1980 self.assertTrue(isinstance(p12.get_certificate(), (X509, type(None))))
1981
1982 # Oh ho. It puts the certificate into the ca certificates list, in
1983 # fact. Totally bogus, I would think. Nevertheless, let's exploit
1984 # that to check to see if it reconstructed the certificate we expected
1985 # it to. At some point, hopefully this will change so that
1986 # p12.get_certificate() is actually what returns the loaded
1987 # certificate.
1988 self.assertEqual(
1989 cleartextCertificatePEM,
1990 dump_certificate(FILETYPE_PEM, p12.get_ca_certificates()[0]))
Rick Dean623ee362009-07-17 12:22:16 -05001991
1992
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001993 def gen_pkcs12(self, cert_pem=None, key_pem=None, ca_pem=None, friendly_name=None):
Rick Dean623ee362009-07-17 12:22:16 -05001994 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001995 Generate a PKCS12 object with components from PEM. Verify that the set
1996 functions return None.
Rick Dean623ee362009-07-17 12:22:16 -05001997 """
Rick Deanf94096c2009-07-18 14:23:06 -05001998 p12 = PKCS12()
1999 if cert_pem:
2000 ret = p12.set_certificate(load_certificate(FILETYPE_PEM, cert_pem))
2001 self.assertEqual(ret, None)
2002 if key_pem:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002003 ret = p12.set_privatekey(load_privatekey(FILETYPE_PEM, key_pem))
Rick Deanf94096c2009-07-18 14:23:06 -05002004 self.assertEqual(ret, None)
2005 if ca_pem:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002006 ret = p12.set_ca_certificates((load_certificate(FILETYPE_PEM, ca_pem),))
Rick Deanf94096c2009-07-18 14:23:06 -05002007 self.assertEqual(ret, None)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002008 if friendly_name:
2009 ret = p12.set_friendlyname(friendly_name)
Rick Dean42d69e12009-07-20 11:36:08 -05002010 self.assertEqual(ret, None)
Rick Deanf94096c2009-07-18 14:23:06 -05002011 return p12
2012
2013
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002014 def check_recovery(self, p12_str, key=None, cert=None, ca=None, passwd=b"",
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002015 extra=()):
Rick Deanf94096c2009-07-18 14:23:06 -05002016 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002017 Use openssl program to confirm three components are recoverable from a
2018 PKCS12 string.
Rick Deanf94096c2009-07-18 14:23:06 -05002019 """
2020 if key:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002021 recovered_key = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002022 p12_str, b"pkcs12", b"-nocerts", b"-nodes", b"-passin",
2023 b"pass:" + passwd, *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05002024 self.assertEqual(recovered_key[-len(key):], key)
2025 if cert:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002026 recovered_cert = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002027 p12_str, b"pkcs12", b"-clcerts", b"-nodes", b"-passin",
2028 b"pass:" + passwd, b"-nokeys", *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05002029 self.assertEqual(recovered_cert[-len(cert):], cert)
2030 if ca:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002031 recovered_cert = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002032 p12_str, b"pkcs12", b"-cacerts", b"-nodes", b"-passin",
2033 b"pass:" + passwd, b"-nokeys", *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05002034 self.assertEqual(recovered_cert[-len(ca):], ca)
2035
2036
Stephen Holsapple38482622014-04-05 20:29:34 -07002037 def verify_pkcs12_container(self, p12):
2038 """
2039 Verify that the PKCS#12 container contains the correct client
2040 certificate and private key.
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002041
2042 :param p12: The PKCS12 instance to verify.
2043 :type p12: :py:class:`PKCS12`
Stephen Holsapple38482622014-04-05 20:29:34 -07002044 """
2045 cert_pem = dump_certificate(FILETYPE_PEM, p12.get_certificate())
2046 key_pem = dump_privatekey(FILETYPE_PEM, p12.get_privatekey())
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002047 self.assertEqual(
2048 (client_cert_pem, client_key_pem, None),
2049 (cert_pem, key_pem, p12.get_ca_certificates()))
Stephen Holsapple38482622014-04-05 20:29:34 -07002050
2051
Rick Deanf94096c2009-07-18 14:23:06 -05002052 def test_load_pkcs12(self):
2053 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002054 A PKCS12 string generated using the openssl command line can be loaded
Jonathan Ballet648875f2011-07-16 14:14:58 +09002055 with :py:obj:`load_pkcs12` and its components extracted and examined.
Rick Deanf94096c2009-07-18 14:23:06 -05002056 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002057 passwd = b"whatever"
Rick Dean623ee362009-07-17 12:22:16 -05002058 pem = client_key_pem + client_cert_pem
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002059 p12_str = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002060 pem, b"pkcs12", b"-export", b"-clcerts", b"-passout", b"pass:" + passwd)
Stephen Holsapple38482622014-04-05 20:29:34 -07002061 p12 = load_pkcs12(p12_str, passphrase=passwd)
2062 self.verify_pkcs12_container(p12)
2063
2064
2065 def test_load_pkcs12_no_passphrase(self):
2066 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002067 A PKCS12 string generated using openssl command line can be loaded with
2068 :py:obj:`load_pkcs12` without a passphrase and its components extracted
2069 and examined.
Stephen Holsapple38482622014-04-05 20:29:34 -07002070 """
2071 pem = client_key_pem + client_cert_pem
2072 p12_str = _runopenssl(
2073 pem, b"pkcs12", b"-export", b"-clcerts", b"-passout", b"pass:")
2074 p12 = load_pkcs12(p12_str)
2075 self.verify_pkcs12_container(p12)
2076
2077
2078 def _dump_and_load(self, dump_passphrase, load_passphrase):
2079 """
2080 A helper method to dump and load a PKCS12 object.
2081 """
2082 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem)
2083 dumped_p12 = p12.export(passphrase=dump_passphrase, iter=2, maciter=3)
2084 return load_pkcs12(dumped_p12, passphrase=load_passphrase)
2085
2086
2087 def test_load_pkcs12_null_passphrase_load_empty(self):
2088 """
2089 A PKCS12 string can be dumped with a null passphrase, loaded with an
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002090 empty passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002091 extracted and examined.
2092 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002093 self.verify_pkcs12_container(
2094 self._dump_and_load(dump_passphrase=None, load_passphrase=b''))
Stephen Holsapple38482622014-04-05 20:29:34 -07002095
2096
2097 def test_load_pkcs12_null_passphrase_load_null(self):
2098 """
2099 A PKCS12 string can be dumped with a null passphrase, loaded with a
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002100 null passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002101 extracted and examined.
2102 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002103 self.verify_pkcs12_container(
2104 self._dump_and_load(dump_passphrase=None, load_passphrase=None))
Stephen Holsapple38482622014-04-05 20:29:34 -07002105
2106
2107 def test_load_pkcs12_empty_passphrase_load_empty(self):
2108 """
2109 A PKCS12 string can be dumped with an empty passphrase, loaded with an
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002110 empty passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002111 extracted and examined.
2112 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002113 self.verify_pkcs12_container(
2114 self._dump_and_load(dump_passphrase=b'', load_passphrase=b''))
Stephen Holsapple38482622014-04-05 20:29:34 -07002115
2116
2117 def test_load_pkcs12_empty_passphrase_load_null(self):
2118 """
2119 A PKCS12 string can be dumped with an empty passphrase, loaded with a
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002120 null passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002121 extracted and examined.
2122 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002123 self.verify_pkcs12_container(
2124 self._dump_and_load(dump_passphrase=b'', load_passphrase=None))
Rick Deanf94096c2009-07-18 14:23:06 -05002125
Rick Deanee568302009-07-24 09:56:29 -05002126
2127 def test_load_pkcs12_garbage(self):
2128 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002129 :py:obj:`load_pkcs12` raises :py:obj:`OpenSSL.crypto.Error` when passed a string
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002130 which is not a PKCS12 dump.
Rick Deanee568302009-07-24 09:56:29 -05002131 """
2132 passwd = 'whatever'
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002133 e = self.assertRaises(Error, load_pkcs12, b'fruit loops', passwd)
Jean-Paul Calderonede075462014-01-18 10:34:12 -05002134 self.assertEqual( e.args[0][0][0], 'asn1 encoding routines')
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -04002135 self.assertEqual( len(e.args[0][0]), 3)
Rick Deanee568302009-07-24 09:56:29 -05002136
2137
Rick Deanf94096c2009-07-18 14:23:06 -05002138 def test_replace(self):
2139 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002140 :py:obj:`PKCS12.set_certificate` replaces the certificate in a PKCS12 cluster.
2141 :py:obj:`PKCS12.set_privatekey` replaces the private key.
2142 :py:obj:`PKCS12.set_ca_certificates` replaces the CA certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05002143 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002144 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
2145 p12.set_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2146 p12.set_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002147 root_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05002148 client_cert = load_certificate(FILETYPE_PEM, client_cert_pem)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002149 p12.set_ca_certificates([root_cert]) # not a tuple
Rick Dean623ee362009-07-17 12:22:16 -05002150 self.assertEqual(1, len(p12.get_ca_certificates()))
2151 self.assertEqual(root_cert, p12.get_ca_certificates()[0])
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002152 p12.set_ca_certificates([client_cert, root_cert])
Rick Deanf94096c2009-07-18 14:23:06 -05002153 self.assertEqual(2, len(p12.get_ca_certificates()))
2154 self.assertEqual(client_cert, p12.get_ca_certificates()[0])
2155 self.assertEqual(root_cert, p12.get_ca_certificates()[1])
2156
2157
2158 def test_friendly_name(self):
2159 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002160 The *friendlyName* of a PKCS12 can be set and retrieved via
Jonathan Ballet648875f2011-07-16 14:14:58 +09002161 :py:obj:`PKCS12.get_friendlyname` and :py:obj:`PKCS12_set_friendlyname`, and a
2162 :py:obj:`PKCS12` with a friendly name set can be dumped with :py:obj:`PKCS12.export`.
Rick Deanf94096c2009-07-18 14:23:06 -05002163 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002164 passwd = b'Dogmeat[]{}!@#$%^&*()~`?/.,<>-_+=";:'
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002165 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -04002166 for friendly_name in [b('Serverlicious'), None, b('###')]:
Rick Dean42d69e12009-07-20 11:36:08 -05002167 p12.set_friendlyname(friendly_name)
2168 self.assertEqual(p12.get_friendlyname(), friendly_name)
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002169 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
Rick Dean42d69e12009-07-20 11:36:08 -05002170 reloaded_p12 = load_pkcs12(dumped_p12, passwd)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002171 self.assertEqual(
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -04002172 p12.get_friendlyname(), reloaded_p12.get_friendlyname())
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002173 # We would use the openssl program to confirm the friendly
2174 # name, but it is not possible. The pkcs12 command
2175 # does not store the friendly name in the cert's
Rick Dean42d69e12009-07-20 11:36:08 -05002176 # alias, which we could then extract.
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002177 self.check_recovery(
2178 dumped_p12, key=server_key_pem, cert=server_cert_pem,
2179 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05002180
2181
2182 def test_various_empty_passphrases(self):
2183 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002184 Test that missing, None, and '' passphrases are identical for PKCS12
2185 export.
Rick Deanf94096c2009-07-18 14:23:06 -05002186 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002187 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002188 passwd = b""
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002189 dumped_p12_empty = p12.export(iter=2, maciter=0, passphrase=passwd)
2190 dumped_p12_none = p12.export(iter=3, maciter=2, passphrase=None)
2191 dumped_p12_nopw = p12.export(iter=9, maciter=4)
2192 for dumped_p12 in [dumped_p12_empty, dumped_p12_none, dumped_p12_nopw]:
2193 self.check_recovery(
2194 dumped_p12, key=client_key_pem, cert=client_cert_pem,
2195 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05002196
2197
2198 def test_removing_ca_cert(self):
2199 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002200 Passing :py:obj:`None` to :py:obj:`PKCS12.set_ca_certificates` removes all CA
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002201 certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05002202 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002203 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
2204 p12.set_ca_certificates(None)
Rick Dean623ee362009-07-17 12:22:16 -05002205 self.assertEqual(None, p12.get_ca_certificates())
Rick Deanf94096c2009-07-18 14:23:06 -05002206
2207
2208 def test_export_without_mac(self):
2209 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002210 Exporting a PKCS12 with a :py:obj:`maciter` of ``-1`` excludes the MAC
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002211 entirely.
Rick Deanf94096c2009-07-18 14:23:06 -05002212 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002213 passwd = b"Lake Michigan"
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002214 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Dean623ee362009-07-17 12:22:16 -05002215 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002216 self.check_recovery(
2217 dumped_p12, key=server_key_pem, cert=server_cert_pem,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002218 passwd=passwd, extra=(b"-nomacver",))
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002219
2220
2221 def test_load_without_mac(self):
2222 """
2223 Loading a PKCS12 without a MAC does something other than crash.
2224 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002225 passwd = b"Lake Michigan"
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002226 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
2227 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Rick Dean321a0512009-08-13 17:21:29 -05002228 try:
2229 recovered_p12 = load_pkcs12(dumped_p12, passwd)
2230 # The person who generated this PCKS12 should be flogged,
2231 # or better yet we should have a means to determine
2232 # whether a PCKS12 had a MAC that was verified.
2233 # Anyway, libopenssl chooses to allow it, so the
2234 # pyopenssl binding does as well.
2235 self.assertTrue(isinstance(recovered_p12, PKCS12))
2236 except Error:
2237 # Failing here with an exception is preferred as some openssl
2238 # versions do.
2239 pass
Rick Dean623ee362009-07-17 12:22:16 -05002240
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002241
Rick Dean25bcc1f2009-07-20 11:53:13 -05002242 def test_zero_len_list_for_ca(self):
2243 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002244 A PKCS12 with an empty CA certificates list can be exported.
Rick Dean25bcc1f2009-07-20 11:53:13 -05002245 """
2246 passwd = 'Hobie 18'
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002247 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002248 # p12.set_ca_certificates([])
2249 # self.assertEqual((), p12.get_ca_certificates())
2250 # dumped_p12 = p12.export(passphrase=passwd, iter=3)
2251 # self.check_recovery(
2252 # dumped_p12, key=server_key_pem, cert=server_cert_pem,
2253 # passwd=passwd)
Rick Dean25bcc1f2009-07-20 11:53:13 -05002254
2255
Rick Deanf94096c2009-07-18 14:23:06 -05002256 def test_export_without_args(self):
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002257 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002258 All the arguments to :py:obj:`PKCS12.export` are optional.
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002259 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002260 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05002261 dumped_p12 = p12.export() # no args
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002262 self.check_recovery(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002263 dumped_p12, key=server_key_pem, cert=server_cert_pem, passwd=b"")
Rick Deanf94096c2009-07-18 14:23:06 -05002264
2265
2266 def test_key_cert_mismatch(self):
2267 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002268 :py:obj:`PKCS12.export` raises an exception when a key and certificate
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002269 mismatch.
Rick Deanf94096c2009-07-18 14:23:06 -05002270 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002271 p12 = self.gen_pkcs12(server_cert_pem, client_key_pem, root_cert_pem)
2272 self.assertRaises(Error, p12.export)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002273
2274
2275
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002276# These quoting functions taken directly from Twisted's twisted.python.win32.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002277_cmdLineQuoteRe = re.compile(br'(\\*)"')
2278_cmdLineQuoteRe2 = re.compile(br'(\\+)\Z')
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002279def cmdLineQuote(s):
2280 """
2281 Internal method for quoting a single command-line argument.
2282
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002283 See http://www.perlmonks.org/?node_id=764004
2284
Jonathan Ballet648875f2011-07-16 14:14:58 +09002285 :type: :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002286 :param s: A single unquoted string to quote for something that is expecting
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002287 cmd.exe-style quoting
2288
Jonathan Ballet648875f2011-07-16 14:14:58 +09002289 :rtype: :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002290 :return: A cmd.exe-style quoted string
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002291 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002292 s = _cmdLineQuoteRe2.sub(br"\1\1", _cmdLineQuoteRe.sub(br'\1\1\\"', s))
2293 return b'"' + s + b'"'
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002294
2295
2296
2297def quoteArguments(arguments):
2298 """
2299 Quote an iterable of command-line arguments for passing to CreateProcess or
Jonathan Ballet648875f2011-07-16 14:14:58 +09002300 a similar API. This allows the list passed to :py:obj:`reactor.spawnProcess` to
2301 match the child process's :py:obj:`sys.argv` properly.
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002302
Jonathan Ballet648875f2011-07-16 14:14:58 +09002303 :type arguments: :py:obj:`iterable` of :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002304 :param arguments: An iterable of unquoted arguments to quote
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002305
Jonathan Ballet648875f2011-07-16 14:14:58 +09002306 :rtype: :py:obj:`str`
2307 :return: A space-delimited string containing quoted versions of :py:obj:`arguments`
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002308 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002309 return b' '.join(map(cmdLineQuote, arguments))
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002310
2311
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002312
Rick Dean4c9ad612009-07-17 15:05:22 -05002313def _runopenssl(pem, *args):
2314 """
2315 Run the command line openssl tool with the given arguments and write
Rick Dean55d1ce62009-08-13 17:40:24 -05002316 the given PEM to its stdin. Not safe for quotes.
Rick Dean4c9ad612009-07-17 15:05:22 -05002317 """
Jean-Paul Calderone038de952009-08-21 12:16:06 -04002318 if os.name == 'posix':
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002319 command = b"openssl " + b" ".join([
2320 (b"'" + arg.replace(b"'", b"'\\''") + b"'")
2321 for arg in args])
Rick Dean55d1ce62009-08-13 17:40:24 -05002322 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002323 command = b"openssl " + quoteArguments(args)
2324 proc = Popen(native(command), shell=True, stdin=PIPE, stdout=PIPE)
Jean-Paul Calderone62ca8da2010-08-11 19:58:08 -04002325 proc.stdin.write(pem)
2326 proc.stdin.close()
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002327 output = proc.stdout.read()
2328 proc.stdout.close()
2329 proc.wait()
2330 return output
Rick Dean4c9ad612009-07-17 15:05:22 -05002331
2332
2333
Jean-Paul Calderone18808652009-07-05 12:54:05 -04002334class FunctionTests(TestCase):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002335 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002336 Tests for free-functions in the :py:obj:`OpenSSL.crypto` module.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002337 """
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002338
2339 def test_load_privatekey_invalid_format(self):
2340 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002341 :py:obj:`load_privatekey` raises :py:obj:`ValueError` if passed an unknown filetype.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002342 """
2343 self.assertRaises(ValueError, load_privatekey, 100, root_key_pem)
2344
2345
2346 def test_load_privatekey_invalid_passphrase_type(self):
2347 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002348 :py:obj:`load_privatekey` raises :py:obj:`TypeError` if passed a passphrase that is
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002349 neither a :py:obj:`str` nor a callable.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002350 """
2351 self.assertRaises(
2352 TypeError,
2353 load_privatekey,
2354 FILETYPE_PEM, encryptedPrivateKeyPEMPassphrase, object())
2355
2356
2357 def test_load_privatekey_wrong_args(self):
2358 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002359 :py:obj:`load_privatekey` raises :py:obj:`TypeError` if called with the wrong number
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002360 of arguments.
2361 """
2362 self.assertRaises(TypeError, load_privatekey)
2363
2364
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002365 def test_load_privatekey_wrongPassphrase(self):
2366 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002367 :py:obj:`load_privatekey` raises :py:obj:`OpenSSL.crypto.Error` when it is passed an
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002368 encrypted PEM and an incorrect passphrase.
2369 """
2370 self.assertRaises(
2371 Error,
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002372 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, b("quack"))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002373
2374
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002375 def test_load_privatekey_passphraseWrongType(self):
2376 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002377 :py:obj:`load_privatekey` raises :py:obj:`ValueError` when it is passed a passphrase
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002378 with a private key encoded in a format, that doesn't support
2379 encryption.
2380 """
2381 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2382 blob = dump_privatekey(FILETYPE_ASN1, key)
2383 self.assertRaises(ValueError,
2384 load_privatekey, FILETYPE_ASN1, blob, "secret")
2385
2386
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002387 def test_load_privatekey_passphrase(self):
2388 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002389 :py:obj:`load_privatekey` can create a :py:obj:`PKey` object from an encrypted PEM
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002390 string if given the passphrase.
2391 """
2392 key = load_privatekey(
2393 FILETYPE_PEM, encryptedPrivateKeyPEM,
2394 encryptedPrivateKeyPEMPassphrase)
2395 self.assertTrue(isinstance(key, PKeyType))
2396
2397
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002398 def test_load_privatekey_passphrase_exception(self):
2399 """
2400 If the passphrase callback raises an exception, that exception is raised
2401 by :py:obj:`load_privatekey`.
2402 """
2403 def cb(ignored):
2404 raise ArithmeticError
2405
2406 self.assertRaises(ArithmeticError,
2407 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2408
2409
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002410 def test_load_privatekey_wrongPassphraseCallback(self):
2411 """
Jean-Paul Calderoned440a082011-09-14 11:02:05 -04002412 :py:obj:`load_privatekey` raises :py:obj:`OpenSSL.crypto.Error` when it
2413 is passed an encrypted PEM and a passphrase callback which returns an
2414 incorrect passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002415 """
2416 called = []
2417 def cb(*a):
2418 called.append(None)
Jean-Paul Calderoned440a082011-09-14 11:02:05 -04002419 return b("quack")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002420 self.assertRaises(
2421 Error,
2422 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2423 self.assertTrue(called)
2424
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002425
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002426 def test_load_privatekey_passphraseCallback(self):
2427 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002428 :py:obj:`load_privatekey` can create a :py:obj:`PKey` object from an encrypted PEM
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002429 string if given a passphrase callback which returns the correct
2430 password.
2431 """
2432 called = []
2433 def cb(writing):
2434 called.append(writing)
2435 return encryptedPrivateKeyPEMPassphrase
2436 key = load_privatekey(FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2437 self.assertTrue(isinstance(key, PKeyType))
2438 self.assertEqual(called, [False])
2439
2440
Jean-Paul Calderone105cb952011-09-14 10:16:46 -04002441 def test_load_privatekey_passphrase_wrong_return_type(self):
2442 """
2443 :py:obj:`load_privatekey` raises :py:obj:`ValueError` if the passphrase
2444 callback returns something other than a byte string.
2445 """
2446 self.assertRaises(
2447 ValueError,
2448 load_privatekey,
2449 FILETYPE_PEM, encryptedPrivateKeyPEM, lambda *args: 3)
2450
2451
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002452 def test_dump_privatekey_wrong_args(self):
2453 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002454 :py:obj:`dump_privatekey` raises :py:obj:`TypeError` if called with the wrong number
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002455 of arguments.
2456 """
2457 self.assertRaises(TypeError, dump_privatekey)
Jean-Paul Calderone1eeccd82011-09-14 10:18:52 -04002458 # If cipher name is given, password is required.
2459 self.assertRaises(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002460 TypeError, dump_privatekey, FILETYPE_PEM, PKey(), GOOD_CIPHER)
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002461
2462
2463 def test_dump_privatekey_unknown_cipher(self):
2464 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002465 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` if called with an unrecognized
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002466 cipher name.
2467 """
2468 key = PKey()
2469 key.generate_key(TYPE_RSA, 512)
2470 self.assertRaises(
2471 ValueError, dump_privatekey,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002472 FILETYPE_PEM, key, BAD_CIPHER, "passphrase")
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002473
2474
2475 def test_dump_privatekey_invalid_passphrase_type(self):
2476 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002477 :py:obj:`dump_privatekey` raises :py:obj:`TypeError` if called with a passphrase which
2478 is neither a :py:obj:`str` nor a callable.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002479 """
2480 key = PKey()
2481 key.generate_key(TYPE_RSA, 512)
2482 self.assertRaises(
2483 TypeError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002484 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, object())
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002485
2486
2487 def test_dump_privatekey_invalid_filetype(self):
2488 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002489 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` if called with an unrecognized
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002490 filetype.
2491 """
2492 key = PKey()
2493 key.generate_key(TYPE_RSA, 512)
2494 self.assertRaises(ValueError, dump_privatekey, 100, key)
2495
2496
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002497 def test_load_privatekey_passphraseCallbackLength(self):
2498 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002499 :py:obj:`crypto.load_privatekey` should raise an error when the passphrase
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002500 provided by the callback is too long, not silently truncate it.
2501 """
2502 def cb(ignored):
2503 return "a" * 1025
2504
2505 self.assertRaises(ValueError,
2506 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2507
2508
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002509 def test_dump_privatekey_passphrase(self):
2510 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002511 :py:obj:`dump_privatekey` writes an encrypted PEM when given a passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002512 """
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002513 passphrase = b("foo")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002514 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002515 pem = dump_privatekey(FILETYPE_PEM, key, GOOD_CIPHER, passphrase)
2516 self.assertTrue(isinstance(pem, binary_type))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002517 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
2518 self.assertTrue(isinstance(loadedKey, PKeyType))
2519 self.assertEqual(loadedKey.type(), key.type())
2520 self.assertEqual(loadedKey.bits(), key.bits())
2521
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002522
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002523 def test_dump_privatekey_passphraseWrongType(self):
2524 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002525 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` when it is passed a passphrase
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002526 with a private key encoded in a format, that doesn't support
2527 encryption.
2528 """
2529 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2530 self.assertRaises(ValueError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002531 dump_privatekey, FILETYPE_ASN1, key, GOOD_CIPHER, "secret")
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002532
2533
Rick Dean5b7b6372009-04-01 11:34:06 -05002534 def test_dump_certificate(self):
2535 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002536 :py:obj:`dump_certificate` writes PEM, DER, and text.
Rick Dean5b7b6372009-04-01 11:34:06 -05002537 """
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002538 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
Rick Dean5b7b6372009-04-01 11:34:06 -05002539 cert = load_certificate(FILETYPE_PEM, pemData)
2540 dumped_pem = dump_certificate(FILETYPE_PEM, cert)
2541 self.assertEqual(dumped_pem, cleartextCertificatePEM)
2542 dumped_der = dump_certificate(FILETYPE_ASN1, cert)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002543 good_der = _runopenssl(dumped_pem, b"x509", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002544 self.assertEqual(dumped_der, good_der)
2545 cert2 = load_certificate(FILETYPE_ASN1, dumped_der)
2546 dumped_pem2 = dump_certificate(FILETYPE_PEM, cert2)
2547 self.assertEqual(dumped_pem2, cleartextCertificatePEM)
2548 dumped_text = dump_certificate(FILETYPE_TEXT, cert)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002549 good_text = _runopenssl(dumped_pem, b"x509", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002550 self.assertEqual(dumped_text, good_text)
2551
2552
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002553 def test_dump_privatekey_pem(self):
Rick Dean5b7b6372009-04-01 11:34:06 -05002554 """
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002555 :py:obj:`dump_privatekey` writes a PEM
Rick Dean5b7b6372009-04-01 11:34:06 -05002556 """
2557 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -04002558 self.assertTrue(key.check())
Rick Dean5b7b6372009-04-01 11:34:06 -05002559 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2560 self.assertEqual(dumped_pem, cleartextPrivateKeyPEM)
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002561
2562
2563 def test_dump_privatekey_asn1(self):
2564 """
2565 :py:obj:`dump_privatekey` writes a DER
2566 """
2567 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2568 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2569
Rick Dean5b7b6372009-04-01 11:34:06 -05002570 dumped_der = dump_privatekey(FILETYPE_ASN1, key)
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002571 # XXX This OpenSSL call writes "writing RSA key" to standard out. Sad.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002572 good_der = _runopenssl(dumped_pem, b"rsa", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002573 self.assertEqual(dumped_der, good_der)
2574 key2 = load_privatekey(FILETYPE_ASN1, dumped_der)
2575 dumped_pem2 = dump_privatekey(FILETYPE_PEM, key2)
2576 self.assertEqual(dumped_pem2, cleartextPrivateKeyPEM)
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002577
2578
2579 def test_dump_privatekey_text(self):
2580 """
2581 :py:obj:`dump_privatekey` writes a text
2582 """
2583 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2584 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2585
Rick Dean5b7b6372009-04-01 11:34:06 -05002586 dumped_text = dump_privatekey(FILETYPE_TEXT, key)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002587 good_text = _runopenssl(dumped_pem, b"rsa", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002588 self.assertEqual(dumped_text, good_text)
2589
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002590
Rick Dean5b7b6372009-04-01 11:34:06 -05002591 def test_dump_certificate_request(self):
2592 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002593 :py:obj:`dump_certificate_request` writes a PEM, DER, and text.
Rick Dean5b7b6372009-04-01 11:34:06 -05002594 """
2595 req = load_certificate_request(FILETYPE_PEM, cleartextCertificateRequestPEM)
2596 dumped_pem = dump_certificate_request(FILETYPE_PEM, req)
2597 self.assertEqual(dumped_pem, cleartextCertificateRequestPEM)
2598 dumped_der = dump_certificate_request(FILETYPE_ASN1, req)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002599 good_der = _runopenssl(dumped_pem, b"req", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002600 self.assertEqual(dumped_der, good_der)
2601 req2 = load_certificate_request(FILETYPE_ASN1, dumped_der)
2602 dumped_pem2 = dump_certificate_request(FILETYPE_PEM, req2)
2603 self.assertEqual(dumped_pem2, cleartextCertificateRequestPEM)
2604 dumped_text = dump_certificate_request(FILETYPE_TEXT, req)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002605 good_text = _runopenssl(dumped_pem, b"req", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002606 self.assertEqual(dumped_text, good_text)
Jean-Paul Calderoneaf43cdf2010-08-03 18:40:52 -04002607 self.assertRaises(ValueError, dump_certificate_request, 100, req)
Rick Dean5b7b6372009-04-01 11:34:06 -05002608
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002609
2610 def test_dump_privatekey_passphraseCallback(self):
2611 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002612 :py:obj:`dump_privatekey` writes an encrypted PEM when given a callback which
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002613 returns the correct passphrase.
2614 """
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002615 passphrase = b("foo")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002616 called = []
2617 def cb(writing):
2618 called.append(writing)
2619 return passphrase
2620 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002621 pem = dump_privatekey(FILETYPE_PEM, key, GOOD_CIPHER, cb)
2622 self.assertTrue(isinstance(pem, binary_type))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002623 self.assertEqual(called, [True])
2624 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
2625 self.assertTrue(isinstance(loadedKey, PKeyType))
2626 self.assertEqual(loadedKey.type(), key.type())
2627 self.assertEqual(loadedKey.bits(), key.bits())
Rick Dean5b7b6372009-04-01 11:34:06 -05002628
2629
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002630 def test_dump_privatekey_passphrase_exception(self):
2631 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002632 :py:obj:`dump_privatekey` should not overwrite the exception raised
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002633 by the passphrase callback.
2634 """
2635 def cb(ignored):
2636 raise ArithmeticError
2637
2638 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2639 self.assertRaises(ArithmeticError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002640 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, cb)
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002641
2642
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002643 def test_dump_privatekey_passphraseCallbackLength(self):
2644 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002645 :py:obj:`crypto.dump_privatekey` should raise an error when the passphrase
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002646 provided by the callback is too long, not silently truncate it.
2647 """
2648 def cb(ignored):
2649 return "a" * 1025
2650
2651 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2652 self.assertRaises(ValueError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002653 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, cb)
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002654
2655
Alex Gaynor4b9c96a2014-08-14 09:51:48 -07002656 def test_load_pkcs7_data_pem(self):
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002657 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002658 :py:obj:`load_pkcs7_data` accepts a PKCS#7 string and returns an instance of
2659 :py:obj:`PKCS7Type`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002660 """
2661 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2662 self.assertTrue(isinstance(pkcs7, PKCS7Type))
2663
2664
Alex Gaynor4b9c96a2014-08-14 09:51:48 -07002665 def test_load_pkcs7_data_asn1(self):
Alex Gaynor9875a912014-08-14 13:35:05 -07002666 """
2667 :py:obj:`load_pkcs7_data` accepts a bytes containing ASN1 data
2668 representing PKCS#7 and returns an instance of :py:obj`PKCS7Type`.
2669 """
Alex Gaynor4b9c96a2014-08-14 09:51:48 -07002670 pkcs7 = load_pkcs7_data(FILETYPE_ASN1, pkcs7DataASN1)
2671 self.assertTrue(isinstance(pkcs7, PKCS7Type))
2672
2673
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002674 def test_load_pkcs7_data_invalid(self):
2675 """
2676 If the data passed to :py:obj:`load_pkcs7_data` is invalid,
2677 :py:obj:`Error` is raised.
2678 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002679 self.assertRaises(Error, load_pkcs7_data, FILETYPE_PEM, b"foo")
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002680
2681
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002682
Jean-Paul Calderone4a68b402013-12-29 16:54:58 -05002683class LoadCertificateTests(TestCase):
2684 """
2685 Tests for :py:obj:`load_certificate_request`.
2686 """
2687 def test_badFileType(self):
2688 """
2689 If the file type passed to :py:obj:`load_certificate_request` is
2690 neither :py:obj:`FILETYPE_PEM` nor :py:obj:`FILETYPE_ASN1` then
2691 :py:class:`ValueError` is raised.
2692 """
2693 self.assertRaises(ValueError, load_certificate_request, object(), b"")
2694
2695
2696
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002697class PKCS7Tests(TestCase):
2698 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002699 Tests for :py:obj:`PKCS7Type`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002700 """
2701 def test_type(self):
2702 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002703 :py:obj:`PKCS7Type` is a type object.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002704 """
2705 self.assertTrue(isinstance(PKCS7Type, type))
2706 self.assertEqual(PKCS7Type.__name__, 'PKCS7')
2707
2708 # XXX This doesn't currently work.
2709 # self.assertIdentical(PKCS7, PKCS7Type)
2710
2711
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002712 # XXX Opposite results for all these following methods
2713
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002714 def test_type_is_signed_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002715 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002716 :py:obj:`PKCS7Type.type_is_signed` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002717 arguments.
2718 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002719 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2720 self.assertRaises(TypeError, pkcs7.type_is_signed, None)
2721
2722
2723 def test_type_is_signed(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002724 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002725 :py:obj:`PKCS7Type.type_is_signed` returns :py:obj:`True` if the PKCS7 object is of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002726 the type *signed*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002727 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002728 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2729 self.assertTrue(pkcs7.type_is_signed())
2730
2731
2732 def test_type_is_enveloped_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002733 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002734 :py:obj:`PKCS7Type.type_is_enveloped` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002735 arguments.
2736 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002737 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2738 self.assertRaises(TypeError, pkcs7.type_is_enveloped, None)
2739
2740
2741 def test_type_is_enveloped(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002742 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002743 :py:obj:`PKCS7Type.type_is_enveloped` returns :py:obj:`False` if the PKCS7 object is
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002744 not of the type *enveloped*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002745 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002746 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2747 self.assertFalse(pkcs7.type_is_enveloped())
2748
2749
2750 def test_type_is_signedAndEnveloped_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002751 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002752 :py:obj:`PKCS7Type.type_is_signedAndEnveloped` raises :py:obj:`TypeError` if called
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002753 with any arguments.
2754 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002755 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2756 self.assertRaises(TypeError, pkcs7.type_is_signedAndEnveloped, None)
2757
2758
2759 def test_type_is_signedAndEnveloped(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002760 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002761 :py:obj:`PKCS7Type.type_is_signedAndEnveloped` returns :py:obj:`False` if the PKCS7
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002762 object is not of the type *signed and enveloped*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002763 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002764 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2765 self.assertFalse(pkcs7.type_is_signedAndEnveloped())
2766
2767
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002768 def test_type_is_data(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002769 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002770 :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 -04002771 the type data.
2772 """
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002773 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2774 self.assertFalse(pkcs7.type_is_data())
2775
2776
2777 def test_type_is_data_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002778 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002779 :py:obj:`PKCS7Type.type_is_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002780 arguments.
2781 """
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002782 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2783 self.assertRaises(TypeError, pkcs7.type_is_data, None)
2784
2785
Jean-Paul Calderone97b28ca2010-07-30 10:56:07 -04002786 def test_get_type_name_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002787 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002788 :py:obj:`PKCS7Type.get_type_name` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002789 arguments.
2790 """
Jean-Paul Calderone97b28ca2010-07-30 10:56:07 -04002791 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2792 self.assertRaises(TypeError, pkcs7.get_type_name, None)
2793
2794
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002795 def test_get_type_name(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002796 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002797 :py:obj:`PKCS7Type.get_type_name` returns a :py:obj:`str` giving the type name.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002798 """
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002799 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
Jean-Paul Calderone07640f12010-08-22 17:14:43 -04002800 self.assertEquals(pkcs7.get_type_name(), b('pkcs7-signedData'))
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002801
2802
2803 def test_attribute(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002804 """
2805 If an attribute other than one of the methods tested here is accessed on
Jonathan Ballet648875f2011-07-16 14:14:58 +09002806 an instance of :py:obj:`PKCS7Type`, :py:obj:`AttributeError` is raised.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002807 """
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002808 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2809 self.assertRaises(AttributeError, getattr, pkcs7, "foo")
2810
2811
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002812
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002813class NetscapeSPKITests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002814 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002815 Tests for :py:obj:`OpenSSL.crypto.NetscapeSPKI`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002816 """
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002817 def signable(self):
2818 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002819 Return a new :py:obj:`NetscapeSPKI` for use with signing tests.
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002820 """
2821 return NetscapeSPKI()
2822
2823
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002824 def test_type(self):
2825 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002826 :py:obj:`NetscapeSPKI` and :py:obj:`NetscapeSPKIType` refer to the same type object
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002827 and can be used to create instances of that type.
2828 """
2829 self.assertIdentical(NetscapeSPKI, NetscapeSPKIType)
2830 self.assertConsistentType(NetscapeSPKI, 'NetscapeSPKI')
2831
2832
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002833 def test_construction(self):
2834 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002835 :py:obj:`NetscapeSPKI` returns an instance of :py:obj:`NetscapeSPKIType`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002836 """
2837 nspki = NetscapeSPKI()
2838 self.assertTrue(isinstance(nspki, NetscapeSPKIType))
2839
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002840
Jean-Paul Calderone969efaa2010-08-03 18:19:19 -04002841 def test_invalid_attribute(self):
2842 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002843 Accessing a non-existent attribute of a :py:obj:`NetscapeSPKI` instance causes
2844 an :py:obj:`AttributeError` to be raised.
Jean-Paul Calderone969efaa2010-08-03 18:19:19 -04002845 """
2846 nspki = NetscapeSPKI()
2847 self.assertRaises(AttributeError, lambda: nspki.foo)
2848
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002849
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002850 def test_b64_encode(self):
2851 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002852 :py:obj:`NetscapeSPKI.b64_encode` encodes the certificate to a base64 blob.
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002853 """
2854 nspki = NetscapeSPKI()
2855 blob = nspki.b64_encode()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002856 self.assertTrue(isinstance(blob, binary_type))
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002857
2858
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002859
Rick Dean536ba022009-07-24 23:57:27 -05002860class RevokedTests(TestCase):
2861 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002862 Tests for :py:obj:`OpenSSL.crypto.Revoked`
Rick Dean536ba022009-07-24 23:57:27 -05002863 """
2864 def test_construction(self):
2865 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002866 Confirm we can create :py:obj:`OpenSSL.crypto.Revoked`. Check
Rick Dean536ba022009-07-24 23:57:27 -05002867 that it is empty.
2868 """
2869 revoked = Revoked()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002870 self.assertTrue(isinstance(revoked, Revoked))
2871 self.assertEquals(type(revoked), Revoked)
2872 self.assertEquals(revoked.get_serial(), b('00'))
2873 self.assertEquals(revoked.get_rev_date(), None)
2874 self.assertEquals(revoked.get_reason(), None)
Rick Dean536ba022009-07-24 23:57:27 -05002875
2876
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002877 def test_construction_wrong_args(self):
2878 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002879 Calling :py:obj:`OpenSSL.crypto.Revoked` with any arguments results
2880 in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002881 """
2882 self.assertRaises(TypeError, Revoked, None)
2883 self.assertRaises(TypeError, Revoked, 1)
2884 self.assertRaises(TypeError, Revoked, "foo")
2885
2886
Rick Dean536ba022009-07-24 23:57:27 -05002887 def test_serial(self):
2888 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002889 Confirm we can set and get serial numbers from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002890 :py:obj:`OpenSSL.crypto.Revoked`. Confirm errors are handled
Rick Dean536ba022009-07-24 23:57:27 -05002891 with grace.
2892 """
2893 revoked = Revoked()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002894 ret = revoked.set_serial(b('10b'))
2895 self.assertEquals(ret, None)
Rick Dean536ba022009-07-24 23:57:27 -05002896 ser = revoked.get_serial()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002897 self.assertEquals(ser, b('010B'))
Rick Dean536ba022009-07-24 23:57:27 -05002898
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002899 revoked.set_serial(b('31ppp')) # a type error would be nice
Rick Dean536ba022009-07-24 23:57:27 -05002900 ser = revoked.get_serial()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002901 self.assertEquals(ser, b('31'))
Rick Dean536ba022009-07-24 23:57:27 -05002902
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002903 self.assertRaises(ValueError, revoked.set_serial, b('pqrst'))
Rick Dean536ba022009-07-24 23:57:27 -05002904 self.assertRaises(TypeError, revoked.set_serial, 100)
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002905 self.assertRaises(TypeError, revoked.get_serial, 1)
2906 self.assertRaises(TypeError, revoked.get_serial, None)
2907 self.assertRaises(TypeError, revoked.get_serial, "")
Rick Dean536ba022009-07-24 23:57:27 -05002908
2909
2910 def test_date(self):
2911 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002912 Confirm we can set and get revocation dates from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002913 :py:obj:`OpenSSL.crypto.Revoked`. Confirm errors are handled
Rick Dean536ba022009-07-24 23:57:27 -05002914 with grace.
2915 """
2916 revoked = Revoked()
2917 date = revoked.get_rev_date()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002918 self.assertEquals(date, None)
Rick Dean536ba022009-07-24 23:57:27 -05002919
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002920 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05002921 ret = revoked.set_rev_date(now)
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002922 self.assertEqual(ret, None)
Rick Dean536ba022009-07-24 23:57:27 -05002923 date = revoked.get_rev_date()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002924 self.assertEqual(date, now)
Rick Dean536ba022009-07-24 23:57:27 -05002925
2926
Rick Dean6385faf2009-07-26 00:07:47 -05002927 def test_reason(self):
2928 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002929 Confirm we can set and get revocation reasons from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002930 :py:obj:`OpenSSL.crypto.Revoked`. The "get" need to work
Rick Dean6385faf2009-07-26 00:07:47 -05002931 as "set". Likewise, each reason of all_reasons() must work.
2932 """
2933 revoked = Revoked()
2934 for r in revoked.all_reasons():
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002935 for x in range(2):
Rick Dean6385faf2009-07-26 00:07:47 -05002936 ret = revoked.set_reason(r)
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002937 self.assertEquals(ret, None)
Rick Dean6385faf2009-07-26 00:07:47 -05002938 reason = revoked.get_reason()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002939 self.assertEquals(
2940 reason.lower().replace(b(' '), b('')),
2941 r.lower().replace(b(' '), b('')))
Rick Dean6385faf2009-07-26 00:07:47 -05002942 r = reason # again with the resp of get
2943
2944 revoked.set_reason(None)
2945 self.assertEqual(revoked.get_reason(), None)
2946
2947
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002948 def test_set_reason_wrong_arguments(self):
Rick Dean6385faf2009-07-26 00:07:47 -05002949 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002950 Calling :py:obj:`OpenSSL.crypto.Revoked.set_reason` with other than
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002951 one argument, or an argument which isn't a valid reason,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002952 results in :py:obj:`TypeError` or :py:obj:`ValueError` being raised.
Rick Dean6385faf2009-07-26 00:07:47 -05002953 """
2954 revoked = Revoked()
2955 self.assertRaises(TypeError, revoked.set_reason, 100)
Jean-Paul Calderone281b62b2010-08-28 14:22:29 -04002956 self.assertRaises(ValueError, revoked.set_reason, b('blue'))
Rick Dean6385faf2009-07-26 00:07:47 -05002957
Rick Dean536ba022009-07-24 23:57:27 -05002958
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002959 def test_get_reason_wrong_arguments(self):
2960 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002961 Calling :py:obj:`OpenSSL.crypto.Revoked.get_reason` with any
2962 arguments results in :py:obj:`TypeError` being raised.
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002963 """
2964 revoked = Revoked()
2965 self.assertRaises(TypeError, revoked.get_reason, None)
2966 self.assertRaises(TypeError, revoked.get_reason, 1)
2967 self.assertRaises(TypeError, revoked.get_reason, "foo")
2968
2969
2970
Rick Dean536ba022009-07-24 23:57:27 -05002971class CRLTests(TestCase):
2972 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002973 Tests for :py:obj:`OpenSSL.crypto.CRL`
Rick Dean536ba022009-07-24 23:57:27 -05002974 """
2975 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
2976 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2977
2978 def test_construction(self):
2979 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002980 Confirm we can create :py:obj:`OpenSSL.crypto.CRL`. Check
Rick Dean536ba022009-07-24 23:57:27 -05002981 that it is empty
2982 """
2983 crl = CRL()
2984 self.assertTrue( isinstance(crl, CRL) )
2985 self.assertEqual(crl.get_revoked(), None)
2986
2987
Jean-Paul Calderone2efd03e2010-01-30 13:59:55 -05002988 def test_construction_wrong_args(self):
2989 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002990 Calling :py:obj:`OpenSSL.crypto.CRL` with any number of arguments
2991 results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone2efd03e2010-01-30 13:59:55 -05002992 """
2993 self.assertRaises(TypeError, CRL, 1)
2994 self.assertRaises(TypeError, CRL, "")
2995 self.assertRaises(TypeError, CRL, None)
2996
2997
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002998 def _get_crl(self):
Rick Dean536ba022009-07-24 23:57:27 -05002999 """
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003000 Get a new ``CRL`` with a revocation.
Rick Dean536ba022009-07-24 23:57:27 -05003001 """
3002 crl = CRL()
3003 revoked = Revoked()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003004 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05003005 revoked.set_rev_date(now)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003006 revoked.set_serial(b('3ab'))
3007 revoked.set_reason(b('sUpErSeDEd'))
Rick Dean536ba022009-07-24 23:57:27 -05003008 crl.add_revoked(revoked)
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003009 return crl
Rick Dean536ba022009-07-24 23:57:27 -05003010
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003011
3012 def test_export_pem(self):
3013 """
3014 If not passed a format, ``CRL.export`` returns a "PEM" format string
3015 representing a serial number, a revoked reason, and certificate issuer
3016 information.
3017 """
3018 crl = self._get_crl()
Rick Dean536ba022009-07-24 23:57:27 -05003019 # PEM format
3020 dumped_crl = crl.export(self.cert, self.pkey, days=20)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003021 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003022
3023 # These magic values are based on the way the CRL above was constructed
3024 # and with what certificate it was exported.
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003025 text.index(b('Serial Number: 03AB'))
3026 text.index(b('Superseded'))
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003027 text.index(
3028 b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA')
3029 )
3030
3031
3032 def test_export_der(self):
3033 """
3034 If passed ``FILETYPE_ASN1`` for the format, ``CRL.export`` returns a
3035 "DER" format string representing a serial number, a revoked reason, and
3036 certificate issuer information.
3037 """
3038 crl = self._get_crl()
Rick Dean536ba022009-07-24 23:57:27 -05003039
3040 # DER format
3041 dumped_crl = crl.export(self.cert, self.pkey, FILETYPE_ASN1)
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003042 text = _runopenssl(
3043 dumped_crl, b"crl", b"-noout", b"-text", b"-inform", b"DER"
3044 )
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003045 text.index(b('Serial Number: 03AB'))
3046 text.index(b('Superseded'))
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003047 text.index(
3048 b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA')
3049 )
3050
3051
3052 def test_export_text(self):
3053 """
3054 If passed ``FILETYPE_TEXT`` for the format, ``CRL.export`` returns a
3055 text format string like the one produced by the openssl command line
3056 tool.
3057 """
3058 crl = self._get_crl()
3059
3060 dumped_crl = crl.export(self.cert, self.pkey, FILETYPE_ASN1)
3061 text = _runopenssl(
3062 dumped_crl, b"crl", b"-noout", b"-text", b"-inform", b"DER"
3063 )
Rick Dean536ba022009-07-24 23:57:27 -05003064
3065 # text format
3066 dumped_text = crl.export(self.cert, self.pkey, type=FILETYPE_TEXT)
3067 self.assertEqual(text, dumped_text)
3068
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003069
3070 def test_export_custom_digest(self):
3071 """
3072 If passed the name of a digest function, ``CRL.export`` uses a
3073 signature algorithm based on that digest function.
3074 """
3075 crl = self._get_crl()
Bulat Gaifullin1966c972014-09-22 09:47:20 +04003076 dumped_crl = crl.export(self.cert, self.pkey, digest='sha1')
3077 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
3078 text.index(b('Signature Algorithm: sha1'))
3079
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003080
3081 def test_export_default_digest(self):
3082 """
3083 If not passed the name of a digest function, ``CRL.export`` uses a
3084 signature algorithm based on MD5 and emits a deprecation warning.
3085 """
3086 crl = self._get_crl()
3087 with catch_warnings(record=True) as catcher:
3088 simplefilter("always")
3089 dumped_crl = crl.export(self.cert, self.pkey)
3090 self.assertEqual(
3091 "The default message digest (md5) is deprecated. "
3092 "Pass the name of a message digest explicitly.",
3093 str(catcher[0].message),
3094 )
Bulat Gaifullin1966c972014-09-22 09:47:20 +04003095 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
3096 text.index(b('Signature Algorithm: md5'))
3097
Rick Dean536ba022009-07-24 23:57:27 -05003098
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -04003099 def test_export_invalid(self):
3100 """
3101 If :py:obj:`CRL.export` is used with an uninitialized :py:obj:`X509`
Jean-Paul Calderoneb5871072012-03-09 14:58:00 -08003102 instance, :py:obj:`OpenSSL.crypto.Error` is raised.
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -04003103 """
3104 crl = CRL()
3105 self.assertRaises(Error, crl.export, X509(), PKey())
3106
3107
Jean-Paul Calderone56515342010-01-30 13:49:38 -05003108 def test_add_revoked_keyword(self):
3109 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003110 :py:obj:`OpenSSL.CRL.add_revoked` accepts its single argument as the
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003111 ``revoked`` keyword argument.
Jean-Paul Calderone56515342010-01-30 13:49:38 -05003112 """
3113 crl = CRL()
3114 revoked = Revoked()
3115 crl.add_revoked(revoked=revoked)
3116 self.assertTrue(isinstance(crl.get_revoked()[0], Revoked))
3117
Rick Dean6385faf2009-07-26 00:07:47 -05003118
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05003119 def test_export_wrong_args(self):
3120 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003121 Calling :py:obj:`OpenSSL.CRL.export` with fewer than two or more than
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05003122 four arguments, or with arguments other than the certificate,
3123 private key, integer file type, and integer number of days it
Jonathan Ballet648875f2011-07-16 14:14:58 +09003124 expects, results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05003125 """
3126 crl = CRL()
3127 self.assertRaises(TypeError, crl.export)
3128 self.assertRaises(TypeError, crl.export, self.cert)
Bulat Gaifullin925f7862014-09-22 10:10:44 +04003129 self.assertRaises(TypeError, crl.export, self.cert, self.pkey, FILETYPE_PEM, 10, "md5", "foo")
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05003130
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05003131 self.assertRaises(TypeError, crl.export, None, self.pkey, FILETYPE_PEM, 10)
3132 self.assertRaises(TypeError, crl.export, self.cert, None, FILETYPE_PEM, 10)
3133 self.assertRaises(TypeError, crl.export, self.cert, self.pkey, None, 10)
3134 self.assertRaises(TypeError, crl.export, self.cert, FILETYPE_PEM, None)
3135
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05003136
Jean-Paul Calderoneea198422010-01-30 13:58:23 -05003137 def test_export_unknown_filetype(self):
3138 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003139 Calling :py:obj:`OpenSSL.CRL.export` with a file type other than
3140 :py:obj:`FILETYPE_PEM`, :py:obj:`FILETYPE_ASN1`, or :py:obj:`FILETYPE_TEXT` results
3141 in a :py:obj:`ValueError` being raised.
Jean-Paul Calderoneea198422010-01-30 13:58:23 -05003142 """
3143 crl = CRL()
3144 self.assertRaises(ValueError, crl.export, self.cert, self.pkey, 100, 10)
3145
3146
Bulat Gaifullin925f7862014-09-22 10:10:44 +04003147 def test_export_unknown_digest(self):
Bulat Gaifullin5f9eea42014-09-23 19:35:15 +04003148 """
3149 Calling :py:obj:`OpenSSL.CRL.export` with a unsupported digest results
3150 in a :py:obj:`ValueError` being raised.
3151 """
Bulat Gaifullin925f7862014-09-22 10:10:44 +04003152 crl = CRL()
3153 self.assertRaises(ValueError, crl.export, self.cert, self.pkey, FILETYPE_PEM, 10, "strange-digest")
3154
3155
Rick Dean536ba022009-07-24 23:57:27 -05003156 def test_get_revoked(self):
3157 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05003158 Use python to create a simple CRL with two revocations.
Jonathan Ballet648875f2011-07-16 14:14:58 +09003159 Get back the :py:obj:`Revoked` using :py:obj:`OpenSSL.CRL.get_revoked` and
Rick Dean536ba022009-07-24 23:57:27 -05003160 verify them.
3161 """
3162 crl = CRL()
3163
3164 revoked = Revoked()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003165 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05003166 revoked.set_rev_date(now)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003167 revoked.set_serial(b('3ab'))
Rick Dean536ba022009-07-24 23:57:27 -05003168 crl.add_revoked(revoked)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003169 revoked.set_serial(b('100'))
3170 revoked.set_reason(b('sUpErSeDEd'))
Rick Dean536ba022009-07-24 23:57:27 -05003171 crl.add_revoked(revoked)
3172
3173 revs = crl.get_revoked()
3174 self.assertEqual(len(revs), 2)
3175 self.assertEqual(type(revs[0]), Revoked)
3176 self.assertEqual(type(revs[1]), Revoked)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003177 self.assertEqual(revs[0].get_serial(), b('03AB'))
3178 self.assertEqual(revs[1].get_serial(), b('0100'))
Rick Dean536ba022009-07-24 23:57:27 -05003179 self.assertEqual(revs[0].get_rev_date(), now)
3180 self.assertEqual(revs[1].get_rev_date(), now)
3181
3182
Jean-Paul Calderone46bdce42010-01-30 13:44:16 -05003183 def test_get_revoked_wrong_args(self):
3184 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003185 Calling :py:obj:`OpenSSL.CRL.get_revoked` with any arguments results
3186 in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone46bdce42010-01-30 13:44:16 -05003187 """
3188 crl = CRL()
3189 self.assertRaises(TypeError, crl.get_revoked, None)
3190 self.assertRaises(TypeError, crl.get_revoked, 1)
3191 self.assertRaises(TypeError, crl.get_revoked, "")
3192 self.assertRaises(TypeError, crl.get_revoked, "", 1, None)
3193
3194
Jean-Paul Calderoneecef6fa2010-01-30 13:47:18 -05003195 def test_add_revoked_wrong_args(self):
3196 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003197 Calling :py:obj:`OpenSSL.CRL.add_revoked` with other than one
3198 argument results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderoneecef6fa2010-01-30 13:47:18 -05003199 """
3200 crl = CRL()
3201 self.assertRaises(TypeError, crl.add_revoked)
3202 self.assertRaises(TypeError, crl.add_revoked, 1, 2)
3203 self.assertRaises(TypeError, crl.add_revoked, "foo", "bar")
3204
3205
Rick Dean536ba022009-07-24 23:57:27 -05003206 def test_load_crl(self):
3207 """
3208 Load a known CRL and inspect its revocations. Both
3209 PEM and DER formats are loaded.
3210 """
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003211 crl = load_crl(FILETYPE_PEM, crlData)
Rick Dean536ba022009-07-24 23:57:27 -05003212 revs = crl.get_revoked()
3213 self.assertEqual(len(revs), 2)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003214 self.assertEqual(revs[0].get_serial(), b('03AB'))
Rick Dean6385faf2009-07-26 00:07:47 -05003215 self.assertEqual(revs[0].get_reason(), None)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003216 self.assertEqual(revs[1].get_serial(), b('0100'))
3217 self.assertEqual(revs[1].get_reason(), b('Superseded'))
Rick Dean536ba022009-07-24 23:57:27 -05003218
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003219 der = _runopenssl(crlData, b"crl", b"-outform", b"DER")
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05003220 crl = load_crl(FILETYPE_ASN1, der)
Rick Dean536ba022009-07-24 23:57:27 -05003221 revs = crl.get_revoked()
3222 self.assertEqual(len(revs), 2)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003223 self.assertEqual(revs[0].get_serial(), b('03AB'))
Rick Dean6385faf2009-07-26 00:07:47 -05003224 self.assertEqual(revs[0].get_reason(), None)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003225 self.assertEqual(revs[1].get_serial(), b('0100'))
3226 self.assertEqual(revs[1].get_reason(), b('Superseded'))
Rick Dean536ba022009-07-24 23:57:27 -05003227
3228
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003229 def test_load_crl_wrong_args(self):
3230 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003231 Calling :py:obj:`OpenSSL.crypto.load_crl` with other than two
3232 arguments results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003233 """
3234 self.assertRaises(TypeError, load_crl)
3235 self.assertRaises(TypeError, load_crl, FILETYPE_PEM)
3236 self.assertRaises(TypeError, load_crl, FILETYPE_PEM, crlData, None)
3237
3238
3239 def test_load_crl_bad_filetype(self):
3240 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003241 Calling :py:obj:`OpenSSL.crypto.load_crl` with an unknown file type
3242 raises a :py:obj:`ValueError`.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003243 """
3244 self.assertRaises(ValueError, load_crl, 100, crlData)
3245
3246
3247 def test_load_crl_bad_data(self):
3248 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003249 Calling :py:obj:`OpenSSL.crypto.load_crl` with file data which can't
3250 be loaded raises a :py:obj:`OpenSSL.crypto.Error`.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003251 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003252 self.assertRaises(Error, load_crl, FILETYPE_PEM, b"hello, world")
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003253
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04003254
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -05003255
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003256class X509StoreContextTests(TestCase):
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003257 """
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003258 Tests for :py:obj:`OpenSSL.crypto.X509StoreContext`.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003259 """
3260 root_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3261 intermediate_cert = load_certificate(FILETYPE_PEM, intermediate_cert_pem)
3262 intermediate_server_cert = load_certificate(FILETYPE_PEM, intermediate_server_cert_pem)
3263
3264 def test_valid(self):
3265 """
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003266 :py:obj:`verify_certificate` returns ``None`` when called with a certificate
Jean-Paul Calderone06e01b92015-01-18 15:43:13 -05003267 and valid chain.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003268 """
3269 store = X509Store()
3270 store.add_cert(self.root_cert)
3271 store.add_cert(self.intermediate_cert)
3272 store_ctx = X509StoreContext(store, self.intermediate_server_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003273 self.assertEqual(store_ctx.verify_certificate(), None)
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003274
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003275
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003276 def test_reuse(self):
3277 """
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003278 :py:obj:`verify_certificate` can be called multiple times with the same
Jean-Paul Calderone06e01b92015-01-18 15:43:13 -05003279 ``X509StoreContext`` instance to produce the same result.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003280 """
3281 store = X509Store()
3282 store.add_cert(self.root_cert)
3283 store.add_cert(self.intermediate_cert)
3284 store_ctx = X509StoreContext(store, self.intermediate_server_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003285 self.assertEqual(store_ctx.verify_certificate(), None)
3286 self.assertEqual(store_ctx.verify_certificate(), None)
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003287
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003288
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003289 def test_trusted_self_signed(self):
3290 """
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003291 :py:obj:`verify_certificate` returns ``None`` when called with a self-signed
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003292 certificate and itself in the chain.
3293 """
3294 store = X509Store()
3295 store.add_cert(self.root_cert)
3296 store_ctx = X509StoreContext(store, self.root_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003297 self.assertEqual(store_ctx.verify_certificate(), None)
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003298
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003299
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003300 def test_untrusted_self_signed(self):
3301 """
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003302 :py:obj:`verify_certificate` raises error when a self-signed certificate is
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003303 verified without itself in the chain.
3304 """
3305 store = X509Store()
3306 store_ctx = X509StoreContext(store, self.root_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003307 e = self.assertRaises(X509StoreContextError, store_ctx.verify_certificate)
Jean-Paul Calderone4c10a1e2015-01-18 16:31:27 -05003308 self.assertEqual(e.args[0][2], 'self signed certificate')
Jean-Paul Calderone06e01b92015-01-18 15:43:13 -05003309 self.assertEqual(e.certificate.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003310
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003311
3312 def test_invalid_chain_no_root(self):
3313 """
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003314 :py:obj:`verify_certificate` raises error when a root certificate is missing
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003315 from the chain.
3316 """
3317 store = X509Store()
3318 store.add_cert(self.intermediate_cert)
3319 store_ctx = X509StoreContext(store, self.intermediate_server_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003320 e = self.assertRaises(X509StoreContextError, store_ctx.verify_certificate)
Jean-Paul Calderone4c10a1e2015-01-18 16:31:27 -05003321 self.assertEqual(e.args[0][2], 'unable to get issuer certificate')
Jean-Paul Calderone06e01b92015-01-18 15:43:13 -05003322 self.assertEqual(e.certificate.get_subject().CN, 'intermediate')
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003323
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003324
3325 def test_invalid_chain_no_intermediate(self):
3326 """
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003327 :py:obj:`verify_certificate` raises error when an intermediate certificate is
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003328 missing from the chain.
3329 """
3330 store = X509Store()
3331 store.add_cert(self.root_cert)
3332 store_ctx = X509StoreContext(store, self.intermediate_server_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003333 e = self.assertRaises(X509StoreContextError, store_ctx.verify_certificate)
Jean-Paul Calderone4c10a1e2015-01-18 16:31:27 -05003334 self.assertEqual(e.args[0][2], 'unable to get local issuer certificate')
Jean-Paul Calderone06e01b92015-01-18 15:43:13 -05003335 self.assertEqual(e.certificate.get_subject().CN, 'intermediate-service')
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003336
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003337
Stephen Holsapple46a09252015-02-12 14:45:43 -08003338 def test_modification_pre_verify(self):
3339 """
3340 :py:obj:`verify_certificate` can use a store context modified after
3341 instantiation.
3342 """
3343 store_bad = X509Store()
3344 store_bad.add_cert(self.intermediate_cert)
3345 store_good = X509Store()
3346 store_good.add_cert(self.root_cert)
3347 store_good.add_cert(self.intermediate_cert)
3348 store_ctx = X509StoreContext(store_bad, self.intermediate_server_cert)
3349 e = self.assertRaises(X509StoreContextError, store_ctx.verify_certificate)
3350 self.assertEqual(e.args[0][2], 'unable to get issuer certificate')
3351 self.assertEqual(e.certificate.get_subject().CN, 'intermediate')
3352 store_ctx.set_store(store_good)
3353 self.assertEqual(store_ctx.verify_certificate(), None)
3354
3355
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04003356
3357class SignVerifyTests(TestCase):
3358 """
3359 Tests for :py:obj:`OpenSSL.crypto.sign` and :py:obj:`OpenSSL.crypto.verify`.
3360 """
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04003361 def test_sign_verify(self):
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04003362 """
3363 :py:obj:`sign` generates a cryptographic signature which :py:obj:`verify` can check.
3364 """
3365 content = b(
James Yonan7c2e5d32010-02-27 05:45:50 -07003366 "It was a bright cold day in April, and the clocks were striking "
Jean-Paul Calderoned08feb02010-10-12 21:53:24 -04003367 "thirteen. Winston Smith, his chin nuzzled into his breast in an "
James Yonan7c2e5d32010-02-27 05:45:50 -07003368 "effort to escape the vile wind, slipped quickly through the "
3369 "glass doors of Victory Mansions, though not quickly enough to "
3370 "prevent a swirl of gritty dust from entering along with him.")
3371
3372 # sign the content with this private key
3373 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
3374 # verify the content with this cert
3375 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3376 # certificate unrelated to priv_key, used to trigger an error
3377 bad_cert = load_certificate(FILETYPE_PEM, server_cert_pem)
3378
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003379 for digest in ['md5', 'sha1']:
3380 sig = sign(priv_key, content, digest)
3381
James Yonan7c2e5d32010-02-27 05:45:50 -07003382 # Verify the signature of content, will throw an exception if error.
3383 verify(good_cert, sig, content, digest)
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003384
Jean-Paul Calderone9538f142010-10-13 22:13:40 -04003385 # This should fail because the certificate doesn't match the
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003386 # private key that was used to sign the content.
Jean-Paul Calderone9538f142010-10-13 22:13:40 -04003387 self.assertRaises(Error, verify, bad_cert, sig, content, digest)
James Yonan7c2e5d32010-02-27 05:45:50 -07003388
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04003389 # This should fail because we've "tainted" the content after
Jean-Paul Calderone9828f662010-12-08 22:57:26 -05003390 # signing it.
3391 self.assertRaises(
Jonathan Ballet648875f2011-07-16 14:14:58 +09003392 Error, verify,
Jean-Paul Calderone9828f662010-12-08 22:57:26 -05003393 good_cert, sig, content + b("tainted"), digest)
3394
3395 # test that unknown digest types fail
3396 self.assertRaises(
3397 ValueError, sign, priv_key, content, "strange-digest")
3398 self.assertRaises(
3399 ValueError, verify, good_cert, sig, content, "strange-digest")
3400
Rick Dean5b7b6372009-04-01 11:34:06 -05003401
3402 def test_sign_nulls(self):
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -05003403 """
3404 :py:obj:`sign` produces a signature for a string with embedded nulls.
3405 """
3406 content = b("Watch out! \0 Did you see it?")
3407 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
3408 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3409 sig = sign(priv_key, content, "sha1")
3410 verify(good_cert, sig, content, "sha1")
3411
3412
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003413
3414class EllipticCurveTests(TestCase):
3415 """
3416 Tests for :py:class:`_EllipticCurve`, :py:obj:`get_elliptic_curve`, and
3417 :py:obj:`get_elliptic_curves`.
3418 """
3419 def test_set(self):
3420 """
3421 :py:obj:`get_elliptic_curves` returns a :py:obj:`set`.
3422 """
3423 self.assertIsInstance(get_elliptic_curves(), set)
3424
3425
3426 def test_some_curves(self):
3427 """
3428 If :py:mod:`cryptography` has elliptic curve support then the set
3429 returned by :py:obj:`get_elliptic_curves` has some elliptic curves in
3430 it.
3431
3432 There could be an OpenSSL that violates this assumption. If so, this
3433 test will fail and we'll find out.
3434 """
3435 curves = get_elliptic_curves()
3436 if lib.Cryptography_HAS_EC:
3437 self.assertTrue(curves)
3438 else:
3439 self.assertFalse(curves)
3440
3441
3442 def test_a_curve(self):
3443 """
3444 :py:obj:`get_elliptic_curve` can be used to retrieve a particular
3445 supported curve.
3446 """
3447 curves = get_elliptic_curves()
3448 if curves:
3449 curve = next(iter(curves))
3450 self.assertEqual(curve.name, get_elliptic_curve(curve.name).name)
3451 else:
Jean-Paul Calderoneeb86f3a2014-04-19 09:45:57 -04003452 self.assertRaises(ValueError, get_elliptic_curve, u("prime256v1"))
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003453
3454
3455 def test_not_a_curve(self):
3456 """
3457 :py:obj:`get_elliptic_curve` raises :py:class:`ValueError` if called
3458 with a name which does not identify a supported curve.
3459 """
3460 self.assertRaises(
Jean-Paul Calderone5a82db92014-04-19 09:51:29 -04003461 ValueError, get_elliptic_curve, u("this curve was just invented"))
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003462
3463
3464 def test_repr(self):
3465 """
3466 The string representation of a curve object includes simply states the
3467 object is a curve and what its name is.
3468 """
3469 curves = get_elliptic_curves()
3470 if curves:
3471 curve = next(iter(curves))
3472 self.assertEqual("<Curve %r>" % (curve.name,), repr(curve))
3473
3474
3475 def test_to_EC_KEY(self):
3476 """
3477 The curve object can export a version of itself as an EC_KEY* via the
3478 private :py:meth:`_EllipticCurve._to_EC_KEY`.
3479 """
3480 curves = get_elliptic_curves()
3481 if curves:
3482 curve = next(iter(curves))
3483 # It's not easy to assert anything about this object. However, see
3484 # leakcheck/crypto.py for a test that demonstrates it at least does
3485 # not leak memory.
3486 curve._to_EC_KEY()
3487
3488
Jean-Paul Calderone1be77082014-04-30 18:17:41 -04003489
3490class EllipticCurveFactory(object):
3491 """
3492 A helper to get the names of two curves.
3493 """
3494 def __init__(self):
3495 curves = iter(get_elliptic_curves())
3496 try:
3497 self.curve_name = next(curves).name
3498 self.another_curve_name = next(curves).name
3499 except StopIteration:
3500 self.curve_name = self.another_curve_name = None
3501
3502
3503
3504class EllipticCurveEqualityTests(TestCase, EqualityTestsMixin):
3505 """
3506 Tests :py:type:`_EllipticCurve`\ 's implementation of ``==`` and ``!=``.
3507 """
3508 curve_factory = EllipticCurveFactory()
3509
3510 if curve_factory.curve_name is None:
3511 skip = "There are no curves available there can be no curve objects."
3512
3513
3514 def anInstance(self):
3515 """
3516 Get the curve object for an arbitrary curve supported by the system.
3517 """
3518 return get_elliptic_curve(self.curve_factory.curve_name)
3519
3520
3521 def anotherInstance(self):
3522 """
3523 Get the curve object for an arbitrary curve supported by the system -
3524 but not the one returned by C{anInstance}.
3525 """
3526 return get_elliptic_curve(self.curve_factory.another_curve_name)
3527
3528
3529
Jean-Paul Calderone22c31242014-05-01 07:49:47 -04003530class EllipticCurveHashTests(TestCase):
3531 """
3532 Tests for :py:type:`_EllipticCurve`\ 's implementation of hashing (thus use
3533 as an item in a :py:type:`dict` or :py:type:`set`).
3534 """
3535 curve_factory = EllipticCurveFactory()
3536
3537 if curve_factory.curve_name is None:
3538 skip = "There are no curves available there can be no curve objects."
3539
3540
3541 def test_contains(self):
3542 """
3543 The ``in`` operator reports that a :py:type:`set` containing a curve
3544 does contain that curve.
3545 """
3546 curve = get_elliptic_curve(self.curve_factory.curve_name)
3547 curves = set([curve])
3548 self.assertIn(curve, curves)
3549
3550
3551 def test_does_not_contain(self):
3552 """
3553 The ``in`` operator reports that a :py:type:`set` not containing a
3554 curve does not contain that curve.
3555 """
3556 curve = get_elliptic_curve(self.curve_factory.curve_name)
3557 curves = set([get_elliptic_curve(self.curve_factory.another_curve_name)])
3558 self.assertNotIn(curve, curves)
3559
3560
3561
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -05003562if __name__ == '__main__':
3563 main()