blob: 8b310dd143f85459163ae03b42ad5e6e344f6252 [file] [log] [blame]
Jean-Paul Calderone8671c852011-03-02 19:26:20 -05001# Copyright (c) Jean-Paul Calderone
2# See LICENSE file for details.
Jean-Paul Calderone8b63d452008-03-21 18:31:12 -04003
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -05004"""
Jonathan Ballet648875f2011-07-16 14:14:58 +09005Unit tests for :py:mod:`OpenSSL.crypto`.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -05006"""
7
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04008from unittest import main
Jean-Paul Calderone60432792015-04-13 12:26:07 -04009from warnings import catch_warnings, simplefilter
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -040010
Alex Gaynor4b9c96a2014-08-14 09:51:48 -070011import base64
12import os
13import re
Jean-Paul Calderone62ca8da2010-08-11 19:58:08 -040014from subprocess import PIPE, Popen
Rick Dean47262da2009-07-08 16:17:17 -050015from datetime import datetime, timedelta
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -050016
Alex Gaynorb8e38992015-09-04 08:14:04 -040017from six import u, b, binary_type
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050018
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -050019from OpenSSL.crypto import TYPE_RSA, TYPE_DSA, Error, PKey, PKeyType
Jean-Paul Calderone78381d22008-03-06 23:35:22 -050020from OpenSSL.crypto import X509, X509Type, X509Name, X509NameType
Stephen Holsapple08ffaa62015-01-30 17:18:40 -080021from OpenSSL.crypto import X509Store, X509StoreType, X509StoreContext, X509StoreContextError
Stephen Holsapple0d9815f2014-08-27 19:36:53 -070022from OpenSSL.crypto import X509Req, X509ReqType
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -050023from OpenSSL.crypto import X509Extension, X509ExtensionType
Rick Dean5b7b6372009-04-01 11:34:06 -050024from OpenSSL.crypto import load_certificate, load_privatekey
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -040025from OpenSSL.crypto import FILETYPE_PEM, FILETYPE_ASN1, FILETYPE_TEXT
Jean-Paul Calderone71919862009-04-01 13:01:19 -040026from OpenSSL.crypto import dump_certificate, load_certificate_request
27from OpenSSL.crypto import dump_certificate_request, dump_privatekey
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -040028from OpenSSL.crypto import PKCS7Type, load_pkcs7_data
Jean-Paul Calderone9178ee62010-01-25 17:55:30 -050029from OpenSSL.crypto import PKCS12, PKCS12Type, load_pkcs12
Rick Dean536ba022009-07-24 23:57:27 -050030from OpenSSL.crypto import CRL, Revoked, load_crl
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -040031from OpenSSL.crypto import NetscapeSPKI, NetscapeSPKIType
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040032from OpenSSL.crypto import (
33 sign, verify, get_elliptic_curve, get_elliptic_curves)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -040034from OpenSSL.test.util import (
35 EqualityTestsMixin, TestCase, WARNING_TYPE_EXPECTED
36)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040037from OpenSSL._util import native, lib
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040038
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -040039def normalize_certificate_pem(pem):
40 return dump_certificate(FILETYPE_PEM, load_certificate(FILETYPE_PEM, pem))
41
42
43def normalize_privatekey_pem(pem):
44 return dump_privatekey(FILETYPE_PEM, load_privatekey(FILETYPE_PEM, pem))
45
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040046
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050047GOOD_CIPHER = "blowfish"
48BAD_CIPHER = "zippers"
49
50GOOD_DIGEST = "MD5"
51BAD_DIGEST = "monkeys"
52
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040053root_cert_pem = b("""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -050054MIIC7TCCAlagAwIBAgIIPQzE4MbeufQwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE
55BhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdU
56ZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwIhgPMjAwOTAzMjUxMjM2
57NThaGA8yMDE3MDYxMTEyMzY1OFowWDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklM
58MRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9U
59ZXN0aW5nIFJvb3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPmaQumL
60urpE527uSEHdL1pqcDRmWzu+98Y6YHzT/J7KWEamyMCNZ6fRW1JCR782UQ8a07fy
612xXsKy4WdKaxyG8CcatwmXvpvRQ44dSANMihHELpANTdyVp6DCysED6wkQFurHlF
621dshEaJw8b/ypDhmbVIo6Ci1xvCJqivbLFnbAgMBAAGjgbswgbgwHQYDVR0OBBYE
63FINVdy1eIfFJDAkk51QJEo3IfgSuMIGIBgNVHSMEgYAwfoAUg1V3LV4h8UkMCSTn
64VAkSjch+BK6hXKRaMFgxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UE
65BxMHQ2hpY2FnbzEQMA4GA1UEChMHVGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBS
66b290IENBggg9DMTgxt659DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB
67AGGCDazMJGoWNBpc03u6+smc95dEead2KlZXBATOdFT1VesY3+nUOqZhEhTGlDMi
68hkgaZnzoIq/Uamidegk4hirsCT/R+6vsKAAxNTcBjUeZjlykCJWy5ojShGftXIKY
69w/njVbKMXrvc83qmTdGl3TAM0fxQIpqgcglFLveEBgzn
70-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040071""")
Rick Dean94e46fd2009-07-18 14:51:24 -050072
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040073root_key_pem = b("""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -050074MIICXQIBAAKBgQD5mkLpi7q6ROdu7khB3S9aanA0Zls7vvfGOmB80/yeylhGpsjA
75jWen0VtSQke/NlEPGtO38tsV7CsuFnSmschvAnGrcJl76b0UOOHUgDTIoRxC6QDU
763claegwsrBA+sJEBbqx5RdXbIRGicPG/8qQ4Zm1SKOgotcbwiaor2yxZ2wIDAQAB
77AoGBAPCgMpmLxzwDaUmcFbTJUvlLW1hoxNNYSu2jIZm1k/hRAcE60JYwvBkgz3UB
78yMEh0AtLxYe0bFk6EHah11tMUPgscbCq73snJ++8koUw+csk22G65hOs51bVb7Aa
796JBe67oLzdtvgCUFAA2qfrKzWRZzAdhUirQUZgySZk+Xq1pBAkEA/kZG0A6roTSM
80BVnx7LnPfsycKUsTumorpXiylZJjTi9XtmzxhrYN6wgZlDOOwOLgSQhszGpxVoMD
81u3gByT1b2QJBAPtL3mSKdvwRu/+40zaZLwvSJRxaj0mcE4BJOS6Oqs/hS1xRlrNk
82PpQ7WJ4yM6ZOLnXzm2mKyxm50Mv64109FtMCQQDOqS2KkjHaLowTGVxwC0DijMfr
83I9Lf8sSQk32J5VWCySWf5gGTfEnpmUa41gKTMJIbqZZLucNuDcOtzUaeWZlZAkA8
84ttXigLnCqR486JDPTi9ZscoZkZ+w7y6e/hH8t6d5Vjt48JVyfjPIaJY+km58LcN3
856AWSeGAdtRFHVzR7oHjVAkB4hutvxiOeiIVQNBhM6RSI9aBPMI21DoX2JRoxvNW2
86cbvAhow217X9V0dVerEOKxnNYspXRrh36h7k4mQA+sDq
87-----END RSA PRIVATE KEY-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040088""")
Rick Dean94e46fd2009-07-18 14:51:24 -050089
Stephen Holsapple0d9815f2014-08-27 19:36:53 -070090intermediate_cert_pem = b("""-----BEGIN CERTIFICATE-----
91MIICVzCCAcCgAwIBAgIRAMPzhm6//0Y/g2pmnHR2C4cwDQYJKoZIhvcNAQENBQAw
92WDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAw
93DgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwHhcNMTQw
94ODI4MDIwNDA4WhcNMjQwODI1MDIwNDA4WjBmMRUwEwYDVQQDEwxpbnRlcm1lZGlh
95dGUxDDAKBgNVBAoTA29yZzERMA8GA1UECxMIb3JnLXVuaXQxCzAJBgNVBAYTAlVT
96MQswCQYDVQQIEwJDQTESMBAGA1UEBxMJU2FuIERpZWdvMIGfMA0GCSqGSIb3DQEB
97AQUAA4GNADCBiQKBgQDYcEQw5lfbEQRjr5Yy4yxAHGV0b9Al+Lmu7wLHMkZ/ZMmK
98FGIbljbviiD1Nz97Oh2cpB91YwOXOTN2vXHq26S+A5xe8z/QJbBsyghMur88CjdT
9921H2qwMa+r5dCQwEhuGIiZ3KbzB/n4DTMYI5zy4IYPv0pjxShZn4aZTCCK2IUwID
100AQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBDQUAA4GBAPIWSkLX
101QRMApOjjyC+tMxumT5e2pMqChHmxobQK4NMdrf2VCx+cRT6EmY8sK3/Xl/X8UBQ+
1029n5zXb1ZwhW/sTWgUvmOceJ4/XVs9FkdWOOn1J0XBch9ZIiFe/s5ASIgG7fUdcUF
1039mAWS6FK2ca3xIh5kIupCXOFa0dPvlw/YUFT
104-----END CERTIFICATE-----
105""")
106
107intermediate_key_pem = b("""-----BEGIN RSA PRIVATE KEY-----
108MIICWwIBAAKBgQDYcEQw5lfbEQRjr5Yy4yxAHGV0b9Al+Lmu7wLHMkZ/ZMmKFGIb
109ljbviiD1Nz97Oh2cpB91YwOXOTN2vXHq26S+A5xe8z/QJbBsyghMur88CjdT21H2
110qwMa+r5dCQwEhuGIiZ3KbzB/n4DTMYI5zy4IYPv0pjxShZn4aZTCCK2IUwIDAQAB
111AoGAfSZVV80pSeOKHTYfbGdNY/jHdU9eFUa/33YWriXU+77EhpIItJjkRRgivIfo
112rhFJpBSGmDLblaqepm8emsXMeH4+2QzOYIf0QGGP6E6scjTt1PLqdqKfVJ1a2REN
113147cujNcmFJb/5VQHHMpaPTgttEjlzuww4+BCDPsVRABWrkCQQD3loH36nLoQTtf
114+kQq0T6Bs9/UWkTAGo0ND81ALj0F8Ie1oeZg6RNT96RxZ3aVuFTESTv6/TbjWywO
115wdzlmV1vAkEA38rTJ6PTwaJlw5OttdDzAXGPB9tDmzh9oSi7cHwQQXizYd8MBYx4
116sjHUKD3dCQnb1dxJFhd3BT5HsnkRMbVZXQJAbXduH17ZTzcIOXc9jHDXYiFVZV5D
11752vV0WCbLzVCZc3jMrtSUKa8lPN5EWrdU3UchWybyG0MR5mX8S5lrF4SoQJAIyUD
118DBKaSqpqONCUUx1BTFS9FYrFjzbL4+c1qHCTTPTblt8kUCrDOZjBrKAqeiTmNSum
119/qUot9YUBF8m6BuGsQJATHHmdFy/fG1VLkyBp49CAa8tN3Z5r/CgTznI4DfMTf4C
120NbRHn2UmYlwQBa+L5lg9phewNe8aEwpPyPLoV85U8Q==
121-----END RSA PRIVATE KEY-----
122""")
123
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400124server_cert_pem = b("""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500125MIICKDCCAZGgAwIBAgIJAJn/HpR21r/8MA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
126BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
127VGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBSb290IENBMCIYDzIwMDkwMzI1MTIz
128NzUzWhgPMjAxNzA2MTExMjM3NTNaMBgxFjAUBgNVBAMTDWxvdmVseSBzZXJ2ZXIw
129gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAL6m+G653V0tpBC/OKl22VxOi2Cv
130lK4TYu9LHSDP9uDVTe7V5D5Tl6qzFoRRx5pfmnkqT5B+W9byp2NU3FC5hLm5zSAr
131b45meUhjEJ/ifkZgbNUjHdBIGP9MAQUHZa5WKdkGIJvGAvs8UzUqlr4TBWQIB24+
132lJ+Ukk/CRgasrYwdAgMBAAGjNjA0MB0GA1UdDgQWBBS4kC7Ij0W1TZXZqXQFAM2e
133gKEG2DATBgNVHSUEDDAKBggrBgEFBQcDATANBgkqhkiG9w0BAQUFAAOBgQBh30Li
134dJ+NlxIOx5343WqIBka3UbsOb2kxWrbkVCrvRapCMLCASO4FqiKWM+L0VDBprqIp
1352mgpFQ6FHpoIENGvJhdEKpptQ5i7KaGhnDNTfdy3x1+h852G99f1iyj0RmbuFcM8
136uzujnS8YXWvM7DM1Ilozk4MzPug8jzFp5uhKCQ==
137-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400138""")
Rick Dean94e46fd2009-07-18 14:51:24 -0500139
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -0400140server_key_pem = normalize_privatekey_pem(b("""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500141MIICWwIBAAKBgQC+pvhuud1dLaQQvzipdtlcTotgr5SuE2LvSx0gz/bg1U3u1eQ+
142U5eqsxaEUceaX5p5Kk+QflvW8qdjVNxQuYS5uc0gK2+OZnlIYxCf4n5GYGzVIx3Q
143SBj/TAEFB2WuVinZBiCbxgL7PFM1Kpa+EwVkCAduPpSflJJPwkYGrK2MHQIDAQAB
144AoGAbwuZ0AR6JveahBaczjfnSpiFHf+mve2UxoQdpyr6ROJ4zg/PLW5K/KXrC48G
145j6f3tXMrfKHcpEoZrQWUfYBRCUsGD5DCazEhD8zlxEHahIsqpwA0WWssJA2VOLEN
146j6DuV2pCFbw67rfTBkTSo32ahfXxEKev5KswZk0JIzH3ooECQQDgzS9AI89h0gs8
147Dt+1m11Rzqo3vZML7ZIyGApUzVan+a7hbc33nbGRkAXjHaUBJO31it/H6dTO+uwX
148msWwNG5ZAkEA2RyFKs5xR5USTFaKLWCgpH/ydV96KPOpBND7TKQx62snDenFNNbn
149FwwOhpahld+vqhYk+pfuWWUpQciE+Bu7ZQJASjfT4sQv4qbbKK/scePicnDdx9th
1504e1EeB9xwb+tXXXUo/6Bor/AcUNwfiQ6Zt9PZOK9sR3lMZSsP7rMi7kzuQJABie6
1511sXXjFH7nNJvRG4S39cIxq8YRYTy68II/dlB2QzGpKxV/POCxbJ/zu0CU79tuYK7
152NaeNCFfH3aeTrX0LyQJAMBWjWmeKM2G2sCExheeQK0ROnaBC8itCECD4Jsve4nqf
153r50+LF74iLXFwqysVCebPKMOpDWp/qQ1BbJQIPs7/A==
154-----END RSA PRIVATE KEY-----
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -0400155"""))
Rick Dean94e46fd2009-07-18 14:51:24 -0500156
Stephen Holsapple0d9815f2014-08-27 19:36:53 -0700157intermediate_server_cert_pem = b("""-----BEGIN CERTIFICATE-----
158MIICWDCCAcGgAwIBAgIRAPQFY9jfskSihdiNSNdt6GswDQYJKoZIhvcNAQENBQAw
159ZjEVMBMGA1UEAxMMaW50ZXJtZWRpYXRlMQwwCgYDVQQKEwNvcmcxETAPBgNVBAsT
160CG9yZy11bml0MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVNh
161biBEaWVnbzAeFw0xNDA4MjgwMjEwNDhaFw0yNDA4MjUwMjEwNDhaMG4xHTAbBgNV
162BAMTFGludGVybWVkaWF0ZS1zZXJ2aWNlMQwwCgYDVQQKEwNvcmcxETAPBgNVBAsT
163CG9yZy11bml0MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVNh
164biBEaWVnbzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqpJZygd+w1faLOr1
165iOAmbBhx5SZWcTCZ/ZjHQTJM7GuPT624QkqsixFghRKdDROwpwnAP7gMRukLqiy4
166+kRuGT5OfyGggL95i2xqA+zehjj08lSTlvGHpePJgCyTavIy5+Ljsj4DKnKyuhxm
167biXTRrH83NDgixVkObTEmh/OVK0CAwEAATANBgkqhkiG9w0BAQ0FAAOBgQBa0Npw
168UkzjaYEo1OUE1sTI6Mm4riTIHMak4/nswKh9hYup//WVOlr/RBSBtZ7Q/BwbjobN
1693bfAtV7eSAqBsfxYXyof7G1ALANQERkq3+oyLP1iVt08W1WOUlIMPhdCF/QuCwy6
170x9MJLhUCGLJPM+O2rAPWVD9wCmvq10ALsiH3yA==
171-----END CERTIFICATE-----
172""")
173
174intermediate_server_key_pem = b("""-----BEGIN RSA PRIVATE KEY-----
175MIICXAIBAAKBgQCqklnKB37DV9os6vWI4CZsGHHlJlZxMJn9mMdBMkzsa49PrbhC
176SqyLEWCFEp0NE7CnCcA/uAxG6QuqLLj6RG4ZPk5/IaCAv3mLbGoD7N6GOPTyVJOW
1778Yel48mALJNq8jLn4uOyPgMqcrK6HGZuJdNGsfzc0OCLFWQ5tMSaH85UrQIDAQAB
178AoGAIQ594j5zna3/9WaPsTgnmhlesVctt4AAx/n827DA4ayyuHFlXUuVhtoWR5Pk
1795ezj9mtYW8DyeCegABnsu2vZni/CdvU6uiS1Hv6qM1GyYDm9KWgovIP9rQCDSGaz
180d57IWVGxx7ODFkm3gN5nxnSBOFVHytuW1J7FBRnEsehRroECQQDXHFOv82JuXDcz
181z3+4c74IEURdOHcbycxlppmK9kFqm5lsUdydnnGW+mvwDk0APOB7Wg7vyFyr393e
182dpmBDCzNAkEAyv6tVbTKUYhSjW+QhabJo896/EqQEYUmtMXxk4cQnKeR/Ao84Rkf
183EqD5IykMUfUI0jJU4DGX+gWZ10a7kNbHYQJAVFCuHNFxS4Cpwo0aqtnzKoZaHY/8
184X9ABZfafSHCtw3Op92M+7ikkrOELXdS9KdKyyqbKJAKNEHF3LbOfB44WIQJAA2N4
1859UNNVUsXRbElEnYUS529CdUczo4QdVgQjkvk5RiPAUwSdBd9Q0xYnFOlFwEmIowg
186ipWJWe0aAlP18ZcEQQJBAL+5lekZ/GUdQoZ4HAsN5a9syrzavJ9VvU1KOOPorPZK
187nMRZbbQgP+aSB7yl6K0gaLaZ8XaK0pjxNBh6ASqg9f4=
188-----END RSA PRIVATE KEY-----
189""")
190
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400191client_cert_pem = b("""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500192MIICJjCCAY+gAwIBAgIJAKxpFI5lODkjMA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
193BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
194VGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBSb290IENBMCIYDzIwMDkwMzI1MTIz
195ODA1WhgPMjAxNzA2MTExMjM4MDVaMBYxFDASBgNVBAMTC3VnbHkgY2xpZW50MIGf
196MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDAZh/SRtNm5ntMT4qb6YzEpTroMlq2
197rn+GrRHRiZ+xkCw/CGNhbtPir7/QxaUj26BSmQrHw1bGKEbPsWiW7bdXSespl+xK
198iku4G/KvnnmWdeJHqsiXeUZtqurMELcPQAw9xPHEuhqqUJvvEoMTsnCEqGM+7Dtb
199oCRajYyHfluARQIDAQABozYwNDAdBgNVHQ4EFgQUNQB+qkaOaEVecf1J3TTUtAff
2000fAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQEFBQADgYEAyv/Jh7gM
201Q3OHvmsFEEvRI+hsW8y66zK4K5de239Y44iZrFYkt7Q5nBPMEWDj4F2hLYWL/qtI
2029Zdr0U4UDCU9SmmGYh4o7R4TZ5pGFvBYvjhHbkSFYFQXZxKUi+WUxplP6I0wr2KJ
203PSTJCjJOn3xo2NTKRgV1gaoTf2EhL+RG8TQ=
204-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400205""")
Rick Dean94e46fd2009-07-18 14:51:24 -0500206
Jean-Paul Calderone22cbe502011-05-04 17:01:43 -0400207client_key_pem = normalize_privatekey_pem(b("""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500208MIICXgIBAAKBgQDAZh/SRtNm5ntMT4qb6YzEpTroMlq2rn+GrRHRiZ+xkCw/CGNh
209btPir7/QxaUj26BSmQrHw1bGKEbPsWiW7bdXSespl+xKiku4G/KvnnmWdeJHqsiX
210eUZtqurMELcPQAw9xPHEuhqqUJvvEoMTsnCEqGM+7DtboCRajYyHfluARQIDAQAB
211AoGATkZ+NceY5Glqyl4mD06SdcKfV65814vg2EL7V9t8+/mi9rYL8KztSXGlQWPX
212zuHgtRoMl78yQ4ZJYOBVo+nsx8KZNRCEBlE19bamSbQLCeQMenWnpeYyQUZ908gF
213h6L9qsFVJepgA9RDgAjyDoS5CaWCdCCPCH2lDkdcqC54SVUCQQDseuduc4wi8h4t
214V8AahUn9fn9gYfhoNuM0gdguTA0nPLVWz4hy1yJiWYQe0H7NLNNTmCKiLQaJpAbb
215TC6vE8C7AkEA0Ee8CMJUc20BnGEmxwgWcVuqFWaKCo8jTH1X38FlATUsyR3krjW2
216dL3yDD9NwHxsYP7nTKp/U8MV7U9IBn4y/wJBAJl7H0/BcLeRmuJk7IqJ7b635iYB
217D/9beFUw3MUXmQXZUfyYz39xf6CDZsu1GEdEC5haykeln3Of4M9d/4Kj+FcCQQCY
218si6xwT7GzMDkk/ko684AV3KPc/h6G0yGtFIrMg7J3uExpR/VdH2KgwMkZXisSMvw
219JJEQjOMCVsEJlRk54WWjAkEAzoZNH6UhDdBK5F38rVt/y4SEHgbSfJHIAmPS32Kq
220f6GGcfNpip0Uk7q7udTKuX7Q/buZi/C4YW7u3VKAquv9NA==
221-----END RSA PRIVATE KEY-----
Jean-Paul Calderone22cbe502011-05-04 17:01:43 -0400222"""))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400223
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400224cleartextCertificatePEM = b("""-----BEGIN CERTIFICATE-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400225MIIC7TCCAlagAwIBAgIIPQzE4MbeufQwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE
226BhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdU
227ZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwIhgPMjAwOTAzMjUxMjM2
228NThaGA8yMDE3MDYxMTEyMzY1OFowWDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklM
229MRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9U
230ZXN0aW5nIFJvb3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPmaQumL
231urpE527uSEHdL1pqcDRmWzu+98Y6YHzT/J7KWEamyMCNZ6fRW1JCR782UQ8a07fy
2322xXsKy4WdKaxyG8CcatwmXvpvRQ44dSANMihHELpANTdyVp6DCysED6wkQFurHlF
2331dshEaJw8b/ypDhmbVIo6Ci1xvCJqivbLFnbAgMBAAGjgbswgbgwHQYDVR0OBBYE
234FINVdy1eIfFJDAkk51QJEo3IfgSuMIGIBgNVHSMEgYAwfoAUg1V3LV4h8UkMCSTn
235VAkSjch+BK6hXKRaMFgxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UE
236BxMHQ2hpY2FnbzEQMA4GA1UEChMHVGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBS
237b290IENBggg9DMTgxt659DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB
238AGGCDazMJGoWNBpc03u6+smc95dEead2KlZXBATOdFT1VesY3+nUOqZhEhTGlDMi
239hkgaZnzoIq/Uamidegk4hirsCT/R+6vsKAAxNTcBjUeZjlykCJWy5ojShGftXIKY
240w/njVbKMXrvc83qmTdGl3TAM0fxQIpqgcglFLveEBgzn
241-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400242""")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400243
Jean-Paul Calderoned50d2042011-05-04 17:00:49 -0400244cleartextPrivateKeyPEM = normalize_privatekey_pem(b("""\
245-----BEGIN RSA PRIVATE KEY-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400246MIICXQIBAAKBgQD5mkLpi7q6ROdu7khB3S9aanA0Zls7vvfGOmB80/yeylhGpsjA
247jWen0VtSQke/NlEPGtO38tsV7CsuFnSmschvAnGrcJl76b0UOOHUgDTIoRxC6QDU
2483claegwsrBA+sJEBbqx5RdXbIRGicPG/8qQ4Zm1SKOgotcbwiaor2yxZ2wIDAQAB
249AoGBAPCgMpmLxzwDaUmcFbTJUvlLW1hoxNNYSu2jIZm1k/hRAcE60JYwvBkgz3UB
250yMEh0AtLxYe0bFk6EHah11tMUPgscbCq73snJ++8koUw+csk22G65hOs51bVb7Aa
2516JBe67oLzdtvgCUFAA2qfrKzWRZzAdhUirQUZgySZk+Xq1pBAkEA/kZG0A6roTSM
252BVnx7LnPfsycKUsTumorpXiylZJjTi9XtmzxhrYN6wgZlDOOwOLgSQhszGpxVoMD
253u3gByT1b2QJBAPtL3mSKdvwRu/+40zaZLwvSJRxaj0mcE4BJOS6Oqs/hS1xRlrNk
254PpQ7WJ4yM6ZOLnXzm2mKyxm50Mv64109FtMCQQDOqS2KkjHaLowTGVxwC0DijMfr
255I9Lf8sSQk32J5VWCySWf5gGTfEnpmUa41gKTMJIbqZZLucNuDcOtzUaeWZlZAkA8
256ttXigLnCqR486JDPTi9ZscoZkZ+w7y6e/hH8t6d5Vjt48JVyfjPIaJY+km58LcN3
2576AWSeGAdtRFHVzR7oHjVAkB4hutvxiOeiIVQNBhM6RSI9aBPMI21DoX2JRoxvNW2
258cbvAhow217X9V0dVerEOKxnNYspXRrh36h7k4mQA+sDq
259-----END RSA PRIVATE KEY-----
Jean-Paul Calderoned50d2042011-05-04 17:00:49 -0400260"""))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400261
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400262cleartextCertificateRequestPEM = b("""-----BEGIN CERTIFICATE REQUEST-----
263MIIBnjCCAQcCAQAwXjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQH
264EwdDaGljYWdvMRcwFQYDVQQKEw5NeSBDb21wYW55IEx0ZDEXMBUGA1UEAxMORnJl
265ZGVyaWNrIERlYW4wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANp6Y17WzKSw
266BsUWkXdqg6tnXy8H8hA1msCMWpc+/2KJ4mbv5NyD6UD+/SqagQqulPbF/DFea9nA
267E0zhmHJELcM8gUTIlXv/cgDWnmK4xj8YkjVUiCdqKRAKeuzLG1pGmwwF5lGeJpXN
268xQn5ecR0UYSOWj6TTGXB9VyUMQzCClcBAgMBAAGgADANBgkqhkiG9w0BAQUFAAOB
269gQAAJGuF/R/GGbeC7FbFW+aJgr9ee0Xbl6nlhu7pTe67k+iiKT2dsl2ti68MVTnu
270Vrb3HUNqOkiwsJf6kCtq5oPn3QVYzTa76Dt2y3Rtzv6boRSlmlfrgS92GNma8JfR
271oICQk3nAudi6zl1Dix3BCv1pUp5KMtGn3MeDEi6QFGy2rA==
272-----END CERTIFICATE REQUEST-----
273""")
Rick Dean5b7b6372009-04-01 11:34:06 -0500274
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400275encryptedPrivateKeyPEM = b("""-----BEGIN RSA PRIVATE KEY-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400276Proc-Type: 4,ENCRYPTED
277DEK-Info: DES-EDE3-CBC,9573604A18579E9E
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400278
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400279SHOho56WxDkT0ht10UTeKc0F5u8cqIa01kzFAmETw0MAs8ezYtK15NPdCXUm3X/2
280a17G7LSF5bkxOgZ7vpXyMzun/owrj7CzvLxyncyEFZWvtvzaAhPhvTJtTIB3kf8B
2818+qRcpTGK7NgXEgYBW5bj1y4qZkD4zCL9o9NQzsKI3Ie8i0239jsDOWR38AxjXBH
282mGwAQ4Z6ZN5dnmM4fhMIWsmFf19sNyAML4gHenQCHhmXbjXeVq47aC2ProInJbrm
283+00TcisbAQ40V9aehVbcDKtS4ZbMVDwncAjpXpcncC54G76N6j7F7wL7L/FuXa3A
284fvSVy9n2VfF/pJ3kYSflLHH2G/DFxjF7dl0GxhKPxJjp3IJi9VtuvmN9R2jZWLQF
285tfC8dXgy/P9CfFQhlinqBTEwgH0oZ/d4k4NVFDSdEMaSdmBAjlHpc+Vfdty3HVnV
286rKXj//wslsFNm9kIwJGIgKUa/n2jsOiydrsk1mgH7SmNCb3YHgZhbbnq0qLat/HC
287gHDt3FHpNQ31QzzL3yrenFB2L9osIsnRsDTPFNi4RX4SpDgNroxOQmyzCCV6H+d4
288o1mcnNiZSdxLZxVKccq0AfRpHqpPAFnJcQHP6xyT9MZp6fBa0XkxDnt9kNU8H3Qw
2897SJWZ69VXjBUzMlQViLuaWMgTnL+ZVyFZf9hTF7U/ef4HMLMAVNdiaGG+G+AjCV/
290MbzjS007Oe4qqBnCWaFPSnJX6uLApeTbqAxAeyCql56ULW5x6vDMNC3dwjvS/CEh
29111n8RkgFIQA0AhuKSIg3CbuartRsJnWOLwgLTzsrKYL4yRog1RJrtw==
292-----END RSA PRIVATE KEY-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400293""")
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400294
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400295encryptedPrivateKeyPEMPassphrase = b("foobar")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400296
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400297# Some PKCS#7 stuff. Generated with the openssl command line:
298#
299# openssl crl2pkcs7 -inform pem -outform pem -certfile s.pem -nocrl
300#
301# with a certificate and key (but the key should be irrelevant) in s.pem
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400302pkcs7Data = b("""\
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400303-----BEGIN PKCS7-----
304MIIDNwYJKoZIhvcNAQcCoIIDKDCCAyQCAQExADALBgkqhkiG9w0BBwGgggMKMIID
305BjCCAm+gAwIBAgIBATANBgkqhkiG9w0BAQQFADB7MQswCQYDVQQGEwJTRzERMA8G
306A1UEChMITTJDcnlwdG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtN
307MkNyeXB0byBDZXJ0aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNA
308cG9zdDEuY29tMB4XDTAwMDkxMDA5NTEzMFoXDTAyMDkxMDA5NTEzMFowUzELMAkG
309A1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwlsb2NhbGhvc3Qx
310HTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tMFwwDQYJKoZIhvcNAQEBBQAD
311SwAwSAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh5kwI
312zOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEAAaOCAQQwggEAMAkGA1UdEwQCMAAw
313LAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0G
314A1UdDgQWBBTPhIKSvnsmYsBVNWjj0m3M2z0qVTCBpQYDVR0jBIGdMIGagBT7hyNp
31565w6kxXlxb8pUU/+7Sg4AaF/pH0wezELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0y
316Q3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlwdG8g
317Q2VydGlmaWNhdGUgTWFzdGVyMR0wGwYJKoZIhvcNAQkBFg5uZ3BzQHBvc3QxLmNv
318bYIBADANBgkqhkiG9w0BAQQFAAOBgQA7/CqT6PoHycTdhEStWNZde7M/2Yc6BoJu
319VwnW8YxGO8Sn6UJ4FeffZNcYZddSDKosw8LtPOeWoK3JINjAk5jiPQ2cww++7QGG
320/g5NDjxFZNDJP1dGiLAxPW6JXwov4v0FmdzfLOZ01jDcgQQZqEpYlgpuI5JEWUQ9
321Ho4EzbYCOaEAMQA=
322-----END PKCS7-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400323""")
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400324
Alex Gaynor8fa1dd62014-08-14 09:57:51 -0700325pkcs7DataASN1 = base64.b64decode(b"""
Alex Gaynor4b9c96a2014-08-14 09:51:48 -0700326MIIDNwYJKoZIhvcNAQcCoIIDKDCCAyQCAQExADALBgkqhkiG9w0BBwGgggMKMIID
327BjCCAm+gAwIBAgIBATANBgkqhkiG9w0BAQQFADB7MQswCQYDVQQGEwJTRzERMA8G
328A1UEChMITTJDcnlwdG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtN
329MkNyeXB0byBDZXJ0aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNA
330cG9zdDEuY29tMB4XDTAwMDkxMDA5NTEzMFoXDTAyMDkxMDA5NTEzMFowUzELMAkG
331A1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwlsb2NhbGhvc3Qx
332HTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tMFwwDQYJKoZIhvcNAQEBBQAD
333SwAwSAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh5kwI
334zOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEAAaOCAQQwggEAMAkGA1UdEwQCMAAw
335LAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0G
336A1UdDgQWBBTPhIKSvnsmYsBVNWjj0m3M2z0qVTCBpQYDVR0jBIGdMIGagBT7hyNp
33765w6kxXlxb8pUU/+7Sg4AaF/pH0wezELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0y
338Q3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlwdG8g
339Q2VydGlmaWNhdGUgTWFzdGVyMR0wGwYJKoZIhvcNAQkBFg5uZ3BzQHBvc3QxLmNv
340bYIBADANBgkqhkiG9w0BAQQFAAOBgQA7/CqT6PoHycTdhEStWNZde7M/2Yc6BoJu
341VwnW8YxGO8Sn6UJ4FeffZNcYZddSDKosw8LtPOeWoK3JINjAk5jiPQ2cww++7QGG
342/g5NDjxFZNDJP1dGiLAxPW6JXwov4v0FmdzfLOZ01jDcgQQZqEpYlgpuI5JEWUQ9
343Ho4EzbYCOaEAMQA=
Alex Gaynor8fa1dd62014-08-14 09:57:51 -0700344""")
Alex Gaynor4b9c96a2014-08-14 09:51:48 -0700345
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400346crlData = b("""\
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -0500347-----BEGIN X509 CRL-----
348MIIBWzCBxTANBgkqhkiG9w0BAQQFADBYMQswCQYDVQQGEwJVUzELMAkGA1UECBMC
349SUwxEDAOBgNVBAcTB0NoaWNhZ28xEDAOBgNVBAoTB1Rlc3RpbmcxGDAWBgNVBAMT
350D1Rlc3RpbmcgUm9vdCBDQRcNMDkwNzI2MDQzNDU2WhcNMTIwOTI3MDI0MTUyWjA8
351MBUCAgOrGA8yMDA5MDcyNTIzMzQ1NlowIwICAQAYDzIwMDkwNzI1MjMzNDU2WjAM
352MAoGA1UdFQQDCgEEMA0GCSqGSIb3DQEBBAUAA4GBAEBt7xTs2htdD3d4ErrcGAw1
3534dKcVnIWTutoI7xxen26Wwvh8VCsT7i/UeP+rBl9rC/kfjWjzQk3/zleaarGTpBT
3540yp4HXRFFoRhhSE/hP+eteaPXRgrsNRLHe9ZDd69wmh7J1wMDb0m81RG7kqcbsid
355vrzEeLDRiiPl92dyyWmu
356-----END X509 CRL-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400357""")
Jean-Paul Calderonee890db32010-08-22 16:55:15 -0400358
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400359
360# A broken RSA private key which can be used to test the error path through
361# PKey.check.
362inconsistentPrivateKeyPEM = b("""-----BEGIN RSA PRIVATE KEY-----
363MIIBPAIBAAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh
3645kwIzOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEaAQJBAIqm/bz4NA1H++Vx5Ewx
365OcKp3w19QSaZAwlGRtsUxrP7436QjnREM3Bm8ygU11BjkPVmtrKm6AayQfCHqJoT
366zIECIQDW0BoMoL0HOYM/mrTLhaykYAVqgIeJsPjvkEhTFXWBuQIhAM3deFAvWNu4
367nklUQ37XsCT2c9tmNt1LAT+slG2JOTTRAiAuXDtC/m3NYVwyHfFm+zKHRzHkClk2
368HjubeEgjpj32AQIhAJqMGTaZVOwevTXvvHwNeH+vRWsAYU/gbx+OQB+7VOcBAiEA
369oolb6NMg/R3enNPvS1O4UU1H8wpaF77L4yiSWlE0p4w=
370-----END RSA PRIVATE KEY-----
371""")
372
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -0400373# certificate with NULL bytes in subjectAltName and common name
374
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400375nulbyteSubjectAltNamePEM = b("""-----BEGIN CERTIFICATE-----
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -0400376MIIE2DCCA8CgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBxTELMAkGA1UEBhMCVVMx
377DzANBgNVBAgMBk9yZWdvbjESMBAGA1UEBwwJQmVhdmVydG9uMSMwIQYDVQQKDBpQ
378eXRob24gU29mdHdhcmUgRm91bmRhdGlvbjEgMB4GA1UECwwXUHl0aG9uIENvcmUg
379RGV2ZWxvcG1lbnQxJDAiBgNVBAMMG251bGwucHl0aG9uLm9yZwBleGFtcGxlLm9y
380ZzEkMCIGCSqGSIb3DQEJARYVcHl0aG9uLWRldkBweXRob24ub3JnMB4XDTEzMDgw
381NzEzMTE1MloXDTEzMDgwNzEzMTI1MlowgcUxCzAJBgNVBAYTAlVTMQ8wDQYDVQQI
382DAZPcmVnb24xEjAQBgNVBAcMCUJlYXZlcnRvbjEjMCEGA1UECgwaUHl0aG9uIFNv
383ZnR3YXJlIEZvdW5kYXRpb24xIDAeBgNVBAsMF1B5dGhvbiBDb3JlIERldmVsb3Bt
384ZW50MSQwIgYDVQQDDBtudWxsLnB5dGhvbi5vcmcAZXhhbXBsZS5vcmcxJDAiBgkq
385hkiG9w0BCQEWFXB5dGhvbi1kZXZAcHl0aG9uLm9yZzCCASIwDQYJKoZIhvcNAQEB
386BQADggEPADCCAQoCggEBALXq7cn7Rn1vO3aA3TrzA5QLp6bb7B3f/yN0CJ2XFj+j
387pHs+Gw6WWSUDpybiiKnPec33BFawq3kyblnBMjBU61ioy5HwQqVkJ8vUVjGIUq3P
388vX/wBmQfzCe4o4uM89gpHyUL9UYGG8oCRa17dgqcv7u5rg0Wq2B1rgY+nHwx3JIv
389KRrgSwyRkGzpN8WQ1yrXlxWjgI9de0mPVDDUlywcWze1q2kwaEPTM3hLAmD1PESA
390oY/n8A/RXoeeRs9i/Pm/DGUS8ZPINXk/yOzsR/XvvkTVroIeLZqfmFpnZeF0cHzL
39108LODkVJJ9zjLdT7SA4vnne4FEbAxDbKAq5qkYzaL4UCAwEAAaOB0DCBzTAMBgNV
392HRMBAf8EAjAAMB0GA1UdDgQWBBSIWlXAUv9hzVKjNQ/qWpwkOCL3XDALBgNVHQ8E
393BAMCBeAwgZAGA1UdEQSBiDCBhYIeYWx0bnVsbC5weXRob24ub3JnAGV4YW1wbGUu
394Y29tgSBudWxsQHB5dGhvbi5vcmcAdXNlckBleGFtcGxlLm9yZ4YpaHR0cDovL251
395bGwucHl0aG9uLm9yZwBodHRwOi8vZXhhbXBsZS5vcmeHBMAAAgGHECABDbgAAAAA
396AAAAAAAAAAEwDQYJKoZIhvcNAQEFBQADggEBAKxPRe99SaghcI6IWT7UNkJw9aO9
397i9eo0Fj2MUqxpKbdb9noRDy2CnHWf7EIYZ1gznXPdwzSN4YCjV5d+Q9xtBaowT0j
398HPERs1ZuytCNNJTmhyqZ8q6uzMLoht4IqH/FBfpvgaeC5tBTnTT0rD5A/olXeimk
399kX4LxlEx5RAvpGB2zZVRGr6LobD9rVK91xuHYNIxxxfEGE8tCCWjp0+3ksri9SXx
400VHWBnbM9YaL32u3hxm8sYB/Yb8WSBavJCWJJqRStVRHM1koZlJmXNx2BX4vPo6iW
401RFEIPQsFZRLrtnCAiEhyT8bC2s/Njlu6ly9gtJZWSV46Q3ZjBL4q9sHKqZQ=
402-----END CERTIFICATE-----""")
403
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400404
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400405class X509ExtTests(TestCase):
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400406 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900407 Tests for :py:class:`OpenSSL.crypto.X509Extension`.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400408 """
409
410 def setUp(self):
411 """
412 Create a new private key and start a certificate request (for a test
413 method to finish in one way or another).
414 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -0800415 super(X509ExtTests, self).setUp()
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400416 # Basic setup stuff to generate a certificate
417 self.pkey = PKey()
418 self.pkey.generate_key(TYPE_RSA, 384)
419 self.req = X509Req()
420 self.req.set_pubkey(self.pkey)
421 # Authority good you have.
422 self.req.get_subject().commonName = "Yoda root CA"
423 self.x509 = X509()
424 self.subject = self.x509.get_subject()
425 self.subject.commonName = self.req.get_subject().commonName
426 self.x509.set_issuer(self.subject)
427 self.x509.set_pubkey(self.pkey)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400428 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
429 expire = b((datetime.now() + timedelta(days=100)).strftime("%Y%m%d%H%M%SZ"))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400430 self.x509.set_notBefore(now)
431 self.x509.set_notAfter(expire)
432
433
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -0800434 def tearDown(self):
435 """
436 Forget all of the pyOpenSSL objects so they can be garbage collected,
437 their memory released, and not interfere with the leak detection code.
438 """
439 self.pkey = self.req = self.x509 = self.subject = None
440 super(X509ExtTests, self).tearDown()
441
442
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400443 def test_str(self):
444 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900445 The string representation of :py:class:`X509Extension` instances as returned by
446 :py:data:`str` includes stuff.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400447 """
448 # This isn't necessarily the best string representation. Perhaps it
449 # will be changed/improved in the future.
450 self.assertEquals(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400451 str(X509Extension(b('basicConstraints'), True, b('CA:false'))),
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400452 'CA:FALSE')
453
454
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400455 def test_type(self):
456 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900457 :py:class:`X509Extension` and :py:class:`X509ExtensionType` refer to the same type object
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400458 and can be used to create instances of that type.
459 """
460 self.assertIdentical(X509Extension, X509ExtensionType)
461 self.assertConsistentType(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400462 X509Extension,
463 'X509Extension', b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400464
465
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500466 def test_construction(self):
467 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900468 :py:class:`X509Extension` accepts an extension type name, a critical flag,
469 and an extension value and returns an :py:class:`X509ExtensionType` instance.
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500470 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400471 basic = X509Extension(b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500472 self.assertTrue(
473 isinstance(basic, X509ExtensionType),
474 "%r is of type %r, should be %r" % (
475 basic, type(basic), X509ExtensionType))
476
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400477 comment = X509Extension(
478 b('nsComment'), False, b('pyOpenSSL unit test'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500479 self.assertTrue(
480 isinstance(comment, X509ExtensionType),
481 "%r is of type %r, should be %r" % (
482 comment, type(comment), X509ExtensionType))
483
484
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500485 def test_invalid_extension(self):
486 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900487 :py:class:`X509Extension` raises something if it is passed a bad extension
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500488 name or value.
489 """
490 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400491 Error, X509Extension, b('thisIsMadeUp'), False, b('hi'))
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500492 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400493 Error, X509Extension, b('basicConstraints'), False, b('blah blah'))
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500494
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500495 # Exercise a weird one (an extension which uses the r2i method). This
496 # exercises the codepath that requires a non-NULL ctx to be passed to
497 # X509V3_EXT_nconf. It can't work now because we provide no
498 # configuration database. It might be made to work in the future.
499 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400500 Error, X509Extension, b('proxyCertInfo'), True,
501 b('language:id-ppl-anyLanguage,pathlen:1,policy:text:AB'))
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500502
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500503
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500504 def test_get_critical(self):
505 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900506 :py:meth:`X509ExtensionType.get_critical` returns the value of the
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500507 extension's critical flag.
508 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400509 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500510 self.assertTrue(ext.get_critical())
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400511 ext = X509Extension(b('basicConstraints'), False, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500512 self.assertFalse(ext.get_critical())
513
Jean-Paul Calderone7535dab2008-03-06 18:53:11 -0500514
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500515 def test_get_short_name(self):
516 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900517 :py:meth:`X509ExtensionType.get_short_name` returns a string giving the short
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500518 type name of the extension.
519 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400520 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
521 self.assertEqual(ext.get_short_name(), b('basicConstraints'))
522 ext = X509Extension(b('nsComment'), True, b('foo bar'))
523 self.assertEqual(ext.get_short_name(), b('nsComment'))
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500524
525
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400526 def test_get_data(self):
527 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900528 :py:meth:`X509Extension.get_data` returns a string giving the data of the
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400529 extension.
530 """
531 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
532 # Expect to get back the DER encoded form of CA:true.
533 self.assertEqual(ext.get_data(), b('0\x03\x01\x01\xff'))
534
535
536 def test_get_data_wrong_args(self):
537 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900538 :py:meth:`X509Extension.get_data` raises :py:exc:`TypeError` if passed any arguments.
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400539 """
540 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
541 self.assertRaises(TypeError, ext.get_data, None)
542 self.assertRaises(TypeError, ext.get_data, "foo")
543 self.assertRaises(TypeError, ext.get_data, 7)
544
545
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400546 def test_unused_subject(self):
Rick Dean47262da2009-07-08 16:17:17 -0500547 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900548 The :py:data:`subject` parameter to :py:class:`X509Extension` may be provided for an
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400549 extension which does not use it and is ignored in this case.
Rick Dean47262da2009-07-08 16:17:17 -0500550 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400551 ext1 = X509Extension(
552 b('basicConstraints'), False, b('CA:TRUE'), subject=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400553 self.x509.add_extensions([ext1])
554 self.x509.sign(self.pkey, 'sha1')
555 # This is a little lame. Can we think of a better way?
556 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400557 self.assertTrue(b('X509v3 Basic Constraints:') in text)
558 self.assertTrue(b('CA:TRUE') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400559
560
561 def test_subject(self):
562 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900563 If an extension requires a subject, the :py:data:`subject` parameter to
564 :py:class:`X509Extension` provides its value.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400565 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400566 ext3 = X509Extension(
567 b('subjectKeyIdentifier'), False, b('hash'), subject=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400568 self.x509.add_extensions([ext3])
569 self.x509.sign(self.pkey, 'sha1')
570 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400571 self.assertTrue(b('X509v3 Subject Key Identifier:') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400572
573
574 def test_missing_subject(self):
575 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900576 If an extension requires a subject and the :py:data:`subject` parameter is
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400577 given no value, something happens.
578 """
579 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400580 Error, X509Extension, b('subjectKeyIdentifier'), False, b('hash'))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400581
582
583 def test_invalid_subject(self):
584 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900585 If the :py:data:`subject` parameter is given a value which is not an
586 :py:class:`X509` instance, :py:exc:`TypeError` is raised.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400587 """
588 for badObj in [True, object(), "hello", [], self]:
589 self.assertRaises(
590 TypeError,
591 X509Extension,
592 'basicConstraints', False, 'CA:TRUE', subject=badObj)
593
594
595 def test_unused_issuer(self):
596 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900597 The :py:data:`issuer` parameter to :py:class:`X509Extension` may be provided for an
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400598 extension which does not use it and is ignored in this case.
599 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400600 ext1 = X509Extension(
601 b('basicConstraints'), False, b('CA:TRUE'), issuer=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400602 self.x509.add_extensions([ext1])
603 self.x509.sign(self.pkey, 'sha1')
604 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400605 self.assertTrue(b('X509v3 Basic Constraints:') in text)
606 self.assertTrue(b('CA:TRUE') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400607
608
609 def test_issuer(self):
610 """
Alex Gaynor3b0ee972014-11-15 09:17:33 -0800611 If an extension requires an issuer, the :py:data:`issuer` parameter to
Jonathan Ballet648875f2011-07-16 14:14:58 +0900612 :py:class:`X509Extension` provides its value.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400613 """
614 ext2 = X509Extension(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400615 b('authorityKeyIdentifier'), False, b('issuer:always'),
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400616 issuer=self.x509)
617 self.x509.add_extensions([ext2])
618 self.x509.sign(self.pkey, 'sha1')
619 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400620 self.assertTrue(b('X509v3 Authority Key Identifier:') in text)
621 self.assertTrue(b('DirName:/CN=Yoda root CA') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400622
623
624 def test_missing_issuer(self):
625 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900626 If an extension requires an issue and the :py:data:`issuer` parameter is given
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400627 no value, something happens.
628 """
629 self.assertRaises(
630 Error,
631 X509Extension,
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400632 b('authorityKeyIdentifier'), False,
633 b('keyid:always,issuer:always'))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400634
635
636 def test_invalid_issuer(self):
637 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900638 If the :py:data:`issuer` parameter is given a value which is not an
639 :py:class:`X509` instance, :py:exc:`TypeError` is raised.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400640 """
641 for badObj in [True, object(), "hello", [], self]:
642 self.assertRaises(
643 TypeError,
644 X509Extension,
645 'authorityKeyIdentifier', False, 'keyid:always,issuer:always',
646 issuer=badObj)
Rick Dean47262da2009-07-08 16:17:17 -0500647
648
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500649
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400650class PKeyTests(TestCase):
Jean-Paul Calderoneac930e12008-03-06 18:50:51 -0500651 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900652 Unit tests for :py:class:`OpenSSL.crypto.PKey`.
Jean-Paul Calderoneac930e12008-03-06 18:50:51 -0500653 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400654 def test_type(self):
655 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900656 :py:class:`PKey` and :py:class:`PKeyType` refer to the same type object
657 and can be used to create instances of that type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400658 """
659 self.assertIdentical(PKey, PKeyType)
660 self.assertConsistentType(PKey, 'PKey')
661
662
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500663 def test_construction(self):
664 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900665 :py:class:`PKey` takes no arguments and returns a new :py:class:`PKey` instance.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500666 """
667 self.assertRaises(TypeError, PKey, None)
668 key = PKey()
669 self.assertTrue(
670 isinstance(key, PKeyType),
671 "%r is of type %r, should be %r" % (key, type(key), PKeyType))
672
673
674 def test_pregeneration(self):
675 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900676 :py:attr:`PKeyType.bits` and :py:attr:`PKeyType.type` return :py:data:`0` before the key is
677 generated. :py:attr:`PKeyType.check` raises :py:exc:`TypeError` before the key is
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500678 generated.
679 """
680 key = PKey()
681 self.assertEqual(key.type(), 0)
682 self.assertEqual(key.bits(), 0)
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400683 self.assertRaises(TypeError, key.check)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500684
685
686 def test_failedGeneration(self):
687 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900688 :py:meth:`PKeyType.generate_key` takes two arguments, the first giving the key
689 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 -0500690 number of bits to generate. If an invalid type is specified or
Jonathan Ballet648875f2011-07-16 14:14:58 +0900691 generation fails, :py:exc:`Error` is raised. If an invalid number of bits is
692 specified, :py:exc:`ValueError` or :py:exc:`Error` is raised.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500693 """
694 key = PKey()
695 self.assertRaises(TypeError, key.generate_key)
696 self.assertRaises(TypeError, key.generate_key, 1, 2, 3)
697 self.assertRaises(TypeError, key.generate_key, "foo", "bar")
698 self.assertRaises(Error, key.generate_key, -1, 0)
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500699
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500700 self.assertRaises(ValueError, key.generate_key, TYPE_RSA, -1)
701 self.assertRaises(ValueError, key.generate_key, TYPE_RSA, 0)
Jean-Paul Calderoned71fe982008-03-06 00:31:50 -0500702
703 # XXX RSA generation for small values of bits is fairly buggy in a wide
704 # range of OpenSSL versions. I need to figure out what the safe lower
705 # bound for a reasonable number of OpenSSL versions is and explicitly
706 # check for that in the wrapper. The failure behavior is typically an
707 # infinite loop inside OpenSSL.
708
709 # self.assertRaises(Error, key.generate_key, TYPE_RSA, 2)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500710
711 # XXX DSA generation seems happy with any number of bits. The DSS
712 # says bits must be between 512 and 1024 inclusive. OpenSSL's DSA
713 # generator doesn't seem to care about the upper limit at all. For
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500714 # the lower limit, it uses 512 if anything smaller is specified.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500715 # So, it doesn't seem possible to make generate_key fail for
716 # TYPE_DSA with a bits argument which is at least an int.
717
718 # self.assertRaises(Error, key.generate_key, TYPE_DSA, -7)
719
720
721 def test_rsaGeneration(self):
722 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900723 :py:meth:`PKeyType.generate_key` generates an RSA key when passed
724 :py:data:`TYPE_RSA` as a type and a reasonable number of bits.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500725 """
726 bits = 128
727 key = PKey()
728 key.generate_key(TYPE_RSA, bits)
729 self.assertEqual(key.type(), TYPE_RSA)
730 self.assertEqual(key.bits(), bits)
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -0400731 self.assertTrue(key.check())
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500732
733
734 def test_dsaGeneration(self):
735 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900736 :py:meth:`PKeyType.generate_key` generates a DSA key when passed
737 :py:data:`TYPE_DSA` as a type and a reasonable number of bits.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500738 """
739 # 512 is a magic number. The DSS (Digital Signature Standard)
740 # allows a minimum of 512 bits for DSA. DSA_generate_parameters
741 # will silently promote any value below 512 to 512.
742 bits = 512
743 key = PKey()
744 key.generate_key(TYPE_DSA, bits)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800745 # self.assertEqual(key.type(), TYPE_DSA)
746 # self.assertEqual(key.bits(), bits)
747 # self.assertRaises(TypeError, key.check)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500748
749
750 def test_regeneration(self):
751 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900752 :py:meth:`PKeyType.generate_key` can be called multiple times on the same
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500753 key to generate new keys.
754 """
755 key = PKey()
756 for type, bits in [(TYPE_RSA, 512), (TYPE_DSA, 576)]:
757 key.generate_key(type, bits)
758 self.assertEqual(key.type(), type)
759 self.assertEqual(key.bits(), bits)
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500760
761
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400762 def test_inconsistentKey(self):
763 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900764 :py:`PKeyType.check` returns :py:exc:`Error` if the key is not consistent.
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400765 """
766 key = load_privatekey(FILETYPE_PEM, inconsistentPrivateKeyPEM)
Jean-Paul Calderoned338e4e2009-05-13 15:45:07 -0400767 self.assertRaises(Error, key.check)
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400768
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500769
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400770 def test_check_wrong_args(self):
771 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900772 :py:meth:`PKeyType.check` raises :py:exc:`TypeError` if called with any arguments.
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400773 """
774 self.assertRaises(TypeError, PKey().check, None)
775 self.assertRaises(TypeError, PKey().check, object())
776 self.assertRaises(TypeError, PKey().check, 1)
777
778
Jean-Paul Calderone02d01972011-10-31 10:39:29 -0400779 def test_check_public_key(self):
780 """
781 :py:meth:`PKeyType.check` raises :py:exc:`TypeError` if only the public
782 part of the key is available.
783 """
784 # A trick to get a public-only key
785 key = PKey()
786 key.generate_key(TYPE_RSA, 512)
787 cert = X509()
788 cert.set_pubkey(key)
789 pub = cert.get_pubkey()
790 self.assertRaises(TypeError, pub.check)
791
792
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400793
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400794class X509NameTests(TestCase):
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500795 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900796 Unit tests for :py:class:`OpenSSL.crypto.X509Name`.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500797 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500798 def _x509name(self, **attrs):
799 # XXX There's no other way to get a new X509Name yet.
800 name = X509().get_subject()
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400801 attrs = list(attrs.items())
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500802 # Make the order stable - order matters!
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400803 def key(attr):
804 return attr[1]
805 attrs.sort(key=key)
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500806 for k, v in attrs:
807 setattr(name, k, v)
808 return name
809
810
Rick Deane15b1472009-07-09 15:53:42 -0500811 def test_type(self):
812 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900813 The type of X509Name objects is :py:class:`X509NameType`.
Rick Deane15b1472009-07-09 15:53:42 -0500814 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400815 self.assertIdentical(X509Name, X509NameType)
816 self.assertEqual(X509NameType.__name__, 'X509Name')
817 self.assertTrue(isinstance(X509NameType, type))
818
Rick Deane15b1472009-07-09 15:53:42 -0500819 name = self._x509name()
820 self.assertTrue(
821 isinstance(name, X509NameType),
822 "%r is of type %r, should be %r" % (
823 name, type(name), X509NameType))
Rick Deane15b1472009-07-09 15:53:42 -0500824
825
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400826 def test_onlyStringAttributes(self):
827 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900828 Attempting to set a non-:py:data:`str` attribute name on an :py:class:`X509NameType`
829 instance causes :py:exc:`TypeError` to be raised.
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400830 """
831 name = self._x509name()
832 # Beyond these cases, you may also think that unicode should be
833 # rejected. Sorry, you're wrong. unicode is automatically converted to
834 # str outside of the control of X509Name, so there's no way to reject
835 # it.
Jean-Paul Calderoneff363be2013-03-03 10:21:23 -0800836
837 # Also, this used to test str subclasses, but that test is less relevant
838 # now that the implementation is in Python instead of C. Also PyPy
839 # automatically converts str subclasses to str when they are passed to
840 # setattr, so we can't test it on PyPy. Apparently CPython does this
841 # sometimes as well.
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400842 self.assertRaises(TypeError, setattr, name, None, "hello")
843 self.assertRaises(TypeError, setattr, name, 30, "hello")
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400844
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -0500845
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400846 def test_setInvalidAttribute(self):
847 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900848 Attempting to set any attribute name on an :py:class:`X509NameType` instance for
849 which no corresponding NID is defined causes :py:exc:`AttributeError` to be
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400850 raised.
851 """
852 name = self._x509name()
853 self.assertRaises(AttributeError, setattr, name, "no such thing", None)
854
855
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500856 def test_attributes(self):
857 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900858 :py:class:`X509NameType` instances have attributes for each standard (?)
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500859 X509Name field.
860 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500861 name = self._x509name()
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500862 name.commonName = "foo"
863 self.assertEqual(name.commonName, "foo")
864 self.assertEqual(name.CN, "foo")
865 name.CN = "baz"
866 self.assertEqual(name.commonName, "baz")
867 self.assertEqual(name.CN, "baz")
868 name.commonName = "bar"
869 self.assertEqual(name.commonName, "bar")
870 self.assertEqual(name.CN, "bar")
871 name.CN = "quux"
872 self.assertEqual(name.commonName, "quux")
873 self.assertEqual(name.CN, "quux")
874
875
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500876 def test_copy(self):
877 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900878 :py:class:`X509Name` creates a new :py:class:`X509NameType` instance with all the same
879 attributes as an existing :py:class:`X509NameType` instance when called with
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500880 one.
881 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500882 name = self._x509name(commonName="foo", emailAddress="bar@example.com")
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500883
884 copy = X509Name(name)
885 self.assertEqual(copy.commonName, "foo")
886 self.assertEqual(copy.emailAddress, "bar@example.com")
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500887
888 # Mutate the copy and ensure the original is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500889 copy.commonName = "baz"
890 self.assertEqual(name.commonName, "foo")
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500891
892 # Mutate the original and ensure the copy is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500893 name.emailAddress = "quux@example.com"
894 self.assertEqual(copy.emailAddress, "bar@example.com")
895
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500896
897 def test_repr(self):
898 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900899 :py:func:`repr` passed an :py:class:`X509NameType` instance should return a string
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500900 containing a description of the type and the NIDs which have been set
901 on it.
902 """
903 name = self._x509name(commonName="foo", emailAddress="bar")
904 self.assertEqual(
905 repr(name),
906 "<X509Name object '/emailAddress=bar/CN=foo'>")
907
908
909 def test_comparison(self):
910 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900911 :py:class:`X509NameType` instances should compare based on their NIDs.
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500912 """
913 def _equality(a, b, assertTrue, assertFalse):
914 assertTrue(a == b, "(%r == %r) --> False" % (a, b))
915 assertFalse(a != b)
916 assertTrue(b == a)
917 assertFalse(b != a)
918
919 def assertEqual(a, b):
920 _equality(a, b, self.assertTrue, self.assertFalse)
921
922 # Instances compare equal to themselves.
923 name = self._x509name()
924 assertEqual(name, name)
925
926 # Empty instances should compare equal to each other.
927 assertEqual(self._x509name(), self._x509name())
928
929 # Instances with equal NIDs should compare equal to each other.
930 assertEqual(self._x509name(commonName="foo"),
931 self._x509name(commonName="foo"))
932
933 # Instance with equal NIDs set using different aliases should compare
934 # equal to each other.
935 assertEqual(self._x509name(commonName="foo"),
936 self._x509name(CN="foo"))
937
938 # Instances with more than one NID with the same values should compare
939 # equal to each other.
940 assertEqual(self._x509name(CN="foo", organizationalUnitName="bar"),
941 self._x509name(commonName="foo", OU="bar"))
942
943 def assertNotEqual(a, b):
944 _equality(a, b, self.assertFalse, self.assertTrue)
945
946 # Instances with different values for the same NID should not compare
947 # equal to each other.
948 assertNotEqual(self._x509name(CN="foo"),
949 self._x509name(CN="bar"))
950
951 # Instances with different NIDs should not compare equal to each other.
952 assertNotEqual(self._x509name(CN="foo"),
953 self._x509name(OU="foo"))
954
955 def _inequality(a, b, assertTrue, assertFalse):
956 assertTrue(a < b)
957 assertTrue(a <= b)
958 assertTrue(b > a)
959 assertTrue(b >= a)
960 assertFalse(a > b)
961 assertFalse(a >= b)
962 assertFalse(b < a)
963 assertFalse(b <= a)
964
965 def assertLessThan(a, b):
966 _inequality(a, b, self.assertTrue, self.assertFalse)
967
968 # An X509Name with a NID with a value which sorts less than the value
969 # of the same NID on another X509Name compares less than the other
970 # X509Name.
971 assertLessThan(self._x509name(CN="abc"),
972 self._x509name(CN="def"))
973
974 def assertGreaterThan(a, b):
975 _inequality(a, b, self.assertFalse, self.assertTrue)
976
977 # An X509Name with a NID with a value which sorts greater than the
978 # value of the same NID on another X509Name compares greater than the
979 # other X509Name.
980 assertGreaterThan(self._x509name(CN="def"),
981 self._x509name(CN="abc"))
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -0500982
983
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400984 def test_hash(self):
985 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900986 :py:meth:`X509Name.hash` returns an integer hash based on the value of the
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400987 name.
988 """
989 a = self._x509name(CN="foo")
990 b = self._x509name(CN="foo")
991 self.assertEqual(a.hash(), b.hash())
992 a.CN = "bar"
993 self.assertNotEqual(a.hash(), b.hash())
994
995
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400996 def test_der(self):
997 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900998 :py:meth:`X509Name.der` returns the DER encoded form of the name.
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400999 """
1000 a = self._x509name(CN="foo", C="US")
1001 self.assertEqual(
1002 a.der(),
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -04001003 b('0\x1b1\x0b0\t\x06\x03U\x04\x06\x13\x02US'
D.S. Ljungmark5533e252014-05-31 13:18:41 +02001004 '1\x0c0\n\x06\x03U\x04\x03\x0c\x03foo'))
Jean-Paul Calderonee957a002008-03-25 15:16:51 -04001005
1006
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -04001007 def test_get_components(self):
1008 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001009 :py:meth:`X509Name.get_components` returns a :py:data:`list` of
1010 two-tuples of :py:data:`str`
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -04001011 giving the NIDs and associated values which make up the name.
1012 """
1013 a = self._x509name()
1014 self.assertEqual(a.get_components(), [])
1015 a.CN = "foo"
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -04001016 self.assertEqual(a.get_components(), [(b("CN"), b("foo"))])
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -04001017 a.organizationalUnitName = "bar"
1018 self.assertEqual(
1019 a.get_components(),
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -04001020 [(b("CN"), b("foo")), (b("OU"), b("bar"))])
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -04001021
Jean-Paul Calderone110cd092008-03-24 17:27:42 -04001022
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001023 def test_load_nul_byte_attribute(self):
1024 """
Jean-Paul Calderone9af07b02013-08-23 16:07:31 -04001025 An :py:class:`OpenSSL.crypto.X509Name` from an
1026 :py:class:`OpenSSL.crypto.X509` instance loaded from a file can have a
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001027 NUL byte in the value of one of its attributes.
1028 """
1029 cert = load_certificate(FILETYPE_PEM, nulbyteSubjectAltNamePEM)
1030 subject = cert.get_subject()
1031 self.assertEqual(
Jean-Paul Calderone06754fc2013-08-23 15:47:47 -04001032 "null.python.org\x00example.org", subject.commonName)
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001033
1034
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -05001035 def test_setAttributeFailure(self):
1036 """
1037 If the value of an attribute cannot be set for some reason then
1038 :py:class:`OpenSSL.crypto.Error` is raised.
1039 """
1040 name = self._x509name()
1041 # This value is too long
1042 self.assertRaises(Error, setattr, name, "O", b"x" * 512)
1043
1044
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001045
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001046class _PKeyInteractionTestsMixin:
1047 """
1048 Tests which involve another thing and a PKey.
1049 """
1050 def signable(self):
1051 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001052 Return something with a :py:meth:`set_pubkey`, :py:meth:`set_pubkey`,
1053 and :py:meth:`sign` method.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001054 """
1055 raise NotImplementedError()
1056
1057
1058 def test_signWithUngenerated(self):
1059 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001060 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when pass a
1061 :py:class:`PKey` with no parts.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001062 """
1063 request = self.signable()
1064 key = PKey()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001065 self.assertRaises(ValueError, request.sign, key, GOOD_DIGEST)
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001066
1067
1068 def test_signWithPublicKey(self):
1069 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001070 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when pass a
1071 :py:class:`PKey` with no private part as the signing key.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001072 """
1073 request = self.signable()
1074 key = PKey()
1075 key.generate_key(TYPE_RSA, 512)
1076 request.set_pubkey(key)
1077 pub = request.get_pubkey()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001078 self.assertRaises(ValueError, request.sign, pub, GOOD_DIGEST)
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001079
1080
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -04001081 def test_signWithUnknownDigest(self):
1082 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001083 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when passed a digest name which is
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -04001084 not known.
1085 """
1086 request = self.signable()
1087 key = PKey()
1088 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001089 self.assertRaises(ValueError, request.sign, key, BAD_DIGEST)
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -04001090
1091
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04001092 def test_sign(self):
1093 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001094 :py:meth:`X509Req.sign` succeeds when passed a private key object and a valid
1095 digest function. :py:meth:`X509Req.verify` can be used to check the signature.
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04001096 """
1097 request = self.signable()
1098 key = PKey()
1099 key.generate_key(TYPE_RSA, 512)
1100 request.set_pubkey(key)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001101 request.sign(key, GOOD_DIGEST)
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04001102 # If the type has a verify method, cover that too.
1103 if getattr(request, 'verify', None) is not None:
1104 pub = request.get_pubkey()
1105 self.assertTrue(request.verify(pub))
1106 # Make another key that won't verify.
1107 key = PKey()
1108 key.generate_key(TYPE_RSA, 512)
1109 self.assertRaises(Error, request.verify, key)
1110
1111
1112
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001113
Jean-Paul Calderone18808652009-07-05 12:54:05 -04001114class X509ReqTests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001115 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001116 Tests for :py:class:`OpenSSL.crypto.X509Req`.
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001117 """
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001118 def signable(self):
1119 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001120 Create and return a new :py:class:`X509Req`.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001121 """
1122 return X509Req()
1123
1124
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001125 def test_type(self):
1126 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001127 :py:obj:`X509Req` and :py:obj:`X509ReqType` refer to the same type object and can be
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001128 used to create instances of that type.
1129 """
1130 self.assertIdentical(X509Req, X509ReqType)
1131 self.assertConsistentType(X509Req, 'X509Req')
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001132
1133
1134 def test_construction(self):
1135 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001136 :py:obj:`X509Req` takes no arguments and returns an :py:obj:`X509ReqType` instance.
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001137 """
1138 request = X509Req()
1139 self.assertTrue(
1140 isinstance(request, X509ReqType),
1141 "%r is of type %r, should be %r" % (request, type(request), X509ReqType))
1142
1143
Jean-Paul Calderone8dd19b82008-12-28 20:41:16 -05001144 def test_version(self):
1145 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001146 :py:obj:`X509ReqType.set_version` sets the X.509 version of the certificate
1147 request. :py:obj:`X509ReqType.get_version` returns the X.509 version of
Jean-Paul Calderone8dd19b82008-12-28 20:41:16 -05001148 the certificate request. The initial value of the version is 0.
1149 """
1150 request = X509Req()
1151 self.assertEqual(request.get_version(), 0)
1152 request.set_version(1)
1153 self.assertEqual(request.get_version(), 1)
1154 request.set_version(3)
1155 self.assertEqual(request.get_version(), 3)
1156
1157
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001158 def test_version_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001159 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001160 :py:obj:`X509ReqType.set_version` raises :py:obj:`TypeError` if called with the wrong
1161 number of arguments or with a non-:py:obj:`int` argument.
1162 :py:obj:`X509ReqType.get_version` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001163 arguments.
1164 """
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001165 request = X509Req()
1166 self.assertRaises(TypeError, request.set_version)
1167 self.assertRaises(TypeError, request.set_version, "foo")
1168 self.assertRaises(TypeError, request.set_version, 1, 2)
1169 self.assertRaises(TypeError, request.get_version, None)
1170
1171
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001172 def test_get_subject(self):
1173 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001174 :py:obj:`X509ReqType.get_subject` returns an :py:obj:`X509Name` for the subject of
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001175 the request and which is valid even after the request object is
1176 otherwise dead.
1177 """
1178 request = X509Req()
1179 subject = request.get_subject()
1180 self.assertTrue(
1181 isinstance(subject, X509NameType),
1182 "%r is of type %r, should be %r" % (subject, type(subject), X509NameType))
1183 subject.commonName = "foo"
1184 self.assertEqual(request.get_subject().commonName, "foo")
1185 del request
1186 subject.commonName = "bar"
1187 self.assertEqual(subject.commonName, "bar")
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001188
1189
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001190 def test_get_subject_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001191 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001192 :py:obj:`X509ReqType.get_subject` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001193 arguments.
1194 """
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001195 request = X509Req()
1196 self.assertRaises(TypeError, request.get_subject, None)
1197
1198
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001199 def test_add_extensions(self):
1200 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001201 :py:obj:`X509Req.add_extensions` accepts a :py:obj:`list` of :py:obj:`X509Extension`
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001202 instances and adds them to the X509 request.
1203 """
1204 request = X509Req()
1205 request.add_extensions([
Jean-Paul Calderonee16f9f32010-08-22 19:20:37 -04001206 X509Extension(b('basicConstraints'), True, b('CA:false'))])
Stephen Holsappleca545b72014-01-28 21:43:25 -08001207 exts = request.get_extensions()
Stephen Holsapple7fbdf642014-03-01 20:05:47 -08001208 self.assertEqual(len(exts), 1)
1209 self.assertEqual(exts[0].get_short_name(), b('basicConstraints'))
1210 self.assertEqual(exts[0].get_critical(), 1)
1211 self.assertEqual(exts[0].get_data(), b('0\x00'))
1212
1213
1214 def test_get_extensions(self):
1215 """
1216 :py:obj:`X509Req.get_extensions` returns a :py:obj:`list` of
1217 extensions added to this X509 request.
1218 """
1219 request = X509Req()
1220 exts = request.get_extensions()
1221 self.assertEqual(exts, [])
1222 request.add_extensions([
1223 X509Extension(b('basicConstraints'), True, b('CA:true')),
1224 X509Extension(b('keyUsage'), False, b('digitalSignature'))])
1225 exts = request.get_extensions()
1226 self.assertEqual(len(exts), 2)
1227 self.assertEqual(exts[0].get_short_name(), b('basicConstraints'))
1228 self.assertEqual(exts[0].get_critical(), 1)
1229 self.assertEqual(exts[0].get_data(), b('0\x03\x01\x01\xff'))
1230 self.assertEqual(exts[1].get_short_name(), b('keyUsage'))
1231 self.assertEqual(exts[1].get_critical(), 0)
1232 self.assertEqual(exts[1].get_data(), b('\x03\x02\x07\x80'))
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001233
1234
1235 def test_add_extensions_wrong_args(self):
1236 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001237 :py:obj:`X509Req.add_extensions` raises :py:obj:`TypeError` if called with the wrong
1238 number of arguments or with a non-:py:obj:`list`. Or it raises :py:obj:`ValueError`
1239 if called with a :py:obj:`list` containing objects other than :py:obj:`X509Extension`
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001240 instances.
1241 """
1242 request = X509Req()
1243 self.assertRaises(TypeError, request.add_extensions)
1244 self.assertRaises(TypeError, request.add_extensions, object())
1245 self.assertRaises(ValueError, request.add_extensions, [object()])
1246 self.assertRaises(TypeError, request.add_extensions, [], None)
1247
1248
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001249 def test_verify_wrong_args(self):
1250 """
1251 :py:obj:`X509Req.verify` raises :py:obj:`TypeError` if called with zero
1252 arguments or more than one argument or if passed anything other than a
1253 :py:obj:`PKey` instance as its single argument.
1254 """
1255 request = X509Req()
1256 self.assertRaises(TypeError, request.verify)
1257 self.assertRaises(TypeError, request.verify, object())
1258 self.assertRaises(TypeError, request.verify, PKey(), object())
1259
1260
1261 def test_verify_uninitialized_key(self):
1262 """
1263 :py:obj:`X509Req.verify` raises :py:obj:`OpenSSL.crypto.Error` if called
1264 with a :py:obj:`OpenSSL.crypto.PKey` which contains no key data.
1265 """
1266 request = X509Req()
1267 pkey = PKey()
1268 self.assertRaises(Error, request.verify, pkey)
1269
1270
1271 def test_verify_wrong_key(self):
1272 """
1273 :py:obj:`X509Req.verify` raises :py:obj:`OpenSSL.crypto.Error` if called
1274 with a :py:obj:`OpenSSL.crypto.PKey` which does not represent the public
1275 part of the key which signed the request.
1276 """
1277 request = X509Req()
1278 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001279 request.sign(pkey, GOOD_DIGEST)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001280 another_pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
1281 self.assertRaises(Error, request.verify, another_pkey)
1282
1283
1284 def test_verify_success(self):
1285 """
1286 :py:obj:`X509Req.verify` returns :py:obj:`True` if called with a
Alex Gaynor3b0ee972014-11-15 09:17:33 -08001287 :py:obj:`OpenSSL.crypto.PKey` which represents the public part of the key
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001288 which signed the request.
1289 """
1290 request = X509Req()
1291 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001292 request.sign(pkey, GOOD_DIGEST)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001293 self.assertEqual(True, request.verify(pkey))
1294
1295
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001296
Jean-Paul Calderone18808652009-07-05 12:54:05 -04001297class X509Tests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001298 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001299 Tests for :py:obj:`OpenSSL.crypto.X509`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001300 """
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001301 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
Jean-Paul Calderone8114b452008-03-25 15:27:59 -04001302
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001303 extpem = """
1304-----BEGIN CERTIFICATE-----
1305MIIC3jCCAkegAwIBAgIJAJHFjlcCgnQzMA0GCSqGSIb3DQEBBQUAMEcxCzAJBgNV
1306BAYTAlNFMRUwEwYDVQQIEwxXZXN0ZXJib3R0b20xEjAQBgNVBAoTCUNhdGFsb2dp
1307eDENMAsGA1UEAxMEUm9vdDAeFw0wODA0MjIxNDQ1MzhaFw0wOTA0MjIxNDQ1Mzha
1308MFQxCzAJBgNVBAYTAlNFMQswCQYDVQQIEwJXQjEUMBIGA1UEChMLT3Blbk1ldGFk
1309aXIxIjAgBgNVBAMTGW5vZGUxLm9tMi5vcGVubWV0YWRpci5vcmcwgZ8wDQYJKoZI
1310hvcNAQEBBQADgY0AMIGJAoGBAPIcQMrwbk2nESF/0JKibj9i1x95XYAOwP+LarwT
1311Op4EQbdlI9SY+uqYqlERhF19w7CS+S6oyqx0DRZSk4Y9dZ9j9/xgm2u/f136YS1u
1312zgYFPvfUs6PqYLPSM8Bw+SjJ+7+2+TN+Tkiof9WP1cMjodQwOmdsiRbR0/J7+b1B
1313hec1AgMBAAGjgcQwgcEwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNT
1314TCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFIdHsBcMVVMbAO7j6NCj
131503HgLnHaMB8GA1UdIwQYMBaAFL2h9Bf9Mre4vTdOiHTGAt7BRY/8MEYGA1UdEQQ/
1316MD2CDSouZXhhbXBsZS5vcmeCESoub20yLmV4bWFwbGUuY29thwSC7wgKgRNvbTJA
1317b3Blbm1ldGFkaXIub3JnMA0GCSqGSIb3DQEBBQUAA4GBALd7WdXkp2KvZ7/PuWZA
1318MPlIxyjS+Ly11+BNE0xGQRp9Wz+2lABtpgNqssvU156+HkKd02rGheb2tj7MX9hG
1319uZzbwDAZzJPjzDQDD7d3cWsrVcfIdqVU7epHqIadnOF+X0ghJ39pAm6VVadnSXCt
1320WpOdIpB8KksUTCzV591Nr1wd
1321-----END CERTIFICATE-----
1322 """
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001323 def signable(self):
1324 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001325 Create and return a new :py:obj:`X509`.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001326 """
1327 return X509()
1328
1329
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001330 def test_type(self):
1331 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001332 :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 -04001333 to create instances of that type.
1334 """
1335 self.assertIdentical(X509, X509Type)
1336 self.assertConsistentType(X509, 'X509')
1337
1338
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001339 def test_construction(self):
1340 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001341 :py:obj:`X509` takes no arguments and returns an instance of :py:obj:`X509Type`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001342 """
1343 certificate = X509()
1344 self.assertTrue(
1345 isinstance(certificate, X509Type),
1346 "%r is of type %r, should be %r" % (certificate,
1347 type(certificate),
1348 X509Type))
Rick Deane15b1472009-07-09 15:53:42 -05001349 self.assertEqual(type(X509Type).__name__, 'type')
1350 self.assertEqual(type(certificate).__name__, 'X509')
1351 self.assertEqual(type(certificate), X509Type)
Rick Dean04113e72009-07-16 12:06:35 -05001352 self.assertEqual(type(certificate), X509)
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001353
1354
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001355 def test_get_version_wrong_args(self):
1356 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001357 :py:obj:`X509.get_version` raises :py:obj:`TypeError` if invoked with any arguments.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001358 """
1359 cert = X509()
1360 self.assertRaises(TypeError, cert.get_version, None)
1361
1362
1363 def test_set_version_wrong_args(self):
1364 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001365 :py:obj:`X509.set_version` raises :py:obj:`TypeError` if invoked with the wrong number
1366 of arguments or an argument not of type :py:obj:`int`.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001367 """
1368 cert = X509()
1369 self.assertRaises(TypeError, cert.set_version)
1370 self.assertRaises(TypeError, cert.set_version, None)
1371 self.assertRaises(TypeError, cert.set_version, 1, None)
1372
1373
1374 def test_version(self):
1375 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001376 :py:obj:`X509.set_version` sets the certificate version number.
1377 :py:obj:`X509.get_version` retrieves it.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001378 """
1379 cert = X509()
1380 cert.set_version(1234)
1381 self.assertEquals(cert.get_version(), 1234)
1382
1383
1384 def test_get_serial_number_wrong_args(self):
1385 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001386 :py:obj:`X509.get_serial_number` raises :py:obj:`TypeError` if invoked with any
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001387 arguments.
1388 """
1389 cert = X509()
1390 self.assertRaises(TypeError, cert.get_serial_number, None)
1391
1392
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001393 def test_serial_number(self):
1394 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001395 The serial number of an :py:obj:`X509Type` can be retrieved and modified with
1396 :py:obj:`X509Type.get_serial_number` and :py:obj:`X509Type.set_serial_number`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001397 """
1398 certificate = X509()
1399 self.assertRaises(TypeError, certificate.set_serial_number)
1400 self.assertRaises(TypeError, certificate.set_serial_number, 1, 2)
1401 self.assertRaises(TypeError, certificate.set_serial_number, "1")
1402 self.assertRaises(TypeError, certificate.set_serial_number, 5.5)
1403 self.assertEqual(certificate.get_serial_number(), 0)
1404 certificate.set_serial_number(1)
1405 self.assertEqual(certificate.get_serial_number(), 1)
1406 certificate.set_serial_number(2 ** 32 + 1)
1407 self.assertEqual(certificate.get_serial_number(), 2 ** 32 + 1)
1408 certificate.set_serial_number(2 ** 64 + 1)
1409 self.assertEqual(certificate.get_serial_number(), 2 ** 64 + 1)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001410 certificate.set_serial_number(2 ** 128 + 1)
1411 self.assertEqual(certificate.get_serial_number(), 2 ** 128 + 1)
1412
1413
1414 def _setBoundTest(self, which):
1415 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001416 :py:obj:`X509Type.set_notBefore` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001417 GENERALIZEDTIME and sets the beginning of the certificate's validity
1418 period to it.
1419 """
1420 certificate = X509()
1421 set = getattr(certificate, 'set_not' + which)
1422 get = getattr(certificate, 'get_not' + which)
1423
Jean-Paul Calderonee0615b52008-03-09 21:44:46 -04001424 # Starts with no value.
1425 self.assertEqual(get(), None)
1426
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001427 # GMT (Or is it UTC?) -exarkun
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001428 when = b("20040203040506Z")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001429 set(when)
1430 self.assertEqual(get(), when)
1431
1432 # A plus two hours and thirty minutes offset
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001433 when = b("20040203040506+0530")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001434 set(when)
1435 self.assertEqual(get(), when)
1436
1437 # A minus one hour fifteen minutes offset
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001438 when = b("20040203040506-0115")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001439 set(when)
1440 self.assertEqual(get(), when)
1441
1442 # An invalid string results in a ValueError
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001443 self.assertRaises(ValueError, set, b("foo bar"))
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001444
Jean-Paul Calderone31ca2002010-01-30 15:14:43 -05001445 # The wrong number of arguments results in a TypeError.
1446 self.assertRaises(TypeError, set)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001447 self.assertRaises(TypeError, set, b("20040203040506Z"), b("20040203040506Z"))
1448 self.assertRaises(TypeError, get, b("foo bar"))
1449
Jean-Paul Calderone31ca2002010-01-30 15:14:43 -05001450
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001451 # XXX ASN1_TIME (not GENERALIZEDTIME)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001452
1453 def test_set_notBefore(self):
1454 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001455 :py:obj:`X509Type.set_notBefore` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001456 GENERALIZEDTIME and sets the beginning of the certificate's validity
1457 period to it.
1458 """
1459 self._setBoundTest("Before")
1460
1461
1462 def test_set_notAfter(self):
1463 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001464 :py:obj:`X509Type.set_notAfter` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001465 GENERALIZEDTIME and sets the end of the certificate's validity period
1466 to it.
1467 """
1468 self._setBoundTest("After")
Jean-Paul Calderone76576d52008-03-24 16:04:46 -04001469
1470
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001471 def test_get_notBefore(self):
1472 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001473 :py:obj:`X509Type.get_notBefore` returns a string in the format of an ASN1
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001474 GENERALIZEDTIME even for certificates which store it as UTCTIME
1475 internally.
1476 """
Jean-Paul Calderone8114b452008-03-25 15:27:59 -04001477 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001478 self.assertEqual(cert.get_notBefore(), b("20090325123658Z"))
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001479
Rick Dean38a05c82009-07-18 01:41:30 -05001480
1481 def test_get_notAfter(self):
1482 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001483 :py:obj:`X509Type.get_notAfter` returns a string in the format of an ASN1
Rick Dean38a05c82009-07-18 01:41:30 -05001484 GENERALIZEDTIME even for certificates which store it as UTCTIME
1485 internally.
1486 """
1487 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001488 self.assertEqual(cert.get_notAfter(), b("20170611123658Z"))
Rick Dean38a05c82009-07-18 01:41:30 -05001489
1490
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001491 def test_gmtime_adj_notBefore_wrong_args(self):
1492 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001493 :py:obj:`X509Type.gmtime_adj_notBefore` raises :py:obj:`TypeError` if called with the
1494 wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001495 """
1496 cert = X509()
1497 self.assertRaises(TypeError, cert.gmtime_adj_notBefore)
1498 self.assertRaises(TypeError, cert.gmtime_adj_notBefore, None)
1499 self.assertRaises(TypeError, cert.gmtime_adj_notBefore, 123, None)
1500
1501
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001502 def test_gmtime_adj_notBefore(self):
1503 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001504 :py:obj:`X509Type.gmtime_adj_notBefore` changes the not-before timestamp to be
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001505 the current time plus the number of seconds passed in.
1506 """
1507 cert = load_certificate(FILETYPE_PEM, self.pemData)
Maximilian Hilsbed25c92015-07-25 12:58:07 +02001508 not_before_min = datetime.utcnow().replace(microsecond=0) + timedelta(seconds=100)
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001509 cert.gmtime_adj_notBefore(100)
Maximilian Hilsbed25c92015-07-25 12:58:07 +02001510 not_before = datetime.strptime(cert.get_notBefore().decode(), "%Y%m%d%H%M%SZ")
1511 not_before_max = datetime.utcnow() + timedelta(seconds=100)
1512 self.assertTrue(not_before_min <= not_before <= not_before_max)
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001513
1514
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001515 def test_gmtime_adj_notAfter_wrong_args(self):
1516 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001517 :py:obj:`X509Type.gmtime_adj_notAfter` raises :py:obj:`TypeError` if called with the
1518 wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001519 """
1520 cert = X509()
1521 self.assertRaises(TypeError, cert.gmtime_adj_notAfter)
1522 self.assertRaises(TypeError, cert.gmtime_adj_notAfter, None)
1523 self.assertRaises(TypeError, cert.gmtime_adj_notAfter, 123, None)
1524
1525
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001526 def test_gmtime_adj_notAfter(self):
1527 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001528 :py:obj:`X509Type.gmtime_adj_notAfter` changes the not-after timestamp to be
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001529 the current time plus the number of seconds passed in.
1530 """
1531 cert = load_certificate(FILETYPE_PEM, self.pemData)
Maximilian Hilsbed25c92015-07-25 12:58:07 +02001532 not_after_min = datetime.utcnow().replace(microsecond=0) + timedelta(seconds=100)
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001533 cert.gmtime_adj_notAfter(100)
Maximilian Hilsbed25c92015-07-25 12:58:07 +02001534 not_after = datetime.strptime(cert.get_notAfter().decode(), "%Y%m%d%H%M%SZ")
1535 not_after_max = datetime.utcnow() + timedelta(seconds=100)
1536 self.assertTrue(not_after_min <= not_after <= not_after_max)
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001537
1538
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001539 def test_has_expired_wrong_args(self):
1540 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001541 :py:obj:`X509Type.has_expired` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001542 arguments.
1543 """
1544 cert = X509()
1545 self.assertRaises(TypeError, cert.has_expired, None)
1546
1547
1548 def test_has_expired(self):
1549 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001550 :py:obj:`X509Type.has_expired` returns :py:obj:`True` if the certificate's not-after
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001551 time is in the past.
1552 """
1553 cert = X509()
1554 cert.gmtime_adj_notAfter(-1)
1555 self.assertTrue(cert.has_expired())
1556
1557
1558 def test_has_not_expired(self):
1559 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001560 :py:obj:`X509Type.has_expired` returns :py:obj:`False` if the certificate's not-after
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001561 time is in the future.
1562 """
1563 cert = X509()
1564 cert.gmtime_adj_notAfter(2)
1565 self.assertFalse(cert.has_expired())
1566
Jeff Tangfc18f7b2015-04-15 17:42:33 -04001567 def test_root_has_not_expired(self):
1568 """
1569 :py:obj:`X509Type.has_expired` returns :py:obj:`False` if the certificate's not-after
1570 time is in the future.
1571 """
1572 cert = load_certificate(FILETYPE_PEM, root_cert_pem)
1573 self.assertFalse(cert.has_expired())
1574
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001575
Rick Dean38a05c82009-07-18 01:41:30 -05001576 def test_digest(self):
1577 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001578 :py:obj:`X509.digest` returns a string giving ":"-separated hex-encoded words
Rick Dean38a05c82009-07-18 01:41:30 -05001579 of the digest of the certificate.
1580 """
Jeff Tangfc18f7b2015-04-15 17:42:33 -04001581 cert = load_certificate(FILETYPE_PEM, root_cert_pem)
Rick Dean38a05c82009-07-18 01:41:30 -05001582 self.assertEqual(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001583 # This is MD5 instead of GOOD_DIGEST because the digest algorithm
1584 # actually matters to the assertion (ie, another arbitrary, good
1585 # digest will not product the same digest).
Jeff Tangfc18f7b2015-04-15 17:42:33 -04001586 # Digest verified with the command:
1587 # openssl x509 -in root_cert.pem -noout -fingerprint -md5
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001588 cert.digest("MD5"),
Jeff Tangfc18f7b2015-04-15 17:42:33 -04001589 b("19:B3:05:26:2B:F8:F2:FF:0B:8F:21:07:A8:28:B8:75"))
Rick Dean38a05c82009-07-18 01:41:30 -05001590
1591
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001592 def _extcert(self, pkey, extensions):
1593 cert = X509()
1594 cert.set_pubkey(pkey)
1595 cert.get_subject().commonName = "Unit Tests"
1596 cert.get_issuer().commonName = "Unit Tests"
1597 when = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
1598 cert.set_notBefore(when)
1599 cert.set_notAfter(when)
1600
1601 cert.add_extensions(extensions)
Jeff Tangfc18f7b2015-04-15 17:42:33 -04001602 cert.sign(pkey, 'sha1')
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001603 return load_certificate(
1604 FILETYPE_PEM, dump_certificate(FILETYPE_PEM, cert))
1605
1606
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001607 def test_extension_count(self):
1608 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001609 :py:obj:`X509.get_extension_count` returns the number of extensions that are
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001610 present in the certificate.
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001611 """
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001612 pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001613 ca = X509Extension(b('basicConstraints'), True, b('CA:FALSE'))
1614 key = X509Extension(b('keyUsage'), True, b('digitalSignature'))
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001615 subjectAltName = X509Extension(
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001616 b('subjectAltName'), True, b('DNS:example.com'))
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001617
1618 # Try a certificate with no extensions at all.
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001619 c = self._extcert(pkey, [])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001620 self.assertEqual(c.get_extension_count(), 0)
1621
1622 # And a certificate with one
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001623 c = self._extcert(pkey, [ca])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001624 self.assertEqual(c.get_extension_count(), 1)
1625
1626 # And a certificate with several
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001627 c = self._extcert(pkey, [ca, key, subjectAltName])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001628 self.assertEqual(c.get_extension_count(), 3)
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001629
1630
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001631 def test_get_extension(self):
1632 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001633 :py:obj:`X509.get_extension` takes an integer and returns an :py:obj:`X509Extension`
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001634 corresponding to the extension at that index.
1635 """
1636 pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001637 ca = X509Extension(b('basicConstraints'), True, b('CA:FALSE'))
1638 key = X509Extension(b('keyUsage'), True, b('digitalSignature'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001639 subjectAltName = X509Extension(
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001640 b('subjectAltName'), False, b('DNS:example.com'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001641
1642 cert = self._extcert(pkey, [ca, key, subjectAltName])
1643
1644 ext = cert.get_extension(0)
1645 self.assertTrue(isinstance(ext, X509Extension))
1646 self.assertTrue(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001647 self.assertEqual(ext.get_short_name(), b('basicConstraints'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001648
1649 ext = cert.get_extension(1)
1650 self.assertTrue(isinstance(ext, X509Extension))
1651 self.assertTrue(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001652 self.assertEqual(ext.get_short_name(), b('keyUsage'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001653
1654 ext = cert.get_extension(2)
1655 self.assertTrue(isinstance(ext, X509Extension))
1656 self.assertFalse(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001657 self.assertEqual(ext.get_short_name(), b('subjectAltName'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001658
1659 self.assertRaises(IndexError, cert.get_extension, -1)
1660 self.assertRaises(IndexError, cert.get_extension, 4)
1661 self.assertRaises(TypeError, cert.get_extension, "hello")
1662
1663
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001664 def test_nullbyte_subjectAltName(self):
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001665 """
Jean-Paul Calderone9af07b02013-08-23 16:07:31 -04001666 The fields of a `subjectAltName` extension on an X509 may contain NUL
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001667 bytes and this value is reflected in the string representation of the
1668 extension object.
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001669 """
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001670 cert = load_certificate(FILETYPE_PEM, nulbyteSubjectAltNamePEM)
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001671
1672 ext = cert.get_extension(3)
1673 self.assertEqual(ext.get_short_name(), b('subjectAltName'))
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001674 self.assertEqual(
1675 b("DNS:altnull.python.org\x00example.com, "
1676 "email:null@python.org\x00user@example.org, "
1677 "URI:http://null.python.org\x00http://example.org, "
1678 "IP Address:192.0.2.1, IP Address:2001:DB8:0:0:0:0:0:1\n"),
1679 b(str(ext)))
1680
Rick Dean38a05c82009-07-18 01:41:30 -05001681
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001682 def test_invalid_digest_algorithm(self):
1683 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001684 :py:obj:`X509.digest` raises :py:obj:`ValueError` if called with an unrecognized hash
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001685 algorithm.
1686 """
1687 cert = X509()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001688 self.assertRaises(ValueError, cert.digest, BAD_DIGEST)
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001689
1690
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001691 def test_get_subject_wrong_args(self):
1692 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001693 :py:obj:`X509.get_subject` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001694 """
1695 cert = X509()
1696 self.assertRaises(TypeError, cert.get_subject, None)
1697
1698
1699 def test_get_subject(self):
1700 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001701 :py:obj:`X509.get_subject` returns an :py:obj:`X509Name` instance.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001702 """
1703 cert = load_certificate(FILETYPE_PEM, self.pemData)
1704 subj = cert.get_subject()
1705 self.assertTrue(isinstance(subj, X509Name))
1706 self.assertEquals(
1707 subj.get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001708 [(b('C'), b('US')), (b('ST'), b('IL')), (b('L'), b('Chicago')),
1709 (b('O'), b('Testing')), (b('CN'), b('Testing Root CA'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001710
1711
1712 def test_set_subject_wrong_args(self):
1713 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001714 :py:obj:`X509.set_subject` raises a :py:obj:`TypeError` if called with the wrong
1715 number of arguments or an argument not of type :py:obj:`X509Name`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001716 """
1717 cert = X509()
1718 self.assertRaises(TypeError, cert.set_subject)
1719 self.assertRaises(TypeError, cert.set_subject, None)
1720 self.assertRaises(TypeError, cert.set_subject, cert.get_subject(), None)
1721
1722
1723 def test_set_subject(self):
1724 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001725 :py:obj:`X509.set_subject` changes the subject of the certificate to the one
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001726 passed in.
1727 """
1728 cert = X509()
1729 name = cert.get_subject()
1730 name.C = 'AU'
1731 name.O = 'Unit Tests'
1732 cert.set_subject(name)
1733 self.assertEquals(
1734 cert.get_subject().get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001735 [(b('C'), b('AU')), (b('O'), b('Unit Tests'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001736
1737
1738 def test_get_issuer_wrong_args(self):
1739 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001740 :py:obj:`X509.get_issuer` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001741 """
1742 cert = X509()
1743 self.assertRaises(TypeError, cert.get_issuer, None)
1744
1745
1746 def test_get_issuer(self):
1747 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001748 :py:obj:`X509.get_issuer` returns an :py:obj:`X509Name` instance.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001749 """
1750 cert = load_certificate(FILETYPE_PEM, self.pemData)
1751 subj = cert.get_issuer()
1752 self.assertTrue(isinstance(subj, X509Name))
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001753 comp = subj.get_components()
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001754 self.assertEquals(
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001755 comp,
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001756 [(b('C'), b('US')), (b('ST'), b('IL')), (b('L'), b('Chicago')),
1757 (b('O'), b('Testing')), (b('CN'), b('Testing Root CA'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001758
1759
1760 def test_set_issuer_wrong_args(self):
1761 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001762 :py:obj:`X509.set_issuer` raises a :py:obj:`TypeError` if called with the wrong
1763 number of arguments or an argument not of type :py:obj:`X509Name`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001764 """
1765 cert = X509()
1766 self.assertRaises(TypeError, cert.set_issuer)
1767 self.assertRaises(TypeError, cert.set_issuer, None)
1768 self.assertRaises(TypeError, cert.set_issuer, cert.get_issuer(), None)
1769
1770
1771 def test_set_issuer(self):
1772 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001773 :py:obj:`X509.set_issuer` changes the issuer of the certificate to the one
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001774 passed in.
1775 """
1776 cert = X509()
1777 name = cert.get_issuer()
1778 name.C = 'AU'
1779 name.O = 'Unit Tests'
1780 cert.set_issuer(name)
1781 self.assertEquals(
1782 cert.get_issuer().get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001783 [(b('C'), b('AU')), (b('O'), b('Unit Tests'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001784
1785
1786 def test_get_pubkey_uninitialized(self):
1787 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001788 When called on a certificate with no public key, :py:obj:`X509.get_pubkey`
1789 raises :py:obj:`OpenSSL.crypto.Error`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001790 """
1791 cert = X509()
1792 self.assertRaises(Error, cert.get_pubkey)
1793
1794
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001795 def test_subject_name_hash_wrong_args(self):
1796 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001797 :py:obj:`X509.subject_name_hash` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001798 arguments.
1799 """
1800 cert = X509()
1801 self.assertRaises(TypeError, cert.subject_name_hash, None)
1802
1803
1804 def test_subject_name_hash(self):
1805 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001806 :py:obj:`X509.subject_name_hash` returns the hash of the certificate's subject
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001807 name.
1808 """
1809 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -04001810 self.assertIn(
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001811 cert.subject_name_hash(),
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -04001812 [3350047874, # OpenSSL 0.9.8, MD5
1813 3278919224, # OpenSSL 1.0.0, SHA1
1814 ])
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001815
1816
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001817 def test_get_signature_algorithm(self):
1818 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001819 :py:obj:`X509Type.get_signature_algorithm` returns a string which means
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001820 the algorithm used to sign the certificate.
1821 """
1822 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001823 self.assertEqual(
1824 b("sha1WithRSAEncryption"), cert.get_signature_algorithm())
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001825
1826
1827 def test_get_undefined_signature_algorithm(self):
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001828 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001829 :py:obj:`X509Type.get_signature_algorithm` raises :py:obj:`ValueError` if the
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001830 signature algorithm is undefined or unknown.
1831 """
1832 # This certificate has been modified to indicate a bogus OID in the
1833 # signature algorithm field so that OpenSSL does not recognize it.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001834 certPEM = b("""\
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001835-----BEGIN CERTIFICATE-----
1836MIIC/zCCAmigAwIBAgIBATAGBgJ8BQUAMHsxCzAJBgNVBAYTAlNHMREwDwYDVQQK
1837EwhNMkNyeXB0bzEUMBIGA1UECxMLTTJDcnlwdG8gQ0ExJDAiBgNVBAMTG00yQ3J5
1838cHRvIENlcnRpZmljYXRlIE1hc3RlcjEdMBsGCSqGSIb3DQEJARYObmdwc0Bwb3N0
1839MS5jb20wHhcNMDAwOTEwMDk1MTMwWhcNMDIwOTEwMDk1MTMwWjBTMQswCQYDVQQG
1840EwJTRzERMA8GA1UEChMITTJDcnlwdG8xEjAQBgNVBAMTCWxvY2FsaG9zdDEdMBsG
1841CSqGSIb3DQEJARYObmdwc0Bwb3N0MS5jb20wXDANBgkqhkiG9w0BAQEFAANLADBI
1842AkEArL57d26W9fNXvOhNlZzlPOACmvwOZ5AdNgLzJ1/MfsQQJ7hHVeHmTAjM664V
1843+fXvwUGJLziCeBo1ysWLRnl8CQIDAQABo4IBBDCCAQAwCQYDVR0TBAIwADAsBglg
1844hkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0O
1845BBYEFM+EgpK+eyZiwFU1aOPSbczbPSpVMIGlBgNVHSMEgZ0wgZqAFPuHI2nrnDqT
1846FeXFvylRT/7tKDgBoX+kfTB7MQswCQYDVQQGEwJTRzERMA8GA1UEChMITTJDcnlw
1847dG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtNMkNyeXB0byBDZXJ0
1848aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tggEA
1849MA0GCSqGSIb3DQEBBAUAA4GBADv8KpPo+gfJxN2ERK1Y1l17sz/ZhzoGgm5XCdbx
1850jEY7xKfpQngV599k1xhl11IMqizDwu0855agrckg2MCTmOI9DZzDD77tAYb+Dk0O
1851PEVk0Mk/V0aIsDE9bolfCi/i/QWZ3N8s5nTWMNyBBBmoSliWCm4jkkRZRD0ejgTN
1852tgI5
1853-----END CERTIFICATE-----
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001854""")
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001855 cert = load_certificate(FILETYPE_PEM, certPEM)
1856 self.assertRaises(ValueError, cert.get_signature_algorithm)
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001857
1858
Rick Dean38a05c82009-07-18 01:41:30 -05001859
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001860class X509StoreTests(TestCase):
1861 """
1862 Test for :py:obj:`OpenSSL.crypto.X509Store`.
1863 """
1864 def test_type(self):
1865 """
1866 :py:obj:`X509StoreType` is a type object.
1867 """
1868 self.assertIdentical(X509Store, X509StoreType)
1869 self.assertConsistentType(X509Store, 'X509Store')
1870
1871
1872 def test_add_cert_wrong_args(self):
1873 store = X509Store()
1874 self.assertRaises(TypeError, store.add_cert)
1875 self.assertRaises(TypeError, store.add_cert, object())
1876 self.assertRaises(TypeError, store.add_cert, X509(), object())
1877
1878
1879 def test_add_cert(self):
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001880 """
1881 :py:obj:`X509Store.add_cert` adds a :py:obj:`X509` instance to the
1882 certificate store.
1883 """
1884 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001885 store = X509Store()
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001886 store.add_cert(cert)
1887
1888
1889 def test_add_cert_rejects_duplicate(self):
1890 """
1891 :py:obj:`X509Store.add_cert` raises :py:obj:`OpenSSL.crypto.Error` if an
1892 attempt is made to add the same certificate to the store more than once.
1893 """
1894 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
1895 store = X509Store()
1896 store.add_cert(cert)
1897 self.assertRaises(Error, store.add_cert, cert)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001898
1899
1900
Rick Dean623ee362009-07-17 12:22:16 -05001901class PKCS12Tests(TestCase):
1902 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001903 Test for :py:obj:`OpenSSL.crypto.PKCS12` and :py:obj:`OpenSSL.crypto.load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001904 """
1905 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
1906
Jean-Paul Calderonec3a41f72009-07-25 12:36:02 -04001907 def test_type(self):
1908 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001909 :py:obj:`PKCS12Type` is a type object.
Jean-Paul Calderonec3a41f72009-07-25 12:36:02 -04001910 """
1911 self.assertIdentical(PKCS12, PKCS12Type)
1912 self.assertConsistentType(PKCS12, 'PKCS12')
1913
1914
Rick Deanf94096c2009-07-18 14:23:06 -05001915 def test_empty_construction(self):
Rick Dean38a05c82009-07-18 01:41:30 -05001916 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001917 :py:obj:`PKCS12` returns a new instance of :py:obj:`PKCS12` with no certificate,
Jean-Paul Calderonedc857b52009-07-25 12:25:07 -04001918 private key, CA certificates, or friendly name.
Rick Dean38a05c82009-07-18 01:41:30 -05001919 """
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001920 p12 = PKCS12()
Rick Dean623ee362009-07-17 12:22:16 -05001921 self.assertEqual(None, p12.get_certificate())
1922 self.assertEqual(None, p12.get_privatekey())
1923 self.assertEqual(None, p12.get_ca_certificates())
Rick Dean42d69e12009-07-20 11:36:08 -05001924 self.assertEqual(None, p12.get_friendlyname())
Rick Dean623ee362009-07-17 12:22:16 -05001925
Rick Dean38a05c82009-07-18 01:41:30 -05001926
Rick Dean623ee362009-07-17 12:22:16 -05001927 def test_type_errors(self):
Rick Dean38a05c82009-07-18 01:41:30 -05001928 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001929 The :py:obj:`PKCS12` setter functions (:py:obj:`set_certificate`, :py:obj:`set_privatekey`,
1930 :py:obj:`set_ca_certificates`, and :py:obj:`set_friendlyname`) raise :py:obj:`TypeError`
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001931 when passed objects of types other than those expected.
Rick Dean38a05c82009-07-18 01:41:30 -05001932 """
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001933 p12 = PKCS12()
Rick Dean623ee362009-07-17 12:22:16 -05001934 self.assertRaises(TypeError, p12.set_certificate, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05001935 self.assertRaises(TypeError, p12.set_certificate, PKey())
1936 self.assertRaises(TypeError, p12.set_certificate, X509)
Rick Dean623ee362009-07-17 12:22:16 -05001937 self.assertRaises(TypeError, p12.set_privatekey, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05001938 self.assertRaises(TypeError, p12.set_privatekey, 'legbone')
1939 self.assertRaises(TypeError, p12.set_privatekey, X509())
Rick Dean623ee362009-07-17 12:22:16 -05001940 self.assertRaises(TypeError, p12.set_ca_certificates, 3)
1941 self.assertRaises(TypeError, p12.set_ca_certificates, X509())
1942 self.assertRaises(TypeError, p12.set_ca_certificates, (3, 4))
Rick Deanf94096c2009-07-18 14:23:06 -05001943 self.assertRaises(TypeError, p12.set_ca_certificates, ( PKey(), ))
Rick Dean42d69e12009-07-20 11:36:08 -05001944 self.assertRaises(TypeError, p12.set_friendlyname, 6)
1945 self.assertRaises(TypeError, p12.set_friendlyname, ('foo', 'bar'))
Rick Dean623ee362009-07-17 12:22:16 -05001946
Rick Dean38a05c82009-07-18 01:41:30 -05001947
Rick Dean623ee362009-07-17 12:22:16 -05001948 def test_key_only(self):
1949 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001950 A :py:obj:`PKCS12` with only a private key can be exported using
1951 :py:obj:`PKCS12.export` and loaded again using :py:obj:`load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001952 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001953 passwd = b"blah"
Rick Dean623ee362009-07-17 12:22:16 -05001954 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001955 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001956 p12.set_privatekey(pkey)
Rick Dean623ee362009-07-17 12:22:16 -05001957 self.assertEqual(None, p12.get_certificate())
1958 self.assertEqual(pkey, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05001959 try:
1960 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
1961 except Error:
1962 # Some versions of OpenSSL will throw an exception
1963 # for this nearly useless PKCS12 we tried to generate:
1964 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
1965 return
Rick Dean623ee362009-07-17 12:22:16 -05001966 p12 = load_pkcs12(dumped_p12, passwd)
1967 self.assertEqual(None, p12.get_ca_certificates())
1968 self.assertEqual(None, p12.get_certificate())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001969
1970 # OpenSSL fails to bring the key back to us. So sad. Perhaps in the
1971 # future this will be improved.
1972 self.assertTrue(isinstance(p12.get_privatekey(), (PKey, type(None))))
Rick Dean623ee362009-07-17 12:22:16 -05001973
Rick Dean38a05c82009-07-18 01:41:30 -05001974
Rick Dean623ee362009-07-17 12:22:16 -05001975 def test_cert_only(self):
1976 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001977 A :py:obj:`PKCS12` with only a certificate can be exported using
1978 :py:obj:`PKCS12.export` and loaded again using :py:obj:`load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001979 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001980 passwd = b"blah"
Rick Dean623ee362009-07-17 12:22:16 -05001981 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001982 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001983 p12.set_certificate(cert)
Rick Dean623ee362009-07-17 12:22:16 -05001984 self.assertEqual(cert, p12.get_certificate())
1985 self.assertEqual(None, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05001986 try:
1987 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
1988 except Error:
1989 # Some versions of OpenSSL will throw an exception
1990 # for this nearly useless PKCS12 we tried to generate:
1991 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
1992 return
Rick Dean623ee362009-07-17 12:22:16 -05001993 p12 = load_pkcs12(dumped_p12, passwd)
1994 self.assertEqual(None, p12.get_privatekey())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001995
1996 # OpenSSL fails to bring the cert back to us. Groany mcgroan.
1997 self.assertTrue(isinstance(p12.get_certificate(), (X509, type(None))))
1998
1999 # Oh ho. It puts the certificate into the ca certificates list, in
2000 # fact. Totally bogus, I would think. Nevertheless, let's exploit
2001 # that to check to see if it reconstructed the certificate we expected
2002 # it to. At some point, hopefully this will change so that
2003 # p12.get_certificate() is actually what returns the loaded
2004 # certificate.
2005 self.assertEqual(
2006 cleartextCertificatePEM,
2007 dump_certificate(FILETYPE_PEM, p12.get_ca_certificates()[0]))
Rick Dean623ee362009-07-17 12:22:16 -05002008
2009
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002010 def gen_pkcs12(self, cert_pem=None, key_pem=None, ca_pem=None, friendly_name=None):
Rick Dean623ee362009-07-17 12:22:16 -05002011 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002012 Generate a PKCS12 object with components from PEM. Verify that the set
2013 functions return None.
Rick Dean623ee362009-07-17 12:22:16 -05002014 """
Rick Deanf94096c2009-07-18 14:23:06 -05002015 p12 = PKCS12()
2016 if cert_pem:
2017 ret = p12.set_certificate(load_certificate(FILETYPE_PEM, cert_pem))
2018 self.assertEqual(ret, None)
2019 if key_pem:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002020 ret = p12.set_privatekey(load_privatekey(FILETYPE_PEM, key_pem))
Rick Deanf94096c2009-07-18 14:23:06 -05002021 self.assertEqual(ret, None)
2022 if ca_pem:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002023 ret = p12.set_ca_certificates((load_certificate(FILETYPE_PEM, ca_pem),))
Rick Deanf94096c2009-07-18 14:23:06 -05002024 self.assertEqual(ret, None)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002025 if friendly_name:
2026 ret = p12.set_friendlyname(friendly_name)
Rick Dean42d69e12009-07-20 11:36:08 -05002027 self.assertEqual(ret, None)
Rick Deanf94096c2009-07-18 14:23:06 -05002028 return p12
2029
2030
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002031 def check_recovery(self, p12_str, key=None, cert=None, ca=None, passwd=b"",
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002032 extra=()):
Rick Deanf94096c2009-07-18 14:23:06 -05002033 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002034 Use openssl program to confirm three components are recoverable from a
2035 PKCS12 string.
Rick Deanf94096c2009-07-18 14:23:06 -05002036 """
2037 if key:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002038 recovered_key = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002039 p12_str, b"pkcs12", b"-nocerts", b"-nodes", b"-passin",
2040 b"pass:" + passwd, *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05002041 self.assertEqual(recovered_key[-len(key):], key)
2042 if cert:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002043 recovered_cert = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002044 p12_str, b"pkcs12", b"-clcerts", b"-nodes", b"-passin",
2045 b"pass:" + passwd, b"-nokeys", *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05002046 self.assertEqual(recovered_cert[-len(cert):], cert)
2047 if ca:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002048 recovered_cert = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002049 p12_str, b"pkcs12", b"-cacerts", b"-nodes", b"-passin",
2050 b"pass:" + passwd, b"-nokeys", *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05002051 self.assertEqual(recovered_cert[-len(ca):], ca)
2052
2053
Stephen Holsapple38482622014-04-05 20:29:34 -07002054 def verify_pkcs12_container(self, p12):
2055 """
2056 Verify that the PKCS#12 container contains the correct client
2057 certificate and private key.
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002058
2059 :param p12: The PKCS12 instance to verify.
2060 :type p12: :py:class:`PKCS12`
Stephen Holsapple38482622014-04-05 20:29:34 -07002061 """
2062 cert_pem = dump_certificate(FILETYPE_PEM, p12.get_certificate())
2063 key_pem = dump_privatekey(FILETYPE_PEM, p12.get_privatekey())
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002064 self.assertEqual(
2065 (client_cert_pem, client_key_pem, None),
2066 (cert_pem, key_pem, p12.get_ca_certificates()))
Stephen Holsapple38482622014-04-05 20:29:34 -07002067
2068
Rick Deanf94096c2009-07-18 14:23:06 -05002069 def test_load_pkcs12(self):
2070 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002071 A PKCS12 string generated using the openssl command line can be loaded
Jonathan Ballet648875f2011-07-16 14:14:58 +09002072 with :py:obj:`load_pkcs12` and its components extracted and examined.
Rick Deanf94096c2009-07-18 14:23:06 -05002073 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002074 passwd = b"whatever"
Rick Dean623ee362009-07-17 12:22:16 -05002075 pem = client_key_pem + client_cert_pem
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002076 p12_str = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002077 pem, b"pkcs12", b"-export", b"-clcerts", b"-passout", b"pass:" + passwd)
Stephen Holsapple38482622014-04-05 20:29:34 -07002078 p12 = load_pkcs12(p12_str, passphrase=passwd)
2079 self.verify_pkcs12_container(p12)
2080
2081
Abraham Martinc5484ba2015-03-25 15:33:05 +00002082 def test_load_pkcs12_text_passphrase(self):
2083 """
2084 A PKCS12 string generated using the openssl command line can be loaded
2085 with :py:obj:`load_pkcs12` and its components extracted and examined.
2086 Using text as passphrase instead of bytes. DeprecationWarning expected.
2087 """
2088 pem = client_key_pem + client_cert_pem
2089 passwd = b"whatever"
2090 p12_str = _runopenssl(pem, b"pkcs12", b"-export", b"-clcerts",
2091 b"-passout", b"pass:" + passwd)
2092 with catch_warnings(record=True) as w:
2093 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002094 p12 = load_pkcs12(p12_str, passphrase=b"whatever".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002095
2096 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002097 "{0} for passphrase is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002098 WARNING_TYPE_EXPECTED
2099 ),
2100 str(w[-1].message)
2101 )
2102 self.assertIs(w[-1].category, DeprecationWarning)
2103
Abraham Martinc5484ba2015-03-25 15:33:05 +00002104 self.verify_pkcs12_container(p12)
2105
2106
Stephen Holsapple38482622014-04-05 20:29:34 -07002107 def test_load_pkcs12_no_passphrase(self):
2108 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002109 A PKCS12 string generated using openssl command line can be loaded with
2110 :py:obj:`load_pkcs12` without a passphrase and its components extracted
2111 and examined.
Stephen Holsapple38482622014-04-05 20:29:34 -07002112 """
2113 pem = client_key_pem + client_cert_pem
2114 p12_str = _runopenssl(
2115 pem, b"pkcs12", b"-export", b"-clcerts", b"-passout", b"pass:")
2116 p12 = load_pkcs12(p12_str)
2117 self.verify_pkcs12_container(p12)
2118
2119
2120 def _dump_and_load(self, dump_passphrase, load_passphrase):
2121 """
2122 A helper method to dump and load a PKCS12 object.
2123 """
2124 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem)
2125 dumped_p12 = p12.export(passphrase=dump_passphrase, iter=2, maciter=3)
2126 return load_pkcs12(dumped_p12, passphrase=load_passphrase)
2127
2128
2129 def test_load_pkcs12_null_passphrase_load_empty(self):
2130 """
2131 A PKCS12 string can be dumped with a null passphrase, loaded with an
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002132 empty passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002133 extracted and examined.
2134 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002135 self.verify_pkcs12_container(
2136 self._dump_and_load(dump_passphrase=None, load_passphrase=b''))
Stephen Holsapple38482622014-04-05 20:29:34 -07002137
2138
2139 def test_load_pkcs12_null_passphrase_load_null(self):
2140 """
2141 A PKCS12 string can be dumped with a null passphrase, loaded with a
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002142 null passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002143 extracted and examined.
2144 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002145 self.verify_pkcs12_container(
2146 self._dump_and_load(dump_passphrase=None, load_passphrase=None))
Stephen Holsapple38482622014-04-05 20:29:34 -07002147
2148
2149 def test_load_pkcs12_empty_passphrase_load_empty(self):
2150 """
2151 A PKCS12 string can be dumped with an empty passphrase, loaded with an
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002152 empty passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002153 extracted and examined.
2154 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002155 self.verify_pkcs12_container(
2156 self._dump_and_load(dump_passphrase=b'', load_passphrase=b''))
Stephen Holsapple38482622014-04-05 20:29:34 -07002157
2158
2159 def test_load_pkcs12_empty_passphrase_load_null(self):
2160 """
2161 A PKCS12 string can be dumped with an empty passphrase, loaded with a
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002162 null passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002163 extracted and examined.
2164 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002165 self.verify_pkcs12_container(
2166 self._dump_and_load(dump_passphrase=b'', load_passphrase=None))
Rick Deanf94096c2009-07-18 14:23:06 -05002167
Rick Deanee568302009-07-24 09:56:29 -05002168
2169 def test_load_pkcs12_garbage(self):
2170 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002171 :py:obj:`load_pkcs12` raises :py:obj:`OpenSSL.crypto.Error` when passed a string
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002172 which is not a PKCS12 dump.
Rick Deanee568302009-07-24 09:56:29 -05002173 """
2174 passwd = 'whatever'
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002175 e = self.assertRaises(Error, load_pkcs12, b'fruit loops', passwd)
Jean-Paul Calderonede075462014-01-18 10:34:12 -05002176 self.assertEqual( e.args[0][0][0], 'asn1 encoding routines')
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -04002177 self.assertEqual( len(e.args[0][0]), 3)
Rick Deanee568302009-07-24 09:56:29 -05002178
2179
Rick Deanf94096c2009-07-18 14:23:06 -05002180 def test_replace(self):
2181 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002182 :py:obj:`PKCS12.set_certificate` replaces the certificate in a PKCS12 cluster.
2183 :py:obj:`PKCS12.set_privatekey` replaces the private key.
2184 :py:obj:`PKCS12.set_ca_certificates` replaces the CA certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05002185 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002186 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
2187 p12.set_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2188 p12.set_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002189 root_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05002190 client_cert = load_certificate(FILETYPE_PEM, client_cert_pem)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002191 p12.set_ca_certificates([root_cert]) # not a tuple
Rick Dean623ee362009-07-17 12:22:16 -05002192 self.assertEqual(1, len(p12.get_ca_certificates()))
2193 self.assertEqual(root_cert, p12.get_ca_certificates()[0])
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002194 p12.set_ca_certificates([client_cert, root_cert])
Rick Deanf94096c2009-07-18 14:23:06 -05002195 self.assertEqual(2, len(p12.get_ca_certificates()))
2196 self.assertEqual(client_cert, p12.get_ca_certificates()[0])
2197 self.assertEqual(root_cert, p12.get_ca_certificates()[1])
2198
2199
2200 def test_friendly_name(self):
2201 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002202 The *friendlyName* of a PKCS12 can be set and retrieved via
Jonathan Ballet648875f2011-07-16 14:14:58 +09002203 :py:obj:`PKCS12.get_friendlyname` and :py:obj:`PKCS12_set_friendlyname`, and a
2204 :py:obj:`PKCS12` with a friendly name set can be dumped with :py:obj:`PKCS12.export`.
Rick Deanf94096c2009-07-18 14:23:06 -05002205 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002206 passwd = b'Dogmeat[]{}!@#$%^&*()~`?/.,<>-_+=";:'
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002207 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -04002208 for friendly_name in [b('Serverlicious'), None, b('###')]:
Rick Dean42d69e12009-07-20 11:36:08 -05002209 p12.set_friendlyname(friendly_name)
2210 self.assertEqual(p12.get_friendlyname(), friendly_name)
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002211 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
Rick Dean42d69e12009-07-20 11:36:08 -05002212 reloaded_p12 = load_pkcs12(dumped_p12, passwd)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002213 self.assertEqual(
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -04002214 p12.get_friendlyname(), reloaded_p12.get_friendlyname())
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002215 # We would use the openssl program to confirm the friendly
2216 # name, but it is not possible. The pkcs12 command
2217 # does not store the friendly name in the cert's
Rick Dean42d69e12009-07-20 11:36:08 -05002218 # alias, which we could then extract.
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002219 self.check_recovery(
2220 dumped_p12, key=server_key_pem, cert=server_cert_pem,
2221 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05002222
2223
2224 def test_various_empty_passphrases(self):
2225 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002226 Test that missing, None, and '' passphrases are identical for PKCS12
2227 export.
Rick Deanf94096c2009-07-18 14:23:06 -05002228 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002229 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002230 passwd = b""
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002231 dumped_p12_empty = p12.export(iter=2, maciter=0, passphrase=passwd)
2232 dumped_p12_none = p12.export(iter=3, maciter=2, passphrase=None)
2233 dumped_p12_nopw = p12.export(iter=9, maciter=4)
2234 for dumped_p12 in [dumped_p12_empty, dumped_p12_none, dumped_p12_nopw]:
2235 self.check_recovery(
2236 dumped_p12, key=client_key_pem, cert=client_cert_pem,
2237 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05002238
2239
2240 def test_removing_ca_cert(self):
2241 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002242 Passing :py:obj:`None` to :py:obj:`PKCS12.set_ca_certificates` removes all CA
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002243 certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05002244 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002245 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
2246 p12.set_ca_certificates(None)
Rick Dean623ee362009-07-17 12:22:16 -05002247 self.assertEqual(None, p12.get_ca_certificates())
Rick Deanf94096c2009-07-18 14:23:06 -05002248
2249
2250 def test_export_without_mac(self):
2251 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002252 Exporting a PKCS12 with a :py:obj:`maciter` of ``-1`` excludes the MAC
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002253 entirely.
Rick Deanf94096c2009-07-18 14:23:06 -05002254 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002255 passwd = b"Lake Michigan"
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002256 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Dean623ee362009-07-17 12:22:16 -05002257 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002258 self.check_recovery(
2259 dumped_p12, key=server_key_pem, cert=server_cert_pem,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002260 passwd=passwd, extra=(b"-nomacver",))
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002261
2262
2263 def test_load_without_mac(self):
2264 """
2265 Loading a PKCS12 without a MAC does something other than crash.
2266 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002267 passwd = b"Lake Michigan"
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002268 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
2269 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Rick Dean321a0512009-08-13 17:21:29 -05002270 try:
2271 recovered_p12 = load_pkcs12(dumped_p12, passwd)
2272 # The person who generated this PCKS12 should be flogged,
2273 # or better yet we should have a means to determine
2274 # whether a PCKS12 had a MAC that was verified.
2275 # Anyway, libopenssl chooses to allow it, so the
2276 # pyopenssl binding does as well.
2277 self.assertTrue(isinstance(recovered_p12, PKCS12))
2278 except Error:
2279 # Failing here with an exception is preferred as some openssl
2280 # versions do.
2281 pass
Rick Dean623ee362009-07-17 12:22:16 -05002282
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002283
Rick Dean25bcc1f2009-07-20 11:53:13 -05002284 def test_zero_len_list_for_ca(self):
2285 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002286 A PKCS12 with an empty CA certificates list can be exported.
Rick Dean25bcc1f2009-07-20 11:53:13 -05002287 """
2288 passwd = 'Hobie 18'
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002289 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002290 # p12.set_ca_certificates([])
2291 # self.assertEqual((), p12.get_ca_certificates())
2292 # dumped_p12 = p12.export(passphrase=passwd, iter=3)
2293 # self.check_recovery(
2294 # dumped_p12, key=server_key_pem, cert=server_cert_pem,
2295 # passwd=passwd)
Rick Dean25bcc1f2009-07-20 11:53:13 -05002296
2297
Rick Deanf94096c2009-07-18 14:23:06 -05002298 def test_export_without_args(self):
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002299 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002300 All the arguments to :py:obj:`PKCS12.export` are optional.
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002301 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002302 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05002303 dumped_p12 = p12.export() # no args
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002304 self.check_recovery(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002305 dumped_p12, key=server_key_pem, cert=server_cert_pem, passwd=b"")
Rick Deanf94096c2009-07-18 14:23:06 -05002306
2307
Abraham Martinc5484ba2015-03-25 15:33:05 +00002308 def test_export_without_bytes(self):
2309 """
2310 Test :py:obj:`PKCS12.export` with text not bytes as passphrase
2311 """
2312 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
2313
2314 with catch_warnings(record=True) as w:
2315 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002316 dumped_p12 = p12.export(passphrase=b"randomtext".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002317 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002318 "{0} for passphrase is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002319 WARNING_TYPE_EXPECTED
2320 ),
2321 str(w[-1].message)
2322 )
2323 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinc5484ba2015-03-25 15:33:05 +00002324 self.check_recovery(
2325 dumped_p12, key=server_key_pem, cert=server_cert_pem, passwd=b"randomtext")
2326
2327
Rick Deanf94096c2009-07-18 14:23:06 -05002328 def test_key_cert_mismatch(self):
2329 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002330 :py:obj:`PKCS12.export` raises an exception when a key and certificate
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002331 mismatch.
Rick Deanf94096c2009-07-18 14:23:06 -05002332 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002333 p12 = self.gen_pkcs12(server_cert_pem, client_key_pem, root_cert_pem)
2334 self.assertRaises(Error, p12.export)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002335
2336
2337
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002338# These quoting functions taken directly from Twisted's twisted.python.win32.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002339_cmdLineQuoteRe = re.compile(br'(\\*)"')
2340_cmdLineQuoteRe2 = re.compile(br'(\\+)\Z')
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002341def cmdLineQuote(s):
2342 """
2343 Internal method for quoting a single command-line argument.
2344
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002345 See http://www.perlmonks.org/?node_id=764004
2346
Jonathan Ballet648875f2011-07-16 14:14:58 +09002347 :type: :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002348 :param s: A single unquoted string to quote for something that is expecting
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002349 cmd.exe-style quoting
2350
Jonathan Ballet648875f2011-07-16 14:14:58 +09002351 :rtype: :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002352 :return: A cmd.exe-style quoted string
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002353 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002354 s = _cmdLineQuoteRe2.sub(br"\1\1", _cmdLineQuoteRe.sub(br'\1\1\\"', s))
2355 return b'"' + s + b'"'
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002356
2357
2358
2359def quoteArguments(arguments):
2360 """
2361 Quote an iterable of command-line arguments for passing to CreateProcess or
Jonathan Ballet648875f2011-07-16 14:14:58 +09002362 a similar API. This allows the list passed to :py:obj:`reactor.spawnProcess` to
2363 match the child process's :py:obj:`sys.argv` properly.
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002364
Jonathan Ballet648875f2011-07-16 14:14:58 +09002365 :type arguments: :py:obj:`iterable` of :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002366 :param arguments: An iterable of unquoted arguments to quote
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002367
Jonathan Ballet648875f2011-07-16 14:14:58 +09002368 :rtype: :py:obj:`str`
2369 :return: A space-delimited string containing quoted versions of :py:obj:`arguments`
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002370 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002371 return b' '.join(map(cmdLineQuote, arguments))
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002372
2373
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002374
Rick Dean4c9ad612009-07-17 15:05:22 -05002375def _runopenssl(pem, *args):
2376 """
2377 Run the command line openssl tool with the given arguments and write
Rick Dean55d1ce62009-08-13 17:40:24 -05002378 the given PEM to its stdin. Not safe for quotes.
Rick Dean4c9ad612009-07-17 15:05:22 -05002379 """
Jean-Paul Calderone038de952009-08-21 12:16:06 -04002380 if os.name == 'posix':
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002381 command = b"openssl " + b" ".join([
2382 (b"'" + arg.replace(b"'", b"'\\''") + b"'")
2383 for arg in args])
Rick Dean55d1ce62009-08-13 17:40:24 -05002384 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002385 command = b"openssl " + quoteArguments(args)
2386 proc = Popen(native(command), shell=True, stdin=PIPE, stdout=PIPE)
Jean-Paul Calderone62ca8da2010-08-11 19:58:08 -04002387 proc.stdin.write(pem)
2388 proc.stdin.close()
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002389 output = proc.stdout.read()
2390 proc.stdout.close()
2391 proc.wait()
2392 return output
Rick Dean4c9ad612009-07-17 15:05:22 -05002393
2394
2395
Jean-Paul Calderone18808652009-07-05 12:54:05 -04002396class FunctionTests(TestCase):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002397 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002398 Tests for free-functions in the :py:obj:`OpenSSL.crypto` module.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002399 """
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002400
2401 def test_load_privatekey_invalid_format(self):
2402 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002403 :py:obj:`load_privatekey` raises :py:obj:`ValueError` if passed an unknown filetype.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002404 """
2405 self.assertRaises(ValueError, load_privatekey, 100, root_key_pem)
2406
2407
2408 def test_load_privatekey_invalid_passphrase_type(self):
2409 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002410 :py:obj:`load_privatekey` raises :py:obj:`TypeError` if passed a passphrase that is
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002411 neither a :py:obj:`str` nor a callable.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002412 """
2413 self.assertRaises(
2414 TypeError,
2415 load_privatekey,
2416 FILETYPE_PEM, encryptedPrivateKeyPEMPassphrase, object())
2417
2418
2419 def test_load_privatekey_wrong_args(self):
2420 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002421 :py:obj:`load_privatekey` raises :py:obj:`TypeError` if called with the wrong number
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002422 of arguments.
2423 """
2424 self.assertRaises(TypeError, load_privatekey)
2425
2426
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002427 def test_load_privatekey_wrongPassphrase(self):
2428 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002429 :py:obj:`load_privatekey` raises :py:obj:`OpenSSL.crypto.Error` when it is passed an
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002430 encrypted PEM and an incorrect passphrase.
2431 """
2432 self.assertRaises(
2433 Error,
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002434 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, b("quack"))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002435
2436
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002437 def test_load_privatekey_passphraseWrongType(self):
2438 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002439 :py:obj:`load_privatekey` raises :py:obj:`ValueError` when it is passed a passphrase
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002440 with a private key encoded in a format, that doesn't support
2441 encryption.
2442 """
2443 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2444 blob = dump_privatekey(FILETYPE_ASN1, key)
2445 self.assertRaises(ValueError,
2446 load_privatekey, FILETYPE_ASN1, blob, "secret")
2447
2448
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002449 def test_load_privatekey_passphrase(self):
2450 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002451 :py:obj:`load_privatekey` can create a :py:obj:`PKey` object from an encrypted PEM
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002452 string if given the passphrase.
2453 """
2454 key = load_privatekey(
2455 FILETYPE_PEM, encryptedPrivateKeyPEM,
2456 encryptedPrivateKeyPEMPassphrase)
2457 self.assertTrue(isinstance(key, PKeyType))
2458
2459
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002460 def test_load_privatekey_passphrase_exception(self):
2461 """
2462 If the passphrase callback raises an exception, that exception is raised
2463 by :py:obj:`load_privatekey`.
2464 """
2465 def cb(ignored):
2466 raise ArithmeticError
2467
2468 self.assertRaises(ArithmeticError,
2469 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2470
2471
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002472 def test_load_privatekey_wrongPassphraseCallback(self):
2473 """
Jean-Paul Calderoned440a082011-09-14 11:02:05 -04002474 :py:obj:`load_privatekey` raises :py:obj:`OpenSSL.crypto.Error` when it
2475 is passed an encrypted PEM and a passphrase callback which returns an
2476 incorrect passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002477 """
2478 called = []
2479 def cb(*a):
2480 called.append(None)
Jean-Paul Calderoned440a082011-09-14 11:02:05 -04002481 return b("quack")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002482 self.assertRaises(
2483 Error,
2484 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2485 self.assertTrue(called)
2486
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002487
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002488 def test_load_privatekey_passphraseCallback(self):
2489 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002490 :py:obj:`load_privatekey` can create a :py:obj:`PKey` object from an encrypted PEM
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002491 string if given a passphrase callback which returns the correct
2492 password.
2493 """
2494 called = []
2495 def cb(writing):
2496 called.append(writing)
2497 return encryptedPrivateKeyPEMPassphrase
2498 key = load_privatekey(FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2499 self.assertTrue(isinstance(key, PKeyType))
2500 self.assertEqual(called, [False])
2501
2502
Jean-Paul Calderone105cb952011-09-14 10:16:46 -04002503 def test_load_privatekey_passphrase_wrong_return_type(self):
2504 """
2505 :py:obj:`load_privatekey` raises :py:obj:`ValueError` if the passphrase
2506 callback returns something other than a byte string.
2507 """
2508 self.assertRaises(
2509 ValueError,
2510 load_privatekey,
2511 FILETYPE_PEM, encryptedPrivateKeyPEM, lambda *args: 3)
2512
2513
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002514 def test_dump_privatekey_wrong_args(self):
2515 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002516 :py:obj:`dump_privatekey` raises :py:obj:`TypeError` if called with the wrong number
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002517 of arguments.
2518 """
2519 self.assertRaises(TypeError, dump_privatekey)
Jean-Paul Calderone1eeccd82011-09-14 10:18:52 -04002520 # If cipher name is given, password is required.
2521 self.assertRaises(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002522 TypeError, dump_privatekey, FILETYPE_PEM, PKey(), GOOD_CIPHER)
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002523
2524
2525 def test_dump_privatekey_unknown_cipher(self):
2526 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002527 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` if called with an unrecognized
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002528 cipher name.
2529 """
2530 key = PKey()
2531 key.generate_key(TYPE_RSA, 512)
2532 self.assertRaises(
2533 ValueError, dump_privatekey,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002534 FILETYPE_PEM, key, BAD_CIPHER, "passphrase")
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002535
2536
2537 def test_dump_privatekey_invalid_passphrase_type(self):
2538 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002539 :py:obj:`dump_privatekey` raises :py:obj:`TypeError` if called with a passphrase which
2540 is neither a :py:obj:`str` nor a callable.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002541 """
2542 key = PKey()
2543 key.generate_key(TYPE_RSA, 512)
2544 self.assertRaises(
2545 TypeError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002546 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, object())
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002547
2548
2549 def test_dump_privatekey_invalid_filetype(self):
2550 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002551 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` if called with an unrecognized
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002552 filetype.
2553 """
2554 key = PKey()
2555 key.generate_key(TYPE_RSA, 512)
2556 self.assertRaises(ValueError, dump_privatekey, 100, key)
2557
2558
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002559 def test_load_privatekey_passphraseCallbackLength(self):
2560 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002561 :py:obj:`crypto.load_privatekey` should raise an error when the passphrase
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002562 provided by the callback is too long, not silently truncate it.
2563 """
2564 def cb(ignored):
2565 return "a" * 1025
2566
2567 self.assertRaises(ValueError,
2568 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2569
2570
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002571 def test_dump_privatekey_passphrase(self):
2572 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002573 :py:obj:`dump_privatekey` writes an encrypted PEM when given a passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002574 """
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002575 passphrase = b("foo")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002576 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002577 pem = dump_privatekey(FILETYPE_PEM, key, GOOD_CIPHER, passphrase)
2578 self.assertTrue(isinstance(pem, binary_type))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002579 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
2580 self.assertTrue(isinstance(loadedKey, PKeyType))
2581 self.assertEqual(loadedKey.type(), key.type())
2582 self.assertEqual(loadedKey.bits(), key.bits())
2583
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002584
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002585 def test_dump_privatekey_passphraseWrongType(self):
2586 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002587 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` when it is passed a passphrase
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002588 with a private key encoded in a format, that doesn't support
2589 encryption.
2590 """
2591 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2592 self.assertRaises(ValueError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002593 dump_privatekey, FILETYPE_ASN1, key, GOOD_CIPHER, "secret")
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002594
2595
Rick Dean5b7b6372009-04-01 11:34:06 -05002596 def test_dump_certificate(self):
2597 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002598 :py:obj:`dump_certificate` writes PEM, DER, and text.
Rick Dean5b7b6372009-04-01 11:34:06 -05002599 """
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002600 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
Rick Dean5b7b6372009-04-01 11:34:06 -05002601 cert = load_certificate(FILETYPE_PEM, pemData)
2602 dumped_pem = dump_certificate(FILETYPE_PEM, cert)
2603 self.assertEqual(dumped_pem, cleartextCertificatePEM)
2604 dumped_der = dump_certificate(FILETYPE_ASN1, cert)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002605 good_der = _runopenssl(dumped_pem, b"x509", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002606 self.assertEqual(dumped_der, good_der)
2607 cert2 = load_certificate(FILETYPE_ASN1, dumped_der)
2608 dumped_pem2 = dump_certificate(FILETYPE_PEM, cert2)
2609 self.assertEqual(dumped_pem2, cleartextCertificatePEM)
2610 dumped_text = dump_certificate(FILETYPE_TEXT, cert)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002611 good_text = _runopenssl(dumped_pem, b"x509", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002612 self.assertEqual(dumped_text, good_text)
2613
2614
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002615 def test_dump_privatekey_pem(self):
Rick Dean5b7b6372009-04-01 11:34:06 -05002616 """
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002617 :py:obj:`dump_privatekey` writes a PEM
Rick Dean5b7b6372009-04-01 11:34:06 -05002618 """
2619 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -04002620 self.assertTrue(key.check())
Rick Dean5b7b6372009-04-01 11:34:06 -05002621 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2622 self.assertEqual(dumped_pem, cleartextPrivateKeyPEM)
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002623
2624
2625 def test_dump_privatekey_asn1(self):
2626 """
2627 :py:obj:`dump_privatekey` writes a DER
2628 """
2629 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2630 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2631
Rick Dean5b7b6372009-04-01 11:34:06 -05002632 dumped_der = dump_privatekey(FILETYPE_ASN1, key)
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002633 # XXX This OpenSSL call writes "writing RSA key" to standard out. Sad.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002634 good_der = _runopenssl(dumped_pem, b"rsa", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002635 self.assertEqual(dumped_der, good_der)
2636 key2 = load_privatekey(FILETYPE_ASN1, dumped_der)
2637 dumped_pem2 = dump_privatekey(FILETYPE_PEM, key2)
2638 self.assertEqual(dumped_pem2, cleartextPrivateKeyPEM)
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002639
2640
2641 def test_dump_privatekey_text(self):
2642 """
2643 :py:obj:`dump_privatekey` writes a text
2644 """
2645 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2646 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2647
Rick Dean5b7b6372009-04-01 11:34:06 -05002648 dumped_text = dump_privatekey(FILETYPE_TEXT, key)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002649 good_text = _runopenssl(dumped_pem, b"rsa", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002650 self.assertEqual(dumped_text, good_text)
2651
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002652
Rick Dean5b7b6372009-04-01 11:34:06 -05002653 def test_dump_certificate_request(self):
2654 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002655 :py:obj:`dump_certificate_request` writes a PEM, DER, and text.
Rick Dean5b7b6372009-04-01 11:34:06 -05002656 """
2657 req = load_certificate_request(FILETYPE_PEM, cleartextCertificateRequestPEM)
2658 dumped_pem = dump_certificate_request(FILETYPE_PEM, req)
2659 self.assertEqual(dumped_pem, cleartextCertificateRequestPEM)
2660 dumped_der = dump_certificate_request(FILETYPE_ASN1, req)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002661 good_der = _runopenssl(dumped_pem, b"req", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002662 self.assertEqual(dumped_der, good_der)
2663 req2 = load_certificate_request(FILETYPE_ASN1, dumped_der)
2664 dumped_pem2 = dump_certificate_request(FILETYPE_PEM, req2)
2665 self.assertEqual(dumped_pem2, cleartextCertificateRequestPEM)
2666 dumped_text = dump_certificate_request(FILETYPE_TEXT, req)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002667 good_text = _runopenssl(dumped_pem, b"req", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002668 self.assertEqual(dumped_text, good_text)
Jean-Paul Calderoneaf43cdf2010-08-03 18:40:52 -04002669 self.assertRaises(ValueError, dump_certificate_request, 100, req)
Rick Dean5b7b6372009-04-01 11:34:06 -05002670
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002671
2672 def test_dump_privatekey_passphraseCallback(self):
2673 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002674 :py:obj:`dump_privatekey` writes an encrypted PEM when given a callback which
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002675 returns the correct passphrase.
2676 """
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002677 passphrase = b("foo")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002678 called = []
2679 def cb(writing):
2680 called.append(writing)
2681 return passphrase
2682 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002683 pem = dump_privatekey(FILETYPE_PEM, key, GOOD_CIPHER, cb)
2684 self.assertTrue(isinstance(pem, binary_type))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002685 self.assertEqual(called, [True])
2686 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
2687 self.assertTrue(isinstance(loadedKey, PKeyType))
2688 self.assertEqual(loadedKey.type(), key.type())
2689 self.assertEqual(loadedKey.bits(), key.bits())
Rick Dean5b7b6372009-04-01 11:34:06 -05002690
2691
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002692 def test_dump_privatekey_passphrase_exception(self):
2693 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002694 :py:obj:`dump_privatekey` should not overwrite the exception raised
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002695 by the passphrase callback.
2696 """
2697 def cb(ignored):
2698 raise ArithmeticError
2699
2700 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2701 self.assertRaises(ArithmeticError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002702 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, cb)
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002703
2704
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002705 def test_dump_privatekey_passphraseCallbackLength(self):
2706 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002707 :py:obj:`crypto.dump_privatekey` should raise an error when the passphrase
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002708 provided by the callback is too long, not silently truncate it.
2709 """
2710 def cb(ignored):
2711 return "a" * 1025
2712
2713 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2714 self.assertRaises(ValueError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002715 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, cb)
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002716
2717
Alex Gaynor4b9c96a2014-08-14 09:51:48 -07002718 def test_load_pkcs7_data_pem(self):
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002719 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002720 :py:obj:`load_pkcs7_data` accepts a PKCS#7 string and returns an instance of
2721 :py:obj:`PKCS7Type`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002722 """
2723 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2724 self.assertTrue(isinstance(pkcs7, PKCS7Type))
2725
2726
Alex Gaynor4b9c96a2014-08-14 09:51:48 -07002727 def test_load_pkcs7_data_asn1(self):
Alex Gaynor9875a912014-08-14 13:35:05 -07002728 """
2729 :py:obj:`load_pkcs7_data` accepts a bytes containing ASN1 data
2730 representing PKCS#7 and returns an instance of :py:obj`PKCS7Type`.
2731 """
Alex Gaynor4b9c96a2014-08-14 09:51:48 -07002732 pkcs7 = load_pkcs7_data(FILETYPE_ASN1, pkcs7DataASN1)
2733 self.assertTrue(isinstance(pkcs7, PKCS7Type))
2734
2735
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002736 def test_load_pkcs7_data_invalid(self):
2737 """
2738 If the data passed to :py:obj:`load_pkcs7_data` is invalid,
2739 :py:obj:`Error` is raised.
2740 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002741 self.assertRaises(Error, load_pkcs7_data, FILETYPE_PEM, b"foo")
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002742
2743
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002744
Jean-Paul Calderone4a68b402013-12-29 16:54:58 -05002745class LoadCertificateTests(TestCase):
2746 """
2747 Tests for :py:obj:`load_certificate_request`.
2748 """
2749 def test_badFileType(self):
2750 """
2751 If the file type passed to :py:obj:`load_certificate_request` is
2752 neither :py:obj:`FILETYPE_PEM` nor :py:obj:`FILETYPE_ASN1` then
2753 :py:class:`ValueError` is raised.
2754 """
2755 self.assertRaises(ValueError, load_certificate_request, object(), b"")
2756
2757
2758
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002759class PKCS7Tests(TestCase):
2760 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002761 Tests for :py:obj:`PKCS7Type`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002762 """
2763 def test_type(self):
2764 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002765 :py:obj:`PKCS7Type` is a type object.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002766 """
2767 self.assertTrue(isinstance(PKCS7Type, type))
2768 self.assertEqual(PKCS7Type.__name__, 'PKCS7')
2769
2770 # XXX This doesn't currently work.
2771 # self.assertIdentical(PKCS7, PKCS7Type)
2772
2773
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002774 # XXX Opposite results for all these following methods
2775
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002776 def test_type_is_signed_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002777 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002778 :py:obj:`PKCS7Type.type_is_signed` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002779 arguments.
2780 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002781 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2782 self.assertRaises(TypeError, pkcs7.type_is_signed, None)
2783
2784
2785 def test_type_is_signed(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002786 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002787 :py:obj:`PKCS7Type.type_is_signed` returns :py:obj:`True` if the PKCS7 object is of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002788 the type *signed*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002789 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002790 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2791 self.assertTrue(pkcs7.type_is_signed())
2792
2793
2794 def test_type_is_enveloped_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002795 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002796 :py:obj:`PKCS7Type.type_is_enveloped` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002797 arguments.
2798 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002799 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2800 self.assertRaises(TypeError, pkcs7.type_is_enveloped, None)
2801
2802
2803 def test_type_is_enveloped(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002804 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002805 :py:obj:`PKCS7Type.type_is_enveloped` returns :py:obj:`False` if the PKCS7 object is
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002806 not of the type *enveloped*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002807 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002808 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2809 self.assertFalse(pkcs7.type_is_enveloped())
2810
2811
2812 def test_type_is_signedAndEnveloped_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002813 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002814 :py:obj:`PKCS7Type.type_is_signedAndEnveloped` raises :py:obj:`TypeError` if called
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002815 with any arguments.
2816 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002817 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2818 self.assertRaises(TypeError, pkcs7.type_is_signedAndEnveloped, None)
2819
2820
2821 def test_type_is_signedAndEnveloped(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002822 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002823 :py:obj:`PKCS7Type.type_is_signedAndEnveloped` returns :py:obj:`False` if the PKCS7
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002824 object is not of the type *signed and enveloped*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002825 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002826 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2827 self.assertFalse(pkcs7.type_is_signedAndEnveloped())
2828
2829
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002830 def test_type_is_data(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002831 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002832 :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 -04002833 the type data.
2834 """
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002835 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2836 self.assertFalse(pkcs7.type_is_data())
2837
2838
2839 def test_type_is_data_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002840 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002841 :py:obj:`PKCS7Type.type_is_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002842 arguments.
2843 """
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002844 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2845 self.assertRaises(TypeError, pkcs7.type_is_data, None)
2846
2847
Jean-Paul Calderone97b28ca2010-07-30 10:56:07 -04002848 def test_get_type_name_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002849 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002850 :py:obj:`PKCS7Type.get_type_name` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002851 arguments.
2852 """
Jean-Paul Calderone97b28ca2010-07-30 10:56:07 -04002853 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2854 self.assertRaises(TypeError, pkcs7.get_type_name, None)
2855
2856
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002857 def test_get_type_name(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002858 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002859 :py:obj:`PKCS7Type.get_type_name` returns a :py:obj:`str` giving the type name.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002860 """
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002861 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
Jean-Paul Calderone07640f12010-08-22 17:14:43 -04002862 self.assertEquals(pkcs7.get_type_name(), b('pkcs7-signedData'))
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002863
2864
2865 def test_attribute(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002866 """
2867 If an attribute other than one of the methods tested here is accessed on
Jonathan Ballet648875f2011-07-16 14:14:58 +09002868 an instance of :py:obj:`PKCS7Type`, :py:obj:`AttributeError` is raised.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002869 """
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002870 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2871 self.assertRaises(AttributeError, getattr, pkcs7, "foo")
2872
2873
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002874
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002875class NetscapeSPKITests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002876 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002877 Tests for :py:obj:`OpenSSL.crypto.NetscapeSPKI`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002878 """
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002879 def signable(self):
2880 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002881 Return a new :py:obj:`NetscapeSPKI` for use with signing tests.
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002882 """
2883 return NetscapeSPKI()
2884
2885
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002886 def test_type(self):
2887 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002888 :py:obj:`NetscapeSPKI` and :py:obj:`NetscapeSPKIType` refer to the same type object
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002889 and can be used to create instances of that type.
2890 """
2891 self.assertIdentical(NetscapeSPKI, NetscapeSPKIType)
2892 self.assertConsistentType(NetscapeSPKI, 'NetscapeSPKI')
2893
2894
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002895 def test_construction(self):
2896 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002897 :py:obj:`NetscapeSPKI` returns an instance of :py:obj:`NetscapeSPKIType`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002898 """
2899 nspki = NetscapeSPKI()
2900 self.assertTrue(isinstance(nspki, NetscapeSPKIType))
2901
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002902
Jean-Paul Calderone969efaa2010-08-03 18:19:19 -04002903 def test_invalid_attribute(self):
2904 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002905 Accessing a non-existent attribute of a :py:obj:`NetscapeSPKI` instance causes
2906 an :py:obj:`AttributeError` to be raised.
Jean-Paul Calderone969efaa2010-08-03 18:19:19 -04002907 """
2908 nspki = NetscapeSPKI()
2909 self.assertRaises(AttributeError, lambda: nspki.foo)
2910
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002911
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002912 def test_b64_encode(self):
2913 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002914 :py:obj:`NetscapeSPKI.b64_encode` encodes the certificate to a base64 blob.
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002915 """
2916 nspki = NetscapeSPKI()
2917 blob = nspki.b64_encode()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002918 self.assertTrue(isinstance(blob, binary_type))
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002919
2920
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002921
Rick Dean536ba022009-07-24 23:57:27 -05002922class RevokedTests(TestCase):
2923 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002924 Tests for :py:obj:`OpenSSL.crypto.Revoked`
Rick Dean536ba022009-07-24 23:57:27 -05002925 """
2926 def test_construction(self):
2927 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002928 Confirm we can create :py:obj:`OpenSSL.crypto.Revoked`. Check
Rick Dean536ba022009-07-24 23:57:27 -05002929 that it is empty.
2930 """
2931 revoked = Revoked()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002932 self.assertTrue(isinstance(revoked, Revoked))
2933 self.assertEquals(type(revoked), Revoked)
2934 self.assertEquals(revoked.get_serial(), b('00'))
2935 self.assertEquals(revoked.get_rev_date(), None)
2936 self.assertEquals(revoked.get_reason(), None)
Rick Dean536ba022009-07-24 23:57:27 -05002937
2938
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002939 def test_construction_wrong_args(self):
2940 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002941 Calling :py:obj:`OpenSSL.crypto.Revoked` with any arguments results
2942 in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002943 """
2944 self.assertRaises(TypeError, Revoked, None)
2945 self.assertRaises(TypeError, Revoked, 1)
2946 self.assertRaises(TypeError, Revoked, "foo")
2947
2948
Rick Dean536ba022009-07-24 23:57:27 -05002949 def test_serial(self):
2950 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002951 Confirm we can set and get serial numbers from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002952 :py:obj:`OpenSSL.crypto.Revoked`. Confirm errors are handled
Rick Dean536ba022009-07-24 23:57:27 -05002953 with grace.
2954 """
2955 revoked = Revoked()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002956 ret = revoked.set_serial(b('10b'))
2957 self.assertEquals(ret, None)
Rick Dean536ba022009-07-24 23:57:27 -05002958 ser = revoked.get_serial()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002959 self.assertEquals(ser, b('010B'))
Rick Dean536ba022009-07-24 23:57:27 -05002960
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002961 revoked.set_serial(b('31ppp')) # a type error would be nice
Rick Dean536ba022009-07-24 23:57:27 -05002962 ser = revoked.get_serial()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002963 self.assertEquals(ser, b('31'))
Rick Dean536ba022009-07-24 23:57:27 -05002964
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002965 self.assertRaises(ValueError, revoked.set_serial, b('pqrst'))
Rick Dean536ba022009-07-24 23:57:27 -05002966 self.assertRaises(TypeError, revoked.set_serial, 100)
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002967 self.assertRaises(TypeError, revoked.get_serial, 1)
2968 self.assertRaises(TypeError, revoked.get_serial, None)
2969 self.assertRaises(TypeError, revoked.get_serial, "")
Rick Dean536ba022009-07-24 23:57:27 -05002970
2971
2972 def test_date(self):
2973 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002974 Confirm we can set and get revocation dates from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002975 :py:obj:`OpenSSL.crypto.Revoked`. Confirm errors are handled
Rick Dean536ba022009-07-24 23:57:27 -05002976 with grace.
2977 """
2978 revoked = Revoked()
2979 date = revoked.get_rev_date()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002980 self.assertEquals(date, None)
Rick Dean536ba022009-07-24 23:57:27 -05002981
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002982 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05002983 ret = revoked.set_rev_date(now)
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002984 self.assertEqual(ret, None)
Rick Dean536ba022009-07-24 23:57:27 -05002985 date = revoked.get_rev_date()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002986 self.assertEqual(date, now)
Rick Dean536ba022009-07-24 23:57:27 -05002987
2988
Rick Dean6385faf2009-07-26 00:07:47 -05002989 def test_reason(self):
2990 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002991 Confirm we can set and get revocation reasons from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002992 :py:obj:`OpenSSL.crypto.Revoked`. The "get" need to work
Rick Dean6385faf2009-07-26 00:07:47 -05002993 as "set". Likewise, each reason of all_reasons() must work.
2994 """
2995 revoked = Revoked()
2996 for r in revoked.all_reasons():
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002997 for x in range(2):
Rick Dean6385faf2009-07-26 00:07:47 -05002998 ret = revoked.set_reason(r)
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002999 self.assertEquals(ret, None)
Rick Dean6385faf2009-07-26 00:07:47 -05003000 reason = revoked.get_reason()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04003001 self.assertEquals(
3002 reason.lower().replace(b(' '), b('')),
3003 r.lower().replace(b(' '), b('')))
Rick Dean6385faf2009-07-26 00:07:47 -05003004 r = reason # again with the resp of get
3005
3006 revoked.set_reason(None)
3007 self.assertEqual(revoked.get_reason(), None)
3008
3009
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05003010 def test_set_reason_wrong_arguments(self):
Rick Dean6385faf2009-07-26 00:07:47 -05003011 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003012 Calling :py:obj:`OpenSSL.crypto.Revoked.set_reason` with other than
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05003013 one argument, or an argument which isn't a valid reason,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003014 results in :py:obj:`TypeError` or :py:obj:`ValueError` being raised.
Rick Dean6385faf2009-07-26 00:07:47 -05003015 """
3016 revoked = Revoked()
3017 self.assertRaises(TypeError, revoked.set_reason, 100)
Jean-Paul Calderone281b62b2010-08-28 14:22:29 -04003018 self.assertRaises(ValueError, revoked.set_reason, b('blue'))
Rick Dean6385faf2009-07-26 00:07:47 -05003019
Rick Dean536ba022009-07-24 23:57:27 -05003020
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05003021 def test_get_reason_wrong_arguments(self):
3022 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003023 Calling :py:obj:`OpenSSL.crypto.Revoked.get_reason` with any
3024 arguments results in :py:obj:`TypeError` being raised.
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05003025 """
3026 revoked = Revoked()
3027 self.assertRaises(TypeError, revoked.get_reason, None)
3028 self.assertRaises(TypeError, revoked.get_reason, 1)
3029 self.assertRaises(TypeError, revoked.get_reason, "foo")
3030
3031
3032
Rick Dean536ba022009-07-24 23:57:27 -05003033class CRLTests(TestCase):
3034 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003035 Tests for :py:obj:`OpenSSL.crypto.CRL`
Rick Dean536ba022009-07-24 23:57:27 -05003036 """
3037 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
3038 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
3039
3040 def test_construction(self):
3041 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003042 Confirm we can create :py:obj:`OpenSSL.crypto.CRL`. Check
Rick Dean536ba022009-07-24 23:57:27 -05003043 that it is empty
3044 """
3045 crl = CRL()
3046 self.assertTrue( isinstance(crl, CRL) )
3047 self.assertEqual(crl.get_revoked(), None)
3048
3049
Jean-Paul Calderone2efd03e2010-01-30 13:59:55 -05003050 def test_construction_wrong_args(self):
3051 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003052 Calling :py:obj:`OpenSSL.crypto.CRL` with any number of arguments
3053 results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone2efd03e2010-01-30 13:59:55 -05003054 """
3055 self.assertRaises(TypeError, CRL, 1)
3056 self.assertRaises(TypeError, CRL, "")
3057 self.assertRaises(TypeError, CRL, None)
3058
3059
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003060 def _get_crl(self):
Rick Dean536ba022009-07-24 23:57:27 -05003061 """
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003062 Get a new ``CRL`` with a revocation.
Rick Dean536ba022009-07-24 23:57:27 -05003063 """
3064 crl = CRL()
3065 revoked = Revoked()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003066 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05003067 revoked.set_rev_date(now)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003068 revoked.set_serial(b('3ab'))
3069 revoked.set_reason(b('sUpErSeDEd'))
Rick Dean536ba022009-07-24 23:57:27 -05003070 crl.add_revoked(revoked)
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003071 return crl
Rick Dean536ba022009-07-24 23:57:27 -05003072
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003073
3074 def test_export_pem(self):
3075 """
3076 If not passed a format, ``CRL.export`` returns a "PEM" format string
3077 representing a serial number, a revoked reason, and certificate issuer
3078 information.
3079 """
3080 crl = self._get_crl()
Rick Dean536ba022009-07-24 23:57:27 -05003081 # PEM format
3082 dumped_crl = crl.export(self.cert, self.pkey, days=20)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003083 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003084
3085 # These magic values are based on the way the CRL above was constructed
3086 # and with what certificate it was exported.
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003087 text.index(b('Serial Number: 03AB'))
3088 text.index(b('Superseded'))
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003089 text.index(
3090 b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA')
3091 )
3092
3093
3094 def test_export_der(self):
3095 """
3096 If passed ``FILETYPE_ASN1`` for the format, ``CRL.export`` returns a
3097 "DER" format string representing a serial number, a revoked reason, and
3098 certificate issuer information.
3099 """
3100 crl = self._get_crl()
Rick Dean536ba022009-07-24 23:57:27 -05003101
3102 # DER format
3103 dumped_crl = crl.export(self.cert, self.pkey, FILETYPE_ASN1)
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003104 text = _runopenssl(
3105 dumped_crl, b"crl", b"-noout", b"-text", b"-inform", b"DER"
3106 )
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003107 text.index(b('Serial Number: 03AB'))
3108 text.index(b('Superseded'))
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003109 text.index(
3110 b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA')
3111 )
3112
3113
3114 def test_export_text(self):
3115 """
3116 If passed ``FILETYPE_TEXT`` for the format, ``CRL.export`` returns a
3117 text format string like the one produced by the openssl command line
3118 tool.
3119 """
3120 crl = self._get_crl()
3121
3122 dumped_crl = crl.export(self.cert, self.pkey, FILETYPE_ASN1)
3123 text = _runopenssl(
3124 dumped_crl, b"crl", b"-noout", b"-text", b"-inform", b"DER"
3125 )
Rick Dean536ba022009-07-24 23:57:27 -05003126
3127 # text format
3128 dumped_text = crl.export(self.cert, self.pkey, type=FILETYPE_TEXT)
3129 self.assertEqual(text, dumped_text)
3130
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003131
3132 def test_export_custom_digest(self):
3133 """
3134 If passed the name of a digest function, ``CRL.export`` uses a
3135 signature algorithm based on that digest function.
3136 """
3137 crl = self._get_crl()
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04003138 dumped_crl = crl.export(self.cert, self.pkey, digest=b"sha1")
Bulat Gaifullin1966c972014-09-22 09:47:20 +04003139 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
3140 text.index(b('Signature Algorithm: sha1'))
3141
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003142
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04003143 def test_export_md5_digest(self):
3144 """
3145 If passed md5 as the digest function, ``CRL.export`` uses md5 and does
3146 not emit a deprecation warning.
3147 """
3148 crl = self._get_crl()
3149 with catch_warnings(record=True) as catcher:
3150 simplefilter("always")
3151 self.assertEqual(0, len(catcher))
3152 dumped_crl = crl.export(self.cert, self.pkey, digest=b"md5")
3153 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
3154 text.index(b('Signature Algorithm: md5'))
3155
3156
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003157 def test_export_default_digest(self):
3158 """
3159 If not passed the name of a digest function, ``CRL.export`` uses a
3160 signature algorithm based on MD5 and emits a deprecation warning.
3161 """
3162 crl = self._get_crl()
3163 with catch_warnings(record=True) as catcher:
3164 simplefilter("always")
3165 dumped_crl = crl.export(self.cert, self.pkey)
3166 self.assertEqual(
3167 "The default message digest (md5) is deprecated. "
3168 "Pass the name of a message digest explicitly.",
3169 str(catcher[0].message),
3170 )
Bulat Gaifullin1966c972014-09-22 09:47:20 +04003171 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
3172 text.index(b('Signature Algorithm: md5'))
3173
Rick Dean536ba022009-07-24 23:57:27 -05003174
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -04003175 def test_export_invalid(self):
3176 """
3177 If :py:obj:`CRL.export` is used with an uninitialized :py:obj:`X509`
Jean-Paul Calderoneb5871072012-03-09 14:58:00 -08003178 instance, :py:obj:`OpenSSL.crypto.Error` is raised.
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -04003179 """
3180 crl = CRL()
3181 self.assertRaises(Error, crl.export, X509(), PKey())
3182
3183
Jean-Paul Calderone56515342010-01-30 13:49:38 -05003184 def test_add_revoked_keyword(self):
3185 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003186 :py:obj:`OpenSSL.CRL.add_revoked` accepts its single argument as the
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003187 ``revoked`` keyword argument.
Jean-Paul Calderone56515342010-01-30 13:49:38 -05003188 """
3189 crl = CRL()
3190 revoked = Revoked()
3191 crl.add_revoked(revoked=revoked)
3192 self.assertTrue(isinstance(crl.get_revoked()[0], Revoked))
3193
Rick Dean6385faf2009-07-26 00:07:47 -05003194
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05003195 def test_export_wrong_args(self):
3196 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003197 Calling :py:obj:`OpenSSL.CRL.export` with fewer than two or more than
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05003198 four arguments, or with arguments other than the certificate,
3199 private key, integer file type, and integer number of days it
Jonathan Ballet648875f2011-07-16 14:14:58 +09003200 expects, results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05003201 """
3202 crl = CRL()
3203 self.assertRaises(TypeError, crl.export)
3204 self.assertRaises(TypeError, crl.export, self.cert)
Bulat Gaifullin925f7862014-09-22 10:10:44 +04003205 self.assertRaises(TypeError, crl.export, self.cert, self.pkey, FILETYPE_PEM, 10, "md5", "foo")
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05003206
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05003207 self.assertRaises(TypeError, crl.export, None, self.pkey, FILETYPE_PEM, 10)
3208 self.assertRaises(TypeError, crl.export, self.cert, None, FILETYPE_PEM, 10)
3209 self.assertRaises(TypeError, crl.export, self.cert, self.pkey, None, 10)
3210 self.assertRaises(TypeError, crl.export, self.cert, FILETYPE_PEM, None)
3211
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05003212
Jean-Paul Calderoneea198422010-01-30 13:58:23 -05003213 def test_export_unknown_filetype(self):
3214 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003215 Calling :py:obj:`OpenSSL.CRL.export` with a file type other than
3216 :py:obj:`FILETYPE_PEM`, :py:obj:`FILETYPE_ASN1`, or :py:obj:`FILETYPE_TEXT` results
3217 in a :py:obj:`ValueError` being raised.
Jean-Paul Calderoneea198422010-01-30 13:58:23 -05003218 """
3219 crl = CRL()
3220 self.assertRaises(ValueError, crl.export, self.cert, self.pkey, 100, 10)
3221
3222
Bulat Gaifullin925f7862014-09-22 10:10:44 +04003223 def test_export_unknown_digest(self):
Bulat Gaifullin5f9eea42014-09-23 19:35:15 +04003224 """
3225 Calling :py:obj:`OpenSSL.CRL.export` with a unsupported digest results
3226 in a :py:obj:`ValueError` being raised.
3227 """
Bulat Gaifullin925f7862014-09-22 10:10:44 +04003228 crl = CRL()
Jean-Paul Calderone9be85192015-04-13 21:20:51 -04003229 self.assertRaises(
3230 ValueError,
3231 crl.export,
3232 self.cert, self.pkey, FILETYPE_PEM, 10, b"strange-digest"
3233 )
Bulat Gaifullin925f7862014-09-22 10:10:44 +04003234
3235
Rick Dean536ba022009-07-24 23:57:27 -05003236 def test_get_revoked(self):
3237 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05003238 Use python to create a simple CRL with two revocations.
Jonathan Ballet648875f2011-07-16 14:14:58 +09003239 Get back the :py:obj:`Revoked` using :py:obj:`OpenSSL.CRL.get_revoked` and
Rick Dean536ba022009-07-24 23:57:27 -05003240 verify them.
3241 """
3242 crl = CRL()
3243
3244 revoked = Revoked()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003245 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05003246 revoked.set_rev_date(now)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003247 revoked.set_serial(b('3ab'))
Rick Dean536ba022009-07-24 23:57:27 -05003248 crl.add_revoked(revoked)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003249 revoked.set_serial(b('100'))
3250 revoked.set_reason(b('sUpErSeDEd'))
Rick Dean536ba022009-07-24 23:57:27 -05003251 crl.add_revoked(revoked)
3252
3253 revs = crl.get_revoked()
3254 self.assertEqual(len(revs), 2)
3255 self.assertEqual(type(revs[0]), Revoked)
3256 self.assertEqual(type(revs[1]), Revoked)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003257 self.assertEqual(revs[0].get_serial(), b('03AB'))
3258 self.assertEqual(revs[1].get_serial(), b('0100'))
Rick Dean536ba022009-07-24 23:57:27 -05003259 self.assertEqual(revs[0].get_rev_date(), now)
3260 self.assertEqual(revs[1].get_rev_date(), now)
3261
3262
Jean-Paul Calderone46bdce42010-01-30 13:44:16 -05003263 def test_get_revoked_wrong_args(self):
3264 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003265 Calling :py:obj:`OpenSSL.CRL.get_revoked` with any arguments results
3266 in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone46bdce42010-01-30 13:44:16 -05003267 """
3268 crl = CRL()
3269 self.assertRaises(TypeError, crl.get_revoked, None)
3270 self.assertRaises(TypeError, crl.get_revoked, 1)
3271 self.assertRaises(TypeError, crl.get_revoked, "")
3272 self.assertRaises(TypeError, crl.get_revoked, "", 1, None)
3273
3274
Jean-Paul Calderoneecef6fa2010-01-30 13:47:18 -05003275 def test_add_revoked_wrong_args(self):
3276 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003277 Calling :py:obj:`OpenSSL.CRL.add_revoked` with other than one
3278 argument results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderoneecef6fa2010-01-30 13:47:18 -05003279 """
3280 crl = CRL()
3281 self.assertRaises(TypeError, crl.add_revoked)
3282 self.assertRaises(TypeError, crl.add_revoked, 1, 2)
3283 self.assertRaises(TypeError, crl.add_revoked, "foo", "bar")
3284
3285
Rick Dean536ba022009-07-24 23:57:27 -05003286 def test_load_crl(self):
3287 """
3288 Load a known CRL and inspect its revocations. Both
3289 PEM and DER formats are loaded.
3290 """
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003291 crl = load_crl(FILETYPE_PEM, crlData)
Rick Dean536ba022009-07-24 23:57:27 -05003292 revs = crl.get_revoked()
3293 self.assertEqual(len(revs), 2)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003294 self.assertEqual(revs[0].get_serial(), b('03AB'))
Rick Dean6385faf2009-07-26 00:07:47 -05003295 self.assertEqual(revs[0].get_reason(), None)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003296 self.assertEqual(revs[1].get_serial(), b('0100'))
3297 self.assertEqual(revs[1].get_reason(), b('Superseded'))
Rick Dean536ba022009-07-24 23:57:27 -05003298
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003299 der = _runopenssl(crlData, b"crl", b"-outform", b"DER")
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05003300 crl = load_crl(FILETYPE_ASN1, der)
Rick Dean536ba022009-07-24 23:57:27 -05003301 revs = crl.get_revoked()
3302 self.assertEqual(len(revs), 2)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003303 self.assertEqual(revs[0].get_serial(), b('03AB'))
Rick Dean6385faf2009-07-26 00:07:47 -05003304 self.assertEqual(revs[0].get_reason(), None)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003305 self.assertEqual(revs[1].get_serial(), b('0100'))
3306 self.assertEqual(revs[1].get_reason(), b('Superseded'))
Rick Dean536ba022009-07-24 23:57:27 -05003307
3308
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003309 def test_load_crl_wrong_args(self):
3310 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003311 Calling :py:obj:`OpenSSL.crypto.load_crl` with other than two
3312 arguments results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003313 """
3314 self.assertRaises(TypeError, load_crl)
3315 self.assertRaises(TypeError, load_crl, FILETYPE_PEM)
3316 self.assertRaises(TypeError, load_crl, FILETYPE_PEM, crlData, None)
3317
3318
3319 def test_load_crl_bad_filetype(self):
3320 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003321 Calling :py:obj:`OpenSSL.crypto.load_crl` with an unknown file type
3322 raises a :py:obj:`ValueError`.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003323 """
3324 self.assertRaises(ValueError, load_crl, 100, crlData)
3325
3326
3327 def test_load_crl_bad_data(self):
3328 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003329 Calling :py:obj:`OpenSSL.crypto.load_crl` with file data which can't
3330 be loaded raises a :py:obj:`OpenSSL.crypto.Error`.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003331 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003332 self.assertRaises(Error, load_crl, FILETYPE_PEM, b"hello, world")
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003333
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04003334
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -05003335
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003336class X509StoreContextTests(TestCase):
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003337 """
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003338 Tests for :py:obj:`OpenSSL.crypto.X509StoreContext`.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003339 """
3340 root_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3341 intermediate_cert = load_certificate(FILETYPE_PEM, intermediate_cert_pem)
3342 intermediate_server_cert = load_certificate(FILETYPE_PEM, intermediate_server_cert_pem)
3343
3344 def test_valid(self):
3345 """
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003346 :py:obj:`verify_certificate` returns ``None`` when called with a certificate
Jean-Paul Calderone06e01b92015-01-18 15:43:13 -05003347 and valid chain.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003348 """
3349 store = X509Store()
3350 store.add_cert(self.root_cert)
3351 store.add_cert(self.intermediate_cert)
3352 store_ctx = X509StoreContext(store, self.intermediate_server_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003353 self.assertEqual(store_ctx.verify_certificate(), None)
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003354
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003355
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003356 def test_reuse(self):
3357 """
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003358 :py:obj:`verify_certificate` can be called multiple times with the same
Jean-Paul Calderone06e01b92015-01-18 15:43:13 -05003359 ``X509StoreContext`` instance to produce the same result.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003360 """
3361 store = X509Store()
3362 store.add_cert(self.root_cert)
3363 store.add_cert(self.intermediate_cert)
3364 store_ctx = X509StoreContext(store, self.intermediate_server_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003365 self.assertEqual(store_ctx.verify_certificate(), None)
3366 self.assertEqual(store_ctx.verify_certificate(), None)
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003367
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003368
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003369 def test_trusted_self_signed(self):
3370 """
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003371 :py:obj:`verify_certificate` returns ``None`` when called with a self-signed
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003372 certificate and itself in the chain.
3373 """
3374 store = X509Store()
3375 store.add_cert(self.root_cert)
3376 store_ctx = X509StoreContext(store, self.root_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003377 self.assertEqual(store_ctx.verify_certificate(), None)
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003378
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003379
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003380 def test_untrusted_self_signed(self):
3381 """
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003382 :py:obj:`verify_certificate` raises error when a self-signed certificate is
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003383 verified without itself in the chain.
3384 """
3385 store = X509Store()
3386 store_ctx = X509StoreContext(store, self.root_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003387 e = self.assertRaises(X509StoreContextError, store_ctx.verify_certificate)
Jean-Paul Calderone4c10a1e2015-01-18 16:31:27 -05003388 self.assertEqual(e.args[0][2], 'self signed certificate')
Jean-Paul Calderone06e01b92015-01-18 15:43:13 -05003389 self.assertEqual(e.certificate.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003390
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003391
3392 def test_invalid_chain_no_root(self):
3393 """
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003394 :py:obj:`verify_certificate` raises error when a root certificate is missing
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003395 from the chain.
3396 """
3397 store = X509Store()
3398 store.add_cert(self.intermediate_cert)
3399 store_ctx = X509StoreContext(store, self.intermediate_server_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003400 e = self.assertRaises(X509StoreContextError, store_ctx.verify_certificate)
Jean-Paul Calderone4c10a1e2015-01-18 16:31:27 -05003401 self.assertEqual(e.args[0][2], 'unable to get issuer certificate')
Jean-Paul Calderone06e01b92015-01-18 15:43:13 -05003402 self.assertEqual(e.certificate.get_subject().CN, 'intermediate')
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003403
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003404
3405 def test_invalid_chain_no_intermediate(self):
3406 """
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003407 :py:obj:`verify_certificate` raises error when an intermediate certificate is
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003408 missing from the chain.
3409 """
3410 store = X509Store()
3411 store.add_cert(self.root_cert)
3412 store_ctx = X509StoreContext(store, self.intermediate_server_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003413 e = self.assertRaises(X509StoreContextError, store_ctx.verify_certificate)
Jean-Paul Calderone4c10a1e2015-01-18 16:31:27 -05003414 self.assertEqual(e.args[0][2], 'unable to get local issuer certificate')
Jean-Paul Calderone06e01b92015-01-18 15:43:13 -05003415 self.assertEqual(e.certificate.get_subject().CN, 'intermediate-service')
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003416
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003417
Stephen Holsapple46a09252015-02-12 14:45:43 -08003418 def test_modification_pre_verify(self):
3419 """
3420 :py:obj:`verify_certificate` can use a store context modified after
3421 instantiation.
3422 """
3423 store_bad = X509Store()
3424 store_bad.add_cert(self.intermediate_cert)
3425 store_good = X509Store()
3426 store_good.add_cert(self.root_cert)
3427 store_good.add_cert(self.intermediate_cert)
3428 store_ctx = X509StoreContext(store_bad, self.intermediate_server_cert)
3429 e = self.assertRaises(X509StoreContextError, store_ctx.verify_certificate)
3430 self.assertEqual(e.args[0][2], 'unable to get issuer certificate')
3431 self.assertEqual(e.certificate.get_subject().CN, 'intermediate')
3432 store_ctx.set_store(store_good)
3433 self.assertEqual(store_ctx.verify_certificate(), None)
3434
3435
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04003436
3437class SignVerifyTests(TestCase):
3438 """
3439 Tests for :py:obj:`OpenSSL.crypto.sign` and :py:obj:`OpenSSL.crypto.verify`.
3440 """
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04003441 def test_sign_verify(self):
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04003442 """
3443 :py:obj:`sign` generates a cryptographic signature which :py:obj:`verify` can check.
3444 """
3445 content = b(
James Yonan7c2e5d32010-02-27 05:45:50 -07003446 "It was a bright cold day in April, and the clocks were striking "
Jean-Paul Calderoned08feb02010-10-12 21:53:24 -04003447 "thirteen. Winston Smith, his chin nuzzled into his breast in an "
James Yonan7c2e5d32010-02-27 05:45:50 -07003448 "effort to escape the vile wind, slipped quickly through the "
3449 "glass doors of Victory Mansions, though not quickly enough to "
3450 "prevent a swirl of gritty dust from entering along with him.")
3451
3452 # sign the content with this private key
3453 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
3454 # verify the content with this cert
3455 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3456 # certificate unrelated to priv_key, used to trigger an error
3457 bad_cert = load_certificate(FILETYPE_PEM, server_cert_pem)
3458
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003459 for digest in ['md5', 'sha1']:
3460 sig = sign(priv_key, content, digest)
3461
James Yonan7c2e5d32010-02-27 05:45:50 -07003462 # Verify the signature of content, will throw an exception if error.
3463 verify(good_cert, sig, content, digest)
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003464
Jean-Paul Calderone9538f142010-10-13 22:13:40 -04003465 # This should fail because the certificate doesn't match the
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003466 # private key that was used to sign the content.
Jean-Paul Calderone9538f142010-10-13 22:13:40 -04003467 self.assertRaises(Error, verify, bad_cert, sig, content, digest)
James Yonan7c2e5d32010-02-27 05:45:50 -07003468
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04003469 # This should fail because we've "tainted" the content after
Jean-Paul Calderone9828f662010-12-08 22:57:26 -05003470 # signing it.
3471 self.assertRaises(
Jonathan Ballet648875f2011-07-16 14:14:58 +09003472 Error, verify,
Jean-Paul Calderone9828f662010-12-08 22:57:26 -05003473 good_cert, sig, content + b("tainted"), digest)
3474
3475 # test that unknown digest types fail
3476 self.assertRaises(
3477 ValueError, sign, priv_key, content, "strange-digest")
3478 self.assertRaises(
3479 ValueError, verify, good_cert, sig, content, "strange-digest")
3480
Rick Dean5b7b6372009-04-01 11:34:06 -05003481
Abraham Martinc5484ba2015-03-25 15:33:05 +00003482 def test_sign_verify_with_text(self):
3483 """
3484 :py:obj:`sign` generates a cryptographic signature which :py:obj:`verify` can check.
3485 Deprecation warnings raised because using text instead of bytes as content
3486 """
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003487 content = (
Jean-Paul Calderone362c1f52015-03-29 08:01:39 -04003488 b"It was a bright cold day in April, and the clocks were striking "
3489 b"thirteen. Winston Smith, his chin nuzzled into his breast in an "
3490 b"effort to escape the vile wind, slipped quickly through the "
3491 b"glass doors of Victory Mansions, though not quickly enough to "
3492 b"prevent a swirl of gritty dust from entering along with him."
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003493 ).decode("ascii")
Abraham Martinc5484ba2015-03-25 15:33:05 +00003494
3495 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
3496 cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3497 for digest in ['md5', 'sha1']:
3498 with catch_warnings(record=True) as w:
3499 simplefilter("always")
3500 sig = sign(priv_key, content, digest)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003501
3502 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003503 "{0} for data is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003504 WARNING_TYPE_EXPECTED
3505 ),
3506 str(w[-1].message)
3507 )
3508 self.assertIs(w[-1].category, DeprecationWarning)
3509
Abraham Martinc5484ba2015-03-25 15:33:05 +00003510 with catch_warnings(record=True) as w:
3511 simplefilter("always")
3512 verify(cert, sig, content, digest)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003513
3514 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003515 "{0} for data is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003516 WARNING_TYPE_EXPECTED
3517 ),
3518 str(w[-1].message)
3519 )
3520 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinc5484ba2015-03-25 15:33:05 +00003521
3522
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -05003523 def test_sign_nulls(self):
3524 """
3525 :py:obj:`sign` produces a signature for a string with embedded nulls.
3526 """
3527 content = b("Watch out! \0 Did you see it?")
3528 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
3529 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3530 sig = sign(priv_key, content, "sha1")
3531 verify(good_cert, sig, content, "sha1")
3532
3533
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003534
3535class EllipticCurveTests(TestCase):
3536 """
3537 Tests for :py:class:`_EllipticCurve`, :py:obj:`get_elliptic_curve`, and
3538 :py:obj:`get_elliptic_curves`.
3539 """
3540 def test_set(self):
3541 """
3542 :py:obj:`get_elliptic_curves` returns a :py:obj:`set`.
3543 """
3544 self.assertIsInstance(get_elliptic_curves(), set)
3545
3546
3547 def test_some_curves(self):
3548 """
3549 If :py:mod:`cryptography` has elliptic curve support then the set
3550 returned by :py:obj:`get_elliptic_curves` has some elliptic curves in
3551 it.
3552
3553 There could be an OpenSSL that violates this assumption. If so, this
3554 test will fail and we'll find out.
3555 """
3556 curves = get_elliptic_curves()
3557 if lib.Cryptography_HAS_EC:
3558 self.assertTrue(curves)
3559 else:
3560 self.assertFalse(curves)
3561
3562
3563 def test_a_curve(self):
3564 """
3565 :py:obj:`get_elliptic_curve` can be used to retrieve a particular
3566 supported curve.
3567 """
3568 curves = get_elliptic_curves()
3569 if curves:
3570 curve = next(iter(curves))
3571 self.assertEqual(curve.name, get_elliptic_curve(curve.name).name)
3572 else:
Jean-Paul Calderoneeb86f3a2014-04-19 09:45:57 -04003573 self.assertRaises(ValueError, get_elliptic_curve, u("prime256v1"))
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003574
3575
3576 def test_not_a_curve(self):
3577 """
3578 :py:obj:`get_elliptic_curve` raises :py:class:`ValueError` if called
3579 with a name which does not identify a supported curve.
3580 """
3581 self.assertRaises(
Jean-Paul Calderone5a82db92014-04-19 09:51:29 -04003582 ValueError, get_elliptic_curve, u("this curve was just invented"))
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003583
3584
3585 def test_repr(self):
3586 """
3587 The string representation of a curve object includes simply states the
3588 object is a curve and what its name is.
3589 """
3590 curves = get_elliptic_curves()
3591 if curves:
3592 curve = next(iter(curves))
3593 self.assertEqual("<Curve %r>" % (curve.name,), repr(curve))
3594
3595
3596 def test_to_EC_KEY(self):
3597 """
3598 The curve object can export a version of itself as an EC_KEY* via the
3599 private :py:meth:`_EllipticCurve._to_EC_KEY`.
3600 """
3601 curves = get_elliptic_curves()
3602 if curves:
3603 curve = next(iter(curves))
3604 # It's not easy to assert anything about this object. However, see
3605 # leakcheck/crypto.py for a test that demonstrates it at least does
3606 # not leak memory.
3607 curve._to_EC_KEY()
3608
3609
Jean-Paul Calderone1be77082014-04-30 18:17:41 -04003610
3611class EllipticCurveFactory(object):
3612 """
3613 A helper to get the names of two curves.
3614 """
3615 def __init__(self):
3616 curves = iter(get_elliptic_curves())
3617 try:
3618 self.curve_name = next(curves).name
3619 self.another_curve_name = next(curves).name
3620 except StopIteration:
3621 self.curve_name = self.another_curve_name = None
3622
3623
3624
3625class EllipticCurveEqualityTests(TestCase, EqualityTestsMixin):
3626 """
3627 Tests :py:type:`_EllipticCurve`\ 's implementation of ``==`` and ``!=``.
3628 """
3629 curve_factory = EllipticCurveFactory()
3630
3631 if curve_factory.curve_name is None:
3632 skip = "There are no curves available there can be no curve objects."
3633
3634
3635 def anInstance(self):
3636 """
3637 Get the curve object for an arbitrary curve supported by the system.
3638 """
3639 return get_elliptic_curve(self.curve_factory.curve_name)
3640
3641
3642 def anotherInstance(self):
3643 """
3644 Get the curve object for an arbitrary curve supported by the system -
3645 but not the one returned by C{anInstance}.
3646 """
3647 return get_elliptic_curve(self.curve_factory.another_curve_name)
3648
3649
3650
Jean-Paul Calderone22c31242014-05-01 07:49:47 -04003651class EllipticCurveHashTests(TestCase):
3652 """
3653 Tests for :py:type:`_EllipticCurve`\ 's implementation of hashing (thus use
3654 as an item in a :py:type:`dict` or :py:type:`set`).
3655 """
3656 curve_factory = EllipticCurveFactory()
3657
3658 if curve_factory.curve_name is None:
3659 skip = "There are no curves available there can be no curve objects."
3660
3661
3662 def test_contains(self):
3663 """
3664 The ``in`` operator reports that a :py:type:`set` containing a curve
3665 does contain that curve.
3666 """
3667 curve = get_elliptic_curve(self.curve_factory.curve_name)
3668 curves = set([curve])
3669 self.assertIn(curve, curves)
3670
3671
3672 def test_does_not_contain(self):
3673 """
3674 The ``in`` operator reports that a :py:type:`set` not containing a
3675 curve does not contain that curve.
3676 """
3677 curve = get_elliptic_curve(self.curve_factory.curve_name)
3678 curves = set([get_elliptic_curve(self.curve_factory.another_curve_name)])
3679 self.assertNotIn(curve, curves)
3680
3681
3682
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -05003683if __name__ == '__main__':
3684 main()