blob: 54349b4ccdc5d7b577d15c79b6c2e2e0b4d046cc [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 Gaynor791212d2015-09-05 15:46:08 -040017import pytest
18
Alex Gaynorb8e38992015-09-04 08:14:04 -040019from six import u, b, binary_type
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050020
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -050021from OpenSSL.crypto import TYPE_RSA, TYPE_DSA, Error, PKey, PKeyType
Jean-Paul Calderone78381d22008-03-06 23:35:22 -050022from OpenSSL.crypto import X509, X509Type, X509Name, X509NameType
Stephen Holsapple08ffaa62015-01-30 17:18:40 -080023from OpenSSL.crypto import X509Store, X509StoreType, X509StoreContext, X509StoreContextError
Stephen Holsapple0d9815f2014-08-27 19:36:53 -070024from OpenSSL.crypto import X509Req, X509ReqType
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -050025from OpenSSL.crypto import X509Extension, X509ExtensionType
Rick Dean5b7b6372009-04-01 11:34:06 -050026from OpenSSL.crypto import load_certificate, load_privatekey
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -040027from OpenSSL.crypto import FILETYPE_PEM, FILETYPE_ASN1, FILETYPE_TEXT
Jean-Paul Calderone71919862009-04-01 13:01:19 -040028from OpenSSL.crypto import dump_certificate, load_certificate_request
29from OpenSSL.crypto import dump_certificate_request, dump_privatekey
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -040030from OpenSSL.crypto import PKCS7Type, load_pkcs7_data
Jean-Paul Calderone9178ee62010-01-25 17:55:30 -050031from OpenSSL.crypto import PKCS12, PKCS12Type, load_pkcs12
Rick Dean536ba022009-07-24 23:57:27 -050032from OpenSSL.crypto import CRL, Revoked, load_crl
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -040033from OpenSSL.crypto import NetscapeSPKI, NetscapeSPKIType
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040034from OpenSSL.crypto import (
35 sign, verify, get_elliptic_curve, get_elliptic_curves)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -040036from OpenSSL.test.util import (
37 EqualityTestsMixin, TestCase, WARNING_TYPE_EXPECTED
38)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040039from OpenSSL._util import native, lib
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040040
Alex Gaynoraceb3e22015-09-05 12:00:22 -040041
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -040042def normalize_certificate_pem(pem):
43 return dump_certificate(FILETYPE_PEM, load_certificate(FILETYPE_PEM, pem))
44
45
46def normalize_privatekey_pem(pem):
47 return dump_privatekey(FILETYPE_PEM, load_privatekey(FILETYPE_PEM, pem))
48
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040049
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050050GOOD_CIPHER = "blowfish"
51BAD_CIPHER = "zippers"
52
53GOOD_DIGEST = "MD5"
54BAD_DIGEST = "monkeys"
55
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040056root_cert_pem = b("""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -050057MIIC7TCCAlagAwIBAgIIPQzE4MbeufQwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE
58BhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdU
59ZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwIhgPMjAwOTAzMjUxMjM2
60NThaGA8yMDE3MDYxMTEyMzY1OFowWDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklM
61MRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9U
62ZXN0aW5nIFJvb3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPmaQumL
63urpE527uSEHdL1pqcDRmWzu+98Y6YHzT/J7KWEamyMCNZ6fRW1JCR782UQ8a07fy
642xXsKy4WdKaxyG8CcatwmXvpvRQ44dSANMihHELpANTdyVp6DCysED6wkQFurHlF
651dshEaJw8b/ypDhmbVIo6Ci1xvCJqivbLFnbAgMBAAGjgbswgbgwHQYDVR0OBBYE
66FINVdy1eIfFJDAkk51QJEo3IfgSuMIGIBgNVHSMEgYAwfoAUg1V3LV4h8UkMCSTn
67VAkSjch+BK6hXKRaMFgxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UE
68BxMHQ2hpY2FnbzEQMA4GA1UEChMHVGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBS
69b290IENBggg9DMTgxt659DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB
70AGGCDazMJGoWNBpc03u6+smc95dEead2KlZXBATOdFT1VesY3+nUOqZhEhTGlDMi
71hkgaZnzoIq/Uamidegk4hirsCT/R+6vsKAAxNTcBjUeZjlykCJWy5ojShGftXIKY
72w/njVbKMXrvc83qmTdGl3TAM0fxQIpqgcglFLveEBgzn
73-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040074""")
Rick Dean94e46fd2009-07-18 14:51:24 -050075
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040076root_key_pem = b("""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -050077MIICXQIBAAKBgQD5mkLpi7q6ROdu7khB3S9aanA0Zls7vvfGOmB80/yeylhGpsjA
78jWen0VtSQke/NlEPGtO38tsV7CsuFnSmschvAnGrcJl76b0UOOHUgDTIoRxC6QDU
793claegwsrBA+sJEBbqx5RdXbIRGicPG/8qQ4Zm1SKOgotcbwiaor2yxZ2wIDAQAB
80AoGBAPCgMpmLxzwDaUmcFbTJUvlLW1hoxNNYSu2jIZm1k/hRAcE60JYwvBkgz3UB
81yMEh0AtLxYe0bFk6EHah11tMUPgscbCq73snJ++8koUw+csk22G65hOs51bVb7Aa
826JBe67oLzdtvgCUFAA2qfrKzWRZzAdhUirQUZgySZk+Xq1pBAkEA/kZG0A6roTSM
83BVnx7LnPfsycKUsTumorpXiylZJjTi9XtmzxhrYN6wgZlDOOwOLgSQhszGpxVoMD
84u3gByT1b2QJBAPtL3mSKdvwRu/+40zaZLwvSJRxaj0mcE4BJOS6Oqs/hS1xRlrNk
85PpQ7WJ4yM6ZOLnXzm2mKyxm50Mv64109FtMCQQDOqS2KkjHaLowTGVxwC0DijMfr
86I9Lf8sSQk32J5VWCySWf5gGTfEnpmUa41gKTMJIbqZZLucNuDcOtzUaeWZlZAkA8
87ttXigLnCqR486JDPTi9ZscoZkZ+w7y6e/hH8t6d5Vjt48JVyfjPIaJY+km58LcN3
886AWSeGAdtRFHVzR7oHjVAkB4hutvxiOeiIVQNBhM6RSI9aBPMI21DoX2JRoxvNW2
89cbvAhow217X9V0dVerEOKxnNYspXRrh36h7k4mQA+sDq
90-----END RSA PRIVATE KEY-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040091""")
Rick Dean94e46fd2009-07-18 14:51:24 -050092
Stephen Holsapple0d9815f2014-08-27 19:36:53 -070093intermediate_cert_pem = b("""-----BEGIN CERTIFICATE-----
94MIICVzCCAcCgAwIBAgIRAMPzhm6//0Y/g2pmnHR2C4cwDQYJKoZIhvcNAQENBQAw
95WDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAw
96DgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwHhcNMTQw
97ODI4MDIwNDA4WhcNMjQwODI1MDIwNDA4WjBmMRUwEwYDVQQDEwxpbnRlcm1lZGlh
98dGUxDDAKBgNVBAoTA29yZzERMA8GA1UECxMIb3JnLXVuaXQxCzAJBgNVBAYTAlVT
99MQswCQYDVQQIEwJDQTESMBAGA1UEBxMJU2FuIERpZWdvMIGfMA0GCSqGSIb3DQEB
100AQUAA4GNADCBiQKBgQDYcEQw5lfbEQRjr5Yy4yxAHGV0b9Al+Lmu7wLHMkZ/ZMmK
101FGIbljbviiD1Nz97Oh2cpB91YwOXOTN2vXHq26S+A5xe8z/QJbBsyghMur88CjdT
10221H2qwMa+r5dCQwEhuGIiZ3KbzB/n4DTMYI5zy4IYPv0pjxShZn4aZTCCK2IUwID
103AQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBDQUAA4GBAPIWSkLX
104QRMApOjjyC+tMxumT5e2pMqChHmxobQK4NMdrf2VCx+cRT6EmY8sK3/Xl/X8UBQ+
1059n5zXb1ZwhW/sTWgUvmOceJ4/XVs9FkdWOOn1J0XBch9ZIiFe/s5ASIgG7fUdcUF
1069mAWS6FK2ca3xIh5kIupCXOFa0dPvlw/YUFT
107-----END CERTIFICATE-----
108""")
109
110intermediate_key_pem = b("""-----BEGIN RSA PRIVATE KEY-----
111MIICWwIBAAKBgQDYcEQw5lfbEQRjr5Yy4yxAHGV0b9Al+Lmu7wLHMkZ/ZMmKFGIb
112ljbviiD1Nz97Oh2cpB91YwOXOTN2vXHq26S+A5xe8z/QJbBsyghMur88CjdT21H2
113qwMa+r5dCQwEhuGIiZ3KbzB/n4DTMYI5zy4IYPv0pjxShZn4aZTCCK2IUwIDAQAB
114AoGAfSZVV80pSeOKHTYfbGdNY/jHdU9eFUa/33YWriXU+77EhpIItJjkRRgivIfo
115rhFJpBSGmDLblaqepm8emsXMeH4+2QzOYIf0QGGP6E6scjTt1PLqdqKfVJ1a2REN
116147cujNcmFJb/5VQHHMpaPTgttEjlzuww4+BCDPsVRABWrkCQQD3loH36nLoQTtf
117+kQq0T6Bs9/UWkTAGo0ND81ALj0F8Ie1oeZg6RNT96RxZ3aVuFTESTv6/TbjWywO
118wdzlmV1vAkEA38rTJ6PTwaJlw5OttdDzAXGPB9tDmzh9oSi7cHwQQXizYd8MBYx4
119sjHUKD3dCQnb1dxJFhd3BT5HsnkRMbVZXQJAbXduH17ZTzcIOXc9jHDXYiFVZV5D
12052vV0WCbLzVCZc3jMrtSUKa8lPN5EWrdU3UchWybyG0MR5mX8S5lrF4SoQJAIyUD
121DBKaSqpqONCUUx1BTFS9FYrFjzbL4+c1qHCTTPTblt8kUCrDOZjBrKAqeiTmNSum
122/qUot9YUBF8m6BuGsQJATHHmdFy/fG1VLkyBp49CAa8tN3Z5r/CgTznI4DfMTf4C
123NbRHn2UmYlwQBa+L5lg9phewNe8aEwpPyPLoV85U8Q==
124-----END RSA PRIVATE KEY-----
125""")
126
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400127server_cert_pem = b("""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500128MIICKDCCAZGgAwIBAgIJAJn/HpR21r/8MA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
129BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
130VGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBSb290IENBMCIYDzIwMDkwMzI1MTIz
131NzUzWhgPMjAxNzA2MTExMjM3NTNaMBgxFjAUBgNVBAMTDWxvdmVseSBzZXJ2ZXIw
132gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAL6m+G653V0tpBC/OKl22VxOi2Cv
133lK4TYu9LHSDP9uDVTe7V5D5Tl6qzFoRRx5pfmnkqT5B+W9byp2NU3FC5hLm5zSAr
134b45meUhjEJ/ifkZgbNUjHdBIGP9MAQUHZa5WKdkGIJvGAvs8UzUqlr4TBWQIB24+
135lJ+Ukk/CRgasrYwdAgMBAAGjNjA0MB0GA1UdDgQWBBS4kC7Ij0W1TZXZqXQFAM2e
136gKEG2DATBgNVHSUEDDAKBggrBgEFBQcDATANBgkqhkiG9w0BAQUFAAOBgQBh30Li
137dJ+NlxIOx5343WqIBka3UbsOb2kxWrbkVCrvRapCMLCASO4FqiKWM+L0VDBprqIp
1382mgpFQ6FHpoIENGvJhdEKpptQ5i7KaGhnDNTfdy3x1+h852G99f1iyj0RmbuFcM8
139uzujnS8YXWvM7DM1Ilozk4MzPug8jzFp5uhKCQ==
140-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400141""")
Rick Dean94e46fd2009-07-18 14:51:24 -0500142
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -0400143server_key_pem = normalize_privatekey_pem(b("""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500144MIICWwIBAAKBgQC+pvhuud1dLaQQvzipdtlcTotgr5SuE2LvSx0gz/bg1U3u1eQ+
145U5eqsxaEUceaX5p5Kk+QflvW8qdjVNxQuYS5uc0gK2+OZnlIYxCf4n5GYGzVIx3Q
146SBj/TAEFB2WuVinZBiCbxgL7PFM1Kpa+EwVkCAduPpSflJJPwkYGrK2MHQIDAQAB
147AoGAbwuZ0AR6JveahBaczjfnSpiFHf+mve2UxoQdpyr6ROJ4zg/PLW5K/KXrC48G
148j6f3tXMrfKHcpEoZrQWUfYBRCUsGD5DCazEhD8zlxEHahIsqpwA0WWssJA2VOLEN
149j6DuV2pCFbw67rfTBkTSo32ahfXxEKev5KswZk0JIzH3ooECQQDgzS9AI89h0gs8
150Dt+1m11Rzqo3vZML7ZIyGApUzVan+a7hbc33nbGRkAXjHaUBJO31it/H6dTO+uwX
151msWwNG5ZAkEA2RyFKs5xR5USTFaKLWCgpH/ydV96KPOpBND7TKQx62snDenFNNbn
152FwwOhpahld+vqhYk+pfuWWUpQciE+Bu7ZQJASjfT4sQv4qbbKK/scePicnDdx9th
1534e1EeB9xwb+tXXXUo/6Bor/AcUNwfiQ6Zt9PZOK9sR3lMZSsP7rMi7kzuQJABie6
1541sXXjFH7nNJvRG4S39cIxq8YRYTy68II/dlB2QzGpKxV/POCxbJ/zu0CU79tuYK7
155NaeNCFfH3aeTrX0LyQJAMBWjWmeKM2G2sCExheeQK0ROnaBC8itCECD4Jsve4nqf
156r50+LF74iLXFwqysVCebPKMOpDWp/qQ1BbJQIPs7/A==
157-----END RSA PRIVATE KEY-----
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -0400158"""))
Rick Dean94e46fd2009-07-18 14:51:24 -0500159
Stephen Holsapple0d9815f2014-08-27 19:36:53 -0700160intermediate_server_cert_pem = b("""-----BEGIN CERTIFICATE-----
161MIICWDCCAcGgAwIBAgIRAPQFY9jfskSihdiNSNdt6GswDQYJKoZIhvcNAQENBQAw
162ZjEVMBMGA1UEAxMMaW50ZXJtZWRpYXRlMQwwCgYDVQQKEwNvcmcxETAPBgNVBAsT
163CG9yZy11bml0MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVNh
164biBEaWVnbzAeFw0xNDA4MjgwMjEwNDhaFw0yNDA4MjUwMjEwNDhaMG4xHTAbBgNV
165BAMTFGludGVybWVkaWF0ZS1zZXJ2aWNlMQwwCgYDVQQKEwNvcmcxETAPBgNVBAsT
166CG9yZy11bml0MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVNh
167biBEaWVnbzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqpJZygd+w1faLOr1
168iOAmbBhx5SZWcTCZ/ZjHQTJM7GuPT624QkqsixFghRKdDROwpwnAP7gMRukLqiy4
169+kRuGT5OfyGggL95i2xqA+zehjj08lSTlvGHpePJgCyTavIy5+Ljsj4DKnKyuhxm
170biXTRrH83NDgixVkObTEmh/OVK0CAwEAATANBgkqhkiG9w0BAQ0FAAOBgQBa0Npw
171UkzjaYEo1OUE1sTI6Mm4riTIHMak4/nswKh9hYup//WVOlr/RBSBtZ7Q/BwbjobN
1723bfAtV7eSAqBsfxYXyof7G1ALANQERkq3+oyLP1iVt08W1WOUlIMPhdCF/QuCwy6
173x9MJLhUCGLJPM+O2rAPWVD9wCmvq10ALsiH3yA==
174-----END CERTIFICATE-----
175""")
176
177intermediate_server_key_pem = b("""-----BEGIN RSA PRIVATE KEY-----
178MIICXAIBAAKBgQCqklnKB37DV9os6vWI4CZsGHHlJlZxMJn9mMdBMkzsa49PrbhC
179SqyLEWCFEp0NE7CnCcA/uAxG6QuqLLj6RG4ZPk5/IaCAv3mLbGoD7N6GOPTyVJOW
1808Yel48mALJNq8jLn4uOyPgMqcrK6HGZuJdNGsfzc0OCLFWQ5tMSaH85UrQIDAQAB
181AoGAIQ594j5zna3/9WaPsTgnmhlesVctt4AAx/n827DA4ayyuHFlXUuVhtoWR5Pk
1825ezj9mtYW8DyeCegABnsu2vZni/CdvU6uiS1Hv6qM1GyYDm9KWgovIP9rQCDSGaz
183d57IWVGxx7ODFkm3gN5nxnSBOFVHytuW1J7FBRnEsehRroECQQDXHFOv82JuXDcz
184z3+4c74IEURdOHcbycxlppmK9kFqm5lsUdydnnGW+mvwDk0APOB7Wg7vyFyr393e
185dpmBDCzNAkEAyv6tVbTKUYhSjW+QhabJo896/EqQEYUmtMXxk4cQnKeR/Ao84Rkf
186EqD5IykMUfUI0jJU4DGX+gWZ10a7kNbHYQJAVFCuHNFxS4Cpwo0aqtnzKoZaHY/8
187X9ABZfafSHCtw3Op92M+7ikkrOELXdS9KdKyyqbKJAKNEHF3LbOfB44WIQJAA2N4
1889UNNVUsXRbElEnYUS529CdUczo4QdVgQjkvk5RiPAUwSdBd9Q0xYnFOlFwEmIowg
189ipWJWe0aAlP18ZcEQQJBAL+5lekZ/GUdQoZ4HAsN5a9syrzavJ9VvU1KOOPorPZK
190nMRZbbQgP+aSB7yl6K0gaLaZ8XaK0pjxNBh6ASqg9f4=
191-----END RSA PRIVATE KEY-----
192""")
193
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400194client_cert_pem = b("""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500195MIICJjCCAY+gAwIBAgIJAKxpFI5lODkjMA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
196BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
197VGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBSb290IENBMCIYDzIwMDkwMzI1MTIz
198ODA1WhgPMjAxNzA2MTExMjM4MDVaMBYxFDASBgNVBAMTC3VnbHkgY2xpZW50MIGf
199MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDAZh/SRtNm5ntMT4qb6YzEpTroMlq2
200rn+GrRHRiZ+xkCw/CGNhbtPir7/QxaUj26BSmQrHw1bGKEbPsWiW7bdXSespl+xK
201iku4G/KvnnmWdeJHqsiXeUZtqurMELcPQAw9xPHEuhqqUJvvEoMTsnCEqGM+7Dtb
202oCRajYyHfluARQIDAQABozYwNDAdBgNVHQ4EFgQUNQB+qkaOaEVecf1J3TTUtAff
2030fAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQEFBQADgYEAyv/Jh7gM
204Q3OHvmsFEEvRI+hsW8y66zK4K5de239Y44iZrFYkt7Q5nBPMEWDj4F2hLYWL/qtI
2059Zdr0U4UDCU9SmmGYh4o7R4TZ5pGFvBYvjhHbkSFYFQXZxKUi+WUxplP6I0wr2KJ
206PSTJCjJOn3xo2NTKRgV1gaoTf2EhL+RG8TQ=
207-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400208""")
Rick Dean94e46fd2009-07-18 14:51:24 -0500209
Jean-Paul Calderone22cbe502011-05-04 17:01:43 -0400210client_key_pem = normalize_privatekey_pem(b("""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500211MIICXgIBAAKBgQDAZh/SRtNm5ntMT4qb6YzEpTroMlq2rn+GrRHRiZ+xkCw/CGNh
212btPir7/QxaUj26BSmQrHw1bGKEbPsWiW7bdXSespl+xKiku4G/KvnnmWdeJHqsiX
213eUZtqurMELcPQAw9xPHEuhqqUJvvEoMTsnCEqGM+7DtboCRajYyHfluARQIDAQAB
214AoGATkZ+NceY5Glqyl4mD06SdcKfV65814vg2EL7V9t8+/mi9rYL8KztSXGlQWPX
215zuHgtRoMl78yQ4ZJYOBVo+nsx8KZNRCEBlE19bamSbQLCeQMenWnpeYyQUZ908gF
216h6L9qsFVJepgA9RDgAjyDoS5CaWCdCCPCH2lDkdcqC54SVUCQQDseuduc4wi8h4t
217V8AahUn9fn9gYfhoNuM0gdguTA0nPLVWz4hy1yJiWYQe0H7NLNNTmCKiLQaJpAbb
218TC6vE8C7AkEA0Ee8CMJUc20BnGEmxwgWcVuqFWaKCo8jTH1X38FlATUsyR3krjW2
219dL3yDD9NwHxsYP7nTKp/U8MV7U9IBn4y/wJBAJl7H0/BcLeRmuJk7IqJ7b635iYB
220D/9beFUw3MUXmQXZUfyYz39xf6CDZsu1GEdEC5haykeln3Of4M9d/4Kj+FcCQQCY
221si6xwT7GzMDkk/ko684AV3KPc/h6G0yGtFIrMg7J3uExpR/VdH2KgwMkZXisSMvw
222JJEQjOMCVsEJlRk54WWjAkEAzoZNH6UhDdBK5F38rVt/y4SEHgbSfJHIAmPS32Kq
223f6GGcfNpip0Uk7q7udTKuX7Q/buZi/C4YW7u3VKAquv9NA==
224-----END RSA PRIVATE KEY-----
Jean-Paul Calderone22cbe502011-05-04 17:01:43 -0400225"""))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400226
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400227cleartextCertificatePEM = b("""-----BEGIN CERTIFICATE-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400228MIIC7TCCAlagAwIBAgIIPQzE4MbeufQwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE
229BhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdU
230ZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwIhgPMjAwOTAzMjUxMjM2
231NThaGA8yMDE3MDYxMTEyMzY1OFowWDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklM
232MRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9U
233ZXN0aW5nIFJvb3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPmaQumL
234urpE527uSEHdL1pqcDRmWzu+98Y6YHzT/J7KWEamyMCNZ6fRW1JCR782UQ8a07fy
2352xXsKy4WdKaxyG8CcatwmXvpvRQ44dSANMihHELpANTdyVp6DCysED6wkQFurHlF
2361dshEaJw8b/ypDhmbVIo6Ci1xvCJqivbLFnbAgMBAAGjgbswgbgwHQYDVR0OBBYE
237FINVdy1eIfFJDAkk51QJEo3IfgSuMIGIBgNVHSMEgYAwfoAUg1V3LV4h8UkMCSTn
238VAkSjch+BK6hXKRaMFgxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UE
239BxMHQ2hpY2FnbzEQMA4GA1UEChMHVGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBS
240b290IENBggg9DMTgxt659DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB
241AGGCDazMJGoWNBpc03u6+smc95dEead2KlZXBATOdFT1VesY3+nUOqZhEhTGlDMi
242hkgaZnzoIq/Uamidegk4hirsCT/R+6vsKAAxNTcBjUeZjlykCJWy5ojShGftXIKY
243w/njVbKMXrvc83qmTdGl3TAM0fxQIpqgcglFLveEBgzn
244-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400245""")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400246
Jean-Paul Calderoned50d2042011-05-04 17:00:49 -0400247cleartextPrivateKeyPEM = normalize_privatekey_pem(b("""\
248-----BEGIN RSA PRIVATE KEY-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400249MIICXQIBAAKBgQD5mkLpi7q6ROdu7khB3S9aanA0Zls7vvfGOmB80/yeylhGpsjA
250jWen0VtSQke/NlEPGtO38tsV7CsuFnSmschvAnGrcJl76b0UOOHUgDTIoRxC6QDU
2513claegwsrBA+sJEBbqx5RdXbIRGicPG/8qQ4Zm1SKOgotcbwiaor2yxZ2wIDAQAB
252AoGBAPCgMpmLxzwDaUmcFbTJUvlLW1hoxNNYSu2jIZm1k/hRAcE60JYwvBkgz3UB
253yMEh0AtLxYe0bFk6EHah11tMUPgscbCq73snJ++8koUw+csk22G65hOs51bVb7Aa
2546JBe67oLzdtvgCUFAA2qfrKzWRZzAdhUirQUZgySZk+Xq1pBAkEA/kZG0A6roTSM
255BVnx7LnPfsycKUsTumorpXiylZJjTi9XtmzxhrYN6wgZlDOOwOLgSQhszGpxVoMD
256u3gByT1b2QJBAPtL3mSKdvwRu/+40zaZLwvSJRxaj0mcE4BJOS6Oqs/hS1xRlrNk
257PpQ7WJ4yM6ZOLnXzm2mKyxm50Mv64109FtMCQQDOqS2KkjHaLowTGVxwC0DijMfr
258I9Lf8sSQk32J5VWCySWf5gGTfEnpmUa41gKTMJIbqZZLucNuDcOtzUaeWZlZAkA8
259ttXigLnCqR486JDPTi9ZscoZkZ+w7y6e/hH8t6d5Vjt48JVyfjPIaJY+km58LcN3
2606AWSeGAdtRFHVzR7oHjVAkB4hutvxiOeiIVQNBhM6RSI9aBPMI21DoX2JRoxvNW2
261cbvAhow217X9V0dVerEOKxnNYspXRrh36h7k4mQA+sDq
262-----END RSA PRIVATE KEY-----
Jean-Paul Calderoned50d2042011-05-04 17:00:49 -0400263"""))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400264
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400265cleartextCertificateRequestPEM = b("""-----BEGIN CERTIFICATE REQUEST-----
266MIIBnjCCAQcCAQAwXjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQH
267EwdDaGljYWdvMRcwFQYDVQQKEw5NeSBDb21wYW55IEx0ZDEXMBUGA1UEAxMORnJl
268ZGVyaWNrIERlYW4wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANp6Y17WzKSw
269BsUWkXdqg6tnXy8H8hA1msCMWpc+/2KJ4mbv5NyD6UD+/SqagQqulPbF/DFea9nA
270E0zhmHJELcM8gUTIlXv/cgDWnmK4xj8YkjVUiCdqKRAKeuzLG1pGmwwF5lGeJpXN
271xQn5ecR0UYSOWj6TTGXB9VyUMQzCClcBAgMBAAGgADANBgkqhkiG9w0BAQUFAAOB
272gQAAJGuF/R/GGbeC7FbFW+aJgr9ee0Xbl6nlhu7pTe67k+iiKT2dsl2ti68MVTnu
273Vrb3HUNqOkiwsJf6kCtq5oPn3QVYzTa76Dt2y3Rtzv6boRSlmlfrgS92GNma8JfR
274oICQk3nAudi6zl1Dix3BCv1pUp5KMtGn3MeDEi6QFGy2rA==
275-----END CERTIFICATE REQUEST-----
276""")
Rick Dean5b7b6372009-04-01 11:34:06 -0500277
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400278encryptedPrivateKeyPEM = b("""-----BEGIN RSA PRIVATE KEY-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400279Proc-Type: 4,ENCRYPTED
280DEK-Info: DES-EDE3-CBC,9573604A18579E9E
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400281
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400282SHOho56WxDkT0ht10UTeKc0F5u8cqIa01kzFAmETw0MAs8ezYtK15NPdCXUm3X/2
283a17G7LSF5bkxOgZ7vpXyMzun/owrj7CzvLxyncyEFZWvtvzaAhPhvTJtTIB3kf8B
2848+qRcpTGK7NgXEgYBW5bj1y4qZkD4zCL9o9NQzsKI3Ie8i0239jsDOWR38AxjXBH
285mGwAQ4Z6ZN5dnmM4fhMIWsmFf19sNyAML4gHenQCHhmXbjXeVq47aC2ProInJbrm
286+00TcisbAQ40V9aehVbcDKtS4ZbMVDwncAjpXpcncC54G76N6j7F7wL7L/FuXa3A
287fvSVy9n2VfF/pJ3kYSflLHH2G/DFxjF7dl0GxhKPxJjp3IJi9VtuvmN9R2jZWLQF
288tfC8dXgy/P9CfFQhlinqBTEwgH0oZ/d4k4NVFDSdEMaSdmBAjlHpc+Vfdty3HVnV
289rKXj//wslsFNm9kIwJGIgKUa/n2jsOiydrsk1mgH7SmNCb3YHgZhbbnq0qLat/HC
290gHDt3FHpNQ31QzzL3yrenFB2L9osIsnRsDTPFNi4RX4SpDgNroxOQmyzCCV6H+d4
291o1mcnNiZSdxLZxVKccq0AfRpHqpPAFnJcQHP6xyT9MZp6fBa0XkxDnt9kNU8H3Qw
2927SJWZ69VXjBUzMlQViLuaWMgTnL+ZVyFZf9hTF7U/ef4HMLMAVNdiaGG+G+AjCV/
293MbzjS007Oe4qqBnCWaFPSnJX6uLApeTbqAxAeyCql56ULW5x6vDMNC3dwjvS/CEh
29411n8RkgFIQA0AhuKSIg3CbuartRsJnWOLwgLTzsrKYL4yRog1RJrtw==
295-----END RSA PRIVATE KEY-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400296""")
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400297
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400298encryptedPrivateKeyPEMPassphrase = b("foobar")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400299
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400300# Some PKCS#7 stuff. Generated with the openssl command line:
301#
302# openssl crl2pkcs7 -inform pem -outform pem -certfile s.pem -nocrl
303#
304# with a certificate and key (but the key should be irrelevant) in s.pem
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400305pkcs7Data = b("""\
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400306-----BEGIN PKCS7-----
307MIIDNwYJKoZIhvcNAQcCoIIDKDCCAyQCAQExADALBgkqhkiG9w0BBwGgggMKMIID
308BjCCAm+gAwIBAgIBATANBgkqhkiG9w0BAQQFADB7MQswCQYDVQQGEwJTRzERMA8G
309A1UEChMITTJDcnlwdG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtN
310MkNyeXB0byBDZXJ0aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNA
311cG9zdDEuY29tMB4XDTAwMDkxMDA5NTEzMFoXDTAyMDkxMDA5NTEzMFowUzELMAkG
312A1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwlsb2NhbGhvc3Qx
313HTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tMFwwDQYJKoZIhvcNAQEBBQAD
314SwAwSAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh5kwI
315zOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEAAaOCAQQwggEAMAkGA1UdEwQCMAAw
316LAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0G
317A1UdDgQWBBTPhIKSvnsmYsBVNWjj0m3M2z0qVTCBpQYDVR0jBIGdMIGagBT7hyNp
31865w6kxXlxb8pUU/+7Sg4AaF/pH0wezELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0y
319Q3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlwdG8g
320Q2VydGlmaWNhdGUgTWFzdGVyMR0wGwYJKoZIhvcNAQkBFg5uZ3BzQHBvc3QxLmNv
321bYIBADANBgkqhkiG9w0BAQQFAAOBgQA7/CqT6PoHycTdhEStWNZde7M/2Yc6BoJu
322VwnW8YxGO8Sn6UJ4FeffZNcYZddSDKosw8LtPOeWoK3JINjAk5jiPQ2cww++7QGG
323/g5NDjxFZNDJP1dGiLAxPW6JXwov4v0FmdzfLOZ01jDcgQQZqEpYlgpuI5JEWUQ9
324Ho4EzbYCOaEAMQA=
325-----END PKCS7-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400326""")
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400327
Alex Gaynor8fa1dd62014-08-14 09:57:51 -0700328pkcs7DataASN1 = base64.b64decode(b"""
Alex Gaynor4b9c96a2014-08-14 09:51:48 -0700329MIIDNwYJKoZIhvcNAQcCoIIDKDCCAyQCAQExADALBgkqhkiG9w0BBwGgggMKMIID
330BjCCAm+gAwIBAgIBATANBgkqhkiG9w0BAQQFADB7MQswCQYDVQQGEwJTRzERMA8G
331A1UEChMITTJDcnlwdG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtN
332MkNyeXB0byBDZXJ0aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNA
333cG9zdDEuY29tMB4XDTAwMDkxMDA5NTEzMFoXDTAyMDkxMDA5NTEzMFowUzELMAkG
334A1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwlsb2NhbGhvc3Qx
335HTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tMFwwDQYJKoZIhvcNAQEBBQAD
336SwAwSAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh5kwI
337zOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEAAaOCAQQwggEAMAkGA1UdEwQCMAAw
338LAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0G
339A1UdDgQWBBTPhIKSvnsmYsBVNWjj0m3M2z0qVTCBpQYDVR0jBIGdMIGagBT7hyNp
34065w6kxXlxb8pUU/+7Sg4AaF/pH0wezELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0y
341Q3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlwdG8g
342Q2VydGlmaWNhdGUgTWFzdGVyMR0wGwYJKoZIhvcNAQkBFg5uZ3BzQHBvc3QxLmNv
343bYIBADANBgkqhkiG9w0BAQQFAAOBgQA7/CqT6PoHycTdhEStWNZde7M/2Yc6BoJu
344VwnW8YxGO8Sn6UJ4FeffZNcYZddSDKosw8LtPOeWoK3JINjAk5jiPQ2cww++7QGG
345/g5NDjxFZNDJP1dGiLAxPW6JXwov4v0FmdzfLOZ01jDcgQQZqEpYlgpuI5JEWUQ9
346Ho4EzbYCOaEAMQA=
Alex Gaynor8fa1dd62014-08-14 09:57:51 -0700347""")
Alex Gaynor4b9c96a2014-08-14 09:51:48 -0700348
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400349crlData = b("""\
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -0500350-----BEGIN X509 CRL-----
351MIIBWzCBxTANBgkqhkiG9w0BAQQFADBYMQswCQYDVQQGEwJVUzELMAkGA1UECBMC
352SUwxEDAOBgNVBAcTB0NoaWNhZ28xEDAOBgNVBAoTB1Rlc3RpbmcxGDAWBgNVBAMT
353D1Rlc3RpbmcgUm9vdCBDQRcNMDkwNzI2MDQzNDU2WhcNMTIwOTI3MDI0MTUyWjA8
354MBUCAgOrGA8yMDA5MDcyNTIzMzQ1NlowIwICAQAYDzIwMDkwNzI1MjMzNDU2WjAM
355MAoGA1UdFQQDCgEEMA0GCSqGSIb3DQEBBAUAA4GBAEBt7xTs2htdD3d4ErrcGAw1
3564dKcVnIWTutoI7xxen26Wwvh8VCsT7i/UeP+rBl9rC/kfjWjzQk3/zleaarGTpBT
3570yp4HXRFFoRhhSE/hP+eteaPXRgrsNRLHe9ZDd69wmh7J1wMDb0m81RG7kqcbsid
358vrzEeLDRiiPl92dyyWmu
359-----END X509 CRL-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400360""")
Jean-Paul Calderonee890db32010-08-22 16:55:15 -0400361
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400362
363# A broken RSA private key which can be used to test the error path through
364# PKey.check.
365inconsistentPrivateKeyPEM = b("""-----BEGIN RSA PRIVATE KEY-----
366MIIBPAIBAAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh
3675kwIzOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEaAQJBAIqm/bz4NA1H++Vx5Ewx
368OcKp3w19QSaZAwlGRtsUxrP7436QjnREM3Bm8ygU11BjkPVmtrKm6AayQfCHqJoT
369zIECIQDW0BoMoL0HOYM/mrTLhaykYAVqgIeJsPjvkEhTFXWBuQIhAM3deFAvWNu4
370nklUQ37XsCT2c9tmNt1LAT+slG2JOTTRAiAuXDtC/m3NYVwyHfFm+zKHRzHkClk2
371HjubeEgjpj32AQIhAJqMGTaZVOwevTXvvHwNeH+vRWsAYU/gbx+OQB+7VOcBAiEA
372oolb6NMg/R3enNPvS1O4UU1H8wpaF77L4yiSWlE0p4w=
373-----END RSA PRIVATE KEY-----
374""")
375
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -0400376# certificate with NULL bytes in subjectAltName and common name
377
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400378nulbyteSubjectAltNamePEM = b("""-----BEGIN CERTIFICATE-----
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -0400379MIIE2DCCA8CgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBxTELMAkGA1UEBhMCVVMx
380DzANBgNVBAgMBk9yZWdvbjESMBAGA1UEBwwJQmVhdmVydG9uMSMwIQYDVQQKDBpQ
381eXRob24gU29mdHdhcmUgRm91bmRhdGlvbjEgMB4GA1UECwwXUHl0aG9uIENvcmUg
382RGV2ZWxvcG1lbnQxJDAiBgNVBAMMG251bGwucHl0aG9uLm9yZwBleGFtcGxlLm9y
383ZzEkMCIGCSqGSIb3DQEJARYVcHl0aG9uLWRldkBweXRob24ub3JnMB4XDTEzMDgw
384NzEzMTE1MloXDTEzMDgwNzEzMTI1MlowgcUxCzAJBgNVBAYTAlVTMQ8wDQYDVQQI
385DAZPcmVnb24xEjAQBgNVBAcMCUJlYXZlcnRvbjEjMCEGA1UECgwaUHl0aG9uIFNv
386ZnR3YXJlIEZvdW5kYXRpb24xIDAeBgNVBAsMF1B5dGhvbiBDb3JlIERldmVsb3Bt
387ZW50MSQwIgYDVQQDDBtudWxsLnB5dGhvbi5vcmcAZXhhbXBsZS5vcmcxJDAiBgkq
388hkiG9w0BCQEWFXB5dGhvbi1kZXZAcHl0aG9uLm9yZzCCASIwDQYJKoZIhvcNAQEB
389BQADggEPADCCAQoCggEBALXq7cn7Rn1vO3aA3TrzA5QLp6bb7B3f/yN0CJ2XFj+j
390pHs+Gw6WWSUDpybiiKnPec33BFawq3kyblnBMjBU61ioy5HwQqVkJ8vUVjGIUq3P
391vX/wBmQfzCe4o4uM89gpHyUL9UYGG8oCRa17dgqcv7u5rg0Wq2B1rgY+nHwx3JIv
392KRrgSwyRkGzpN8WQ1yrXlxWjgI9de0mPVDDUlywcWze1q2kwaEPTM3hLAmD1PESA
393oY/n8A/RXoeeRs9i/Pm/DGUS8ZPINXk/yOzsR/XvvkTVroIeLZqfmFpnZeF0cHzL
39408LODkVJJ9zjLdT7SA4vnne4FEbAxDbKAq5qkYzaL4UCAwEAAaOB0DCBzTAMBgNV
395HRMBAf8EAjAAMB0GA1UdDgQWBBSIWlXAUv9hzVKjNQ/qWpwkOCL3XDALBgNVHQ8E
396BAMCBeAwgZAGA1UdEQSBiDCBhYIeYWx0bnVsbC5weXRob24ub3JnAGV4YW1wbGUu
397Y29tgSBudWxsQHB5dGhvbi5vcmcAdXNlckBleGFtcGxlLm9yZ4YpaHR0cDovL251
398bGwucHl0aG9uLm9yZwBodHRwOi8vZXhhbXBsZS5vcmeHBMAAAgGHECABDbgAAAAA
399AAAAAAAAAAEwDQYJKoZIhvcNAQEFBQADggEBAKxPRe99SaghcI6IWT7UNkJw9aO9
400i9eo0Fj2MUqxpKbdb9noRDy2CnHWf7EIYZ1gznXPdwzSN4YCjV5d+Q9xtBaowT0j
401HPERs1ZuytCNNJTmhyqZ8q6uzMLoht4IqH/FBfpvgaeC5tBTnTT0rD5A/olXeimk
402kX4LxlEx5RAvpGB2zZVRGr6LobD9rVK91xuHYNIxxxfEGE8tCCWjp0+3ksri9SXx
403VHWBnbM9YaL32u3hxm8sYB/Yb8WSBavJCWJJqRStVRHM1koZlJmXNx2BX4vPo6iW
404RFEIPQsFZRLrtnCAiEhyT8bC2s/Njlu6ly9gtJZWSV46Q3ZjBL4q9sHKqZQ=
405-----END CERTIFICATE-----""")
406
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400407
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400408class X509ExtTests(TestCase):
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400409 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900410 Tests for :py:class:`OpenSSL.crypto.X509Extension`.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400411 """
412
413 def setUp(self):
414 """
415 Create a new private key and start a certificate request (for a test
416 method to finish in one way or another).
417 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -0800418 super(X509ExtTests, self).setUp()
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400419 # Basic setup stuff to generate a certificate
420 self.pkey = PKey()
421 self.pkey.generate_key(TYPE_RSA, 384)
422 self.req = X509Req()
423 self.req.set_pubkey(self.pkey)
424 # Authority good you have.
425 self.req.get_subject().commonName = "Yoda root CA"
426 self.x509 = X509()
427 self.subject = self.x509.get_subject()
428 self.subject.commonName = self.req.get_subject().commonName
429 self.x509.set_issuer(self.subject)
430 self.x509.set_pubkey(self.pkey)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400431 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Alex Gaynor7f636492015-09-04 13:26:52 -0400432 expire = b((datetime.now() + timedelta(days=100)).strftime("%Y%m%d%H%M%SZ"))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400433 self.x509.set_notBefore(now)
434 self.x509.set_notAfter(expire)
435
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -0800436 def tearDown(self):
437 """
438 Forget all of the pyOpenSSL objects so they can be garbage collected,
439 their memory released, and not interfere with the leak detection code.
440 """
441 self.pkey = self.req = self.x509 = self.subject = None
442 super(X509ExtTests, self).tearDown()
443
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400444 def test_str(self):
445 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900446 The string representation of :py:class:`X509Extension` instances as returned by
447 :py:data:`str` includes stuff.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400448 """
449 # This isn't necessarily the best string representation. Perhaps it
450 # will be changed/improved in the future.
451 self.assertEquals(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400452 str(X509Extension(b('basicConstraints'), True, b('CA:false'))),
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400453 'CA:FALSE')
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
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500465 def test_construction(self):
466 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900467 :py:class:`X509Extension` accepts an extension type name, a critical flag,
468 and an extension value and returns an :py:class:`X509ExtensionType` instance.
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500469 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400470 basic = X509Extension(b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500471 self.assertTrue(
472 isinstance(basic, X509ExtensionType),
473 "%r is of type %r, should be %r" % (
474 basic, type(basic), X509ExtensionType))
475
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400476 comment = X509Extension(
477 b('nsComment'), False, b('pyOpenSSL unit test'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500478 self.assertTrue(
479 isinstance(comment, X509ExtensionType),
480 "%r is of type %r, should be %r" % (
481 comment, type(comment), X509ExtensionType))
482
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500483 def test_invalid_extension(self):
484 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900485 :py:class:`X509Extension` raises something if it is passed a bad extension
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500486 name or value.
487 """
488 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400489 Error, X509Extension, b('thisIsMadeUp'), False, b('hi'))
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500490 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400491 Error, X509Extension, b('basicConstraints'), False, b('blah blah'))
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500492
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500493 # Exercise a weird one (an extension which uses the r2i method). This
494 # exercises the codepath that requires a non-NULL ctx to be passed to
495 # X509V3_EXT_nconf. It can't work now because we provide no
496 # configuration database. It might be made to work in the future.
497 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400498 Error, X509Extension, b('proxyCertInfo'), True,
499 b('language:id-ppl-anyLanguage,pathlen:1,policy:text:AB'))
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500500
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500501 def test_get_critical(self):
502 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900503 :py:meth:`X509ExtensionType.get_critical` returns the value of the
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500504 extension's critical flag.
505 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400506 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500507 self.assertTrue(ext.get_critical())
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400508 ext = X509Extension(b('basicConstraints'), False, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500509 self.assertFalse(ext.get_critical())
510
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500511 def test_get_short_name(self):
512 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900513 :py:meth:`X509ExtensionType.get_short_name` returns a string giving the short
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500514 type name of the extension.
515 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400516 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
517 self.assertEqual(ext.get_short_name(), b('basicConstraints'))
518 ext = X509Extension(b('nsComment'), True, b('foo bar'))
519 self.assertEqual(ext.get_short_name(), b('nsComment'))
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500520
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400521 def test_get_data(self):
522 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900523 :py:meth:`X509Extension.get_data` returns a string giving the data of the
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400524 extension.
525 """
526 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
527 # Expect to get back the DER encoded form of CA:true.
528 self.assertEqual(ext.get_data(), b('0\x03\x01\x01\xff'))
529
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400530 def test_get_data_wrong_args(self):
531 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900532 :py:meth:`X509Extension.get_data` raises :py:exc:`TypeError` if passed any arguments.
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400533 """
534 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
535 self.assertRaises(TypeError, ext.get_data, None)
536 self.assertRaises(TypeError, ext.get_data, "foo")
537 self.assertRaises(TypeError, ext.get_data, 7)
538
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400539 def test_unused_subject(self):
Rick Dean47262da2009-07-08 16:17:17 -0500540 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900541 The :py:data:`subject` parameter to :py:class:`X509Extension` may be provided for an
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400542 extension which does not use it and is ignored in this case.
Rick Dean47262da2009-07-08 16:17:17 -0500543 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400544 ext1 = X509Extension(
545 b('basicConstraints'), False, b('CA:TRUE'), subject=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400546 self.x509.add_extensions([ext1])
547 self.x509.sign(self.pkey, 'sha1')
548 # This is a little lame. Can we think of a better way?
549 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400550 self.assertTrue(b('X509v3 Basic Constraints:') in text)
551 self.assertTrue(b('CA:TRUE') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400552
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400553 def test_subject(self):
554 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900555 If an extension requires a subject, the :py:data:`subject` parameter to
556 :py:class:`X509Extension` provides its value.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400557 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400558 ext3 = X509Extension(
559 b('subjectKeyIdentifier'), False, b('hash'), subject=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400560 self.x509.add_extensions([ext3])
561 self.x509.sign(self.pkey, 'sha1')
562 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400563 self.assertTrue(b('X509v3 Subject Key Identifier:') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400564
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400565 def test_missing_subject(self):
566 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900567 If an extension requires a subject and the :py:data:`subject` parameter is
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400568 given no value, something happens.
569 """
570 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400571 Error, X509Extension, b('subjectKeyIdentifier'), False, b('hash'))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400572
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400573 def test_invalid_subject(self):
574 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900575 If the :py:data:`subject` parameter is given a value which is not an
576 :py:class:`X509` instance, :py:exc:`TypeError` is raised.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400577 """
578 for badObj in [True, object(), "hello", [], self]:
579 self.assertRaises(
580 TypeError,
581 X509Extension,
582 'basicConstraints', False, 'CA:TRUE', subject=badObj)
583
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400584 def test_unused_issuer(self):
585 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900586 The :py:data:`issuer` parameter to :py:class:`X509Extension` may be provided for an
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400587 extension which does not use it and is ignored in this case.
588 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400589 ext1 = X509Extension(
590 b('basicConstraints'), False, b('CA:TRUE'), issuer=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400591 self.x509.add_extensions([ext1])
592 self.x509.sign(self.pkey, 'sha1')
593 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400594 self.assertTrue(b('X509v3 Basic Constraints:') in text)
595 self.assertTrue(b('CA:TRUE') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400596
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400597 def test_issuer(self):
598 """
Alex Gaynor3b0ee972014-11-15 09:17:33 -0800599 If an extension requires an issuer, the :py:data:`issuer` parameter to
Jonathan Ballet648875f2011-07-16 14:14:58 +0900600 :py:class:`X509Extension` provides its value.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400601 """
602 ext2 = X509Extension(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400603 b('authorityKeyIdentifier'), False, b('issuer:always'),
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400604 issuer=self.x509)
605 self.x509.add_extensions([ext2])
606 self.x509.sign(self.pkey, 'sha1')
607 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400608 self.assertTrue(b('X509v3 Authority Key Identifier:') in text)
609 self.assertTrue(b('DirName:/CN=Yoda root CA') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400610
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400611 def test_missing_issuer(self):
612 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900613 If an extension requires an issue and the :py:data:`issuer` parameter is given
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400614 no value, something happens.
615 """
616 self.assertRaises(
617 Error,
618 X509Extension,
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400619 b('authorityKeyIdentifier'), False,
620 b('keyid:always,issuer:always'))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400621
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400622 def test_invalid_issuer(self):
623 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900624 If the :py:data:`issuer` parameter is given a value which is not an
625 :py:class:`X509` instance, :py:exc:`TypeError` is raised.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400626 """
627 for badObj in [True, object(), "hello", [], self]:
628 self.assertRaises(
629 TypeError,
630 X509Extension,
631 'authorityKeyIdentifier', False, 'keyid:always,issuer:always',
632 issuer=badObj)
Rick Dean47262da2009-07-08 16:17:17 -0500633
634
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400635class PKeyTests(TestCase):
Jean-Paul Calderoneac930e12008-03-06 18:50:51 -0500636 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900637 Unit tests for :py:class:`OpenSSL.crypto.PKey`.
Jean-Paul Calderoneac930e12008-03-06 18:50:51 -0500638 """
Alex Gaynoraceb3e22015-09-05 12:00:22 -0400639
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400640 def test_type(self):
641 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900642 :py:class:`PKey` and :py:class:`PKeyType` refer to the same type object
643 and can be used to create instances of that type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400644 """
645 self.assertIdentical(PKey, PKeyType)
646 self.assertConsistentType(PKey, 'PKey')
647
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500648 def test_construction(self):
649 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900650 :py:class:`PKey` takes no arguments and returns a new :py:class:`PKey` instance.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500651 """
652 self.assertRaises(TypeError, PKey, None)
653 key = PKey()
654 self.assertTrue(
655 isinstance(key, PKeyType),
656 "%r is of type %r, should be %r" % (key, type(key), PKeyType))
657
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500658 def test_pregeneration(self):
659 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900660 :py:attr:`PKeyType.bits` and :py:attr:`PKeyType.type` return :py:data:`0` before the key is
661 generated. :py:attr:`PKeyType.check` raises :py:exc:`TypeError` before the key is
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500662 generated.
663 """
664 key = PKey()
665 self.assertEqual(key.type(), 0)
666 self.assertEqual(key.bits(), 0)
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400667 self.assertRaises(TypeError, key.check)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500668
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500669 def test_failedGeneration(self):
670 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900671 :py:meth:`PKeyType.generate_key` takes two arguments, the first giving the key
672 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 -0500673 number of bits to generate. If an invalid type is specified or
Jonathan Ballet648875f2011-07-16 14:14:58 +0900674 generation fails, :py:exc:`Error` is raised. If an invalid number of bits is
675 specified, :py:exc:`ValueError` or :py:exc:`Error` is raised.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500676 """
677 key = PKey()
678 self.assertRaises(TypeError, key.generate_key)
679 self.assertRaises(TypeError, key.generate_key, 1, 2, 3)
680 self.assertRaises(TypeError, key.generate_key, "foo", "bar")
681 self.assertRaises(Error, key.generate_key, -1, 0)
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500682
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500683 self.assertRaises(ValueError, key.generate_key, TYPE_RSA, -1)
684 self.assertRaises(ValueError, key.generate_key, TYPE_RSA, 0)
Jean-Paul Calderoned71fe982008-03-06 00:31:50 -0500685
686 # XXX RSA generation for small values of bits is fairly buggy in a wide
687 # range of OpenSSL versions. I need to figure out what the safe lower
688 # bound for a reasonable number of OpenSSL versions is and explicitly
689 # check for that in the wrapper. The failure behavior is typically an
690 # infinite loop inside OpenSSL.
691
692 # self.assertRaises(Error, key.generate_key, TYPE_RSA, 2)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500693
694 # XXX DSA generation seems happy with any number of bits. The DSS
695 # says bits must be between 512 and 1024 inclusive. OpenSSL's DSA
696 # generator doesn't seem to care about the upper limit at all. For
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500697 # the lower limit, it uses 512 if anything smaller is specified.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500698 # So, it doesn't seem possible to make generate_key fail for
699 # TYPE_DSA with a bits argument which is at least an int.
700
701 # self.assertRaises(Error, key.generate_key, TYPE_DSA, -7)
702
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500703 def test_rsaGeneration(self):
704 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900705 :py:meth:`PKeyType.generate_key` generates an RSA key when passed
706 :py:data:`TYPE_RSA` as a type and a reasonable number of bits.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500707 """
708 bits = 128
709 key = PKey()
710 key.generate_key(TYPE_RSA, bits)
711 self.assertEqual(key.type(), TYPE_RSA)
712 self.assertEqual(key.bits(), bits)
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -0400713 self.assertTrue(key.check())
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500714
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500715 def test_dsaGeneration(self):
716 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900717 :py:meth:`PKeyType.generate_key` generates a DSA key when passed
718 :py:data:`TYPE_DSA` as a type and a reasonable number of bits.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500719 """
720 # 512 is a magic number. The DSS (Digital Signature Standard)
721 # allows a minimum of 512 bits for DSA. DSA_generate_parameters
722 # will silently promote any value below 512 to 512.
723 bits = 512
724 key = PKey()
725 key.generate_key(TYPE_DSA, bits)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800726 # self.assertEqual(key.type(), TYPE_DSA)
727 # self.assertEqual(key.bits(), bits)
728 # self.assertRaises(TypeError, key.check)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500729
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500730 def test_regeneration(self):
731 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900732 :py:meth:`PKeyType.generate_key` can be called multiple times on the same
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500733 key to generate new keys.
734 """
735 key = PKey()
736 for type, bits in [(TYPE_RSA, 512), (TYPE_DSA, 576)]:
Alex Gaynor7f636492015-09-04 13:26:52 -0400737 key.generate_key(type, bits)
738 self.assertEqual(key.type(), type)
739 self.assertEqual(key.bits(), bits)
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500740
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400741 def test_inconsistentKey(self):
742 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900743 :py:`PKeyType.check` returns :py:exc:`Error` if the key is not consistent.
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400744 """
745 key = load_privatekey(FILETYPE_PEM, inconsistentPrivateKeyPEM)
Jean-Paul Calderoned338e4e2009-05-13 15:45:07 -0400746 self.assertRaises(Error, key.check)
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400747
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400748 def test_check_wrong_args(self):
749 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900750 :py:meth:`PKeyType.check` raises :py:exc:`TypeError` if called with any arguments.
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400751 """
752 self.assertRaises(TypeError, PKey().check, None)
753 self.assertRaises(TypeError, PKey().check, object())
754 self.assertRaises(TypeError, PKey().check, 1)
755
Jean-Paul Calderone02d01972011-10-31 10:39:29 -0400756 def test_check_public_key(self):
757 """
758 :py:meth:`PKeyType.check` raises :py:exc:`TypeError` if only the public
759 part of the key is available.
760 """
761 # A trick to get a public-only key
762 key = PKey()
763 key.generate_key(TYPE_RSA, 512)
764 cert = X509()
765 cert.set_pubkey(key)
766 pub = cert.get_pubkey()
767 self.assertRaises(TypeError, pub.check)
768
769
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400770class X509NameTests(TestCase):
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500771 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900772 Unit tests for :py:class:`OpenSSL.crypto.X509Name`.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500773 """
Alex Gaynoraceb3e22015-09-05 12:00:22 -0400774
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500775 def _x509name(self, **attrs):
776 # XXX There's no other way to get a new X509Name yet.
777 name = X509().get_subject()
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400778 attrs = list(attrs.items())
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500779 # Make the order stable - order matters!
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400780 def key(attr):
781 return attr[1]
782 attrs.sort(key=key)
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500783 for k, v in attrs:
784 setattr(name, k, v)
785 return name
786
Rick Deane15b1472009-07-09 15:53:42 -0500787 def test_type(self):
788 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900789 The type of X509Name objects is :py:class:`X509NameType`.
Rick Deane15b1472009-07-09 15:53:42 -0500790 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400791 self.assertIdentical(X509Name, X509NameType)
792 self.assertEqual(X509NameType.__name__, 'X509Name')
793 self.assertTrue(isinstance(X509NameType, type))
794
Rick Deane15b1472009-07-09 15:53:42 -0500795 name = self._x509name()
796 self.assertTrue(
797 isinstance(name, X509NameType),
798 "%r is of type %r, should be %r" % (
799 name, type(name), X509NameType))
Rick Deane15b1472009-07-09 15:53:42 -0500800
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400801 def test_onlyStringAttributes(self):
802 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900803 Attempting to set a non-:py:data:`str` attribute name on an :py:class:`X509NameType`
804 instance causes :py:exc:`TypeError` to be raised.
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400805 """
806 name = self._x509name()
807 # Beyond these cases, you may also think that unicode should be
808 # rejected. Sorry, you're wrong. unicode is automatically converted to
809 # str outside of the control of X509Name, so there's no way to reject
810 # it.
Jean-Paul Calderoneff363be2013-03-03 10:21:23 -0800811
812 # Also, this used to test str subclasses, but that test is less relevant
813 # now that the implementation is in Python instead of C. Also PyPy
814 # automatically converts str subclasses to str when they are passed to
815 # setattr, so we can't test it on PyPy. Apparently CPython does this
816 # sometimes as well.
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400817 self.assertRaises(TypeError, setattr, name, None, "hello")
818 self.assertRaises(TypeError, setattr, name, 30, "hello")
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400819
820 def test_setInvalidAttribute(self):
821 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900822 Attempting to set any attribute name on an :py:class:`X509NameType` instance for
823 which no corresponding NID is defined causes :py:exc:`AttributeError` to be
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400824 raised.
825 """
826 name = self._x509name()
827 self.assertRaises(AttributeError, setattr, name, "no such thing", None)
828
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500829 def test_attributes(self):
830 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900831 :py:class:`X509NameType` instances have attributes for each standard (?)
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500832 X509Name field.
833 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500834 name = self._x509name()
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500835 name.commonName = "foo"
836 self.assertEqual(name.commonName, "foo")
837 self.assertEqual(name.CN, "foo")
838 name.CN = "baz"
839 self.assertEqual(name.commonName, "baz")
840 self.assertEqual(name.CN, "baz")
841 name.commonName = "bar"
842 self.assertEqual(name.commonName, "bar")
843 self.assertEqual(name.CN, "bar")
844 name.CN = "quux"
845 self.assertEqual(name.commonName, "quux")
846 self.assertEqual(name.CN, "quux")
847
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500848 def test_copy(self):
849 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900850 :py:class:`X509Name` creates a new :py:class:`X509NameType` instance with all the same
851 attributes as an existing :py:class:`X509NameType` instance when called with
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500852 one.
853 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500854 name = self._x509name(commonName="foo", emailAddress="bar@example.com")
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500855
856 copy = X509Name(name)
857 self.assertEqual(copy.commonName, "foo")
858 self.assertEqual(copy.emailAddress, "bar@example.com")
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500859
860 # Mutate the copy and ensure the original is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500861 copy.commonName = "baz"
862 self.assertEqual(name.commonName, "foo")
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500863
864 # Mutate the original and ensure the copy is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500865 name.emailAddress = "quux@example.com"
866 self.assertEqual(copy.emailAddress, "bar@example.com")
867
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500868 def test_repr(self):
869 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900870 :py:func:`repr` passed an :py:class:`X509NameType` instance should return a string
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500871 containing a description of the type and the NIDs which have been set
872 on it.
873 """
874 name = self._x509name(commonName="foo", emailAddress="bar")
875 self.assertEqual(
876 repr(name),
877 "<X509Name object '/emailAddress=bar/CN=foo'>")
878
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500879 def test_comparison(self):
880 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900881 :py:class:`X509NameType` instances should compare based on their NIDs.
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500882 """
883 def _equality(a, b, assertTrue, assertFalse):
884 assertTrue(a == b, "(%r == %r) --> False" % (a, b))
885 assertFalse(a != b)
886 assertTrue(b == a)
887 assertFalse(b != a)
888
889 def assertEqual(a, b):
890 _equality(a, b, self.assertTrue, self.assertFalse)
891
892 # Instances compare equal to themselves.
893 name = self._x509name()
894 assertEqual(name, name)
895
896 # Empty instances should compare equal to each other.
897 assertEqual(self._x509name(), self._x509name())
898
899 # Instances with equal NIDs should compare equal to each other.
900 assertEqual(self._x509name(commonName="foo"),
901 self._x509name(commonName="foo"))
902
903 # Instance with equal NIDs set using different aliases should compare
904 # equal to each other.
905 assertEqual(self._x509name(commonName="foo"),
906 self._x509name(CN="foo"))
907
908 # Instances with more than one NID with the same values should compare
909 # equal to each other.
910 assertEqual(self._x509name(CN="foo", organizationalUnitName="bar"),
911 self._x509name(commonName="foo", OU="bar"))
912
913 def assertNotEqual(a, b):
914 _equality(a, b, self.assertFalse, self.assertTrue)
915
916 # Instances with different values for the same NID should not compare
917 # equal to each other.
918 assertNotEqual(self._x509name(CN="foo"),
919 self._x509name(CN="bar"))
920
921 # Instances with different NIDs should not compare equal to each other.
922 assertNotEqual(self._x509name(CN="foo"),
923 self._x509name(OU="foo"))
924
925 def _inequality(a, b, assertTrue, assertFalse):
926 assertTrue(a < b)
927 assertTrue(a <= b)
928 assertTrue(b > a)
929 assertTrue(b >= a)
930 assertFalse(a > b)
931 assertFalse(a >= b)
932 assertFalse(b < a)
933 assertFalse(b <= a)
934
935 def assertLessThan(a, b):
936 _inequality(a, b, self.assertTrue, self.assertFalse)
937
938 # An X509Name with a NID with a value which sorts less than the value
939 # of the same NID on another X509Name compares less than the other
940 # X509Name.
941 assertLessThan(self._x509name(CN="abc"),
942 self._x509name(CN="def"))
943
944 def assertGreaterThan(a, b):
945 _inequality(a, b, self.assertFalse, self.assertTrue)
946
947 # An X509Name with a NID with a value which sorts greater than the
948 # value of the same NID on another X509Name compares greater than the
949 # other X509Name.
950 assertGreaterThan(self._x509name(CN="def"),
951 self._x509name(CN="abc"))
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -0500952
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400953 def test_hash(self):
954 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900955 :py:meth:`X509Name.hash` returns an integer hash based on the value of the
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400956 name.
957 """
958 a = self._x509name(CN="foo")
959 b = self._x509name(CN="foo")
960 self.assertEqual(a.hash(), b.hash())
961 a.CN = "bar"
962 self.assertNotEqual(a.hash(), b.hash())
963
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400964 def test_der(self):
965 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900966 :py:meth:`X509Name.der` returns the DER encoded form of the name.
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400967 """
968 a = self._x509name(CN="foo", C="US")
969 self.assertEqual(
970 a.der(),
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -0400971 b('0\x1b1\x0b0\t\x06\x03U\x04\x06\x13\x02US'
D.S. Ljungmark5533e252014-05-31 13:18:41 +0200972 '1\x0c0\n\x06\x03U\x04\x03\x0c\x03foo'))
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400973
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400974 def test_get_components(self):
975 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900976 :py:meth:`X509Name.get_components` returns a :py:data:`list` of
977 two-tuples of :py:data:`str`
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400978 giving the NIDs and associated values which make up the name.
979 """
980 a = self._x509name()
981 self.assertEqual(a.get_components(), [])
982 a.CN = "foo"
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -0400983 self.assertEqual(a.get_components(), [(b("CN"), b("foo"))])
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400984 a.organizationalUnitName = "bar"
985 self.assertEqual(
986 a.get_components(),
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -0400987 [(b("CN"), b("foo")), (b("OU"), b("bar"))])
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400988
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400989 def test_load_nul_byte_attribute(self):
990 """
Jean-Paul Calderone9af07b02013-08-23 16:07:31 -0400991 An :py:class:`OpenSSL.crypto.X509Name` from an
992 :py:class:`OpenSSL.crypto.X509` instance loaded from a file can have a
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400993 NUL byte in the value of one of its attributes.
994 """
995 cert = load_certificate(FILETYPE_PEM, nulbyteSubjectAltNamePEM)
996 subject = cert.get_subject()
997 self.assertEqual(
Jean-Paul Calderone06754fc2013-08-23 15:47:47 -0400998 "null.python.org\x00example.org", subject.commonName)
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400999
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -05001000 def test_setAttributeFailure(self):
1001 """
1002 If the value of an attribute cannot be set for some reason then
1003 :py:class:`OpenSSL.crypto.Error` is raised.
1004 """
1005 name = self._x509name()
1006 # This value is too long
1007 self.assertRaises(Error, setattr, name, "O", b"x" * 512)
1008
1009
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001010class _PKeyInteractionTestsMixin:
1011 """
1012 Tests which involve another thing and a PKey.
1013 """
Alex Gaynoraceb3e22015-09-05 12:00:22 -04001014
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001015 def signable(self):
1016 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001017 Return something with a :py:meth:`set_pubkey`, :py:meth:`set_pubkey`,
1018 and :py:meth:`sign` method.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001019 """
1020 raise NotImplementedError()
1021
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001022 def test_signWithUngenerated(self):
1023 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001024 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when pass a
1025 :py:class:`PKey` with no parts.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001026 """
1027 request = self.signable()
1028 key = PKey()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001029 self.assertRaises(ValueError, request.sign, key, GOOD_DIGEST)
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001030
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001031 def test_signWithPublicKey(self):
1032 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001033 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when pass a
1034 :py:class:`PKey` with no private part as the signing key.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001035 """
1036 request = self.signable()
1037 key = PKey()
1038 key.generate_key(TYPE_RSA, 512)
1039 request.set_pubkey(key)
1040 pub = request.get_pubkey()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001041 self.assertRaises(ValueError, request.sign, pub, GOOD_DIGEST)
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001042
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -04001043 def test_signWithUnknownDigest(self):
1044 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001045 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when passed a digest name which is
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -04001046 not known.
1047 """
1048 request = self.signable()
1049 key = PKey()
1050 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001051 self.assertRaises(ValueError, request.sign, key, BAD_DIGEST)
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -04001052
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04001053 def test_sign(self):
1054 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001055 :py:meth:`X509Req.sign` succeeds when passed a private key object and a valid
1056 digest function. :py:meth:`X509Req.verify` can be used to check the signature.
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04001057 """
1058 request = self.signable()
1059 key = PKey()
1060 key.generate_key(TYPE_RSA, 512)
1061 request.set_pubkey(key)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001062 request.sign(key, GOOD_DIGEST)
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04001063 # If the type has a verify method, cover that too.
1064 if getattr(request, 'verify', None) is not None:
1065 pub = request.get_pubkey()
1066 self.assertTrue(request.verify(pub))
1067 # Make another key that won't verify.
1068 key = PKey()
1069 key.generate_key(TYPE_RSA, 512)
1070 self.assertRaises(Error, request.verify, key)
1071
1072
Jean-Paul Calderone18808652009-07-05 12:54:05 -04001073class X509ReqTests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001074 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001075 Tests for :py:class:`OpenSSL.crypto.X509Req`.
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001076 """
Alex Gaynoraceb3e22015-09-05 12:00:22 -04001077
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001078 def signable(self):
1079 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001080 Create and return a new :py:class:`X509Req`.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001081 """
1082 return X509Req()
1083
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001084 def test_type(self):
1085 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001086 :py:obj:`X509Req` and :py:obj:`X509ReqType` refer to the same type object and can be
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001087 used to create instances of that type.
1088 """
1089 self.assertIdentical(X509Req, X509ReqType)
1090 self.assertConsistentType(X509Req, 'X509Req')
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001091
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001092 def test_construction(self):
1093 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001094 :py:obj:`X509Req` takes no arguments and returns an :py:obj:`X509ReqType` instance.
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001095 """
1096 request = X509Req()
1097 self.assertTrue(
1098 isinstance(request, X509ReqType),
1099 "%r is of type %r, should be %r" % (request, type(request), X509ReqType))
1100
Jean-Paul Calderone8dd19b82008-12-28 20:41:16 -05001101 def test_version(self):
1102 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001103 :py:obj:`X509ReqType.set_version` sets the X.509 version of the certificate
1104 request. :py:obj:`X509ReqType.get_version` returns the X.509 version of
Jean-Paul Calderone8dd19b82008-12-28 20:41:16 -05001105 the certificate request. The initial value of the version is 0.
1106 """
1107 request = X509Req()
1108 self.assertEqual(request.get_version(), 0)
1109 request.set_version(1)
1110 self.assertEqual(request.get_version(), 1)
1111 request.set_version(3)
1112 self.assertEqual(request.get_version(), 3)
1113
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001114 def test_version_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001115 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001116 :py:obj:`X509ReqType.set_version` raises :py:obj:`TypeError` if called with the wrong
1117 number of arguments or with a non-:py:obj:`int` argument.
1118 :py:obj:`X509ReqType.get_version` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001119 arguments.
1120 """
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001121 request = X509Req()
1122 self.assertRaises(TypeError, request.set_version)
1123 self.assertRaises(TypeError, request.set_version, "foo")
1124 self.assertRaises(TypeError, request.set_version, 1, 2)
1125 self.assertRaises(TypeError, request.get_version, None)
1126
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001127 def test_get_subject(self):
1128 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001129 :py:obj:`X509ReqType.get_subject` returns an :py:obj:`X509Name` for the subject of
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001130 the request and which is valid even after the request object is
1131 otherwise dead.
1132 """
1133 request = X509Req()
1134 subject = request.get_subject()
1135 self.assertTrue(
1136 isinstance(subject, X509NameType),
1137 "%r is of type %r, should be %r" % (subject, type(subject), X509NameType))
1138 subject.commonName = "foo"
1139 self.assertEqual(request.get_subject().commonName, "foo")
1140 del request
1141 subject.commonName = "bar"
1142 self.assertEqual(subject.commonName, "bar")
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001143
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001144 def test_get_subject_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001145 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001146 :py:obj:`X509ReqType.get_subject` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001147 arguments.
1148 """
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001149 request = X509Req()
1150 self.assertRaises(TypeError, request.get_subject, None)
1151
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001152 def test_add_extensions(self):
1153 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001154 :py:obj:`X509Req.add_extensions` accepts a :py:obj:`list` of :py:obj:`X509Extension`
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001155 instances and adds them to the X509 request.
1156 """
1157 request = X509Req()
1158 request.add_extensions([
Alex Gaynoraceb3e22015-09-05 12:00:22 -04001159 X509Extension(b('basicConstraints'), True, b('CA:false'))])
Stephen Holsappleca545b72014-01-28 21:43:25 -08001160 exts = request.get_extensions()
Stephen Holsapple7fbdf642014-03-01 20:05:47 -08001161 self.assertEqual(len(exts), 1)
1162 self.assertEqual(exts[0].get_short_name(), b('basicConstraints'))
1163 self.assertEqual(exts[0].get_critical(), 1)
1164 self.assertEqual(exts[0].get_data(), b('0\x00'))
1165
Stephen Holsapple7fbdf642014-03-01 20:05:47 -08001166 def test_get_extensions(self):
1167 """
1168 :py:obj:`X509Req.get_extensions` returns a :py:obj:`list` of
1169 extensions added to this X509 request.
1170 """
1171 request = X509Req()
1172 exts = request.get_extensions()
1173 self.assertEqual(exts, [])
1174 request.add_extensions([
Alex Gaynoraceb3e22015-09-05 12:00:22 -04001175 X509Extension(b('basicConstraints'), True, b('CA:true')),
1176 X509Extension(b('keyUsage'), False, b('digitalSignature'))])
Stephen Holsapple7fbdf642014-03-01 20:05:47 -08001177 exts = request.get_extensions()
1178 self.assertEqual(len(exts), 2)
1179 self.assertEqual(exts[0].get_short_name(), b('basicConstraints'))
1180 self.assertEqual(exts[0].get_critical(), 1)
1181 self.assertEqual(exts[0].get_data(), b('0\x03\x01\x01\xff'))
1182 self.assertEqual(exts[1].get_short_name(), b('keyUsage'))
1183 self.assertEqual(exts[1].get_critical(), 0)
1184 self.assertEqual(exts[1].get_data(), b('\x03\x02\x07\x80'))
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001185
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001186 def test_add_extensions_wrong_args(self):
1187 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001188 :py:obj:`X509Req.add_extensions` raises :py:obj:`TypeError` if called with the wrong
1189 number of arguments or with a non-:py:obj:`list`. Or it raises :py:obj:`ValueError`
1190 if called with a :py:obj:`list` containing objects other than :py:obj:`X509Extension`
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001191 instances.
1192 """
1193 request = X509Req()
1194 self.assertRaises(TypeError, request.add_extensions)
1195 self.assertRaises(TypeError, request.add_extensions, object())
1196 self.assertRaises(ValueError, request.add_extensions, [object()])
1197 self.assertRaises(TypeError, request.add_extensions, [], None)
1198
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001199 def test_verify_wrong_args(self):
1200 """
1201 :py:obj:`X509Req.verify` raises :py:obj:`TypeError` if called with zero
1202 arguments or more than one argument or if passed anything other than a
1203 :py:obj:`PKey` instance as its single argument.
1204 """
1205 request = X509Req()
1206 self.assertRaises(TypeError, request.verify)
1207 self.assertRaises(TypeError, request.verify, object())
1208 self.assertRaises(TypeError, request.verify, PKey(), object())
1209
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001210 def test_verify_uninitialized_key(self):
1211 """
1212 :py:obj:`X509Req.verify` raises :py:obj:`OpenSSL.crypto.Error` if called
1213 with a :py:obj:`OpenSSL.crypto.PKey` which contains no key data.
1214 """
1215 request = X509Req()
1216 pkey = PKey()
1217 self.assertRaises(Error, request.verify, pkey)
1218
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001219 def test_verify_wrong_key(self):
1220 """
1221 :py:obj:`X509Req.verify` raises :py:obj:`OpenSSL.crypto.Error` if called
1222 with a :py:obj:`OpenSSL.crypto.PKey` which does not represent the public
1223 part of the key which signed the request.
1224 """
1225 request = X509Req()
1226 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001227 request.sign(pkey, GOOD_DIGEST)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001228 another_pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
1229 self.assertRaises(Error, request.verify, another_pkey)
1230
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001231 def test_verify_success(self):
1232 """
1233 :py:obj:`X509Req.verify` returns :py:obj:`True` if called with a
Alex Gaynor3b0ee972014-11-15 09:17:33 -08001234 :py:obj:`OpenSSL.crypto.PKey` which represents the public part of the key
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001235 which signed the request.
1236 """
1237 request = X509Req()
1238 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001239 request.sign(pkey, GOOD_DIGEST)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001240 self.assertEqual(True, request.verify(pkey))
1241
1242
Jean-Paul Calderone18808652009-07-05 12:54:05 -04001243class X509Tests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001244 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001245 Tests for :py:obj:`OpenSSL.crypto.X509`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001246 """
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001247 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
Jean-Paul Calderone8114b452008-03-25 15:27:59 -04001248
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001249 extpem = """
1250-----BEGIN CERTIFICATE-----
1251MIIC3jCCAkegAwIBAgIJAJHFjlcCgnQzMA0GCSqGSIb3DQEBBQUAMEcxCzAJBgNV
1252BAYTAlNFMRUwEwYDVQQIEwxXZXN0ZXJib3R0b20xEjAQBgNVBAoTCUNhdGFsb2dp
1253eDENMAsGA1UEAxMEUm9vdDAeFw0wODA0MjIxNDQ1MzhaFw0wOTA0MjIxNDQ1Mzha
1254MFQxCzAJBgNVBAYTAlNFMQswCQYDVQQIEwJXQjEUMBIGA1UEChMLT3Blbk1ldGFk
1255aXIxIjAgBgNVBAMTGW5vZGUxLm9tMi5vcGVubWV0YWRpci5vcmcwgZ8wDQYJKoZI
1256hvcNAQEBBQADgY0AMIGJAoGBAPIcQMrwbk2nESF/0JKibj9i1x95XYAOwP+LarwT
1257Op4EQbdlI9SY+uqYqlERhF19w7CS+S6oyqx0DRZSk4Y9dZ9j9/xgm2u/f136YS1u
1258zgYFPvfUs6PqYLPSM8Bw+SjJ+7+2+TN+Tkiof9WP1cMjodQwOmdsiRbR0/J7+b1B
1259hec1AgMBAAGjgcQwgcEwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNT
1260TCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFIdHsBcMVVMbAO7j6NCj
126103HgLnHaMB8GA1UdIwQYMBaAFL2h9Bf9Mre4vTdOiHTGAt7BRY/8MEYGA1UdEQQ/
1262MD2CDSouZXhhbXBsZS5vcmeCESoub20yLmV4bWFwbGUuY29thwSC7wgKgRNvbTJA
1263b3Blbm1ldGFkaXIub3JnMA0GCSqGSIb3DQEBBQUAA4GBALd7WdXkp2KvZ7/PuWZA
1264MPlIxyjS+Ly11+BNE0xGQRp9Wz+2lABtpgNqssvU156+HkKd02rGheb2tj7MX9hG
1265uZzbwDAZzJPjzDQDD7d3cWsrVcfIdqVU7epHqIadnOF+X0ghJ39pAm6VVadnSXCt
1266WpOdIpB8KksUTCzV591Nr1wd
1267-----END CERTIFICATE-----
1268 """
Alex Gaynoraceb3e22015-09-05 12:00:22 -04001269
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001270 def signable(self):
1271 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001272 Create and return a new :py:obj:`X509`.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001273 """
1274 return X509()
1275
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001276 def test_type(self):
1277 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001278 :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 -04001279 to create instances of that type.
1280 """
1281 self.assertIdentical(X509, X509Type)
1282 self.assertConsistentType(X509, 'X509')
1283
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001284 def test_construction(self):
1285 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001286 :py:obj:`X509` takes no arguments and returns an instance of :py:obj:`X509Type`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001287 """
1288 certificate = X509()
1289 self.assertTrue(
1290 isinstance(certificate, X509Type),
1291 "%r is of type %r, should be %r" % (certificate,
1292 type(certificate),
1293 X509Type))
Rick Deane15b1472009-07-09 15:53:42 -05001294 self.assertEqual(type(X509Type).__name__, 'type')
1295 self.assertEqual(type(certificate).__name__, 'X509')
1296 self.assertEqual(type(certificate), X509Type)
Rick Dean04113e72009-07-16 12:06:35 -05001297 self.assertEqual(type(certificate), X509)
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001298
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001299 def test_get_version_wrong_args(self):
1300 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001301 :py:obj:`X509.get_version` raises :py:obj:`TypeError` if invoked with any arguments.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001302 """
1303 cert = X509()
1304 self.assertRaises(TypeError, cert.get_version, None)
1305
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001306 def test_set_version_wrong_args(self):
1307 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001308 :py:obj:`X509.set_version` raises :py:obj:`TypeError` if invoked with the wrong number
1309 of arguments or an argument not of type :py:obj:`int`.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001310 """
1311 cert = X509()
1312 self.assertRaises(TypeError, cert.set_version)
1313 self.assertRaises(TypeError, cert.set_version, None)
1314 self.assertRaises(TypeError, cert.set_version, 1, None)
1315
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001316 def test_version(self):
1317 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001318 :py:obj:`X509.set_version` sets the certificate version number.
1319 :py:obj:`X509.get_version` retrieves it.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001320 """
1321 cert = X509()
1322 cert.set_version(1234)
1323 self.assertEquals(cert.get_version(), 1234)
1324
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001325 def test_get_serial_number_wrong_args(self):
1326 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001327 :py:obj:`X509.get_serial_number` raises :py:obj:`TypeError` if invoked with any
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001328 arguments.
1329 """
1330 cert = X509()
1331 self.assertRaises(TypeError, cert.get_serial_number, None)
1332
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001333 def test_serial_number(self):
1334 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001335 The serial number of an :py:obj:`X509Type` can be retrieved and modified with
1336 :py:obj:`X509Type.get_serial_number` and :py:obj:`X509Type.set_serial_number`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001337 """
1338 certificate = X509()
1339 self.assertRaises(TypeError, certificate.set_serial_number)
1340 self.assertRaises(TypeError, certificate.set_serial_number, 1, 2)
1341 self.assertRaises(TypeError, certificate.set_serial_number, "1")
1342 self.assertRaises(TypeError, certificate.set_serial_number, 5.5)
1343 self.assertEqual(certificate.get_serial_number(), 0)
1344 certificate.set_serial_number(1)
1345 self.assertEqual(certificate.get_serial_number(), 1)
1346 certificate.set_serial_number(2 ** 32 + 1)
1347 self.assertEqual(certificate.get_serial_number(), 2 ** 32 + 1)
1348 certificate.set_serial_number(2 ** 64 + 1)
1349 self.assertEqual(certificate.get_serial_number(), 2 ** 64 + 1)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001350 certificate.set_serial_number(2 ** 128 + 1)
1351 self.assertEqual(certificate.get_serial_number(), 2 ** 128 + 1)
1352
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001353 def _setBoundTest(self, which):
1354 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001355 :py:obj:`X509Type.set_notBefore` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001356 GENERALIZEDTIME and sets the beginning of the certificate's validity
1357 period to it.
1358 """
1359 certificate = X509()
1360 set = getattr(certificate, 'set_not' + which)
1361 get = getattr(certificate, 'get_not' + which)
1362
Jean-Paul Calderonee0615b52008-03-09 21:44:46 -04001363 # Starts with no value.
1364 self.assertEqual(get(), None)
1365
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001366 # GMT (Or is it UTC?) -exarkun
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001367 when = b("20040203040506Z")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001368 set(when)
1369 self.assertEqual(get(), when)
1370
1371 # A plus two hours and thirty minutes offset
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001372 when = b("20040203040506+0530")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001373 set(when)
1374 self.assertEqual(get(), when)
1375
1376 # A minus one hour fifteen minutes offset
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001377 when = b("20040203040506-0115")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001378 set(when)
1379 self.assertEqual(get(), when)
1380
1381 # An invalid string results in a ValueError
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001382 self.assertRaises(ValueError, set, b("foo bar"))
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001383
Jean-Paul Calderone31ca2002010-01-30 15:14:43 -05001384 # The wrong number of arguments results in a TypeError.
1385 self.assertRaises(TypeError, set)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001386 self.assertRaises(TypeError, set, b("20040203040506Z"), b("20040203040506Z"))
1387 self.assertRaises(TypeError, get, b("foo bar"))
1388
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001389 # XXX ASN1_TIME (not GENERALIZEDTIME)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001390
1391 def test_set_notBefore(self):
1392 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001393 :py:obj:`X509Type.set_notBefore` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001394 GENERALIZEDTIME and sets the beginning of the certificate's validity
1395 period to it.
1396 """
1397 self._setBoundTest("Before")
1398
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001399 def test_set_notAfter(self):
1400 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001401 :py:obj:`X509Type.set_notAfter` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001402 GENERALIZEDTIME and sets the end of the certificate's validity period
1403 to it.
1404 """
1405 self._setBoundTest("After")
Jean-Paul Calderone76576d52008-03-24 16:04:46 -04001406
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001407 def test_get_notBefore(self):
1408 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001409 :py:obj:`X509Type.get_notBefore` returns a string in the format of an ASN1
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001410 GENERALIZEDTIME even for certificates which store it as UTCTIME
1411 internally.
1412 """
Jean-Paul Calderone8114b452008-03-25 15:27:59 -04001413 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001414 self.assertEqual(cert.get_notBefore(), b("20090325123658Z"))
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001415
Rick Dean38a05c82009-07-18 01:41:30 -05001416 def test_get_notAfter(self):
1417 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001418 :py:obj:`X509Type.get_notAfter` returns a string in the format of an ASN1
Rick Dean38a05c82009-07-18 01:41:30 -05001419 GENERALIZEDTIME even for certificates which store it as UTCTIME
1420 internally.
1421 """
1422 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001423 self.assertEqual(cert.get_notAfter(), b("20170611123658Z"))
Rick Dean38a05c82009-07-18 01:41:30 -05001424
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001425 def test_gmtime_adj_notBefore_wrong_args(self):
1426 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001427 :py:obj:`X509Type.gmtime_adj_notBefore` raises :py:obj:`TypeError` if called with the
1428 wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001429 """
1430 cert = X509()
1431 self.assertRaises(TypeError, cert.gmtime_adj_notBefore)
1432 self.assertRaises(TypeError, cert.gmtime_adj_notBefore, None)
1433 self.assertRaises(TypeError, cert.gmtime_adj_notBefore, 123, None)
1434
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001435 def test_gmtime_adj_notBefore(self):
1436 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001437 :py:obj:`X509Type.gmtime_adj_notBefore` changes the not-before timestamp to be
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001438 the current time plus the number of seconds passed in.
1439 """
1440 cert = load_certificate(FILETYPE_PEM, self.pemData)
Maximilian Hilsbed25c92015-07-25 12:58:07 +02001441 not_before_min = datetime.utcnow().replace(microsecond=0) + timedelta(seconds=100)
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001442 cert.gmtime_adj_notBefore(100)
Maximilian Hilsbed25c92015-07-25 12:58:07 +02001443 not_before = datetime.strptime(cert.get_notBefore().decode(), "%Y%m%d%H%M%SZ")
1444 not_before_max = datetime.utcnow() + timedelta(seconds=100)
1445 self.assertTrue(not_before_min <= not_before <= not_before_max)
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001446
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001447 def test_gmtime_adj_notAfter_wrong_args(self):
1448 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001449 :py:obj:`X509Type.gmtime_adj_notAfter` raises :py:obj:`TypeError` if called with the
1450 wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001451 """
1452 cert = X509()
1453 self.assertRaises(TypeError, cert.gmtime_adj_notAfter)
1454 self.assertRaises(TypeError, cert.gmtime_adj_notAfter, None)
1455 self.assertRaises(TypeError, cert.gmtime_adj_notAfter, 123, None)
1456
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001457 def test_gmtime_adj_notAfter(self):
1458 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001459 :py:obj:`X509Type.gmtime_adj_notAfter` changes the not-after timestamp to be
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001460 the current time plus the number of seconds passed in.
1461 """
1462 cert = load_certificate(FILETYPE_PEM, self.pemData)
Maximilian Hilsbed25c92015-07-25 12:58:07 +02001463 not_after_min = datetime.utcnow().replace(microsecond=0) + timedelta(seconds=100)
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001464 cert.gmtime_adj_notAfter(100)
Maximilian Hilsbed25c92015-07-25 12:58:07 +02001465 not_after = datetime.strptime(cert.get_notAfter().decode(), "%Y%m%d%H%M%SZ")
1466 not_after_max = datetime.utcnow() + timedelta(seconds=100)
1467 self.assertTrue(not_after_min <= not_after <= not_after_max)
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001468
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001469 def test_has_expired_wrong_args(self):
1470 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001471 :py:obj:`X509Type.has_expired` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001472 arguments.
1473 """
1474 cert = X509()
1475 self.assertRaises(TypeError, cert.has_expired, None)
1476
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001477 def test_has_expired(self):
1478 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001479 :py:obj:`X509Type.has_expired` returns :py:obj:`True` if the certificate's not-after
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001480 time is in the past.
1481 """
1482 cert = X509()
1483 cert.gmtime_adj_notAfter(-1)
1484 self.assertTrue(cert.has_expired())
1485
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001486 def test_has_not_expired(self):
1487 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001488 :py:obj:`X509Type.has_expired` returns :py:obj:`False` if the certificate's not-after
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001489 time is in the future.
1490 """
1491 cert = X509()
1492 cert.gmtime_adj_notAfter(2)
1493 self.assertFalse(cert.has_expired())
1494
Jeff Tangfc18f7b2015-04-15 17:42:33 -04001495 def test_root_has_not_expired(self):
1496 """
1497 :py:obj:`X509Type.has_expired` returns :py:obj:`False` if the certificate's not-after
1498 time is in the future.
1499 """
1500 cert = load_certificate(FILETYPE_PEM, root_cert_pem)
1501 self.assertFalse(cert.has_expired())
1502
Rick Dean38a05c82009-07-18 01:41:30 -05001503 def test_digest(self):
1504 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001505 :py:obj:`X509.digest` returns a string giving ":"-separated hex-encoded words
Rick Dean38a05c82009-07-18 01:41:30 -05001506 of the digest of the certificate.
1507 """
Jeff Tangfc18f7b2015-04-15 17:42:33 -04001508 cert = load_certificate(FILETYPE_PEM, root_cert_pem)
Rick Dean38a05c82009-07-18 01:41:30 -05001509 self.assertEqual(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001510 # This is MD5 instead of GOOD_DIGEST because the digest algorithm
1511 # actually matters to the assertion (ie, another arbitrary, good
1512 # digest will not product the same digest).
Jeff Tangfc18f7b2015-04-15 17:42:33 -04001513 # Digest verified with the command:
1514 # openssl x509 -in root_cert.pem -noout -fingerprint -md5
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001515 cert.digest("MD5"),
Jeff Tangfc18f7b2015-04-15 17:42:33 -04001516 b("19:B3:05:26:2B:F8:F2:FF:0B:8F:21:07:A8:28:B8:75"))
Rick Dean38a05c82009-07-18 01:41:30 -05001517
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001518 def _extcert(self, pkey, extensions):
1519 cert = X509()
1520 cert.set_pubkey(pkey)
1521 cert.get_subject().commonName = "Unit Tests"
1522 cert.get_issuer().commonName = "Unit Tests"
1523 when = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
1524 cert.set_notBefore(when)
1525 cert.set_notAfter(when)
1526
1527 cert.add_extensions(extensions)
Jeff Tangfc18f7b2015-04-15 17:42:33 -04001528 cert.sign(pkey, 'sha1')
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001529 return load_certificate(
1530 FILETYPE_PEM, dump_certificate(FILETYPE_PEM, cert))
1531
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001532 def test_extension_count(self):
1533 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001534 :py:obj:`X509.get_extension_count` returns the number of extensions that are
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001535 present in the certificate.
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001536 """
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001537 pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001538 ca = X509Extension(b('basicConstraints'), True, b('CA:FALSE'))
1539 key = X509Extension(b('keyUsage'), True, b('digitalSignature'))
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001540 subjectAltName = X509Extension(
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001541 b('subjectAltName'), True, b('DNS:example.com'))
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001542
1543 # Try a certificate with no extensions at all.
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001544 c = self._extcert(pkey, [])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001545 self.assertEqual(c.get_extension_count(), 0)
1546
1547 # And a certificate with one
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001548 c = self._extcert(pkey, [ca])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001549 self.assertEqual(c.get_extension_count(), 1)
1550
1551 # And a certificate with several
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001552 c = self._extcert(pkey, [ca, key, subjectAltName])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001553 self.assertEqual(c.get_extension_count(), 3)
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001554
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001555 def test_get_extension(self):
1556 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001557 :py:obj:`X509.get_extension` takes an integer and returns an :py:obj:`X509Extension`
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001558 corresponding to the extension at that index.
1559 """
1560 pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001561 ca = X509Extension(b('basicConstraints'), True, b('CA:FALSE'))
1562 key = X509Extension(b('keyUsage'), True, b('digitalSignature'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001563 subjectAltName = X509Extension(
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001564 b('subjectAltName'), False, b('DNS:example.com'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001565
1566 cert = self._extcert(pkey, [ca, key, subjectAltName])
1567
1568 ext = cert.get_extension(0)
1569 self.assertTrue(isinstance(ext, X509Extension))
1570 self.assertTrue(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001571 self.assertEqual(ext.get_short_name(), b('basicConstraints'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001572
1573 ext = cert.get_extension(1)
1574 self.assertTrue(isinstance(ext, X509Extension))
1575 self.assertTrue(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001576 self.assertEqual(ext.get_short_name(), b('keyUsage'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001577
1578 ext = cert.get_extension(2)
1579 self.assertTrue(isinstance(ext, X509Extension))
1580 self.assertFalse(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001581 self.assertEqual(ext.get_short_name(), b('subjectAltName'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001582
1583 self.assertRaises(IndexError, cert.get_extension, -1)
1584 self.assertRaises(IndexError, cert.get_extension, 4)
1585 self.assertRaises(TypeError, cert.get_extension, "hello")
1586
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001587 def test_nullbyte_subjectAltName(self):
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001588 """
Jean-Paul Calderone9af07b02013-08-23 16:07:31 -04001589 The fields of a `subjectAltName` extension on an X509 may contain NUL
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001590 bytes and this value is reflected in the string representation of the
1591 extension object.
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001592 """
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001593 cert = load_certificate(FILETYPE_PEM, nulbyteSubjectAltNamePEM)
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001594
1595 ext = cert.get_extension(3)
1596 self.assertEqual(ext.get_short_name(), b('subjectAltName'))
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001597 self.assertEqual(
1598 b("DNS:altnull.python.org\x00example.com, "
1599 "email:null@python.org\x00user@example.org, "
1600 "URI:http://null.python.org\x00http://example.org, "
1601 "IP Address:192.0.2.1, IP Address:2001:DB8:0:0:0:0:0:1\n"),
1602 b(str(ext)))
1603
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001604 def test_invalid_digest_algorithm(self):
1605 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001606 :py:obj:`X509.digest` raises :py:obj:`ValueError` if called with an unrecognized hash
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001607 algorithm.
1608 """
1609 cert = X509()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001610 self.assertRaises(ValueError, cert.digest, BAD_DIGEST)
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001611
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001612 def test_get_subject_wrong_args(self):
1613 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001614 :py:obj:`X509.get_subject` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001615 """
1616 cert = X509()
1617 self.assertRaises(TypeError, cert.get_subject, None)
1618
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001619 def test_get_subject(self):
1620 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001621 :py:obj:`X509.get_subject` returns an :py:obj:`X509Name` instance.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001622 """
1623 cert = load_certificate(FILETYPE_PEM, self.pemData)
1624 subj = cert.get_subject()
1625 self.assertTrue(isinstance(subj, X509Name))
1626 self.assertEquals(
1627 subj.get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001628 [(b('C'), b('US')), (b('ST'), b('IL')), (b('L'), b('Chicago')),
1629 (b('O'), b('Testing')), (b('CN'), b('Testing Root CA'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001630
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001631 def test_set_subject_wrong_args(self):
1632 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001633 :py:obj:`X509.set_subject` raises a :py:obj:`TypeError` if called with the wrong
1634 number of arguments or an argument not of type :py:obj:`X509Name`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001635 """
1636 cert = X509()
1637 self.assertRaises(TypeError, cert.set_subject)
1638 self.assertRaises(TypeError, cert.set_subject, None)
1639 self.assertRaises(TypeError, cert.set_subject, cert.get_subject(), None)
1640
1641
1642 def test_set_subject(self):
1643 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001644 :py:obj:`X509.set_subject` changes the subject of the certificate to the one
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001645 passed in.
1646 """
1647 cert = X509()
1648 name = cert.get_subject()
1649 name.C = 'AU'
1650 name.O = 'Unit Tests'
1651 cert.set_subject(name)
1652 self.assertEquals(
1653 cert.get_subject().get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001654 [(b('C'), b('AU')), (b('O'), b('Unit Tests'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001655
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001656 def test_get_issuer_wrong_args(self):
1657 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001658 :py:obj:`X509.get_issuer` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001659 """
1660 cert = X509()
1661 self.assertRaises(TypeError, cert.get_issuer, None)
1662
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001663 def test_get_issuer(self):
1664 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001665 :py:obj:`X509.get_issuer` returns an :py:obj:`X509Name` instance.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001666 """
1667 cert = load_certificate(FILETYPE_PEM, self.pemData)
1668 subj = cert.get_issuer()
1669 self.assertTrue(isinstance(subj, X509Name))
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001670 comp = subj.get_components()
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001671 self.assertEquals(
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001672 comp,
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001673 [(b('C'), b('US')), (b('ST'), b('IL')), (b('L'), b('Chicago')),
1674 (b('O'), b('Testing')), (b('CN'), b('Testing Root CA'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001675
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001676 def test_set_issuer_wrong_args(self):
1677 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001678 :py:obj:`X509.set_issuer` raises a :py:obj:`TypeError` if called with the wrong
1679 number of arguments or an argument not of type :py:obj:`X509Name`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001680 """
1681 cert = X509()
1682 self.assertRaises(TypeError, cert.set_issuer)
1683 self.assertRaises(TypeError, cert.set_issuer, None)
1684 self.assertRaises(TypeError, cert.set_issuer, cert.get_issuer(), None)
1685
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001686 def test_set_issuer(self):
1687 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001688 :py:obj:`X509.set_issuer` changes the issuer of the certificate to the one
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001689 passed in.
1690 """
1691 cert = X509()
1692 name = cert.get_issuer()
1693 name.C = 'AU'
1694 name.O = 'Unit Tests'
1695 cert.set_issuer(name)
1696 self.assertEquals(
1697 cert.get_issuer().get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001698 [(b('C'), b('AU')), (b('O'), b('Unit Tests'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001699
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001700 def test_get_pubkey_uninitialized(self):
1701 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001702 When called on a certificate with no public key, :py:obj:`X509.get_pubkey`
1703 raises :py:obj:`OpenSSL.crypto.Error`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001704 """
1705 cert = X509()
1706 self.assertRaises(Error, cert.get_pubkey)
1707
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001708 def test_subject_name_hash_wrong_args(self):
1709 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001710 :py:obj:`X509.subject_name_hash` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001711 arguments.
1712 """
1713 cert = X509()
1714 self.assertRaises(TypeError, cert.subject_name_hash, None)
1715
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001716 def test_subject_name_hash(self):
1717 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001718 :py:obj:`X509.subject_name_hash` returns the hash of the certificate's subject
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001719 name.
1720 """
1721 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -04001722 self.assertIn(
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001723 cert.subject_name_hash(),
Alex Gaynoraceb3e22015-09-05 12:00:22 -04001724 [3350047874, # OpenSSL 0.9.8, MD5
1725 3278919224, # OpenSSL 1.0.0, SHA1
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -04001726 ])
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001727
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001728 def test_get_signature_algorithm(self):
1729 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001730 :py:obj:`X509Type.get_signature_algorithm` returns a string which means
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001731 the algorithm used to sign the certificate.
1732 """
1733 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001734 self.assertEqual(
1735 b("sha1WithRSAEncryption"), cert.get_signature_algorithm())
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001736
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001737 def test_get_undefined_signature_algorithm(self):
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001738 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001739 :py:obj:`X509Type.get_signature_algorithm` raises :py:obj:`ValueError` if the
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001740 signature algorithm is undefined or unknown.
1741 """
1742 # This certificate has been modified to indicate a bogus OID in the
1743 # signature algorithm field so that OpenSSL does not recognize it.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001744 certPEM = b("""\
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001745-----BEGIN CERTIFICATE-----
1746MIIC/zCCAmigAwIBAgIBATAGBgJ8BQUAMHsxCzAJBgNVBAYTAlNHMREwDwYDVQQK
1747EwhNMkNyeXB0bzEUMBIGA1UECxMLTTJDcnlwdG8gQ0ExJDAiBgNVBAMTG00yQ3J5
1748cHRvIENlcnRpZmljYXRlIE1hc3RlcjEdMBsGCSqGSIb3DQEJARYObmdwc0Bwb3N0
1749MS5jb20wHhcNMDAwOTEwMDk1MTMwWhcNMDIwOTEwMDk1MTMwWjBTMQswCQYDVQQG
1750EwJTRzERMA8GA1UEChMITTJDcnlwdG8xEjAQBgNVBAMTCWxvY2FsaG9zdDEdMBsG
1751CSqGSIb3DQEJARYObmdwc0Bwb3N0MS5jb20wXDANBgkqhkiG9w0BAQEFAANLADBI
1752AkEArL57d26W9fNXvOhNlZzlPOACmvwOZ5AdNgLzJ1/MfsQQJ7hHVeHmTAjM664V
1753+fXvwUGJLziCeBo1ysWLRnl8CQIDAQABo4IBBDCCAQAwCQYDVR0TBAIwADAsBglg
1754hkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0O
1755BBYEFM+EgpK+eyZiwFU1aOPSbczbPSpVMIGlBgNVHSMEgZ0wgZqAFPuHI2nrnDqT
1756FeXFvylRT/7tKDgBoX+kfTB7MQswCQYDVQQGEwJTRzERMA8GA1UEChMITTJDcnlw
1757dG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtNMkNyeXB0byBDZXJ0
1758aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tggEA
1759MA0GCSqGSIb3DQEBBAUAA4GBADv8KpPo+gfJxN2ERK1Y1l17sz/ZhzoGgm5XCdbx
1760jEY7xKfpQngV599k1xhl11IMqizDwu0855agrckg2MCTmOI9DZzDD77tAYb+Dk0O
1761PEVk0Mk/V0aIsDE9bolfCi/i/QWZ3N8s5nTWMNyBBBmoSliWCm4jkkRZRD0ejgTN
1762tgI5
1763-----END CERTIFICATE-----
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001764""")
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001765 cert = load_certificate(FILETYPE_PEM, certPEM)
1766 self.assertRaises(ValueError, cert.get_signature_algorithm)
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001767
1768
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001769class X509StoreTests(TestCase):
1770 """
1771 Test for :py:obj:`OpenSSL.crypto.X509Store`.
1772 """
Alex Gaynoraceb3e22015-09-05 12:00:22 -04001773
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001774 def test_type(self):
1775 """
1776 :py:obj:`X509StoreType` is a type object.
1777 """
1778 self.assertIdentical(X509Store, X509StoreType)
1779 self.assertConsistentType(X509Store, 'X509Store')
1780
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001781 def test_add_cert_wrong_args(self):
1782 store = X509Store()
1783 self.assertRaises(TypeError, store.add_cert)
1784 self.assertRaises(TypeError, store.add_cert, object())
1785 self.assertRaises(TypeError, store.add_cert, X509(), object())
1786
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001787 def test_add_cert(self):
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001788 """
1789 :py:obj:`X509Store.add_cert` adds a :py:obj:`X509` instance to the
1790 certificate store.
1791 """
1792 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001793 store = X509Store()
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001794 store.add_cert(cert)
1795
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001796 def test_add_cert_rejects_duplicate(self):
1797 """
1798 :py:obj:`X509Store.add_cert` raises :py:obj:`OpenSSL.crypto.Error` if an
1799 attempt is made to add the same certificate to the store more than once.
1800 """
1801 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
1802 store = X509Store()
1803 store.add_cert(cert)
1804 self.assertRaises(Error, store.add_cert, cert)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001805
1806
Rick Dean623ee362009-07-17 12:22:16 -05001807class PKCS12Tests(TestCase):
1808 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001809 Test for :py:obj:`OpenSSL.crypto.PKCS12` and :py:obj:`OpenSSL.crypto.load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001810 """
1811 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
1812
Jean-Paul Calderonec3a41f72009-07-25 12:36:02 -04001813 def test_type(self):
1814 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001815 :py:obj:`PKCS12Type` is a type object.
Jean-Paul Calderonec3a41f72009-07-25 12:36:02 -04001816 """
1817 self.assertIdentical(PKCS12, PKCS12Type)
1818 self.assertConsistentType(PKCS12, 'PKCS12')
1819
Rick Deanf94096c2009-07-18 14:23:06 -05001820 def test_empty_construction(self):
Rick Dean38a05c82009-07-18 01:41:30 -05001821 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001822 :py:obj:`PKCS12` returns a new instance of :py:obj:`PKCS12` with no certificate,
Jean-Paul Calderonedc857b52009-07-25 12:25:07 -04001823 private key, CA certificates, or friendly name.
Rick Dean38a05c82009-07-18 01:41:30 -05001824 """
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001825 p12 = PKCS12()
Rick Dean623ee362009-07-17 12:22:16 -05001826 self.assertEqual(None, p12.get_certificate())
1827 self.assertEqual(None, p12.get_privatekey())
1828 self.assertEqual(None, p12.get_ca_certificates())
Rick Dean42d69e12009-07-20 11:36:08 -05001829 self.assertEqual(None, p12.get_friendlyname())
Rick Dean623ee362009-07-17 12:22:16 -05001830
1831 def test_type_errors(self):
Rick Dean38a05c82009-07-18 01:41:30 -05001832 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001833 The :py:obj:`PKCS12` setter functions (:py:obj:`set_certificate`, :py:obj:`set_privatekey`,
1834 :py:obj:`set_ca_certificates`, and :py:obj:`set_friendlyname`) raise :py:obj:`TypeError`
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001835 when passed objects of types other than those expected.
Rick Dean38a05c82009-07-18 01:41:30 -05001836 """
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001837 p12 = PKCS12()
Rick Dean623ee362009-07-17 12:22:16 -05001838 self.assertRaises(TypeError, p12.set_certificate, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05001839 self.assertRaises(TypeError, p12.set_certificate, PKey())
1840 self.assertRaises(TypeError, p12.set_certificate, X509)
Rick Dean623ee362009-07-17 12:22:16 -05001841 self.assertRaises(TypeError, p12.set_privatekey, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05001842 self.assertRaises(TypeError, p12.set_privatekey, 'legbone')
1843 self.assertRaises(TypeError, p12.set_privatekey, X509())
Rick Dean623ee362009-07-17 12:22:16 -05001844 self.assertRaises(TypeError, p12.set_ca_certificates, 3)
1845 self.assertRaises(TypeError, p12.set_ca_certificates, X509())
1846 self.assertRaises(TypeError, p12.set_ca_certificates, (3, 4))
Alex Gaynor7f636492015-09-04 13:26:52 -04001847 self.assertRaises(TypeError, p12.set_ca_certificates, (PKey(),))
Rick Dean42d69e12009-07-20 11:36:08 -05001848 self.assertRaises(TypeError, p12.set_friendlyname, 6)
1849 self.assertRaises(TypeError, p12.set_friendlyname, ('foo', 'bar'))
Rick Dean623ee362009-07-17 12:22:16 -05001850
1851 def test_key_only(self):
1852 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001853 A :py:obj:`PKCS12` with only a private key can be exported using
1854 :py:obj:`PKCS12.export` and loaded again using :py:obj:`load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001855 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001856 passwd = b"blah"
Rick Dean623ee362009-07-17 12:22:16 -05001857 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001858 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001859 p12.set_privatekey(pkey)
Rick Dean623ee362009-07-17 12:22:16 -05001860 self.assertEqual(None, p12.get_certificate())
1861 self.assertEqual(pkey, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05001862 try:
1863 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
1864 except Error:
1865 # Some versions of OpenSSL will throw an exception
1866 # for this nearly useless PKCS12 we tried to generate:
1867 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
1868 return
Rick Dean623ee362009-07-17 12:22:16 -05001869 p12 = load_pkcs12(dumped_p12, passwd)
1870 self.assertEqual(None, p12.get_ca_certificates())
1871 self.assertEqual(None, p12.get_certificate())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001872
1873 # OpenSSL fails to bring the key back to us. So sad. Perhaps in the
1874 # future this will be improved.
1875 self.assertTrue(isinstance(p12.get_privatekey(), (PKey, type(None))))
Rick Dean623ee362009-07-17 12:22:16 -05001876
1877 def test_cert_only(self):
1878 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001879 A :py:obj:`PKCS12` with only a certificate can be exported using
1880 :py:obj:`PKCS12.export` and loaded again using :py:obj:`load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001881 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001882 passwd = b"blah"
Rick Dean623ee362009-07-17 12:22:16 -05001883 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001884 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001885 p12.set_certificate(cert)
Rick Dean623ee362009-07-17 12:22:16 -05001886 self.assertEqual(cert, p12.get_certificate())
1887 self.assertEqual(None, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05001888 try:
1889 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
1890 except Error:
1891 # Some versions of OpenSSL will throw an exception
1892 # for this nearly useless PKCS12 we tried to generate:
1893 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
1894 return
Rick Dean623ee362009-07-17 12:22:16 -05001895 p12 = load_pkcs12(dumped_p12, passwd)
1896 self.assertEqual(None, p12.get_privatekey())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001897
1898 # OpenSSL fails to bring the cert back to us. Groany mcgroan.
1899 self.assertTrue(isinstance(p12.get_certificate(), (X509, type(None))))
1900
1901 # Oh ho. It puts the certificate into the ca certificates list, in
1902 # fact. Totally bogus, I would think. Nevertheless, let's exploit
1903 # that to check to see if it reconstructed the certificate we expected
1904 # it to. At some point, hopefully this will change so that
1905 # p12.get_certificate() is actually what returns the loaded
1906 # certificate.
1907 self.assertEqual(
1908 cleartextCertificatePEM,
1909 dump_certificate(FILETYPE_PEM, p12.get_ca_certificates()[0]))
Rick Dean623ee362009-07-17 12:22:16 -05001910
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001911 def gen_pkcs12(self, cert_pem=None, key_pem=None, ca_pem=None, friendly_name=None):
Rick Dean623ee362009-07-17 12:22:16 -05001912 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001913 Generate a PKCS12 object with components from PEM. Verify that the set
1914 functions return None.
Rick Dean623ee362009-07-17 12:22:16 -05001915 """
Rick Deanf94096c2009-07-18 14:23:06 -05001916 p12 = PKCS12()
1917 if cert_pem:
1918 ret = p12.set_certificate(load_certificate(FILETYPE_PEM, cert_pem))
1919 self.assertEqual(ret, None)
1920 if key_pem:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001921 ret = p12.set_privatekey(load_privatekey(FILETYPE_PEM, key_pem))
Rick Deanf94096c2009-07-18 14:23:06 -05001922 self.assertEqual(ret, None)
1923 if ca_pem:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001924 ret = p12.set_ca_certificates((load_certificate(FILETYPE_PEM, ca_pem),))
Rick Deanf94096c2009-07-18 14:23:06 -05001925 self.assertEqual(ret, None)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001926 if friendly_name:
1927 ret = p12.set_friendlyname(friendly_name)
Rick Dean42d69e12009-07-20 11:36:08 -05001928 self.assertEqual(ret, None)
Rick Deanf94096c2009-07-18 14:23:06 -05001929 return p12
1930
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001931 def check_recovery(self, p12_str, key=None, cert=None, ca=None, passwd=b"",
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001932 extra=()):
Rick Deanf94096c2009-07-18 14:23:06 -05001933 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001934 Use openssl program to confirm three components are recoverable from a
1935 PKCS12 string.
Rick Deanf94096c2009-07-18 14:23:06 -05001936 """
1937 if key:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001938 recovered_key = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001939 p12_str, b"pkcs12", b"-nocerts", b"-nodes", b"-passin",
1940 b"pass:" + passwd, *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001941 self.assertEqual(recovered_key[-len(key):], key)
1942 if cert:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001943 recovered_cert = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001944 p12_str, b"pkcs12", b"-clcerts", b"-nodes", b"-passin",
1945 b"pass:" + passwd, b"-nokeys", *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001946 self.assertEqual(recovered_cert[-len(cert):], cert)
1947 if ca:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001948 recovered_cert = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001949 p12_str, b"pkcs12", b"-cacerts", b"-nodes", b"-passin",
1950 b"pass:" + passwd, b"-nokeys", *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001951 self.assertEqual(recovered_cert[-len(ca):], ca)
1952
Stephen Holsapple38482622014-04-05 20:29:34 -07001953 def verify_pkcs12_container(self, p12):
1954 """
1955 Verify that the PKCS#12 container contains the correct client
1956 certificate and private key.
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04001957
1958 :param p12: The PKCS12 instance to verify.
1959 :type p12: :py:class:`PKCS12`
Stephen Holsapple38482622014-04-05 20:29:34 -07001960 """
1961 cert_pem = dump_certificate(FILETYPE_PEM, p12.get_certificate())
1962 key_pem = dump_privatekey(FILETYPE_PEM, p12.get_privatekey())
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04001963 self.assertEqual(
1964 (client_cert_pem, client_key_pem, None),
1965 (cert_pem, key_pem, p12.get_ca_certificates()))
Stephen Holsapple38482622014-04-05 20:29:34 -07001966
Rick Deanf94096c2009-07-18 14:23:06 -05001967 def test_load_pkcs12(self):
1968 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001969 A PKCS12 string generated using the openssl command line can be loaded
Jonathan Ballet648875f2011-07-16 14:14:58 +09001970 with :py:obj:`load_pkcs12` and its components extracted and examined.
Rick Deanf94096c2009-07-18 14:23:06 -05001971 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001972 passwd = b"whatever"
Rick Dean623ee362009-07-17 12:22:16 -05001973 pem = client_key_pem + client_cert_pem
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001974 p12_str = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001975 pem, b"pkcs12", b"-export", b"-clcerts", b"-passout", b"pass:" + passwd)
Stephen Holsapple38482622014-04-05 20:29:34 -07001976 p12 = load_pkcs12(p12_str, passphrase=passwd)
1977 self.verify_pkcs12_container(p12)
1978
Abraham Martinc5484ba2015-03-25 15:33:05 +00001979 def test_load_pkcs12_text_passphrase(self):
1980 """
1981 A PKCS12 string generated using the openssl command line can be loaded
1982 with :py:obj:`load_pkcs12` and its components extracted and examined.
1983 Using text as passphrase instead of bytes. DeprecationWarning expected.
1984 """
1985 pem = client_key_pem + client_cert_pem
1986 passwd = b"whatever"
1987 p12_str = _runopenssl(pem, b"pkcs12", b"-export", b"-clcerts",
1988 b"-passout", b"pass:" + passwd)
1989 with catch_warnings(record=True) as w:
1990 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04001991 p12 = load_pkcs12(p12_str, passphrase=b"whatever".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04001992
1993 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04001994 "{0} for passphrase is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04001995 WARNING_TYPE_EXPECTED
1996 ),
1997 str(w[-1].message)
1998 )
1999 self.assertIs(w[-1].category, DeprecationWarning)
2000
Abraham Martinc5484ba2015-03-25 15:33:05 +00002001 self.verify_pkcs12_container(p12)
2002
Stephen Holsapple38482622014-04-05 20:29:34 -07002003 def test_load_pkcs12_no_passphrase(self):
2004 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002005 A PKCS12 string generated using openssl command line can be loaded with
2006 :py:obj:`load_pkcs12` without a passphrase and its components extracted
2007 and examined.
Stephen Holsapple38482622014-04-05 20:29:34 -07002008 """
2009 pem = client_key_pem + client_cert_pem
2010 p12_str = _runopenssl(
2011 pem, b"pkcs12", b"-export", b"-clcerts", b"-passout", b"pass:")
2012 p12 = load_pkcs12(p12_str)
2013 self.verify_pkcs12_container(p12)
2014
Stephen Holsapple38482622014-04-05 20:29:34 -07002015 def _dump_and_load(self, dump_passphrase, load_passphrase):
2016 """
2017 A helper method to dump and load a PKCS12 object.
2018 """
2019 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem)
2020 dumped_p12 = p12.export(passphrase=dump_passphrase, iter=2, maciter=3)
2021 return load_pkcs12(dumped_p12, passphrase=load_passphrase)
2022
Stephen Holsapple38482622014-04-05 20:29:34 -07002023 def test_load_pkcs12_null_passphrase_load_empty(self):
2024 """
2025 A PKCS12 string can be dumped with a null passphrase, loaded with an
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002026 empty passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002027 extracted and examined.
2028 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002029 self.verify_pkcs12_container(
2030 self._dump_and_load(dump_passphrase=None, load_passphrase=b''))
Stephen Holsapple38482622014-04-05 20:29:34 -07002031
Stephen Holsapple38482622014-04-05 20:29:34 -07002032 def test_load_pkcs12_null_passphrase_load_null(self):
2033 """
2034 A PKCS12 string can be dumped with a null passphrase, loaded with a
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002035 null passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002036 extracted and examined.
2037 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002038 self.verify_pkcs12_container(
2039 self._dump_and_load(dump_passphrase=None, load_passphrase=None))
Stephen Holsapple38482622014-04-05 20:29:34 -07002040
Stephen Holsapple38482622014-04-05 20:29:34 -07002041 def test_load_pkcs12_empty_passphrase_load_empty(self):
2042 """
2043 A PKCS12 string can be dumped with an empty passphrase, loaded with an
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002044 empty passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002045 extracted and examined.
2046 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002047 self.verify_pkcs12_container(
2048 self._dump_and_load(dump_passphrase=b'', load_passphrase=b''))
Stephen Holsapple38482622014-04-05 20:29:34 -07002049
Stephen Holsapple38482622014-04-05 20:29:34 -07002050 def test_load_pkcs12_empty_passphrase_load_null(self):
2051 """
2052 A PKCS12 string can be dumped with an empty passphrase, loaded with a
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002053 null passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002054 extracted and examined.
2055 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002056 self.verify_pkcs12_container(
2057 self._dump_and_load(dump_passphrase=b'', load_passphrase=None))
Rick Deanf94096c2009-07-18 14:23:06 -05002058
Rick Deanee568302009-07-24 09:56:29 -05002059 def test_load_pkcs12_garbage(self):
2060 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002061 :py:obj:`load_pkcs12` raises :py:obj:`OpenSSL.crypto.Error` when passed a string
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002062 which is not a PKCS12 dump.
Rick Deanee568302009-07-24 09:56:29 -05002063 """
2064 passwd = 'whatever'
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002065 e = self.assertRaises(Error, load_pkcs12, b'fruit loops', passwd)
Alex Gaynor7f636492015-09-04 13:26:52 -04002066 self.assertEqual(e.args[0][0][0], 'asn1 encoding routines')
2067 self.assertEqual(len(e.args[0][0]), 3)
Rick Deanee568302009-07-24 09:56:29 -05002068
Rick Deanf94096c2009-07-18 14:23:06 -05002069 def test_replace(self):
2070 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002071 :py:obj:`PKCS12.set_certificate` replaces the certificate in a PKCS12 cluster.
2072 :py:obj:`PKCS12.set_privatekey` replaces the private key.
2073 :py:obj:`PKCS12.set_ca_certificates` replaces the CA certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05002074 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002075 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
2076 p12.set_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2077 p12.set_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002078 root_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05002079 client_cert = load_certificate(FILETYPE_PEM, client_cert_pem)
Alex Gaynoraceb3e22015-09-05 12:00:22 -04002080 p12.set_ca_certificates([root_cert]) # not a tuple
Rick Dean623ee362009-07-17 12:22:16 -05002081 self.assertEqual(1, len(p12.get_ca_certificates()))
2082 self.assertEqual(root_cert, p12.get_ca_certificates()[0])
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002083 p12.set_ca_certificates([client_cert, root_cert])
Rick Deanf94096c2009-07-18 14:23:06 -05002084 self.assertEqual(2, len(p12.get_ca_certificates()))
2085 self.assertEqual(client_cert, p12.get_ca_certificates()[0])
2086 self.assertEqual(root_cert, p12.get_ca_certificates()[1])
2087
Rick Deanf94096c2009-07-18 14:23:06 -05002088 def test_friendly_name(self):
2089 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002090 The *friendlyName* of a PKCS12 can be set and retrieved via
Jonathan Ballet648875f2011-07-16 14:14:58 +09002091 :py:obj:`PKCS12.get_friendlyname` and :py:obj:`PKCS12_set_friendlyname`, and a
2092 :py:obj:`PKCS12` with a friendly name set can be dumped with :py:obj:`PKCS12.export`.
Rick Deanf94096c2009-07-18 14:23:06 -05002093 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002094 passwd = b'Dogmeat[]{}!@#$%^&*()~`?/.,<>-_+=";:'
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002095 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -04002096 for friendly_name in [b('Serverlicious'), None, b('###')]:
Rick Dean42d69e12009-07-20 11:36:08 -05002097 p12.set_friendlyname(friendly_name)
2098 self.assertEqual(p12.get_friendlyname(), friendly_name)
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002099 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
Rick Dean42d69e12009-07-20 11:36:08 -05002100 reloaded_p12 = load_pkcs12(dumped_p12, passwd)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002101 self.assertEqual(
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -04002102 p12.get_friendlyname(), reloaded_p12.get_friendlyname())
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002103 # We would use the openssl program to confirm the friendly
2104 # name, but it is not possible. The pkcs12 command
2105 # does not store the friendly name in the cert's
Rick Dean42d69e12009-07-20 11:36:08 -05002106 # alias, which we could then extract.
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002107 self.check_recovery(
2108 dumped_p12, key=server_key_pem, cert=server_cert_pem,
2109 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05002110
Rick Deanf94096c2009-07-18 14:23:06 -05002111 def test_various_empty_passphrases(self):
2112 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002113 Test that missing, None, and '' passphrases are identical for PKCS12
2114 export.
Rick Deanf94096c2009-07-18 14:23:06 -05002115 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002116 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002117 passwd = b""
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002118 dumped_p12_empty = p12.export(iter=2, maciter=0, passphrase=passwd)
2119 dumped_p12_none = p12.export(iter=3, maciter=2, passphrase=None)
2120 dumped_p12_nopw = p12.export(iter=9, maciter=4)
2121 for dumped_p12 in [dumped_p12_empty, dumped_p12_none, dumped_p12_nopw]:
2122 self.check_recovery(
2123 dumped_p12, key=client_key_pem, cert=client_cert_pem,
2124 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05002125
Rick Deanf94096c2009-07-18 14:23:06 -05002126 def test_removing_ca_cert(self):
2127 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002128 Passing :py:obj:`None` to :py:obj:`PKCS12.set_ca_certificates` removes all CA
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002129 certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05002130 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002131 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
2132 p12.set_ca_certificates(None)
Rick Dean623ee362009-07-17 12:22:16 -05002133 self.assertEqual(None, p12.get_ca_certificates())
Rick Deanf94096c2009-07-18 14:23:06 -05002134
Rick Deanf94096c2009-07-18 14:23:06 -05002135 def test_export_without_mac(self):
2136 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002137 Exporting a PKCS12 with a :py:obj:`maciter` of ``-1`` excludes the MAC
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002138 entirely.
Rick Deanf94096c2009-07-18 14:23:06 -05002139 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002140 passwd = b"Lake Michigan"
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002141 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Dean623ee362009-07-17 12:22:16 -05002142 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002143 self.check_recovery(
2144 dumped_p12, key=server_key_pem, cert=server_cert_pem,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002145 passwd=passwd, extra=(b"-nomacver",))
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002146
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002147 def test_load_without_mac(self):
2148 """
2149 Loading a PKCS12 without a MAC does something other than crash.
2150 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002151 passwd = b"Lake Michigan"
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002152 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
2153 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Rick Dean321a0512009-08-13 17:21:29 -05002154 try:
2155 recovered_p12 = load_pkcs12(dumped_p12, passwd)
2156 # The person who generated this PCKS12 should be flogged,
2157 # or better yet we should have a means to determine
2158 # whether a PCKS12 had a MAC that was verified.
2159 # Anyway, libopenssl chooses to allow it, so the
2160 # pyopenssl binding does as well.
2161 self.assertTrue(isinstance(recovered_p12, PKCS12))
2162 except Error:
2163 # Failing here with an exception is preferred as some openssl
2164 # versions do.
2165 pass
Rick Dean623ee362009-07-17 12:22:16 -05002166
Rick Dean25bcc1f2009-07-20 11:53:13 -05002167 def test_zero_len_list_for_ca(self):
2168 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002169 A PKCS12 with an empty CA certificates list can be exported.
Rick Dean25bcc1f2009-07-20 11:53:13 -05002170 """
2171 passwd = 'Hobie 18'
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002172 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002173 # p12.set_ca_certificates([])
2174 # self.assertEqual((), p12.get_ca_certificates())
2175 # dumped_p12 = p12.export(passphrase=passwd, iter=3)
2176 # self.check_recovery(
2177 # dumped_p12, key=server_key_pem, cert=server_cert_pem,
2178 # passwd=passwd)
Rick Dean25bcc1f2009-07-20 11:53:13 -05002179
Rick Deanf94096c2009-07-18 14:23:06 -05002180 def test_export_without_args(self):
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002181 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002182 All the arguments to :py:obj:`PKCS12.export` are optional.
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002183 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002184 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05002185 dumped_p12 = p12.export() # no args
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002186 self.check_recovery(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002187 dumped_p12, key=server_key_pem, cert=server_cert_pem, passwd=b"")
Rick Deanf94096c2009-07-18 14:23:06 -05002188
Abraham Martinc5484ba2015-03-25 15:33:05 +00002189 def test_export_without_bytes(self):
2190 """
2191 Test :py:obj:`PKCS12.export` with text not bytes as passphrase
2192 """
2193 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
2194
2195 with catch_warnings(record=True) as w:
2196 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002197 dumped_p12 = p12.export(passphrase=b"randomtext".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002198 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002199 "{0} for passphrase is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002200 WARNING_TYPE_EXPECTED
2201 ),
2202 str(w[-1].message)
2203 )
2204 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinc5484ba2015-03-25 15:33:05 +00002205 self.check_recovery(
Alex Gaynor791212d2015-09-05 15:46:08 -04002206 dumped_p12,
2207 key=server_key_pem,
2208 cert=server_cert_pem,
2209 passwd=b"randomtext"
2210 )
Abraham Martinc5484ba2015-03-25 15:33:05 +00002211
Rick Deanf94096c2009-07-18 14:23:06 -05002212 def test_key_cert_mismatch(self):
2213 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002214 :py:obj:`PKCS12.export` raises an exception when a key and certificate
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002215 mismatch.
Rick Deanf94096c2009-07-18 14:23:06 -05002216 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002217 p12 = self.gen_pkcs12(server_cert_pem, client_key_pem, root_cert_pem)
2218 self.assertRaises(Error, p12.export)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002219
2220
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002221# These quoting functions taken directly from Twisted's twisted.python.win32.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002222_cmdLineQuoteRe = re.compile(br'(\\*)"')
2223_cmdLineQuoteRe2 = re.compile(br'(\\+)\Z')
Alex Gaynoraceb3e22015-09-05 12:00:22 -04002224
2225
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002226def cmdLineQuote(s):
2227 """
2228 Internal method for quoting a single command-line argument.
2229
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002230 See http://www.perlmonks.org/?node_id=764004
2231
Jonathan Ballet648875f2011-07-16 14:14:58 +09002232 :type: :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002233 :param s: A single unquoted string to quote for something that is expecting
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002234 cmd.exe-style quoting
2235
Jonathan Ballet648875f2011-07-16 14:14:58 +09002236 :rtype: :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002237 :return: A cmd.exe-style quoted string
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002238 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002239 s = _cmdLineQuoteRe2.sub(br"\1\1", _cmdLineQuoteRe.sub(br'\1\1\\"', s))
2240 return b'"' + s + b'"'
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002241
2242
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002243def quoteArguments(arguments):
2244 """
2245 Quote an iterable of command-line arguments for passing to CreateProcess or
Alex Gaynor791212d2015-09-05 15:46:08 -04002246 a similar API. This allows the list passed to
2247 :py:obj:`reactor.spawnProcess` to match the child process's
2248 :py:obj:`sys.argv` properly.
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002249
Jonathan Ballet648875f2011-07-16 14:14:58 +09002250 :type arguments: :py:obj:`iterable` of :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002251 :param arguments: An iterable of unquoted arguments to quote
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002252
Jonathan Ballet648875f2011-07-16 14:14:58 +09002253 :rtype: :py:obj:`str`
Alex Gaynor791212d2015-09-05 15:46:08 -04002254 :return: A space-delimited string containing quoted versions of
2255 :py:obj:`arguments`
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002256 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002257 return b' '.join(map(cmdLineQuote, arguments))
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002258
2259
Rick Dean4c9ad612009-07-17 15:05:22 -05002260def _runopenssl(pem, *args):
2261 """
2262 Run the command line openssl tool with the given arguments and write
Rick Dean55d1ce62009-08-13 17:40:24 -05002263 the given PEM to its stdin. Not safe for quotes.
Rick Dean4c9ad612009-07-17 15:05:22 -05002264 """
Jean-Paul Calderone038de952009-08-21 12:16:06 -04002265 if os.name == 'posix':
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002266 command = b"openssl " + b" ".join([
2267 (b"'" + arg.replace(b"'", b"'\\''") + b"'")
2268 for arg in args])
Rick Dean55d1ce62009-08-13 17:40:24 -05002269 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002270 command = b"openssl " + quoteArguments(args)
2271 proc = Popen(native(command), shell=True, stdin=PIPE, stdout=PIPE)
Jean-Paul Calderone62ca8da2010-08-11 19:58:08 -04002272 proc.stdin.write(pem)
2273 proc.stdin.close()
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002274 output = proc.stdout.read()
2275 proc.stdout.close()
2276 proc.wait()
2277 return output
Rick Dean4c9ad612009-07-17 15:05:22 -05002278
2279
Jean-Paul Calderone18808652009-07-05 12:54:05 -04002280class FunctionTests(TestCase):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002281 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002282 Tests for free-functions in the :py:obj:`OpenSSL.crypto` module.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002283 """
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002284
2285 def test_load_privatekey_invalid_format(self):
2286 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002287 :py:obj:`load_privatekey` raises :py:obj:`ValueError` if passed an
2288 unknown filetype.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002289 """
2290 self.assertRaises(ValueError, load_privatekey, 100, root_key_pem)
2291
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002292 def test_load_privatekey_invalid_passphrase_type(self):
2293 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002294 :py:obj:`load_privatekey` raises :py:obj:`TypeError` if passed a
2295 passphrase that is neither a :py:obj:`str` nor a callable.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002296 """
2297 self.assertRaises(
2298 TypeError,
2299 load_privatekey,
2300 FILETYPE_PEM, encryptedPrivateKeyPEMPassphrase, object())
2301
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002302 def test_load_privatekey_wrong_args(self):
2303 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002304 :py:obj:`load_privatekey` raises :py:obj:`TypeError` if called with the
2305 wrong number of arguments.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002306 """
2307 self.assertRaises(TypeError, load_privatekey)
2308
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002309 def test_load_privatekey_wrongPassphrase(self):
2310 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002311 :py:obj:`load_privatekey` raises :py:obj:`OpenSSL.crypto.Error` when it
2312 is passed an encrypted PEM and an incorrect passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002313 """
2314 self.assertRaises(
2315 Error,
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002316 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, b("quack"))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002317
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002318 def test_load_privatekey_passphraseWrongType(self):
2319 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002320 :py:obj:`load_privatekey` raises :py:obj:`ValueError` when it is passed
2321 a passphrase with a private key encoded in a format, that doesn't
2322 support encryption.
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002323 """
2324 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2325 blob = dump_privatekey(FILETYPE_ASN1, key)
2326 self.assertRaises(ValueError,
Alex Gaynor791212d2015-09-05 15:46:08 -04002327 load_privatekey, FILETYPE_ASN1, blob, "secret")
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002328
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002329 def test_load_privatekey_passphrase(self):
2330 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002331 :py:obj:`load_privatekey` can create a :py:obj:`PKey` object from an
2332 encrypted PEM string if given the passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002333 """
2334 key = load_privatekey(
2335 FILETYPE_PEM, encryptedPrivateKeyPEM,
2336 encryptedPrivateKeyPEMPassphrase)
2337 self.assertTrue(isinstance(key, PKeyType))
2338
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002339 def test_load_privatekey_passphrase_exception(self):
2340 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002341 If the passphrase callback raises an exception, that exception is
2342 raised by :py:obj:`load_privatekey`.
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002343 """
2344 def cb(ignored):
2345 raise ArithmeticError
2346
Alex Gaynor791212d2015-09-05 15:46:08 -04002347 with pytest.raises(ArithmeticError):
2348 load_privatekey(FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002349
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002350 def test_load_privatekey_wrongPassphraseCallback(self):
2351 """
Jean-Paul Calderoned440a082011-09-14 11:02:05 -04002352 :py:obj:`load_privatekey` raises :py:obj:`OpenSSL.crypto.Error` when it
2353 is passed an encrypted PEM and a passphrase callback which returns an
2354 incorrect passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002355 """
2356 called = []
Alex Gaynoraceb3e22015-09-05 12:00:22 -04002357
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002358 def cb(*a):
2359 called.append(None)
Jean-Paul Calderoned440a082011-09-14 11:02:05 -04002360 return b("quack")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002361 self.assertRaises(
2362 Error,
2363 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2364 self.assertTrue(called)
2365
2366 def test_load_privatekey_passphraseCallback(self):
2367 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002368 :py:obj:`load_privatekey` can create a :py:obj:`PKey` object from an
2369 encrypted PEM string if given a passphrase callback which returns the
2370 correct password.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002371 """
2372 called = []
Alex Gaynoraceb3e22015-09-05 12:00:22 -04002373
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002374 def cb(writing):
2375 called.append(writing)
2376 return encryptedPrivateKeyPEMPassphrase
2377 key = load_privatekey(FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2378 self.assertTrue(isinstance(key, PKeyType))
2379 self.assertEqual(called, [False])
2380
Jean-Paul Calderone105cb952011-09-14 10:16:46 -04002381 def test_load_privatekey_passphrase_wrong_return_type(self):
2382 """
2383 :py:obj:`load_privatekey` raises :py:obj:`ValueError` if the passphrase
2384 callback returns something other than a byte string.
2385 """
2386 self.assertRaises(
2387 ValueError,
2388 load_privatekey,
2389 FILETYPE_PEM, encryptedPrivateKeyPEM, lambda *args: 3)
2390
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002391 def test_dump_privatekey_wrong_args(self):
2392 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002393 :py:obj:`dump_privatekey` raises :py:obj:`TypeError` if called with the
2394 wrong number of arguments.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002395 """
2396 self.assertRaises(TypeError, dump_privatekey)
Jean-Paul Calderone1eeccd82011-09-14 10:18:52 -04002397 # If cipher name is given, password is required.
2398 self.assertRaises(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002399 TypeError, dump_privatekey, FILETYPE_PEM, PKey(), GOOD_CIPHER)
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002400
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002401 def test_dump_privatekey_unknown_cipher(self):
2402 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002403 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` if called with an
2404 unrecognized cipher name.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002405 """
2406 key = PKey()
2407 key.generate_key(TYPE_RSA, 512)
2408 self.assertRaises(
2409 ValueError, dump_privatekey,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002410 FILETYPE_PEM, key, BAD_CIPHER, "passphrase")
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002411
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002412 def test_dump_privatekey_invalid_passphrase_type(self):
2413 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002414 :py:obj:`dump_privatekey` raises :py:obj:`TypeError` if called with a
2415 passphrase which is neither a :py:obj:`str` nor a callable.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002416 """
2417 key = PKey()
2418 key.generate_key(TYPE_RSA, 512)
2419 self.assertRaises(
2420 TypeError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002421 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, object())
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002422
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002423 def test_dump_privatekey_invalid_filetype(self):
2424 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002425 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` if called with an
2426 unrecognized filetype.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002427 """
2428 key = PKey()
2429 key.generate_key(TYPE_RSA, 512)
2430 self.assertRaises(ValueError, dump_privatekey, 100, key)
2431
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002432 def test_load_privatekey_passphraseCallbackLength(self):
2433 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002434 :py:obj:`crypto.load_privatekey` should raise an error when the
2435 passphrase provided by the callback is too long, not silently truncate
2436 it.
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002437 """
2438 def cb(ignored):
2439 return "a" * 1025
2440
Alex Gaynor791212d2015-09-05 15:46:08 -04002441 with pytest.raises(ValueError):
2442 load_privatekey(FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002443
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002444 def test_dump_privatekey_passphrase(self):
2445 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002446 :py:obj:`dump_privatekey` writes an encrypted PEM when given a
2447 passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002448 """
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002449 passphrase = b("foo")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002450 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002451 pem = dump_privatekey(FILETYPE_PEM, key, GOOD_CIPHER, passphrase)
2452 self.assertTrue(isinstance(pem, binary_type))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002453 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
2454 self.assertTrue(isinstance(loadedKey, PKeyType))
2455 self.assertEqual(loadedKey.type(), key.type())
2456 self.assertEqual(loadedKey.bits(), key.bits())
2457
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002458 def test_dump_privatekey_passphraseWrongType(self):
2459 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002460 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` when it is passed
2461 a passphrase with a private key encoded in a format, that doesn't
2462 support encryption.
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002463 """
2464 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Alex Gaynor791212d2015-09-05 15:46:08 -04002465 with pytest.raises(ValueError):
2466 dump_privatekey(FILETYPE_ASN1, key, GOOD_CIPHER, "secret")
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002467
Rick Dean5b7b6372009-04-01 11:34:06 -05002468 def test_dump_certificate(self):
2469 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002470 :py:obj:`dump_certificate` writes PEM, DER, and text.
Rick Dean5b7b6372009-04-01 11:34:06 -05002471 """
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002472 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
Rick Dean5b7b6372009-04-01 11:34:06 -05002473 cert = load_certificate(FILETYPE_PEM, pemData)
2474 dumped_pem = dump_certificate(FILETYPE_PEM, cert)
2475 self.assertEqual(dumped_pem, cleartextCertificatePEM)
2476 dumped_der = dump_certificate(FILETYPE_ASN1, cert)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002477 good_der = _runopenssl(dumped_pem, b"x509", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002478 self.assertEqual(dumped_der, good_der)
2479 cert2 = load_certificate(FILETYPE_ASN1, dumped_der)
2480 dumped_pem2 = dump_certificate(FILETYPE_PEM, cert2)
2481 self.assertEqual(dumped_pem2, cleartextCertificatePEM)
2482 dumped_text = dump_certificate(FILETYPE_TEXT, cert)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002483 good_text = _runopenssl(dumped_pem, b"x509", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002484 self.assertEqual(dumped_text, good_text)
2485
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002486 def test_dump_privatekey_pem(self):
Rick Dean5b7b6372009-04-01 11:34:06 -05002487 """
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002488 :py:obj:`dump_privatekey` writes a PEM
Rick Dean5b7b6372009-04-01 11:34:06 -05002489 """
2490 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -04002491 self.assertTrue(key.check())
Rick Dean5b7b6372009-04-01 11:34:06 -05002492 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2493 self.assertEqual(dumped_pem, cleartextPrivateKeyPEM)
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002494
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002495 def test_dump_privatekey_asn1(self):
2496 """
2497 :py:obj:`dump_privatekey` writes a DER
2498 """
2499 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2500 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2501
Rick Dean5b7b6372009-04-01 11:34:06 -05002502 dumped_der = dump_privatekey(FILETYPE_ASN1, key)
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002503 # XXX This OpenSSL call writes "writing RSA key" to standard out. Sad.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002504 good_der = _runopenssl(dumped_pem, b"rsa", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002505 self.assertEqual(dumped_der, good_der)
2506 key2 = load_privatekey(FILETYPE_ASN1, dumped_der)
2507 dumped_pem2 = dump_privatekey(FILETYPE_PEM, key2)
2508 self.assertEqual(dumped_pem2, cleartextPrivateKeyPEM)
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002509
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002510 def test_dump_privatekey_text(self):
2511 """
2512 :py:obj:`dump_privatekey` writes a text
2513 """
2514 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2515 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2516
Rick Dean5b7b6372009-04-01 11:34:06 -05002517 dumped_text = dump_privatekey(FILETYPE_TEXT, key)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002518 good_text = _runopenssl(dumped_pem, b"rsa", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002519 self.assertEqual(dumped_text, good_text)
2520
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002521
Rick Dean5b7b6372009-04-01 11:34:06 -05002522 def test_dump_certificate_request(self):
2523 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002524 :py:obj:`dump_certificate_request` writes a PEM, DER, and text.
Rick Dean5b7b6372009-04-01 11:34:06 -05002525 """
2526 req = load_certificate_request(FILETYPE_PEM, cleartextCertificateRequestPEM)
2527 dumped_pem = dump_certificate_request(FILETYPE_PEM, req)
2528 self.assertEqual(dumped_pem, cleartextCertificateRequestPEM)
2529 dumped_der = dump_certificate_request(FILETYPE_ASN1, req)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002530 good_der = _runopenssl(dumped_pem, b"req", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002531 self.assertEqual(dumped_der, good_der)
2532 req2 = load_certificate_request(FILETYPE_ASN1, dumped_der)
2533 dumped_pem2 = dump_certificate_request(FILETYPE_PEM, req2)
2534 self.assertEqual(dumped_pem2, cleartextCertificateRequestPEM)
2535 dumped_text = dump_certificate_request(FILETYPE_TEXT, req)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002536 good_text = _runopenssl(dumped_pem, b"req", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002537 self.assertEqual(dumped_text, good_text)
Jean-Paul Calderoneaf43cdf2010-08-03 18:40:52 -04002538 self.assertRaises(ValueError, dump_certificate_request, 100, req)
Rick Dean5b7b6372009-04-01 11:34:06 -05002539
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002540 def test_dump_privatekey_passphraseCallback(self):
2541 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002542 :py:obj:`dump_privatekey` writes an encrypted PEM when given a callback
2543 which returns the correct passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002544 """
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002545 passphrase = b("foo")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002546 called = []
Alex Gaynoraceb3e22015-09-05 12:00:22 -04002547
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002548 def cb(writing):
2549 called.append(writing)
2550 return passphrase
2551 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002552 pem = dump_privatekey(FILETYPE_PEM, key, GOOD_CIPHER, cb)
2553 self.assertTrue(isinstance(pem, binary_type))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002554 self.assertEqual(called, [True])
2555 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
2556 self.assertTrue(isinstance(loadedKey, PKeyType))
2557 self.assertEqual(loadedKey.type(), key.type())
2558 self.assertEqual(loadedKey.bits(), key.bits())
Rick Dean5b7b6372009-04-01 11:34:06 -05002559
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002560 def test_dump_privatekey_passphrase_exception(self):
2561 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002562 :py:obj:`dump_privatekey` should not overwrite the exception raised
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002563 by the passphrase callback.
2564 """
2565 def cb(ignored):
2566 raise ArithmeticError
2567
2568 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2569 self.assertRaises(ArithmeticError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002570 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, cb)
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002571
2572
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002573 def test_dump_privatekey_passphraseCallbackLength(self):
2574 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002575 :py:obj:`crypto.dump_privatekey` should raise an error when the
2576 passphrase provided by the callback is too long, not silently truncate
2577 it.
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002578 """
2579 def cb(ignored):
2580 return "a" * 1025
2581
2582 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2583 self.assertRaises(ValueError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002584 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, cb)
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002585
2586
Alex Gaynor4b9c96a2014-08-14 09:51:48 -07002587 def test_load_pkcs7_data_pem(self):
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002588 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002589 :py:obj:`load_pkcs7_data` accepts a PKCS#7 string and returns an
2590 instance of :py:obj:`PKCS7Type`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002591 """
2592 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2593 self.assertTrue(isinstance(pkcs7, PKCS7Type))
2594
Alex Gaynor4b9c96a2014-08-14 09:51:48 -07002595 def test_load_pkcs7_data_asn1(self):
Alex Gaynor9875a912014-08-14 13:35:05 -07002596 """
2597 :py:obj:`load_pkcs7_data` accepts a bytes containing ASN1 data
2598 representing PKCS#7 and returns an instance of :py:obj`PKCS7Type`.
2599 """
Alex Gaynor4b9c96a2014-08-14 09:51:48 -07002600 pkcs7 = load_pkcs7_data(FILETYPE_ASN1, pkcs7DataASN1)
2601 self.assertTrue(isinstance(pkcs7, PKCS7Type))
2602
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002603 def test_load_pkcs7_data_invalid(self):
2604 """
2605 If the data passed to :py:obj:`load_pkcs7_data` is invalid,
2606 :py:obj:`Error` is raised.
2607 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002608 self.assertRaises(Error, load_pkcs7_data, FILETYPE_PEM, b"foo")
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002609
2610
Jean-Paul Calderone4a68b402013-12-29 16:54:58 -05002611class LoadCertificateTests(TestCase):
2612 """
2613 Tests for :py:obj:`load_certificate_request`.
2614 """
Alex Gaynoraceb3e22015-09-05 12:00:22 -04002615
Jean-Paul Calderone4a68b402013-12-29 16:54:58 -05002616 def test_badFileType(self):
2617 """
2618 If the file type passed to :py:obj:`load_certificate_request` is
2619 neither :py:obj:`FILETYPE_PEM` nor :py:obj:`FILETYPE_ASN1` then
2620 :py:class:`ValueError` is raised.
2621 """
2622 self.assertRaises(ValueError, load_certificate_request, object(), b"")
2623
2624
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002625class PKCS7Tests(TestCase):
2626 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002627 Tests for :py:obj:`PKCS7Type`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002628 """
Alex Gaynoraceb3e22015-09-05 12:00:22 -04002629
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002630 def test_type(self):
2631 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002632 :py:obj:`PKCS7Type` is a type object.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002633 """
2634 self.assertTrue(isinstance(PKCS7Type, type))
2635 self.assertEqual(PKCS7Type.__name__, 'PKCS7')
2636
2637 # XXX This doesn't currently work.
2638 # self.assertIdentical(PKCS7, PKCS7Type)
2639
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002640 # XXX Opposite results for all these following methods
2641
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002642 def test_type_is_signed_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002643 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002644 :py:obj:`PKCS7Type.type_is_signed` raises :py:obj:`TypeError` if called
2645 with any arguments.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002646 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002647 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2648 self.assertRaises(TypeError, pkcs7.type_is_signed, None)
2649
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002650 def test_type_is_signed(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002651 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002652 :py:obj:`PKCS7Type.type_is_signed` returns :py:obj:`True` if the PKCS7
2653 object is of the type *signed*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002654 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002655 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2656 self.assertTrue(pkcs7.type_is_signed())
2657
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002658 def test_type_is_enveloped_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002659 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002660 :py:obj:`PKCS7Type.type_is_enveloped` raises :py:obj:`TypeError` if
2661 called with any arguments.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002662 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002663 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2664 self.assertRaises(TypeError, pkcs7.type_is_enveloped, None)
2665
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002666 def test_type_is_enveloped(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002667 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002668 :py:obj:`PKCS7Type.type_is_enveloped` returns :py:obj:`False` if the
2669 PKCS7 object is not of the type *enveloped*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002670 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002671 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2672 self.assertFalse(pkcs7.type_is_enveloped())
2673
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002674 def test_type_is_signedAndEnveloped_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002675 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002676 :py:obj:`PKCS7Type.type_is_signedAndEnveloped` raises
2677 :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002678 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002679 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2680 self.assertRaises(TypeError, pkcs7.type_is_signedAndEnveloped, None)
2681
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002682 def test_type_is_signedAndEnveloped(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002683 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002684 :py:obj:`PKCS7Type.type_is_signedAndEnveloped` returns :py:obj:`False`
2685 if the PKCS7 object is not of the type *signed and enveloped*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002686 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002687 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2688 self.assertFalse(pkcs7.type_is_signedAndEnveloped())
2689
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002690 def test_type_is_data(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002691 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002692 :py:obj:`PKCS7Type.type_is_data` returns :py:obj:`False` if the PKCS7
2693 object is not of the type data.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002694 """
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002695 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2696 self.assertFalse(pkcs7.type_is_data())
2697
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002698 def test_type_is_data_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002699 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002700 :py:obj:`PKCS7Type.type_is_data` raises :py:obj:`TypeError` if called
2701 with any arguments.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002702 """
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002703 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2704 self.assertRaises(TypeError, pkcs7.type_is_data, None)
2705
Jean-Paul Calderone97b28ca2010-07-30 10:56:07 -04002706 def test_get_type_name_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002707 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002708 :py:obj:`PKCS7Type.get_type_name` raises :py:obj:`TypeError` if called
2709 with any arguments.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002710 """
Jean-Paul Calderone97b28ca2010-07-30 10:56:07 -04002711 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2712 self.assertRaises(TypeError, pkcs7.get_type_name, None)
2713
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002714 def test_get_type_name(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002715 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002716 :py:obj:`PKCS7Type.get_type_name` returns a :py:obj:`str` giving the
2717 type name.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002718 """
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002719 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
Jean-Paul Calderone07640f12010-08-22 17:14:43 -04002720 self.assertEquals(pkcs7.get_type_name(), b('pkcs7-signedData'))
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002721
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002722 def test_attribute(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002723 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002724 If an attribute other than one of the methods tested here is accessed
2725 on an instance of :py:obj:`PKCS7Type`, :py:obj:`AttributeError` is
2726 raised.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002727 """
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002728 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2729 self.assertRaises(AttributeError, getattr, pkcs7, "foo")
2730
2731
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002732class NetscapeSPKITests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002733 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002734 Tests for :py:obj:`OpenSSL.crypto.NetscapeSPKI`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002735 """
Alex Gaynoraceb3e22015-09-05 12:00:22 -04002736
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002737 def signable(self):
2738 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002739 Return a new :py:obj:`NetscapeSPKI` for use with signing tests.
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002740 """
2741 return NetscapeSPKI()
2742
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002743 def test_type(self):
2744 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002745 :py:obj:`NetscapeSPKI` and :py:obj:`NetscapeSPKIType` refer to the same
2746 type object and can be used to create instances of that type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002747 """
2748 self.assertIdentical(NetscapeSPKI, NetscapeSPKIType)
2749 self.assertConsistentType(NetscapeSPKI, 'NetscapeSPKI')
2750
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002751 def test_construction(self):
2752 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002753 :py:obj:`NetscapeSPKI` returns an instance of
2754 :py:obj:`NetscapeSPKIType`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002755 """
2756 nspki = NetscapeSPKI()
2757 self.assertTrue(isinstance(nspki, NetscapeSPKIType))
2758
Jean-Paul Calderone969efaa2010-08-03 18:19:19 -04002759 def test_invalid_attribute(self):
2760 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002761 Accessing a non-existent attribute of a :py:obj:`NetscapeSPKI` instance
2762 causes an :py:obj:`AttributeError` to be raised.
Jean-Paul Calderone969efaa2010-08-03 18:19:19 -04002763 """
2764 nspki = NetscapeSPKI()
2765 self.assertRaises(AttributeError, lambda: nspki.foo)
2766
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002767 def test_b64_encode(self):
2768 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002769 :py:obj:`NetscapeSPKI.b64_encode` encodes the certificate to a base64
2770 blob.
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002771 """
2772 nspki = NetscapeSPKI()
2773 blob = nspki.b64_encode()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002774 self.assertTrue(isinstance(blob, binary_type))
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002775
2776
Rick Dean536ba022009-07-24 23:57:27 -05002777class RevokedTests(TestCase):
2778 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002779 Tests for :py:obj:`OpenSSL.crypto.Revoked`
Rick Dean536ba022009-07-24 23:57:27 -05002780 """
Alex Gaynoraceb3e22015-09-05 12:00:22 -04002781
Rick Dean536ba022009-07-24 23:57:27 -05002782 def test_construction(self):
2783 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002784 Confirm we can create :py:obj:`OpenSSL.crypto.Revoked`. Check
Rick Dean536ba022009-07-24 23:57:27 -05002785 that it is empty.
2786 """
2787 revoked = Revoked()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002788 self.assertTrue(isinstance(revoked, Revoked))
2789 self.assertEquals(type(revoked), Revoked)
2790 self.assertEquals(revoked.get_serial(), b('00'))
2791 self.assertEquals(revoked.get_rev_date(), None)
2792 self.assertEquals(revoked.get_reason(), None)
Rick Dean536ba022009-07-24 23:57:27 -05002793
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002794 def test_construction_wrong_args(self):
2795 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002796 Calling :py:obj:`OpenSSL.crypto.Revoked` with any arguments results
2797 in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002798 """
2799 self.assertRaises(TypeError, Revoked, None)
2800 self.assertRaises(TypeError, Revoked, 1)
2801 self.assertRaises(TypeError, Revoked, "foo")
2802
Rick Dean536ba022009-07-24 23:57:27 -05002803 def test_serial(self):
2804 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002805 Confirm we can set and get serial numbers from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002806 :py:obj:`OpenSSL.crypto.Revoked`. Confirm errors are handled
Rick Dean536ba022009-07-24 23:57:27 -05002807 with grace.
2808 """
2809 revoked = Revoked()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002810 ret = revoked.set_serial(b('10b'))
2811 self.assertEquals(ret, None)
Rick Dean536ba022009-07-24 23:57:27 -05002812 ser = revoked.get_serial()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002813 self.assertEquals(ser, b('010B'))
Rick Dean536ba022009-07-24 23:57:27 -05002814
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002815 revoked.set_serial(b('31ppp')) # a type error would be nice
Rick Dean536ba022009-07-24 23:57:27 -05002816 ser = revoked.get_serial()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002817 self.assertEquals(ser, b('31'))
Rick Dean536ba022009-07-24 23:57:27 -05002818
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002819 self.assertRaises(ValueError, revoked.set_serial, b('pqrst'))
Rick Dean536ba022009-07-24 23:57:27 -05002820 self.assertRaises(TypeError, revoked.set_serial, 100)
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002821 self.assertRaises(TypeError, revoked.get_serial, 1)
2822 self.assertRaises(TypeError, revoked.get_serial, None)
2823 self.assertRaises(TypeError, revoked.get_serial, "")
Rick Dean536ba022009-07-24 23:57:27 -05002824
Rick Dean536ba022009-07-24 23:57:27 -05002825 def test_date(self):
2826 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002827 Confirm we can set and get revocation dates from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002828 :py:obj:`OpenSSL.crypto.Revoked`. Confirm errors are handled
Rick Dean536ba022009-07-24 23:57:27 -05002829 with grace.
2830 """
2831 revoked = Revoked()
2832 date = revoked.get_rev_date()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002833 self.assertEquals(date, None)
Rick Dean536ba022009-07-24 23:57:27 -05002834
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002835 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05002836 ret = revoked.set_rev_date(now)
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002837 self.assertEqual(ret, None)
Rick Dean536ba022009-07-24 23:57:27 -05002838 date = revoked.get_rev_date()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002839 self.assertEqual(date, now)
Rick Dean536ba022009-07-24 23:57:27 -05002840
Rick Dean6385faf2009-07-26 00:07:47 -05002841 def test_reason(self):
2842 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002843 Confirm we can set and get revocation reasons from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002844 :py:obj:`OpenSSL.crypto.Revoked`. The "get" need to work
Rick Dean6385faf2009-07-26 00:07:47 -05002845 as "set". Likewise, each reason of all_reasons() must work.
2846 """
2847 revoked = Revoked()
2848 for r in revoked.all_reasons():
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002849 for x in range(2):
Rick Dean6385faf2009-07-26 00:07:47 -05002850 ret = revoked.set_reason(r)
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002851 self.assertEquals(ret, None)
Rick Dean6385faf2009-07-26 00:07:47 -05002852 reason = revoked.get_reason()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002853 self.assertEquals(
2854 reason.lower().replace(b(' '), b('')),
2855 r.lower().replace(b(' '), b('')))
Alex Gaynoraceb3e22015-09-05 12:00:22 -04002856 r = reason # again with the resp of get
Rick Dean6385faf2009-07-26 00:07:47 -05002857
2858 revoked.set_reason(None)
2859 self.assertEqual(revoked.get_reason(), None)
2860
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002861 def test_set_reason_wrong_arguments(self):
Rick Dean6385faf2009-07-26 00:07:47 -05002862 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002863 Calling :py:obj:`OpenSSL.crypto.Revoked.set_reason` with other than
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002864 one argument, or an argument which isn't a valid reason,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002865 results in :py:obj:`TypeError` or :py:obj:`ValueError` being raised.
Rick Dean6385faf2009-07-26 00:07:47 -05002866 """
2867 revoked = Revoked()
2868 self.assertRaises(TypeError, revoked.set_reason, 100)
Jean-Paul Calderone281b62b2010-08-28 14:22:29 -04002869 self.assertRaises(ValueError, revoked.set_reason, b('blue'))
Rick Dean6385faf2009-07-26 00:07:47 -05002870
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002871 def test_get_reason_wrong_arguments(self):
2872 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002873 Calling :py:obj:`OpenSSL.crypto.Revoked.get_reason` with any
2874 arguments results in :py:obj:`TypeError` being raised.
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002875 """
2876 revoked = Revoked()
2877 self.assertRaises(TypeError, revoked.get_reason, None)
2878 self.assertRaises(TypeError, revoked.get_reason, 1)
2879 self.assertRaises(TypeError, revoked.get_reason, "foo")
2880
2881
Rick Dean536ba022009-07-24 23:57:27 -05002882class CRLTests(TestCase):
2883 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002884 Tests for :py:obj:`OpenSSL.crypto.CRL`
Rick Dean536ba022009-07-24 23:57:27 -05002885 """
2886 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
2887 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2888
2889 def test_construction(self):
2890 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002891 Confirm we can create :py:obj:`OpenSSL.crypto.CRL`. Check
Rick Dean536ba022009-07-24 23:57:27 -05002892 that it is empty
2893 """
2894 crl = CRL()
Alex Gaynor7f636492015-09-04 13:26:52 -04002895 self.assertTrue(isinstance(crl, CRL))
Rick Dean536ba022009-07-24 23:57:27 -05002896 self.assertEqual(crl.get_revoked(), None)
2897
Jean-Paul Calderone2efd03e2010-01-30 13:59:55 -05002898 def test_construction_wrong_args(self):
2899 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002900 Calling :py:obj:`OpenSSL.crypto.CRL` with any number of arguments
2901 results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone2efd03e2010-01-30 13:59:55 -05002902 """
2903 self.assertRaises(TypeError, CRL, 1)
2904 self.assertRaises(TypeError, CRL, "")
2905 self.assertRaises(TypeError, CRL, None)
2906
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002907 def _get_crl(self):
Rick Dean536ba022009-07-24 23:57:27 -05002908 """
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002909 Get a new ``CRL`` with a revocation.
Rick Dean536ba022009-07-24 23:57:27 -05002910 """
2911 crl = CRL()
2912 revoked = Revoked()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002913 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05002914 revoked.set_rev_date(now)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002915 revoked.set_serial(b('3ab'))
2916 revoked.set_reason(b('sUpErSeDEd'))
Rick Dean536ba022009-07-24 23:57:27 -05002917 crl.add_revoked(revoked)
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002918 return crl
Rick Dean536ba022009-07-24 23:57:27 -05002919
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002920 def test_export_pem(self):
2921 """
2922 If not passed a format, ``CRL.export`` returns a "PEM" format string
2923 representing a serial number, a revoked reason, and certificate issuer
2924 information.
2925 """
2926 crl = self._get_crl()
Rick Dean536ba022009-07-24 23:57:27 -05002927 # PEM format
2928 dumped_crl = crl.export(self.cert, self.pkey, days=20)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002929 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002930
2931 # These magic values are based on the way the CRL above was constructed
2932 # and with what certificate it was exported.
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002933 text.index(b('Serial Number: 03AB'))
2934 text.index(b('Superseded'))
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002935 text.index(
2936 b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA')
2937 )
2938
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002939 def test_export_der(self):
2940 """
2941 If passed ``FILETYPE_ASN1`` for the format, ``CRL.export`` returns a
2942 "DER" format string representing a serial number, a revoked reason, and
2943 certificate issuer information.
2944 """
2945 crl = self._get_crl()
Rick Dean536ba022009-07-24 23:57:27 -05002946
2947 # DER format
2948 dumped_crl = crl.export(self.cert, self.pkey, FILETYPE_ASN1)
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002949 text = _runopenssl(
2950 dumped_crl, b"crl", b"-noout", b"-text", b"-inform", b"DER"
2951 )
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002952 text.index(b('Serial Number: 03AB'))
2953 text.index(b('Superseded'))
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002954 text.index(
2955 b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA')
2956 )
2957
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002958 def test_export_text(self):
2959 """
2960 If passed ``FILETYPE_TEXT`` for the format, ``CRL.export`` returns a
2961 text format string like the one produced by the openssl command line
2962 tool.
2963 """
2964 crl = self._get_crl()
2965
2966 dumped_crl = crl.export(self.cert, self.pkey, FILETYPE_ASN1)
2967 text = _runopenssl(
2968 dumped_crl, b"crl", b"-noout", b"-text", b"-inform", b"DER"
2969 )
Rick Dean536ba022009-07-24 23:57:27 -05002970
2971 # text format
2972 dumped_text = crl.export(self.cert, self.pkey, type=FILETYPE_TEXT)
2973 self.assertEqual(text, dumped_text)
2974
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002975 def test_export_custom_digest(self):
2976 """
2977 If passed the name of a digest function, ``CRL.export`` uses a
2978 signature algorithm based on that digest function.
2979 """
2980 crl = self._get_crl()
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002981 dumped_crl = crl.export(self.cert, self.pkey, digest=b"sha1")
Bulat Gaifullin1966c972014-09-22 09:47:20 +04002982 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
2983 text.index(b('Signature Algorithm: sha1'))
2984
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002985 def test_export_md5_digest(self):
2986 """
2987 If passed md5 as the digest function, ``CRL.export`` uses md5 and does
2988 not emit a deprecation warning.
2989 """
2990 crl = self._get_crl()
2991 with catch_warnings(record=True) as catcher:
2992 simplefilter("always")
2993 self.assertEqual(0, len(catcher))
2994 dumped_crl = crl.export(self.cert, self.pkey, digest=b"md5")
2995 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
2996 text.index(b('Signature Algorithm: md5'))
2997
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002998 def test_export_default_digest(self):
2999 """
3000 If not passed the name of a digest function, ``CRL.export`` uses a
3001 signature algorithm based on MD5 and emits a deprecation warning.
3002 """
3003 crl = self._get_crl()
3004 with catch_warnings(record=True) as catcher:
3005 simplefilter("always")
3006 dumped_crl = crl.export(self.cert, self.pkey)
3007 self.assertEqual(
3008 "The default message digest (md5) is deprecated. "
3009 "Pass the name of a message digest explicitly.",
3010 str(catcher[0].message),
3011 )
Bulat Gaifullin1966c972014-09-22 09:47:20 +04003012 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
3013 text.index(b('Signature Algorithm: md5'))
3014
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -04003015 def test_export_invalid(self):
3016 """
3017 If :py:obj:`CRL.export` is used with an uninitialized :py:obj:`X509`
Jean-Paul Calderoneb5871072012-03-09 14:58:00 -08003018 instance, :py:obj:`OpenSSL.crypto.Error` is raised.
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -04003019 """
3020 crl = CRL()
3021 self.assertRaises(Error, crl.export, X509(), PKey())
3022
Jean-Paul Calderone56515342010-01-30 13:49:38 -05003023 def test_add_revoked_keyword(self):
3024 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003025 :py:obj:`OpenSSL.CRL.add_revoked` accepts its single argument as the
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003026 ``revoked`` keyword argument.
Jean-Paul Calderone56515342010-01-30 13:49:38 -05003027 """
3028 crl = CRL()
3029 revoked = Revoked()
3030 crl.add_revoked(revoked=revoked)
3031 self.assertTrue(isinstance(crl.get_revoked()[0], Revoked))
3032
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05003033 def test_export_wrong_args(self):
3034 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003035 Calling :py:obj:`OpenSSL.CRL.export` with fewer than two or more than
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05003036 four arguments, or with arguments other than the certificate,
3037 private key, integer file type, and integer number of days it
Jonathan Ballet648875f2011-07-16 14:14:58 +09003038 expects, results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05003039 """
3040 crl = CRL()
3041 self.assertRaises(TypeError, crl.export)
3042 self.assertRaises(TypeError, crl.export, self.cert)
Bulat Gaifullin925f7862014-09-22 10:10:44 +04003043 self.assertRaises(TypeError, crl.export, self.cert, self.pkey, FILETYPE_PEM, 10, "md5", "foo")
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05003044
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05003045 self.assertRaises(TypeError, crl.export, None, self.pkey, FILETYPE_PEM, 10)
3046 self.assertRaises(TypeError, crl.export, self.cert, None, FILETYPE_PEM, 10)
3047 self.assertRaises(TypeError, crl.export, self.cert, self.pkey, None, 10)
3048 self.assertRaises(TypeError, crl.export, self.cert, FILETYPE_PEM, None)
3049
Jean-Paul Calderoneea198422010-01-30 13:58:23 -05003050 def test_export_unknown_filetype(self):
3051 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003052 Calling :py:obj:`OpenSSL.CRL.export` with a file type other than
Alex Gaynor791212d2015-09-05 15:46:08 -04003053 :py:obj:`FILETYPE_PEM`, :py:obj:`FILETYPE_ASN1`, or
3054 :py:obj:`FILETYPE_TEXT` results in a :py:obj:`ValueError` being raised.
Jean-Paul Calderoneea198422010-01-30 13:58:23 -05003055 """
3056 crl = CRL()
3057 self.assertRaises(ValueError, crl.export, self.cert, self.pkey, 100, 10)
3058
3059
Bulat Gaifullin925f7862014-09-22 10:10:44 +04003060 def test_export_unknown_digest(self):
Bulat Gaifullin5f9eea42014-09-23 19:35:15 +04003061 """
Alex Gaynorca87ff62015-09-04 23:31:03 -04003062 Calling :py:obj:`OpenSSL.CRL.export` with an unsupported digest results
Bulat Gaifullin5f9eea42014-09-23 19:35:15 +04003063 in a :py:obj:`ValueError` being raised.
3064 """
Bulat Gaifullin925f7862014-09-22 10:10:44 +04003065 crl = CRL()
Jean-Paul Calderone9be85192015-04-13 21:20:51 -04003066 self.assertRaises(
3067 ValueError,
3068 crl.export,
3069 self.cert, self.pkey, FILETYPE_PEM, 10, b"strange-digest"
3070 )
Bulat Gaifullin925f7862014-09-22 10:10:44 +04003071
Rick Dean536ba022009-07-24 23:57:27 -05003072 def test_get_revoked(self):
3073 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05003074 Use python to create a simple CRL with two revocations.
Alex Gaynor791212d2015-09-05 15:46:08 -04003075 Get back the :py:obj:`Revoked` using :py:obj:`OpenSSL.CRL.get_revoked`
3076 and verify them.
Rick Dean536ba022009-07-24 23:57:27 -05003077 """
3078 crl = CRL()
3079
3080 revoked = Revoked()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003081 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05003082 revoked.set_rev_date(now)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003083 revoked.set_serial(b('3ab'))
Rick Dean536ba022009-07-24 23:57:27 -05003084 crl.add_revoked(revoked)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003085 revoked.set_serial(b('100'))
3086 revoked.set_reason(b('sUpErSeDEd'))
Rick Dean536ba022009-07-24 23:57:27 -05003087 crl.add_revoked(revoked)
3088
3089 revs = crl.get_revoked()
3090 self.assertEqual(len(revs), 2)
3091 self.assertEqual(type(revs[0]), Revoked)
3092 self.assertEqual(type(revs[1]), Revoked)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003093 self.assertEqual(revs[0].get_serial(), b('03AB'))
3094 self.assertEqual(revs[1].get_serial(), b('0100'))
Rick Dean536ba022009-07-24 23:57:27 -05003095 self.assertEqual(revs[0].get_rev_date(), now)
3096 self.assertEqual(revs[1].get_rev_date(), now)
3097
Jean-Paul Calderone46bdce42010-01-30 13:44:16 -05003098 def test_get_revoked_wrong_args(self):
3099 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003100 Calling :py:obj:`OpenSSL.CRL.get_revoked` with any arguments results
3101 in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone46bdce42010-01-30 13:44:16 -05003102 """
3103 crl = CRL()
3104 self.assertRaises(TypeError, crl.get_revoked, None)
3105 self.assertRaises(TypeError, crl.get_revoked, 1)
3106 self.assertRaises(TypeError, crl.get_revoked, "")
3107 self.assertRaises(TypeError, crl.get_revoked, "", 1, None)
3108
Jean-Paul Calderoneecef6fa2010-01-30 13:47:18 -05003109 def test_add_revoked_wrong_args(self):
3110 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003111 Calling :py:obj:`OpenSSL.CRL.add_revoked` with other than one
3112 argument results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderoneecef6fa2010-01-30 13:47:18 -05003113 """
3114 crl = CRL()
3115 self.assertRaises(TypeError, crl.add_revoked)
3116 self.assertRaises(TypeError, crl.add_revoked, 1, 2)
3117 self.assertRaises(TypeError, crl.add_revoked, "foo", "bar")
3118
Rick Dean536ba022009-07-24 23:57:27 -05003119 def test_load_crl(self):
3120 """
3121 Load a known CRL and inspect its revocations. Both
3122 PEM and DER formats are loaded.
3123 """
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003124 crl = load_crl(FILETYPE_PEM, crlData)
Rick Dean536ba022009-07-24 23:57:27 -05003125 revs = crl.get_revoked()
3126 self.assertEqual(len(revs), 2)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003127 self.assertEqual(revs[0].get_serial(), b('03AB'))
Rick Dean6385faf2009-07-26 00:07:47 -05003128 self.assertEqual(revs[0].get_reason(), None)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003129 self.assertEqual(revs[1].get_serial(), b('0100'))
3130 self.assertEqual(revs[1].get_reason(), b('Superseded'))
Rick Dean536ba022009-07-24 23:57:27 -05003131
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003132 der = _runopenssl(crlData, b"crl", b"-outform", b"DER")
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05003133 crl = load_crl(FILETYPE_ASN1, der)
Rick Dean536ba022009-07-24 23:57:27 -05003134 revs = crl.get_revoked()
3135 self.assertEqual(len(revs), 2)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003136 self.assertEqual(revs[0].get_serial(), b('03AB'))
Rick Dean6385faf2009-07-26 00:07:47 -05003137 self.assertEqual(revs[0].get_reason(), None)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003138 self.assertEqual(revs[1].get_serial(), b('0100'))
3139 self.assertEqual(revs[1].get_reason(), b('Superseded'))
Rick Dean536ba022009-07-24 23:57:27 -05003140
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003141 def test_load_crl_wrong_args(self):
3142 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003143 Calling :py:obj:`OpenSSL.crypto.load_crl` with other than two
3144 arguments results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003145 """
3146 self.assertRaises(TypeError, load_crl)
3147 self.assertRaises(TypeError, load_crl, FILETYPE_PEM)
3148 self.assertRaises(TypeError, load_crl, FILETYPE_PEM, crlData, None)
3149
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003150 def test_load_crl_bad_filetype(self):
3151 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003152 Calling :py:obj:`OpenSSL.crypto.load_crl` with an unknown file type
3153 raises a :py:obj:`ValueError`.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003154 """
3155 self.assertRaises(ValueError, load_crl, 100, crlData)
3156
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003157 def test_load_crl_bad_data(self):
3158 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003159 Calling :py:obj:`OpenSSL.crypto.load_crl` with file data which can't
3160 be loaded raises a :py:obj:`OpenSSL.crypto.Error`.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003161 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003162 self.assertRaises(Error, load_crl, FILETYPE_PEM, b"hello, world")
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003163
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04003164
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003165class X509StoreContextTests(TestCase):
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003166 """
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003167 Tests for :py:obj:`OpenSSL.crypto.X509StoreContext`.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003168 """
3169 root_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3170 intermediate_cert = load_certificate(FILETYPE_PEM, intermediate_cert_pem)
3171 intermediate_server_cert = load_certificate(FILETYPE_PEM, intermediate_server_cert_pem)
3172
3173 def test_valid(self):
3174 """
Alex Gaynor791212d2015-09-05 15:46:08 -04003175 :py:obj:`verify_certificate` returns ``None`` when called with a
3176 certificate and valid chain.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003177 """
3178 store = X509Store()
3179 store.add_cert(self.root_cert)
3180 store.add_cert(self.intermediate_cert)
3181 store_ctx = X509StoreContext(store, self.intermediate_server_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003182 self.assertEqual(store_ctx.verify_certificate(), None)
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003183
3184 def test_reuse(self):
3185 """
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003186 :py:obj:`verify_certificate` can be called multiple times with the same
Jean-Paul Calderone06e01b92015-01-18 15:43:13 -05003187 ``X509StoreContext`` instance to produce the same result.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003188 """
3189 store = X509Store()
3190 store.add_cert(self.root_cert)
3191 store.add_cert(self.intermediate_cert)
3192 store_ctx = X509StoreContext(store, self.intermediate_server_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003193 self.assertEqual(store_ctx.verify_certificate(), None)
3194 self.assertEqual(store_ctx.verify_certificate(), None)
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003195
3196 def test_trusted_self_signed(self):
3197 """
Alex Gaynor791212d2015-09-05 15:46:08 -04003198 :py:obj:`verify_certificate` returns ``None`` when called with a
3199 self-signed certificate and itself in the chain.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003200 """
3201 store = X509Store()
3202 store.add_cert(self.root_cert)
3203 store_ctx = X509StoreContext(store, self.root_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003204 self.assertEqual(store_ctx.verify_certificate(), None)
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003205
3206 def test_untrusted_self_signed(self):
3207 """
Alex Gaynor791212d2015-09-05 15:46:08 -04003208 :py:obj:`verify_certificate` raises error when a self-signed
3209 certificate is verified without itself in the chain.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003210 """
3211 store = X509Store()
3212 store_ctx = X509StoreContext(store, self.root_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003213 e = self.assertRaises(X509StoreContextError, store_ctx.verify_certificate)
Jean-Paul Calderone4c10a1e2015-01-18 16:31:27 -05003214 self.assertEqual(e.args[0][2], 'self signed certificate')
Jean-Paul Calderone06e01b92015-01-18 15:43:13 -05003215 self.assertEqual(e.certificate.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003216
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003217 def test_invalid_chain_no_root(self):
3218 """
Alex Gaynor791212d2015-09-05 15:46:08 -04003219 :py:obj:`verify_certificate` raises error when a root certificate is
3220 missing from the chain.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003221 """
3222 store = X509Store()
3223 store.add_cert(self.intermediate_cert)
3224 store_ctx = X509StoreContext(store, self.intermediate_server_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003225 e = self.assertRaises(X509StoreContextError, store_ctx.verify_certificate)
Jean-Paul Calderone4c10a1e2015-01-18 16:31:27 -05003226 self.assertEqual(e.args[0][2], 'unable to get issuer certificate')
Jean-Paul Calderone06e01b92015-01-18 15:43:13 -05003227 self.assertEqual(e.certificate.get_subject().CN, 'intermediate')
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003228
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003229 def test_invalid_chain_no_intermediate(self):
3230 """
Alex Gaynor791212d2015-09-05 15:46:08 -04003231 :py:obj:`verify_certificate` raises error when an intermediate
3232 certificate is missing from the chain.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003233 """
3234 store = X509Store()
3235 store.add_cert(self.root_cert)
3236 store_ctx = X509StoreContext(store, self.intermediate_server_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003237 e = self.assertRaises(X509StoreContextError, store_ctx.verify_certificate)
Jean-Paul Calderone4c10a1e2015-01-18 16:31:27 -05003238 self.assertEqual(e.args[0][2], 'unable to get local issuer certificate')
Jean-Paul Calderone06e01b92015-01-18 15:43:13 -05003239 self.assertEqual(e.certificate.get_subject().CN, 'intermediate-service')
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003240
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003241
Stephen Holsapple46a09252015-02-12 14:45:43 -08003242 def test_modification_pre_verify(self):
3243 """
3244 :py:obj:`verify_certificate` can use a store context modified after
3245 instantiation.
3246 """
3247 store_bad = X509Store()
3248 store_bad.add_cert(self.intermediate_cert)
3249 store_good = X509Store()
3250 store_good.add_cert(self.root_cert)
3251 store_good.add_cert(self.intermediate_cert)
3252 store_ctx = X509StoreContext(store_bad, self.intermediate_server_cert)
3253 e = self.assertRaises(X509StoreContextError, store_ctx.verify_certificate)
3254 self.assertEqual(e.args[0][2], 'unable to get issuer certificate')
3255 self.assertEqual(e.certificate.get_subject().CN, 'intermediate')
3256 store_ctx.set_store(store_good)
3257 self.assertEqual(store_ctx.verify_certificate(), None)
3258
3259
James Yonan7c2e5d32010-02-27 05:45:50 -07003260class SignVerifyTests(TestCase):
3261 """
Alex Gaynor791212d2015-09-05 15:46:08 -04003262 Tests for :py:obj:`OpenSSL.crypto.sign` and
3263 :py:obj:`OpenSSL.crypto.verify`.
James Yonan7c2e5d32010-02-27 05:45:50 -07003264 """
Alex Gaynoraceb3e22015-09-05 12:00:22 -04003265
James Yonan7c2e5d32010-02-27 05:45:50 -07003266 def test_sign_verify(self):
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04003267 """
Alex Gaynor791212d2015-09-05 15:46:08 -04003268 :py:obj:`sign` generates a cryptographic signature which
3269 :py:obj:`verify` can check.
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04003270 """
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003271 content = b(
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04003272 "It was a bright cold day in April, and the clocks were striking "
3273 "thirteen. Winston Smith, his chin nuzzled into his breast in an "
3274 "effort to escape the vile wind, slipped quickly through the "
3275 "glass doors of Victory Mansions, though not quickly enough to "
3276 "prevent a swirl of gritty dust from entering along with him.")
3277
3278 # sign the content with this private key
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04003279 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04003280 # verify the content with this cert
3281 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3282 # certificate unrelated to priv_key, used to trigger an error
3283 bad_cert = load_certificate(FILETYPE_PEM, server_cert_pem)
James Yonan7c2e5d32010-02-27 05:45:50 -07003284
Jean-Paul Calderoned08feb02010-10-12 21:53:24 -04003285 for digest in ['md5', 'sha1']:
James Yonan7c2e5d32010-02-27 05:45:50 -07003286 sig = sign(priv_key, content, digest)
3287
Alex Gaynoraceb3e22015-09-05 12:00:22 -04003288 # Verify the signature of content, will throw an exception if
3289 # error.
James Yonan7c2e5d32010-02-27 05:45:50 -07003290 verify(good_cert, sig, content, digest)
3291
3292 # This should fail because the certificate doesn't match the
3293 # private key that was used to sign the content.
3294 self.assertRaises(Error, verify, bad_cert, sig, content, digest)
3295
3296 # This should fail because we've "tainted" the content after
3297 # signing it.
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003298 self.assertRaises(
3299 Error, verify,
3300 good_cert, sig, content + b("tainted"), digest)
James Yonan7c2e5d32010-02-27 05:45:50 -07003301
3302 # test that unknown digest types fail
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003303 self.assertRaises(
Jean-Paul Calderone9538f142010-10-13 22:13:40 -04003304 ValueError, sign, priv_key, content, "strange-digest")
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003305 self.assertRaises(
Jean-Paul Calderone9538f142010-10-13 22:13:40 -04003306 ValueError, verify, good_cert, sig, content, "strange-digest")
James Yonan7c2e5d32010-02-27 05:45:50 -07003307
Abraham Martinc5484ba2015-03-25 15:33:05 +00003308 def test_sign_verify_with_text(self):
3309 """
Alex Gaynor791212d2015-09-05 15:46:08 -04003310 :py:obj:`sign` generates a cryptographic signature which
3311 :py:obj:`verify` can check. Deprecation warnings raised because using
3312 text instead of bytes as content
Abraham Martinc5484ba2015-03-25 15:33:05 +00003313 """
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003314 content = (
Jean-Paul Calderone362c1f52015-03-29 08:01:39 -04003315 b"It was a bright cold day in April, and the clocks were striking "
3316 b"thirteen. Winston Smith, his chin nuzzled into his breast in an "
3317 b"effort to escape the vile wind, slipped quickly through the "
3318 b"glass doors of Victory Mansions, though not quickly enough to "
3319 b"prevent a swirl of gritty dust from entering along with him."
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003320 ).decode("ascii")
Abraham Martinc5484ba2015-03-25 15:33:05 +00003321
3322 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
3323 cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3324 for digest in ['md5', 'sha1']:
3325 with catch_warnings(record=True) as w:
3326 simplefilter("always")
3327 sig = sign(priv_key, content, digest)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003328
3329 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003330 "{0} for data is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003331 WARNING_TYPE_EXPECTED
3332 ),
3333 str(w[-1].message)
3334 )
3335 self.assertIs(w[-1].category, DeprecationWarning)
3336
Abraham Martinc5484ba2015-03-25 15:33:05 +00003337 with catch_warnings(record=True) as w:
3338 simplefilter("always")
3339 verify(cert, sig, content, digest)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003340
3341 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003342 "{0} for data is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003343 WARNING_TYPE_EXPECTED
3344 ),
3345 str(w[-1].message)
3346 )
3347 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinc5484ba2015-03-25 15:33:05 +00003348
Jean-Paul Calderone9828f662010-12-08 22:57:26 -05003349 def test_sign_nulls(self):
3350 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003351 :py:obj:`sign` produces a signature for a string with embedded nulls.
Jean-Paul Calderone9828f662010-12-08 22:57:26 -05003352 """
3353 content = b("Watch out! \0 Did you see it?")
3354 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
3355 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3356 sig = sign(priv_key, content, "sha1")
3357 verify(good_cert, sig, content, "sha1")
3358
3359
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003360class EllipticCurveTests(TestCase):
3361 """
3362 Tests for :py:class:`_EllipticCurve`, :py:obj:`get_elliptic_curve`, and
3363 :py:obj:`get_elliptic_curves`.
3364 """
Alex Gaynoraceb3e22015-09-05 12:00:22 -04003365
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003366 def test_set(self):
3367 """
3368 :py:obj:`get_elliptic_curves` returns a :py:obj:`set`.
3369 """
3370 self.assertIsInstance(get_elliptic_curves(), set)
3371
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003372 def test_some_curves(self):
3373 """
3374 If :py:mod:`cryptography` has elliptic curve support then the set
3375 returned by :py:obj:`get_elliptic_curves` has some elliptic curves in
3376 it.
3377
3378 There could be an OpenSSL that violates this assumption. If so, this
3379 test will fail and we'll find out.
3380 """
3381 curves = get_elliptic_curves()
3382 if lib.Cryptography_HAS_EC:
3383 self.assertTrue(curves)
3384 else:
3385 self.assertFalse(curves)
3386
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003387 def test_a_curve(self):
3388 """
3389 :py:obj:`get_elliptic_curve` can be used to retrieve a particular
3390 supported curve.
3391 """
3392 curves = get_elliptic_curves()
3393 if curves:
3394 curve = next(iter(curves))
3395 self.assertEqual(curve.name, get_elliptic_curve(curve.name).name)
3396 else:
Jean-Paul Calderoneeb86f3a2014-04-19 09:45:57 -04003397 self.assertRaises(ValueError, get_elliptic_curve, u("prime256v1"))
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003398
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003399 def test_not_a_curve(self):
3400 """
3401 :py:obj:`get_elliptic_curve` raises :py:class:`ValueError` if called
3402 with a name which does not identify a supported curve.
3403 """
3404 self.assertRaises(
Jean-Paul Calderone5a82db92014-04-19 09:51:29 -04003405 ValueError, get_elliptic_curve, u("this curve was just invented"))
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003406
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003407 def test_repr(self):
3408 """
3409 The string representation of a curve object includes simply states the
3410 object is a curve and what its name is.
3411 """
3412 curves = get_elliptic_curves()
3413 if curves:
3414 curve = next(iter(curves))
3415 self.assertEqual("<Curve %r>" % (curve.name,), repr(curve))
3416
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003417 def test_to_EC_KEY(self):
3418 """
3419 The curve object can export a version of itself as an EC_KEY* via the
3420 private :py:meth:`_EllipticCurve._to_EC_KEY`.
3421 """
3422 curves = get_elliptic_curves()
3423 if curves:
3424 curve = next(iter(curves))
3425 # It's not easy to assert anything about this object. However, see
3426 # leakcheck/crypto.py for a test that demonstrates it at least does
3427 # not leak memory.
3428 curve._to_EC_KEY()
3429
3430
Jean-Paul Calderone1be77082014-04-30 18:17:41 -04003431class EllipticCurveFactory(object):
3432 """
3433 A helper to get the names of two curves.
3434 """
Alex Gaynoraceb3e22015-09-05 12:00:22 -04003435
Jean-Paul Calderone1be77082014-04-30 18:17:41 -04003436 def __init__(self):
3437 curves = iter(get_elliptic_curves())
3438 try:
3439 self.curve_name = next(curves).name
3440 self.another_curve_name = next(curves).name
3441 except StopIteration:
3442 self.curve_name = self.another_curve_name = None
3443
3444
Jean-Paul Calderone1be77082014-04-30 18:17:41 -04003445class EllipticCurveEqualityTests(TestCase, EqualityTestsMixin):
3446 """
3447 Tests :py:type:`_EllipticCurve`\ 's implementation of ``==`` and ``!=``.
3448 """
3449 curve_factory = EllipticCurveFactory()
3450
3451 if curve_factory.curve_name is None:
3452 skip = "There are no curves available there can be no curve objects."
3453
Jean-Paul Calderone1be77082014-04-30 18:17:41 -04003454 def anInstance(self):
3455 """
3456 Get the curve object for an arbitrary curve supported by the system.
3457 """
3458 return get_elliptic_curve(self.curve_factory.curve_name)
3459
Jean-Paul Calderone1be77082014-04-30 18:17:41 -04003460 def anotherInstance(self):
3461 """
3462 Get the curve object for an arbitrary curve supported by the system -
3463 but not the one returned by C{anInstance}.
3464 """
3465 return get_elliptic_curve(self.curve_factory.another_curve_name)
3466
3467
Jean-Paul Calderone22c31242014-05-01 07:49:47 -04003468class EllipticCurveHashTests(TestCase):
3469 """
3470 Tests for :py:type:`_EllipticCurve`\ 's implementation of hashing (thus use
3471 as an item in a :py:type:`dict` or :py:type:`set`).
3472 """
3473 curve_factory = EllipticCurveFactory()
3474
3475 if curve_factory.curve_name is None:
3476 skip = "There are no curves available there can be no curve objects."
3477
Jean-Paul Calderone22c31242014-05-01 07:49:47 -04003478 def test_contains(self):
3479 """
3480 The ``in`` operator reports that a :py:type:`set` containing a curve
3481 does contain that curve.
3482 """
3483 curve = get_elliptic_curve(self.curve_factory.curve_name)
3484 curves = set([curve])
3485 self.assertIn(curve, curves)
3486
Jean-Paul Calderone22c31242014-05-01 07:49:47 -04003487 def test_does_not_contain(self):
3488 """
3489 The ``in`` operator reports that a :py:type:`set` not containing a
3490 curve does not contain that curve.
3491 """
3492 curve = get_elliptic_curve(self.curve_factory.curve_name)
3493 curves = set([get_elliptic_curve(self.curve_factory.another_curve_name)])
3494 self.assertNotIn(curve, curves)
3495
3496
Rick Dean5b7b6372009-04-01 11:34:06 -05003497if __name__ == '__main__':
3498 main()