blob: 5acd2b9a3f362b016c5b2d2aad2e621c82e979cc [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
Abraham Martinc5484ba2015-03-25 15:33:05 +000017from six import u, b, binary_type, PY3
18from warnings import simplefilter
19from warnings import catch_warnings
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
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -040041def normalize_certificate_pem(pem):
42 return dump_certificate(FILETYPE_PEM, load_certificate(FILETYPE_PEM, pem))
43
44
45def normalize_privatekey_pem(pem):
46 return dump_privatekey(FILETYPE_PEM, load_privatekey(FILETYPE_PEM, pem))
47
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040048
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050049GOOD_CIPHER = "blowfish"
50BAD_CIPHER = "zippers"
51
52GOOD_DIGEST = "MD5"
53BAD_DIGEST = "monkeys"
54
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040055root_cert_pem = b("""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -050056MIIC7TCCAlagAwIBAgIIPQzE4MbeufQwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE
57BhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdU
58ZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwIhgPMjAwOTAzMjUxMjM2
59NThaGA8yMDE3MDYxMTEyMzY1OFowWDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklM
60MRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9U
61ZXN0aW5nIFJvb3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPmaQumL
62urpE527uSEHdL1pqcDRmWzu+98Y6YHzT/J7KWEamyMCNZ6fRW1JCR782UQ8a07fy
632xXsKy4WdKaxyG8CcatwmXvpvRQ44dSANMihHELpANTdyVp6DCysED6wkQFurHlF
641dshEaJw8b/ypDhmbVIo6Ci1xvCJqivbLFnbAgMBAAGjgbswgbgwHQYDVR0OBBYE
65FINVdy1eIfFJDAkk51QJEo3IfgSuMIGIBgNVHSMEgYAwfoAUg1V3LV4h8UkMCSTn
66VAkSjch+BK6hXKRaMFgxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UE
67BxMHQ2hpY2FnbzEQMA4GA1UEChMHVGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBS
68b290IENBggg9DMTgxt659DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB
69AGGCDazMJGoWNBpc03u6+smc95dEead2KlZXBATOdFT1VesY3+nUOqZhEhTGlDMi
70hkgaZnzoIq/Uamidegk4hirsCT/R+6vsKAAxNTcBjUeZjlykCJWy5ojShGftXIKY
71w/njVbKMXrvc83qmTdGl3TAM0fxQIpqgcglFLveEBgzn
72-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040073""")
Rick Dean94e46fd2009-07-18 14:51:24 -050074
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040075root_key_pem = b("""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -050076MIICXQIBAAKBgQD5mkLpi7q6ROdu7khB3S9aanA0Zls7vvfGOmB80/yeylhGpsjA
77jWen0VtSQke/NlEPGtO38tsV7CsuFnSmschvAnGrcJl76b0UOOHUgDTIoRxC6QDU
783claegwsrBA+sJEBbqx5RdXbIRGicPG/8qQ4Zm1SKOgotcbwiaor2yxZ2wIDAQAB
79AoGBAPCgMpmLxzwDaUmcFbTJUvlLW1hoxNNYSu2jIZm1k/hRAcE60JYwvBkgz3UB
80yMEh0AtLxYe0bFk6EHah11tMUPgscbCq73snJ++8koUw+csk22G65hOs51bVb7Aa
816JBe67oLzdtvgCUFAA2qfrKzWRZzAdhUirQUZgySZk+Xq1pBAkEA/kZG0A6roTSM
82BVnx7LnPfsycKUsTumorpXiylZJjTi9XtmzxhrYN6wgZlDOOwOLgSQhszGpxVoMD
83u3gByT1b2QJBAPtL3mSKdvwRu/+40zaZLwvSJRxaj0mcE4BJOS6Oqs/hS1xRlrNk
84PpQ7WJ4yM6ZOLnXzm2mKyxm50Mv64109FtMCQQDOqS2KkjHaLowTGVxwC0DijMfr
85I9Lf8sSQk32J5VWCySWf5gGTfEnpmUa41gKTMJIbqZZLucNuDcOtzUaeWZlZAkA8
86ttXigLnCqR486JDPTi9ZscoZkZ+w7y6e/hH8t6d5Vjt48JVyfjPIaJY+km58LcN3
876AWSeGAdtRFHVzR7oHjVAkB4hutvxiOeiIVQNBhM6RSI9aBPMI21DoX2JRoxvNW2
88cbvAhow217X9V0dVerEOKxnNYspXRrh36h7k4mQA+sDq
89-----END RSA PRIVATE KEY-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040090""")
Rick Dean94e46fd2009-07-18 14:51:24 -050091
Stephen Holsapple0d9815f2014-08-27 19:36:53 -070092intermediate_cert_pem = b("""-----BEGIN CERTIFICATE-----
93MIICVzCCAcCgAwIBAgIRAMPzhm6//0Y/g2pmnHR2C4cwDQYJKoZIhvcNAQENBQAw
94WDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAw
95DgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwHhcNMTQw
96ODI4MDIwNDA4WhcNMjQwODI1MDIwNDA4WjBmMRUwEwYDVQQDEwxpbnRlcm1lZGlh
97dGUxDDAKBgNVBAoTA29yZzERMA8GA1UECxMIb3JnLXVuaXQxCzAJBgNVBAYTAlVT
98MQswCQYDVQQIEwJDQTESMBAGA1UEBxMJU2FuIERpZWdvMIGfMA0GCSqGSIb3DQEB
99AQUAA4GNADCBiQKBgQDYcEQw5lfbEQRjr5Yy4yxAHGV0b9Al+Lmu7wLHMkZ/ZMmK
100FGIbljbviiD1Nz97Oh2cpB91YwOXOTN2vXHq26S+A5xe8z/QJbBsyghMur88CjdT
10121H2qwMa+r5dCQwEhuGIiZ3KbzB/n4DTMYI5zy4IYPv0pjxShZn4aZTCCK2IUwID
102AQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBDQUAA4GBAPIWSkLX
103QRMApOjjyC+tMxumT5e2pMqChHmxobQK4NMdrf2VCx+cRT6EmY8sK3/Xl/X8UBQ+
1049n5zXb1ZwhW/sTWgUvmOceJ4/XVs9FkdWOOn1J0XBch9ZIiFe/s5ASIgG7fUdcUF
1059mAWS6FK2ca3xIh5kIupCXOFa0dPvlw/YUFT
106-----END CERTIFICATE-----
107""")
108
109intermediate_key_pem = b("""-----BEGIN RSA PRIVATE KEY-----
110MIICWwIBAAKBgQDYcEQw5lfbEQRjr5Yy4yxAHGV0b9Al+Lmu7wLHMkZ/ZMmKFGIb
111ljbviiD1Nz97Oh2cpB91YwOXOTN2vXHq26S+A5xe8z/QJbBsyghMur88CjdT21H2
112qwMa+r5dCQwEhuGIiZ3KbzB/n4DTMYI5zy4IYPv0pjxShZn4aZTCCK2IUwIDAQAB
113AoGAfSZVV80pSeOKHTYfbGdNY/jHdU9eFUa/33YWriXU+77EhpIItJjkRRgivIfo
114rhFJpBSGmDLblaqepm8emsXMeH4+2QzOYIf0QGGP6E6scjTt1PLqdqKfVJ1a2REN
115147cujNcmFJb/5VQHHMpaPTgttEjlzuww4+BCDPsVRABWrkCQQD3loH36nLoQTtf
116+kQq0T6Bs9/UWkTAGo0ND81ALj0F8Ie1oeZg6RNT96RxZ3aVuFTESTv6/TbjWywO
117wdzlmV1vAkEA38rTJ6PTwaJlw5OttdDzAXGPB9tDmzh9oSi7cHwQQXizYd8MBYx4
118sjHUKD3dCQnb1dxJFhd3BT5HsnkRMbVZXQJAbXduH17ZTzcIOXc9jHDXYiFVZV5D
11952vV0WCbLzVCZc3jMrtSUKa8lPN5EWrdU3UchWybyG0MR5mX8S5lrF4SoQJAIyUD
120DBKaSqpqONCUUx1BTFS9FYrFjzbL4+c1qHCTTPTblt8kUCrDOZjBrKAqeiTmNSum
121/qUot9YUBF8m6BuGsQJATHHmdFy/fG1VLkyBp49CAa8tN3Z5r/CgTznI4DfMTf4C
122NbRHn2UmYlwQBa+L5lg9phewNe8aEwpPyPLoV85U8Q==
123-----END RSA PRIVATE KEY-----
124""")
125
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400126server_cert_pem = b("""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500127MIICKDCCAZGgAwIBAgIJAJn/HpR21r/8MA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
128BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
129VGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBSb290IENBMCIYDzIwMDkwMzI1MTIz
130NzUzWhgPMjAxNzA2MTExMjM3NTNaMBgxFjAUBgNVBAMTDWxvdmVseSBzZXJ2ZXIw
131gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAL6m+G653V0tpBC/OKl22VxOi2Cv
132lK4TYu9LHSDP9uDVTe7V5D5Tl6qzFoRRx5pfmnkqT5B+W9byp2NU3FC5hLm5zSAr
133b45meUhjEJ/ifkZgbNUjHdBIGP9MAQUHZa5WKdkGIJvGAvs8UzUqlr4TBWQIB24+
134lJ+Ukk/CRgasrYwdAgMBAAGjNjA0MB0GA1UdDgQWBBS4kC7Ij0W1TZXZqXQFAM2e
135gKEG2DATBgNVHSUEDDAKBggrBgEFBQcDATANBgkqhkiG9w0BAQUFAAOBgQBh30Li
136dJ+NlxIOx5343WqIBka3UbsOb2kxWrbkVCrvRapCMLCASO4FqiKWM+L0VDBprqIp
1372mgpFQ6FHpoIENGvJhdEKpptQ5i7KaGhnDNTfdy3x1+h852G99f1iyj0RmbuFcM8
138uzujnS8YXWvM7DM1Ilozk4MzPug8jzFp5uhKCQ==
139-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400140""")
Rick Dean94e46fd2009-07-18 14:51:24 -0500141
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -0400142server_key_pem = normalize_privatekey_pem(b("""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500143MIICWwIBAAKBgQC+pvhuud1dLaQQvzipdtlcTotgr5SuE2LvSx0gz/bg1U3u1eQ+
144U5eqsxaEUceaX5p5Kk+QflvW8qdjVNxQuYS5uc0gK2+OZnlIYxCf4n5GYGzVIx3Q
145SBj/TAEFB2WuVinZBiCbxgL7PFM1Kpa+EwVkCAduPpSflJJPwkYGrK2MHQIDAQAB
146AoGAbwuZ0AR6JveahBaczjfnSpiFHf+mve2UxoQdpyr6ROJ4zg/PLW5K/KXrC48G
147j6f3tXMrfKHcpEoZrQWUfYBRCUsGD5DCazEhD8zlxEHahIsqpwA0WWssJA2VOLEN
148j6DuV2pCFbw67rfTBkTSo32ahfXxEKev5KswZk0JIzH3ooECQQDgzS9AI89h0gs8
149Dt+1m11Rzqo3vZML7ZIyGApUzVan+a7hbc33nbGRkAXjHaUBJO31it/H6dTO+uwX
150msWwNG5ZAkEA2RyFKs5xR5USTFaKLWCgpH/ydV96KPOpBND7TKQx62snDenFNNbn
151FwwOhpahld+vqhYk+pfuWWUpQciE+Bu7ZQJASjfT4sQv4qbbKK/scePicnDdx9th
1524e1EeB9xwb+tXXXUo/6Bor/AcUNwfiQ6Zt9PZOK9sR3lMZSsP7rMi7kzuQJABie6
1531sXXjFH7nNJvRG4S39cIxq8YRYTy68II/dlB2QzGpKxV/POCxbJ/zu0CU79tuYK7
154NaeNCFfH3aeTrX0LyQJAMBWjWmeKM2G2sCExheeQK0ROnaBC8itCECD4Jsve4nqf
155r50+LF74iLXFwqysVCebPKMOpDWp/qQ1BbJQIPs7/A==
156-----END RSA PRIVATE KEY-----
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -0400157"""))
Rick Dean94e46fd2009-07-18 14:51:24 -0500158
Stephen Holsapple0d9815f2014-08-27 19:36:53 -0700159intermediate_server_cert_pem = b("""-----BEGIN CERTIFICATE-----
160MIICWDCCAcGgAwIBAgIRAPQFY9jfskSihdiNSNdt6GswDQYJKoZIhvcNAQENBQAw
161ZjEVMBMGA1UEAxMMaW50ZXJtZWRpYXRlMQwwCgYDVQQKEwNvcmcxETAPBgNVBAsT
162CG9yZy11bml0MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVNh
163biBEaWVnbzAeFw0xNDA4MjgwMjEwNDhaFw0yNDA4MjUwMjEwNDhaMG4xHTAbBgNV
164BAMTFGludGVybWVkaWF0ZS1zZXJ2aWNlMQwwCgYDVQQKEwNvcmcxETAPBgNVBAsT
165CG9yZy11bml0MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVNh
166biBEaWVnbzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqpJZygd+w1faLOr1
167iOAmbBhx5SZWcTCZ/ZjHQTJM7GuPT624QkqsixFghRKdDROwpwnAP7gMRukLqiy4
168+kRuGT5OfyGggL95i2xqA+zehjj08lSTlvGHpePJgCyTavIy5+Ljsj4DKnKyuhxm
169biXTRrH83NDgixVkObTEmh/OVK0CAwEAATANBgkqhkiG9w0BAQ0FAAOBgQBa0Npw
170UkzjaYEo1OUE1sTI6Mm4riTIHMak4/nswKh9hYup//WVOlr/RBSBtZ7Q/BwbjobN
1713bfAtV7eSAqBsfxYXyof7G1ALANQERkq3+oyLP1iVt08W1WOUlIMPhdCF/QuCwy6
172x9MJLhUCGLJPM+O2rAPWVD9wCmvq10ALsiH3yA==
173-----END CERTIFICATE-----
174""")
175
176intermediate_server_key_pem = b("""-----BEGIN RSA PRIVATE KEY-----
177MIICXAIBAAKBgQCqklnKB37DV9os6vWI4CZsGHHlJlZxMJn9mMdBMkzsa49PrbhC
178SqyLEWCFEp0NE7CnCcA/uAxG6QuqLLj6RG4ZPk5/IaCAv3mLbGoD7N6GOPTyVJOW
1798Yel48mALJNq8jLn4uOyPgMqcrK6HGZuJdNGsfzc0OCLFWQ5tMSaH85UrQIDAQAB
180AoGAIQ594j5zna3/9WaPsTgnmhlesVctt4AAx/n827DA4ayyuHFlXUuVhtoWR5Pk
1815ezj9mtYW8DyeCegABnsu2vZni/CdvU6uiS1Hv6qM1GyYDm9KWgovIP9rQCDSGaz
182d57IWVGxx7ODFkm3gN5nxnSBOFVHytuW1J7FBRnEsehRroECQQDXHFOv82JuXDcz
183z3+4c74IEURdOHcbycxlppmK9kFqm5lsUdydnnGW+mvwDk0APOB7Wg7vyFyr393e
184dpmBDCzNAkEAyv6tVbTKUYhSjW+QhabJo896/EqQEYUmtMXxk4cQnKeR/Ao84Rkf
185EqD5IykMUfUI0jJU4DGX+gWZ10a7kNbHYQJAVFCuHNFxS4Cpwo0aqtnzKoZaHY/8
186X9ABZfafSHCtw3Op92M+7ikkrOELXdS9KdKyyqbKJAKNEHF3LbOfB44WIQJAA2N4
1879UNNVUsXRbElEnYUS529CdUczo4QdVgQjkvk5RiPAUwSdBd9Q0xYnFOlFwEmIowg
188ipWJWe0aAlP18ZcEQQJBAL+5lekZ/GUdQoZ4HAsN5a9syrzavJ9VvU1KOOPorPZK
189nMRZbbQgP+aSB7yl6K0gaLaZ8XaK0pjxNBh6ASqg9f4=
190-----END RSA PRIVATE KEY-----
191""")
192
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400193client_cert_pem = b("""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500194MIICJjCCAY+gAwIBAgIJAKxpFI5lODkjMA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
195BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
196VGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBSb290IENBMCIYDzIwMDkwMzI1MTIz
197ODA1WhgPMjAxNzA2MTExMjM4MDVaMBYxFDASBgNVBAMTC3VnbHkgY2xpZW50MIGf
198MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDAZh/SRtNm5ntMT4qb6YzEpTroMlq2
199rn+GrRHRiZ+xkCw/CGNhbtPir7/QxaUj26BSmQrHw1bGKEbPsWiW7bdXSespl+xK
200iku4G/KvnnmWdeJHqsiXeUZtqurMELcPQAw9xPHEuhqqUJvvEoMTsnCEqGM+7Dtb
201oCRajYyHfluARQIDAQABozYwNDAdBgNVHQ4EFgQUNQB+qkaOaEVecf1J3TTUtAff
2020fAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQEFBQADgYEAyv/Jh7gM
203Q3OHvmsFEEvRI+hsW8y66zK4K5de239Y44iZrFYkt7Q5nBPMEWDj4F2hLYWL/qtI
2049Zdr0U4UDCU9SmmGYh4o7R4TZ5pGFvBYvjhHbkSFYFQXZxKUi+WUxplP6I0wr2KJ
205PSTJCjJOn3xo2NTKRgV1gaoTf2EhL+RG8TQ=
206-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400207""")
Rick Dean94e46fd2009-07-18 14:51:24 -0500208
Jean-Paul Calderone22cbe502011-05-04 17:01:43 -0400209client_key_pem = normalize_privatekey_pem(b("""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500210MIICXgIBAAKBgQDAZh/SRtNm5ntMT4qb6YzEpTroMlq2rn+GrRHRiZ+xkCw/CGNh
211btPir7/QxaUj26BSmQrHw1bGKEbPsWiW7bdXSespl+xKiku4G/KvnnmWdeJHqsiX
212eUZtqurMELcPQAw9xPHEuhqqUJvvEoMTsnCEqGM+7DtboCRajYyHfluARQIDAQAB
213AoGATkZ+NceY5Glqyl4mD06SdcKfV65814vg2EL7V9t8+/mi9rYL8KztSXGlQWPX
214zuHgtRoMl78yQ4ZJYOBVo+nsx8KZNRCEBlE19bamSbQLCeQMenWnpeYyQUZ908gF
215h6L9qsFVJepgA9RDgAjyDoS5CaWCdCCPCH2lDkdcqC54SVUCQQDseuduc4wi8h4t
216V8AahUn9fn9gYfhoNuM0gdguTA0nPLVWz4hy1yJiWYQe0H7NLNNTmCKiLQaJpAbb
217TC6vE8C7AkEA0Ee8CMJUc20BnGEmxwgWcVuqFWaKCo8jTH1X38FlATUsyR3krjW2
218dL3yDD9NwHxsYP7nTKp/U8MV7U9IBn4y/wJBAJl7H0/BcLeRmuJk7IqJ7b635iYB
219D/9beFUw3MUXmQXZUfyYz39xf6CDZsu1GEdEC5haykeln3Of4M9d/4Kj+FcCQQCY
220si6xwT7GzMDkk/ko684AV3KPc/h6G0yGtFIrMg7J3uExpR/VdH2KgwMkZXisSMvw
221JJEQjOMCVsEJlRk54WWjAkEAzoZNH6UhDdBK5F38rVt/y4SEHgbSfJHIAmPS32Kq
222f6GGcfNpip0Uk7q7udTKuX7Q/buZi/C4YW7u3VKAquv9NA==
223-----END RSA PRIVATE KEY-----
Jean-Paul Calderone22cbe502011-05-04 17:01:43 -0400224"""))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400225
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400226cleartextCertificatePEM = b("""-----BEGIN CERTIFICATE-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400227MIIC7TCCAlagAwIBAgIIPQzE4MbeufQwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE
228BhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdU
229ZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwIhgPMjAwOTAzMjUxMjM2
230NThaGA8yMDE3MDYxMTEyMzY1OFowWDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklM
231MRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9U
232ZXN0aW5nIFJvb3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPmaQumL
233urpE527uSEHdL1pqcDRmWzu+98Y6YHzT/J7KWEamyMCNZ6fRW1JCR782UQ8a07fy
2342xXsKy4WdKaxyG8CcatwmXvpvRQ44dSANMihHELpANTdyVp6DCysED6wkQFurHlF
2351dshEaJw8b/ypDhmbVIo6Ci1xvCJqivbLFnbAgMBAAGjgbswgbgwHQYDVR0OBBYE
236FINVdy1eIfFJDAkk51QJEo3IfgSuMIGIBgNVHSMEgYAwfoAUg1V3LV4h8UkMCSTn
237VAkSjch+BK6hXKRaMFgxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UE
238BxMHQ2hpY2FnbzEQMA4GA1UEChMHVGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBS
239b290IENBggg9DMTgxt659DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB
240AGGCDazMJGoWNBpc03u6+smc95dEead2KlZXBATOdFT1VesY3+nUOqZhEhTGlDMi
241hkgaZnzoIq/Uamidegk4hirsCT/R+6vsKAAxNTcBjUeZjlykCJWy5ojShGftXIKY
242w/njVbKMXrvc83qmTdGl3TAM0fxQIpqgcglFLveEBgzn
243-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400244""")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400245
Jean-Paul Calderoned50d2042011-05-04 17:00:49 -0400246cleartextPrivateKeyPEM = normalize_privatekey_pem(b("""\
247-----BEGIN RSA PRIVATE KEY-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400248MIICXQIBAAKBgQD5mkLpi7q6ROdu7khB3S9aanA0Zls7vvfGOmB80/yeylhGpsjA
249jWen0VtSQke/NlEPGtO38tsV7CsuFnSmschvAnGrcJl76b0UOOHUgDTIoRxC6QDU
2503claegwsrBA+sJEBbqx5RdXbIRGicPG/8qQ4Zm1SKOgotcbwiaor2yxZ2wIDAQAB
251AoGBAPCgMpmLxzwDaUmcFbTJUvlLW1hoxNNYSu2jIZm1k/hRAcE60JYwvBkgz3UB
252yMEh0AtLxYe0bFk6EHah11tMUPgscbCq73snJ++8koUw+csk22G65hOs51bVb7Aa
2536JBe67oLzdtvgCUFAA2qfrKzWRZzAdhUirQUZgySZk+Xq1pBAkEA/kZG0A6roTSM
254BVnx7LnPfsycKUsTumorpXiylZJjTi9XtmzxhrYN6wgZlDOOwOLgSQhszGpxVoMD
255u3gByT1b2QJBAPtL3mSKdvwRu/+40zaZLwvSJRxaj0mcE4BJOS6Oqs/hS1xRlrNk
256PpQ7WJ4yM6ZOLnXzm2mKyxm50Mv64109FtMCQQDOqS2KkjHaLowTGVxwC0DijMfr
257I9Lf8sSQk32J5VWCySWf5gGTfEnpmUa41gKTMJIbqZZLucNuDcOtzUaeWZlZAkA8
258ttXigLnCqR486JDPTi9ZscoZkZ+w7y6e/hH8t6d5Vjt48JVyfjPIaJY+km58LcN3
2596AWSeGAdtRFHVzR7oHjVAkB4hutvxiOeiIVQNBhM6RSI9aBPMI21DoX2JRoxvNW2
260cbvAhow217X9V0dVerEOKxnNYspXRrh36h7k4mQA+sDq
261-----END RSA PRIVATE KEY-----
Jean-Paul Calderoned50d2042011-05-04 17:00:49 -0400262"""))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400263
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400264cleartextCertificateRequestPEM = b("""-----BEGIN CERTIFICATE REQUEST-----
265MIIBnjCCAQcCAQAwXjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQH
266EwdDaGljYWdvMRcwFQYDVQQKEw5NeSBDb21wYW55IEx0ZDEXMBUGA1UEAxMORnJl
267ZGVyaWNrIERlYW4wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANp6Y17WzKSw
268BsUWkXdqg6tnXy8H8hA1msCMWpc+/2KJ4mbv5NyD6UD+/SqagQqulPbF/DFea9nA
269E0zhmHJELcM8gUTIlXv/cgDWnmK4xj8YkjVUiCdqKRAKeuzLG1pGmwwF5lGeJpXN
270xQn5ecR0UYSOWj6TTGXB9VyUMQzCClcBAgMBAAGgADANBgkqhkiG9w0BAQUFAAOB
271gQAAJGuF/R/GGbeC7FbFW+aJgr9ee0Xbl6nlhu7pTe67k+iiKT2dsl2ti68MVTnu
272Vrb3HUNqOkiwsJf6kCtq5oPn3QVYzTa76Dt2y3Rtzv6boRSlmlfrgS92GNma8JfR
273oICQk3nAudi6zl1Dix3BCv1pUp5KMtGn3MeDEi6QFGy2rA==
274-----END CERTIFICATE REQUEST-----
275""")
Rick Dean5b7b6372009-04-01 11:34:06 -0500276
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400277encryptedPrivateKeyPEM = b("""-----BEGIN RSA PRIVATE KEY-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400278Proc-Type: 4,ENCRYPTED
279DEK-Info: DES-EDE3-CBC,9573604A18579E9E
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400280
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400281SHOho56WxDkT0ht10UTeKc0F5u8cqIa01kzFAmETw0MAs8ezYtK15NPdCXUm3X/2
282a17G7LSF5bkxOgZ7vpXyMzun/owrj7CzvLxyncyEFZWvtvzaAhPhvTJtTIB3kf8B
2838+qRcpTGK7NgXEgYBW5bj1y4qZkD4zCL9o9NQzsKI3Ie8i0239jsDOWR38AxjXBH
284mGwAQ4Z6ZN5dnmM4fhMIWsmFf19sNyAML4gHenQCHhmXbjXeVq47aC2ProInJbrm
285+00TcisbAQ40V9aehVbcDKtS4ZbMVDwncAjpXpcncC54G76N6j7F7wL7L/FuXa3A
286fvSVy9n2VfF/pJ3kYSflLHH2G/DFxjF7dl0GxhKPxJjp3IJi9VtuvmN9R2jZWLQF
287tfC8dXgy/P9CfFQhlinqBTEwgH0oZ/d4k4NVFDSdEMaSdmBAjlHpc+Vfdty3HVnV
288rKXj//wslsFNm9kIwJGIgKUa/n2jsOiydrsk1mgH7SmNCb3YHgZhbbnq0qLat/HC
289gHDt3FHpNQ31QzzL3yrenFB2L9osIsnRsDTPFNi4RX4SpDgNroxOQmyzCCV6H+d4
290o1mcnNiZSdxLZxVKccq0AfRpHqpPAFnJcQHP6xyT9MZp6fBa0XkxDnt9kNU8H3Qw
2917SJWZ69VXjBUzMlQViLuaWMgTnL+ZVyFZf9hTF7U/ef4HMLMAVNdiaGG+G+AjCV/
292MbzjS007Oe4qqBnCWaFPSnJX6uLApeTbqAxAeyCql56ULW5x6vDMNC3dwjvS/CEh
29311n8RkgFIQA0AhuKSIg3CbuartRsJnWOLwgLTzsrKYL4yRog1RJrtw==
294-----END RSA PRIVATE KEY-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400295""")
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400296
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400297encryptedPrivateKeyPEMPassphrase = b("foobar")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400298
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400299# Some PKCS#7 stuff. Generated with the openssl command line:
300#
301# openssl crl2pkcs7 -inform pem -outform pem -certfile s.pem -nocrl
302#
303# with a certificate and key (but the key should be irrelevant) in s.pem
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400304pkcs7Data = b("""\
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400305-----BEGIN PKCS7-----
306MIIDNwYJKoZIhvcNAQcCoIIDKDCCAyQCAQExADALBgkqhkiG9w0BBwGgggMKMIID
307BjCCAm+gAwIBAgIBATANBgkqhkiG9w0BAQQFADB7MQswCQYDVQQGEwJTRzERMA8G
308A1UEChMITTJDcnlwdG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtN
309MkNyeXB0byBDZXJ0aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNA
310cG9zdDEuY29tMB4XDTAwMDkxMDA5NTEzMFoXDTAyMDkxMDA5NTEzMFowUzELMAkG
311A1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwlsb2NhbGhvc3Qx
312HTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tMFwwDQYJKoZIhvcNAQEBBQAD
313SwAwSAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh5kwI
314zOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEAAaOCAQQwggEAMAkGA1UdEwQCMAAw
315LAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0G
316A1UdDgQWBBTPhIKSvnsmYsBVNWjj0m3M2z0qVTCBpQYDVR0jBIGdMIGagBT7hyNp
31765w6kxXlxb8pUU/+7Sg4AaF/pH0wezELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0y
318Q3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlwdG8g
319Q2VydGlmaWNhdGUgTWFzdGVyMR0wGwYJKoZIhvcNAQkBFg5uZ3BzQHBvc3QxLmNv
320bYIBADANBgkqhkiG9w0BAQQFAAOBgQA7/CqT6PoHycTdhEStWNZde7M/2Yc6BoJu
321VwnW8YxGO8Sn6UJ4FeffZNcYZddSDKosw8LtPOeWoK3JINjAk5jiPQ2cww++7QGG
322/g5NDjxFZNDJP1dGiLAxPW6JXwov4v0FmdzfLOZ01jDcgQQZqEpYlgpuI5JEWUQ9
323Ho4EzbYCOaEAMQA=
324-----END PKCS7-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400325""")
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400326
Alex Gaynor8fa1dd62014-08-14 09:57:51 -0700327pkcs7DataASN1 = base64.b64decode(b"""
Alex Gaynor4b9c96a2014-08-14 09:51:48 -0700328MIIDNwYJKoZIhvcNAQcCoIIDKDCCAyQCAQExADALBgkqhkiG9w0BBwGgggMKMIID
329BjCCAm+gAwIBAgIBATANBgkqhkiG9w0BAQQFADB7MQswCQYDVQQGEwJTRzERMA8G
330A1UEChMITTJDcnlwdG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtN
331MkNyeXB0byBDZXJ0aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNA
332cG9zdDEuY29tMB4XDTAwMDkxMDA5NTEzMFoXDTAyMDkxMDA5NTEzMFowUzELMAkG
333A1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwlsb2NhbGhvc3Qx
334HTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tMFwwDQYJKoZIhvcNAQEBBQAD
335SwAwSAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh5kwI
336zOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEAAaOCAQQwggEAMAkGA1UdEwQCMAAw
337LAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0G
338A1UdDgQWBBTPhIKSvnsmYsBVNWjj0m3M2z0qVTCBpQYDVR0jBIGdMIGagBT7hyNp
33965w6kxXlxb8pUU/+7Sg4AaF/pH0wezELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0y
340Q3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlwdG8g
341Q2VydGlmaWNhdGUgTWFzdGVyMR0wGwYJKoZIhvcNAQkBFg5uZ3BzQHBvc3QxLmNv
342bYIBADANBgkqhkiG9w0BAQQFAAOBgQA7/CqT6PoHycTdhEStWNZde7M/2Yc6BoJu
343VwnW8YxGO8Sn6UJ4FeffZNcYZddSDKosw8LtPOeWoK3JINjAk5jiPQ2cww++7QGG
344/g5NDjxFZNDJP1dGiLAxPW6JXwov4v0FmdzfLOZ01jDcgQQZqEpYlgpuI5JEWUQ9
345Ho4EzbYCOaEAMQA=
Alex Gaynor8fa1dd62014-08-14 09:57:51 -0700346""")
Alex Gaynor4b9c96a2014-08-14 09:51:48 -0700347
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400348crlData = b("""\
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -0500349-----BEGIN X509 CRL-----
350MIIBWzCBxTANBgkqhkiG9w0BAQQFADBYMQswCQYDVQQGEwJVUzELMAkGA1UECBMC
351SUwxEDAOBgNVBAcTB0NoaWNhZ28xEDAOBgNVBAoTB1Rlc3RpbmcxGDAWBgNVBAMT
352D1Rlc3RpbmcgUm9vdCBDQRcNMDkwNzI2MDQzNDU2WhcNMTIwOTI3MDI0MTUyWjA8
353MBUCAgOrGA8yMDA5MDcyNTIzMzQ1NlowIwICAQAYDzIwMDkwNzI1MjMzNDU2WjAM
354MAoGA1UdFQQDCgEEMA0GCSqGSIb3DQEBBAUAA4GBAEBt7xTs2htdD3d4ErrcGAw1
3554dKcVnIWTutoI7xxen26Wwvh8VCsT7i/UeP+rBl9rC/kfjWjzQk3/zleaarGTpBT
3560yp4HXRFFoRhhSE/hP+eteaPXRgrsNRLHe9ZDd69wmh7J1wMDb0m81RG7kqcbsid
357vrzEeLDRiiPl92dyyWmu
358-----END X509 CRL-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400359""")
Jean-Paul Calderonee890db32010-08-22 16:55:15 -0400360
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400361
362# A broken RSA private key which can be used to test the error path through
363# PKey.check.
364inconsistentPrivateKeyPEM = b("""-----BEGIN RSA PRIVATE KEY-----
365MIIBPAIBAAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh
3665kwIzOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEaAQJBAIqm/bz4NA1H++Vx5Ewx
367OcKp3w19QSaZAwlGRtsUxrP7436QjnREM3Bm8ygU11BjkPVmtrKm6AayQfCHqJoT
368zIECIQDW0BoMoL0HOYM/mrTLhaykYAVqgIeJsPjvkEhTFXWBuQIhAM3deFAvWNu4
369nklUQ37XsCT2c9tmNt1LAT+slG2JOTTRAiAuXDtC/m3NYVwyHfFm+zKHRzHkClk2
370HjubeEgjpj32AQIhAJqMGTaZVOwevTXvvHwNeH+vRWsAYU/gbx+OQB+7VOcBAiEA
371oolb6NMg/R3enNPvS1O4UU1H8wpaF77L4yiSWlE0p4w=
372-----END RSA PRIVATE KEY-----
373""")
374
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -0400375# certificate with NULL bytes in subjectAltName and common name
376
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400377nulbyteSubjectAltNamePEM = b("""-----BEGIN CERTIFICATE-----
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -0400378MIIE2DCCA8CgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBxTELMAkGA1UEBhMCVVMx
379DzANBgNVBAgMBk9yZWdvbjESMBAGA1UEBwwJQmVhdmVydG9uMSMwIQYDVQQKDBpQ
380eXRob24gU29mdHdhcmUgRm91bmRhdGlvbjEgMB4GA1UECwwXUHl0aG9uIENvcmUg
381RGV2ZWxvcG1lbnQxJDAiBgNVBAMMG251bGwucHl0aG9uLm9yZwBleGFtcGxlLm9y
382ZzEkMCIGCSqGSIb3DQEJARYVcHl0aG9uLWRldkBweXRob24ub3JnMB4XDTEzMDgw
383NzEzMTE1MloXDTEzMDgwNzEzMTI1MlowgcUxCzAJBgNVBAYTAlVTMQ8wDQYDVQQI
384DAZPcmVnb24xEjAQBgNVBAcMCUJlYXZlcnRvbjEjMCEGA1UECgwaUHl0aG9uIFNv
385ZnR3YXJlIEZvdW5kYXRpb24xIDAeBgNVBAsMF1B5dGhvbiBDb3JlIERldmVsb3Bt
386ZW50MSQwIgYDVQQDDBtudWxsLnB5dGhvbi5vcmcAZXhhbXBsZS5vcmcxJDAiBgkq
387hkiG9w0BCQEWFXB5dGhvbi1kZXZAcHl0aG9uLm9yZzCCASIwDQYJKoZIhvcNAQEB
388BQADggEPADCCAQoCggEBALXq7cn7Rn1vO3aA3TrzA5QLp6bb7B3f/yN0CJ2XFj+j
389pHs+Gw6WWSUDpybiiKnPec33BFawq3kyblnBMjBU61ioy5HwQqVkJ8vUVjGIUq3P
390vX/wBmQfzCe4o4uM89gpHyUL9UYGG8oCRa17dgqcv7u5rg0Wq2B1rgY+nHwx3JIv
391KRrgSwyRkGzpN8WQ1yrXlxWjgI9de0mPVDDUlywcWze1q2kwaEPTM3hLAmD1PESA
392oY/n8A/RXoeeRs9i/Pm/DGUS8ZPINXk/yOzsR/XvvkTVroIeLZqfmFpnZeF0cHzL
39308LODkVJJ9zjLdT7SA4vnne4FEbAxDbKAq5qkYzaL4UCAwEAAaOB0DCBzTAMBgNV
394HRMBAf8EAjAAMB0GA1UdDgQWBBSIWlXAUv9hzVKjNQ/qWpwkOCL3XDALBgNVHQ8E
395BAMCBeAwgZAGA1UdEQSBiDCBhYIeYWx0bnVsbC5weXRob24ub3JnAGV4YW1wbGUu
396Y29tgSBudWxsQHB5dGhvbi5vcmcAdXNlckBleGFtcGxlLm9yZ4YpaHR0cDovL251
397bGwucHl0aG9uLm9yZwBodHRwOi8vZXhhbXBsZS5vcmeHBMAAAgGHECABDbgAAAAA
398AAAAAAAAAAEwDQYJKoZIhvcNAQEFBQADggEBAKxPRe99SaghcI6IWT7UNkJw9aO9
399i9eo0Fj2MUqxpKbdb9noRDy2CnHWf7EIYZ1gznXPdwzSN4YCjV5d+Q9xtBaowT0j
400HPERs1ZuytCNNJTmhyqZ8q6uzMLoht4IqH/FBfpvgaeC5tBTnTT0rD5A/olXeimk
401kX4LxlEx5RAvpGB2zZVRGr6LobD9rVK91xuHYNIxxxfEGE8tCCWjp0+3ksri9SXx
402VHWBnbM9YaL32u3hxm8sYB/Yb8WSBavJCWJJqRStVRHM1koZlJmXNx2BX4vPo6iW
403RFEIPQsFZRLrtnCAiEhyT8bC2s/Njlu6ly9gtJZWSV46Q3ZjBL4q9sHKqZQ=
404-----END CERTIFICATE-----""")
405
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400406
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400407class X509ExtTests(TestCase):
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400408 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900409 Tests for :py:class:`OpenSSL.crypto.X509Extension`.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400410 """
411
412 def setUp(self):
413 """
414 Create a new private key and start a certificate request (for a test
415 method to finish in one way or another).
416 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -0800417 super(X509ExtTests, self).setUp()
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400418 # Basic setup stuff to generate a certificate
419 self.pkey = PKey()
420 self.pkey.generate_key(TYPE_RSA, 384)
421 self.req = X509Req()
422 self.req.set_pubkey(self.pkey)
423 # Authority good you have.
424 self.req.get_subject().commonName = "Yoda root CA"
425 self.x509 = X509()
426 self.subject = self.x509.get_subject()
427 self.subject.commonName = self.req.get_subject().commonName
428 self.x509.set_issuer(self.subject)
429 self.x509.set_pubkey(self.pkey)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400430 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
431 expire = b((datetime.now() + timedelta(days=100)).strftime("%Y%m%d%H%M%SZ"))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400432 self.x509.set_notBefore(now)
433 self.x509.set_notAfter(expire)
434
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
444
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400445 def test_str(self):
446 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900447 The string representation of :py:class:`X509Extension` instances as returned by
448 :py:data:`str` includes stuff.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400449 """
450 # This isn't necessarily the best string representation. Perhaps it
451 # will be changed/improved in the future.
452 self.assertEquals(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400453 str(X509Extension(b('basicConstraints'), True, b('CA:false'))),
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400454 'CA:FALSE')
455
456
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400457 def test_type(self):
458 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900459 :py:class:`X509Extension` and :py:class:`X509ExtensionType` refer to the same type object
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400460 and can be used to create instances of that type.
461 """
462 self.assertIdentical(X509Extension, X509ExtensionType)
463 self.assertConsistentType(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400464 X509Extension,
465 'X509Extension', b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400466
467
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500468 def test_construction(self):
469 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900470 :py:class:`X509Extension` accepts an extension type name, a critical flag,
471 and an extension value and returns an :py:class:`X509ExtensionType` instance.
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500472 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400473 basic = X509Extension(b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500474 self.assertTrue(
475 isinstance(basic, X509ExtensionType),
476 "%r is of type %r, should be %r" % (
477 basic, type(basic), X509ExtensionType))
478
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400479 comment = X509Extension(
480 b('nsComment'), False, b('pyOpenSSL unit test'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500481 self.assertTrue(
482 isinstance(comment, X509ExtensionType),
483 "%r is of type %r, should be %r" % (
484 comment, type(comment), X509ExtensionType))
485
486
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500487 def test_invalid_extension(self):
488 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900489 :py:class:`X509Extension` raises something if it is passed a bad extension
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500490 name or value.
491 """
492 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400493 Error, X509Extension, b('thisIsMadeUp'), False, b('hi'))
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500494 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400495 Error, X509Extension, b('basicConstraints'), False, b('blah blah'))
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500496
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500497 # Exercise a weird one (an extension which uses the r2i method). This
498 # exercises the codepath that requires a non-NULL ctx to be passed to
499 # X509V3_EXT_nconf. It can't work now because we provide no
500 # configuration database. It might be made to work in the future.
501 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400502 Error, X509Extension, b('proxyCertInfo'), True,
503 b('language:id-ppl-anyLanguage,pathlen:1,policy:text:AB'))
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500504
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500505
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500506 def test_get_critical(self):
507 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900508 :py:meth:`X509ExtensionType.get_critical` returns the value of the
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500509 extension's critical flag.
510 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400511 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500512 self.assertTrue(ext.get_critical())
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400513 ext = X509Extension(b('basicConstraints'), False, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500514 self.assertFalse(ext.get_critical())
515
Jean-Paul Calderone7535dab2008-03-06 18:53:11 -0500516
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500517 def test_get_short_name(self):
518 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900519 :py:meth:`X509ExtensionType.get_short_name` returns a string giving the short
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500520 type name of the extension.
521 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400522 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
523 self.assertEqual(ext.get_short_name(), b('basicConstraints'))
524 ext = X509Extension(b('nsComment'), True, b('foo bar'))
525 self.assertEqual(ext.get_short_name(), b('nsComment'))
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500526
527
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400528 def test_get_data(self):
529 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900530 :py:meth:`X509Extension.get_data` returns a string giving the data of the
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400531 extension.
532 """
533 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
534 # Expect to get back the DER encoded form of CA:true.
535 self.assertEqual(ext.get_data(), b('0\x03\x01\x01\xff'))
536
537
538 def test_get_data_wrong_args(self):
539 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900540 :py:meth:`X509Extension.get_data` raises :py:exc:`TypeError` if passed any arguments.
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400541 """
542 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
543 self.assertRaises(TypeError, ext.get_data, None)
544 self.assertRaises(TypeError, ext.get_data, "foo")
545 self.assertRaises(TypeError, ext.get_data, 7)
546
547
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400548 def test_unused_subject(self):
Rick Dean47262da2009-07-08 16:17:17 -0500549 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900550 The :py:data:`subject` parameter to :py:class:`X509Extension` may be provided for an
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400551 extension which does not use it and is ignored in this case.
Rick Dean47262da2009-07-08 16:17:17 -0500552 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400553 ext1 = X509Extension(
554 b('basicConstraints'), False, b('CA:TRUE'), subject=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400555 self.x509.add_extensions([ext1])
556 self.x509.sign(self.pkey, 'sha1')
557 # This is a little lame. Can we think of a better way?
558 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400559 self.assertTrue(b('X509v3 Basic Constraints:') in text)
560 self.assertTrue(b('CA:TRUE') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400561
562
563 def test_subject(self):
564 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900565 If an extension requires a subject, the :py:data:`subject` parameter to
566 :py:class:`X509Extension` provides its value.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400567 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400568 ext3 = X509Extension(
569 b('subjectKeyIdentifier'), False, b('hash'), subject=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400570 self.x509.add_extensions([ext3])
571 self.x509.sign(self.pkey, 'sha1')
572 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400573 self.assertTrue(b('X509v3 Subject Key Identifier:') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400574
575
576 def test_missing_subject(self):
577 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900578 If an extension requires a subject and the :py:data:`subject` parameter is
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400579 given no value, something happens.
580 """
581 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400582 Error, X509Extension, b('subjectKeyIdentifier'), False, b('hash'))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400583
584
585 def test_invalid_subject(self):
586 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900587 If the :py:data:`subject` parameter is given a value which is not an
588 :py:class:`X509` instance, :py:exc:`TypeError` is raised.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400589 """
590 for badObj in [True, object(), "hello", [], self]:
591 self.assertRaises(
592 TypeError,
593 X509Extension,
594 'basicConstraints', False, 'CA:TRUE', subject=badObj)
595
596
597 def test_unused_issuer(self):
598 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900599 The :py:data:`issuer` parameter to :py:class:`X509Extension` may be provided for an
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400600 extension which does not use it and is ignored in this case.
601 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400602 ext1 = X509Extension(
603 b('basicConstraints'), False, b('CA:TRUE'), issuer=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400604 self.x509.add_extensions([ext1])
605 self.x509.sign(self.pkey, 'sha1')
606 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400607 self.assertTrue(b('X509v3 Basic Constraints:') in text)
608 self.assertTrue(b('CA:TRUE') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400609
610
611 def test_issuer(self):
612 """
Alex Gaynor3b0ee972014-11-15 09:17:33 -0800613 If an extension requires an issuer, the :py:data:`issuer` parameter to
Jonathan Ballet648875f2011-07-16 14:14:58 +0900614 :py:class:`X509Extension` provides its value.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400615 """
616 ext2 = X509Extension(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400617 b('authorityKeyIdentifier'), False, b('issuer:always'),
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400618 issuer=self.x509)
619 self.x509.add_extensions([ext2])
620 self.x509.sign(self.pkey, 'sha1')
621 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400622 self.assertTrue(b('X509v3 Authority Key Identifier:') in text)
623 self.assertTrue(b('DirName:/CN=Yoda root CA') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400624
625
626 def test_missing_issuer(self):
627 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900628 If an extension requires an issue and the :py:data:`issuer` parameter is given
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400629 no value, something happens.
630 """
631 self.assertRaises(
632 Error,
633 X509Extension,
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400634 b('authorityKeyIdentifier'), False,
635 b('keyid:always,issuer:always'))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400636
637
638 def test_invalid_issuer(self):
639 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900640 If the :py:data:`issuer` parameter is given a value which is not an
641 :py:class:`X509` instance, :py:exc:`TypeError` is raised.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400642 """
643 for badObj in [True, object(), "hello", [], self]:
644 self.assertRaises(
645 TypeError,
646 X509Extension,
647 'authorityKeyIdentifier', False, 'keyid:always,issuer:always',
648 issuer=badObj)
Rick Dean47262da2009-07-08 16:17:17 -0500649
650
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500651
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400652class PKeyTests(TestCase):
Jean-Paul Calderoneac930e12008-03-06 18:50:51 -0500653 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900654 Unit tests for :py:class:`OpenSSL.crypto.PKey`.
Jean-Paul Calderoneac930e12008-03-06 18:50:51 -0500655 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400656 def test_type(self):
657 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900658 :py:class:`PKey` and :py:class:`PKeyType` refer to the same type object
659 and can be used to create instances of that type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400660 """
661 self.assertIdentical(PKey, PKeyType)
662 self.assertConsistentType(PKey, 'PKey')
663
664
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500665 def test_construction(self):
666 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900667 :py:class:`PKey` takes no arguments and returns a new :py:class:`PKey` instance.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500668 """
669 self.assertRaises(TypeError, PKey, None)
670 key = PKey()
671 self.assertTrue(
672 isinstance(key, PKeyType),
673 "%r is of type %r, should be %r" % (key, type(key), PKeyType))
674
675
676 def test_pregeneration(self):
677 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900678 :py:attr:`PKeyType.bits` and :py:attr:`PKeyType.type` return :py:data:`0` before the key is
679 generated. :py:attr:`PKeyType.check` raises :py:exc:`TypeError` before the key is
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500680 generated.
681 """
682 key = PKey()
683 self.assertEqual(key.type(), 0)
684 self.assertEqual(key.bits(), 0)
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400685 self.assertRaises(TypeError, key.check)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500686
687
688 def test_failedGeneration(self):
689 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900690 :py:meth:`PKeyType.generate_key` takes two arguments, the first giving the key
691 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 -0500692 number of bits to generate. If an invalid type is specified or
Jonathan Ballet648875f2011-07-16 14:14:58 +0900693 generation fails, :py:exc:`Error` is raised. If an invalid number of bits is
694 specified, :py:exc:`ValueError` or :py:exc:`Error` is raised.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500695 """
696 key = PKey()
697 self.assertRaises(TypeError, key.generate_key)
698 self.assertRaises(TypeError, key.generate_key, 1, 2, 3)
699 self.assertRaises(TypeError, key.generate_key, "foo", "bar")
700 self.assertRaises(Error, key.generate_key, -1, 0)
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500701
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500702 self.assertRaises(ValueError, key.generate_key, TYPE_RSA, -1)
703 self.assertRaises(ValueError, key.generate_key, TYPE_RSA, 0)
Jean-Paul Calderoned71fe982008-03-06 00:31:50 -0500704
705 # XXX RSA generation for small values of bits is fairly buggy in a wide
706 # range of OpenSSL versions. I need to figure out what the safe lower
707 # bound for a reasonable number of OpenSSL versions is and explicitly
708 # check for that in the wrapper. The failure behavior is typically an
709 # infinite loop inside OpenSSL.
710
711 # self.assertRaises(Error, key.generate_key, TYPE_RSA, 2)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500712
713 # XXX DSA generation seems happy with any number of bits. The DSS
714 # says bits must be between 512 and 1024 inclusive. OpenSSL's DSA
715 # generator doesn't seem to care about the upper limit at all. For
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500716 # the lower limit, it uses 512 if anything smaller is specified.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500717 # So, it doesn't seem possible to make generate_key fail for
718 # TYPE_DSA with a bits argument which is at least an int.
719
720 # self.assertRaises(Error, key.generate_key, TYPE_DSA, -7)
721
722
723 def test_rsaGeneration(self):
724 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900725 :py:meth:`PKeyType.generate_key` generates an RSA key when passed
726 :py:data:`TYPE_RSA` as a type and a reasonable number of bits.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500727 """
728 bits = 128
729 key = PKey()
730 key.generate_key(TYPE_RSA, bits)
731 self.assertEqual(key.type(), TYPE_RSA)
732 self.assertEqual(key.bits(), bits)
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -0400733 self.assertTrue(key.check())
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500734
735
736 def test_dsaGeneration(self):
737 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900738 :py:meth:`PKeyType.generate_key` generates a DSA key when passed
739 :py:data:`TYPE_DSA` as a type and a reasonable number of bits.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500740 """
741 # 512 is a magic number. The DSS (Digital Signature Standard)
742 # allows a minimum of 512 bits for DSA. DSA_generate_parameters
743 # will silently promote any value below 512 to 512.
744 bits = 512
745 key = PKey()
746 key.generate_key(TYPE_DSA, bits)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800747 # self.assertEqual(key.type(), TYPE_DSA)
748 # self.assertEqual(key.bits(), bits)
749 # self.assertRaises(TypeError, key.check)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500750
751
752 def test_regeneration(self):
753 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900754 :py:meth:`PKeyType.generate_key` can be called multiple times on the same
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500755 key to generate new keys.
756 """
757 key = PKey()
758 for type, bits in [(TYPE_RSA, 512), (TYPE_DSA, 576)]:
759 key.generate_key(type, bits)
760 self.assertEqual(key.type(), type)
761 self.assertEqual(key.bits(), bits)
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500762
763
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400764 def test_inconsistentKey(self):
765 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900766 :py:`PKeyType.check` returns :py:exc:`Error` if the key is not consistent.
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400767 """
768 key = load_privatekey(FILETYPE_PEM, inconsistentPrivateKeyPEM)
Jean-Paul Calderoned338e4e2009-05-13 15:45:07 -0400769 self.assertRaises(Error, key.check)
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400770
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500771
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400772 def test_check_wrong_args(self):
773 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900774 :py:meth:`PKeyType.check` raises :py:exc:`TypeError` if called with any arguments.
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400775 """
776 self.assertRaises(TypeError, PKey().check, None)
777 self.assertRaises(TypeError, PKey().check, object())
778 self.assertRaises(TypeError, PKey().check, 1)
779
780
Jean-Paul Calderone02d01972011-10-31 10:39:29 -0400781 def test_check_public_key(self):
782 """
783 :py:meth:`PKeyType.check` raises :py:exc:`TypeError` if only the public
784 part of the key is available.
785 """
786 # A trick to get a public-only key
787 key = PKey()
788 key.generate_key(TYPE_RSA, 512)
789 cert = X509()
790 cert.set_pubkey(key)
791 pub = cert.get_pubkey()
792 self.assertRaises(TypeError, pub.check)
793
794
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400795
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400796class X509NameTests(TestCase):
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500797 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900798 Unit tests for :py:class:`OpenSSL.crypto.X509Name`.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500799 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500800 def _x509name(self, **attrs):
801 # XXX There's no other way to get a new X509Name yet.
802 name = X509().get_subject()
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400803 attrs = list(attrs.items())
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500804 # Make the order stable - order matters!
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400805 def key(attr):
806 return attr[1]
807 attrs.sort(key=key)
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500808 for k, v in attrs:
809 setattr(name, k, v)
810 return name
811
812
Rick Deane15b1472009-07-09 15:53:42 -0500813 def test_type(self):
814 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900815 The type of X509Name objects is :py:class:`X509NameType`.
Rick Deane15b1472009-07-09 15:53:42 -0500816 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400817 self.assertIdentical(X509Name, X509NameType)
818 self.assertEqual(X509NameType.__name__, 'X509Name')
819 self.assertTrue(isinstance(X509NameType, type))
820
Rick Deane15b1472009-07-09 15:53:42 -0500821 name = self._x509name()
822 self.assertTrue(
823 isinstance(name, X509NameType),
824 "%r is of type %r, should be %r" % (
825 name, type(name), X509NameType))
Rick Deane15b1472009-07-09 15:53:42 -0500826
827
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400828 def test_onlyStringAttributes(self):
829 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900830 Attempting to set a non-:py:data:`str` attribute name on an :py:class:`X509NameType`
831 instance causes :py:exc:`TypeError` to be raised.
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400832 """
833 name = self._x509name()
834 # Beyond these cases, you may also think that unicode should be
835 # rejected. Sorry, you're wrong. unicode is automatically converted to
836 # str outside of the control of X509Name, so there's no way to reject
837 # it.
Jean-Paul Calderoneff363be2013-03-03 10:21:23 -0800838
839 # Also, this used to test str subclasses, but that test is less relevant
840 # now that the implementation is in Python instead of C. Also PyPy
841 # automatically converts str subclasses to str when they are passed to
842 # setattr, so we can't test it on PyPy. Apparently CPython does this
843 # sometimes as well.
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400844 self.assertRaises(TypeError, setattr, name, None, "hello")
845 self.assertRaises(TypeError, setattr, name, 30, "hello")
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400846
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -0500847
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400848 def test_setInvalidAttribute(self):
849 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900850 Attempting to set any attribute name on an :py:class:`X509NameType` instance for
851 which no corresponding NID is defined causes :py:exc:`AttributeError` to be
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400852 raised.
853 """
854 name = self._x509name()
855 self.assertRaises(AttributeError, setattr, name, "no such thing", None)
856
857
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500858 def test_attributes(self):
859 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900860 :py:class:`X509NameType` instances have attributes for each standard (?)
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500861 X509Name field.
862 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500863 name = self._x509name()
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500864 name.commonName = "foo"
865 self.assertEqual(name.commonName, "foo")
866 self.assertEqual(name.CN, "foo")
867 name.CN = "baz"
868 self.assertEqual(name.commonName, "baz")
869 self.assertEqual(name.CN, "baz")
870 name.commonName = "bar"
871 self.assertEqual(name.commonName, "bar")
872 self.assertEqual(name.CN, "bar")
873 name.CN = "quux"
874 self.assertEqual(name.commonName, "quux")
875 self.assertEqual(name.CN, "quux")
876
877
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500878 def test_copy(self):
879 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900880 :py:class:`X509Name` creates a new :py:class:`X509NameType` instance with all the same
881 attributes as an existing :py:class:`X509NameType` instance when called with
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500882 one.
883 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500884 name = self._x509name(commonName="foo", emailAddress="bar@example.com")
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500885
886 copy = X509Name(name)
887 self.assertEqual(copy.commonName, "foo")
888 self.assertEqual(copy.emailAddress, "bar@example.com")
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500889
890 # Mutate the copy and ensure the original is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500891 copy.commonName = "baz"
892 self.assertEqual(name.commonName, "foo")
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500893
894 # Mutate the original and ensure the copy is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500895 name.emailAddress = "quux@example.com"
896 self.assertEqual(copy.emailAddress, "bar@example.com")
897
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500898
899 def test_repr(self):
900 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900901 :py:func:`repr` passed an :py:class:`X509NameType` instance should return a string
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500902 containing a description of the type and the NIDs which have been set
903 on it.
904 """
905 name = self._x509name(commonName="foo", emailAddress="bar")
906 self.assertEqual(
907 repr(name),
908 "<X509Name object '/emailAddress=bar/CN=foo'>")
909
910
911 def test_comparison(self):
912 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900913 :py:class:`X509NameType` instances should compare based on their NIDs.
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500914 """
915 def _equality(a, b, assertTrue, assertFalse):
916 assertTrue(a == b, "(%r == %r) --> False" % (a, b))
917 assertFalse(a != b)
918 assertTrue(b == a)
919 assertFalse(b != a)
920
921 def assertEqual(a, b):
922 _equality(a, b, self.assertTrue, self.assertFalse)
923
924 # Instances compare equal to themselves.
925 name = self._x509name()
926 assertEqual(name, name)
927
928 # Empty instances should compare equal to each other.
929 assertEqual(self._x509name(), self._x509name())
930
931 # Instances with equal NIDs should compare equal to each other.
932 assertEqual(self._x509name(commonName="foo"),
933 self._x509name(commonName="foo"))
934
935 # Instance with equal NIDs set using different aliases should compare
936 # equal to each other.
937 assertEqual(self._x509name(commonName="foo"),
938 self._x509name(CN="foo"))
939
940 # Instances with more than one NID with the same values should compare
941 # equal to each other.
942 assertEqual(self._x509name(CN="foo", organizationalUnitName="bar"),
943 self._x509name(commonName="foo", OU="bar"))
944
945 def assertNotEqual(a, b):
946 _equality(a, b, self.assertFalse, self.assertTrue)
947
948 # Instances with different values for the same NID should not compare
949 # equal to each other.
950 assertNotEqual(self._x509name(CN="foo"),
951 self._x509name(CN="bar"))
952
953 # Instances with different NIDs should not compare equal to each other.
954 assertNotEqual(self._x509name(CN="foo"),
955 self._x509name(OU="foo"))
956
957 def _inequality(a, b, assertTrue, assertFalse):
958 assertTrue(a < b)
959 assertTrue(a <= b)
960 assertTrue(b > a)
961 assertTrue(b >= a)
962 assertFalse(a > b)
963 assertFalse(a >= b)
964 assertFalse(b < a)
965 assertFalse(b <= a)
966
967 def assertLessThan(a, b):
968 _inequality(a, b, self.assertTrue, self.assertFalse)
969
970 # An X509Name with a NID with a value which sorts less than the value
971 # of the same NID on another X509Name compares less than the other
972 # X509Name.
973 assertLessThan(self._x509name(CN="abc"),
974 self._x509name(CN="def"))
975
976 def assertGreaterThan(a, b):
977 _inequality(a, b, self.assertFalse, self.assertTrue)
978
979 # An X509Name with a NID with a value which sorts greater than the
980 # value of the same NID on another X509Name compares greater than the
981 # other X509Name.
982 assertGreaterThan(self._x509name(CN="def"),
983 self._x509name(CN="abc"))
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -0500984
985
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400986 def test_hash(self):
987 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900988 :py:meth:`X509Name.hash` returns an integer hash based on the value of the
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400989 name.
990 """
991 a = self._x509name(CN="foo")
992 b = self._x509name(CN="foo")
993 self.assertEqual(a.hash(), b.hash())
994 a.CN = "bar"
995 self.assertNotEqual(a.hash(), b.hash())
996
997
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400998 def test_der(self):
999 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001000 :py:meth:`X509Name.der` returns the DER encoded form of the name.
Jean-Paul Calderonee957a002008-03-25 15:16:51 -04001001 """
1002 a = self._x509name(CN="foo", C="US")
1003 self.assertEqual(
1004 a.der(),
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -04001005 b('0\x1b1\x0b0\t\x06\x03U\x04\x06\x13\x02US'
D.S. Ljungmark5533e252014-05-31 13:18:41 +02001006 '1\x0c0\n\x06\x03U\x04\x03\x0c\x03foo'))
Jean-Paul Calderonee957a002008-03-25 15:16:51 -04001007
1008
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -04001009 def test_get_components(self):
1010 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001011 :py:meth:`X509Name.get_components` returns a :py:data:`list` of
1012 two-tuples of :py:data:`str`
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -04001013 giving the NIDs and associated values which make up the name.
1014 """
1015 a = self._x509name()
1016 self.assertEqual(a.get_components(), [])
1017 a.CN = "foo"
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -04001018 self.assertEqual(a.get_components(), [(b("CN"), b("foo"))])
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -04001019 a.organizationalUnitName = "bar"
1020 self.assertEqual(
1021 a.get_components(),
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -04001022 [(b("CN"), b("foo")), (b("OU"), b("bar"))])
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -04001023
Jean-Paul Calderone110cd092008-03-24 17:27:42 -04001024
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001025 def test_load_nul_byte_attribute(self):
1026 """
Jean-Paul Calderone9af07b02013-08-23 16:07:31 -04001027 An :py:class:`OpenSSL.crypto.X509Name` from an
1028 :py:class:`OpenSSL.crypto.X509` instance loaded from a file can have a
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001029 NUL byte in the value of one of its attributes.
1030 """
1031 cert = load_certificate(FILETYPE_PEM, nulbyteSubjectAltNamePEM)
1032 subject = cert.get_subject()
1033 self.assertEqual(
Jean-Paul Calderone06754fc2013-08-23 15:47:47 -04001034 "null.python.org\x00example.org", subject.commonName)
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001035
1036
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -05001037 def test_setAttributeFailure(self):
1038 """
1039 If the value of an attribute cannot be set for some reason then
1040 :py:class:`OpenSSL.crypto.Error` is raised.
1041 """
1042 name = self._x509name()
1043 # This value is too long
1044 self.assertRaises(Error, setattr, name, "O", b"x" * 512)
1045
1046
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001047
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001048class _PKeyInteractionTestsMixin:
1049 """
1050 Tests which involve another thing and a PKey.
1051 """
1052 def signable(self):
1053 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001054 Return something with a :py:meth:`set_pubkey`, :py:meth:`set_pubkey`,
1055 and :py:meth:`sign` method.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001056 """
1057 raise NotImplementedError()
1058
1059
1060 def test_signWithUngenerated(self):
1061 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001062 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when pass a
1063 :py:class:`PKey` with no parts.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001064 """
1065 request = self.signable()
1066 key = PKey()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001067 self.assertRaises(ValueError, request.sign, key, GOOD_DIGEST)
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001068
1069
1070 def test_signWithPublicKey(self):
1071 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001072 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when pass a
1073 :py:class:`PKey` with no private part as the signing key.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001074 """
1075 request = self.signable()
1076 key = PKey()
1077 key.generate_key(TYPE_RSA, 512)
1078 request.set_pubkey(key)
1079 pub = request.get_pubkey()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001080 self.assertRaises(ValueError, request.sign, pub, GOOD_DIGEST)
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001081
1082
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -04001083 def test_signWithUnknownDigest(self):
1084 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001085 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when passed a digest name which is
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -04001086 not known.
1087 """
1088 request = self.signable()
1089 key = PKey()
1090 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001091 self.assertRaises(ValueError, request.sign, key, BAD_DIGEST)
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -04001092
1093
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04001094 def test_sign(self):
1095 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001096 :py:meth:`X509Req.sign` succeeds when passed a private key object and a valid
1097 digest function. :py:meth:`X509Req.verify` can be used to check the signature.
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04001098 """
1099 request = self.signable()
1100 key = PKey()
1101 key.generate_key(TYPE_RSA, 512)
1102 request.set_pubkey(key)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001103 request.sign(key, GOOD_DIGEST)
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04001104 # If the type has a verify method, cover that too.
1105 if getattr(request, 'verify', None) is not None:
1106 pub = request.get_pubkey()
1107 self.assertTrue(request.verify(pub))
1108 # Make another key that won't verify.
1109 key = PKey()
1110 key.generate_key(TYPE_RSA, 512)
1111 self.assertRaises(Error, request.verify, key)
1112
1113
1114
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001115
Jean-Paul Calderone18808652009-07-05 12:54:05 -04001116class X509ReqTests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001117 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001118 Tests for :py:class:`OpenSSL.crypto.X509Req`.
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001119 """
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001120 def signable(self):
1121 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001122 Create and return a new :py:class:`X509Req`.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001123 """
1124 return X509Req()
1125
1126
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001127 def test_type(self):
1128 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001129 :py:obj:`X509Req` and :py:obj:`X509ReqType` refer to the same type object and can be
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001130 used to create instances of that type.
1131 """
1132 self.assertIdentical(X509Req, X509ReqType)
1133 self.assertConsistentType(X509Req, 'X509Req')
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001134
1135
1136 def test_construction(self):
1137 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001138 :py:obj:`X509Req` takes no arguments and returns an :py:obj:`X509ReqType` instance.
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001139 """
1140 request = X509Req()
1141 self.assertTrue(
1142 isinstance(request, X509ReqType),
1143 "%r is of type %r, should be %r" % (request, type(request), X509ReqType))
1144
1145
Jean-Paul Calderone8dd19b82008-12-28 20:41:16 -05001146 def test_version(self):
1147 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001148 :py:obj:`X509ReqType.set_version` sets the X.509 version of the certificate
1149 request. :py:obj:`X509ReqType.get_version` returns the X.509 version of
Jean-Paul Calderone8dd19b82008-12-28 20:41:16 -05001150 the certificate request. The initial value of the version is 0.
1151 """
1152 request = X509Req()
1153 self.assertEqual(request.get_version(), 0)
1154 request.set_version(1)
1155 self.assertEqual(request.get_version(), 1)
1156 request.set_version(3)
1157 self.assertEqual(request.get_version(), 3)
1158
1159
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001160 def test_version_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001161 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001162 :py:obj:`X509ReqType.set_version` raises :py:obj:`TypeError` if called with the wrong
1163 number of arguments or with a non-:py:obj:`int` argument.
1164 :py:obj:`X509ReqType.get_version` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001165 arguments.
1166 """
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001167 request = X509Req()
1168 self.assertRaises(TypeError, request.set_version)
1169 self.assertRaises(TypeError, request.set_version, "foo")
1170 self.assertRaises(TypeError, request.set_version, 1, 2)
1171 self.assertRaises(TypeError, request.get_version, None)
1172
1173
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001174 def test_get_subject(self):
1175 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001176 :py:obj:`X509ReqType.get_subject` returns an :py:obj:`X509Name` for the subject of
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001177 the request and which is valid even after the request object is
1178 otherwise dead.
1179 """
1180 request = X509Req()
1181 subject = request.get_subject()
1182 self.assertTrue(
1183 isinstance(subject, X509NameType),
1184 "%r is of type %r, should be %r" % (subject, type(subject), X509NameType))
1185 subject.commonName = "foo"
1186 self.assertEqual(request.get_subject().commonName, "foo")
1187 del request
1188 subject.commonName = "bar"
1189 self.assertEqual(subject.commonName, "bar")
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001190
1191
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001192 def test_get_subject_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001193 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001194 :py:obj:`X509ReqType.get_subject` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001195 arguments.
1196 """
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001197 request = X509Req()
1198 self.assertRaises(TypeError, request.get_subject, None)
1199
1200
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001201 def test_add_extensions(self):
1202 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001203 :py:obj:`X509Req.add_extensions` accepts a :py:obj:`list` of :py:obj:`X509Extension`
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001204 instances and adds them to the X509 request.
1205 """
1206 request = X509Req()
1207 request.add_extensions([
Jean-Paul Calderonee16f9f32010-08-22 19:20:37 -04001208 X509Extension(b('basicConstraints'), True, b('CA:false'))])
Stephen Holsappleca545b72014-01-28 21:43:25 -08001209 exts = request.get_extensions()
Stephen Holsapple7fbdf642014-03-01 20:05:47 -08001210 self.assertEqual(len(exts), 1)
1211 self.assertEqual(exts[0].get_short_name(), b('basicConstraints'))
1212 self.assertEqual(exts[0].get_critical(), 1)
1213 self.assertEqual(exts[0].get_data(), b('0\x00'))
1214
1215
1216 def test_get_extensions(self):
1217 """
1218 :py:obj:`X509Req.get_extensions` returns a :py:obj:`list` of
1219 extensions added to this X509 request.
1220 """
1221 request = X509Req()
1222 exts = request.get_extensions()
1223 self.assertEqual(exts, [])
1224 request.add_extensions([
1225 X509Extension(b('basicConstraints'), True, b('CA:true')),
1226 X509Extension(b('keyUsage'), False, b('digitalSignature'))])
1227 exts = request.get_extensions()
1228 self.assertEqual(len(exts), 2)
1229 self.assertEqual(exts[0].get_short_name(), b('basicConstraints'))
1230 self.assertEqual(exts[0].get_critical(), 1)
1231 self.assertEqual(exts[0].get_data(), b('0\x03\x01\x01\xff'))
1232 self.assertEqual(exts[1].get_short_name(), b('keyUsage'))
1233 self.assertEqual(exts[1].get_critical(), 0)
1234 self.assertEqual(exts[1].get_data(), b('\x03\x02\x07\x80'))
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001235
1236
1237 def test_add_extensions_wrong_args(self):
1238 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001239 :py:obj:`X509Req.add_extensions` raises :py:obj:`TypeError` if called with the wrong
1240 number of arguments or with a non-:py:obj:`list`. Or it raises :py:obj:`ValueError`
1241 if called with a :py:obj:`list` containing objects other than :py:obj:`X509Extension`
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001242 instances.
1243 """
1244 request = X509Req()
1245 self.assertRaises(TypeError, request.add_extensions)
1246 self.assertRaises(TypeError, request.add_extensions, object())
1247 self.assertRaises(ValueError, request.add_extensions, [object()])
1248 self.assertRaises(TypeError, request.add_extensions, [], None)
1249
1250
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001251 def test_verify_wrong_args(self):
1252 """
1253 :py:obj:`X509Req.verify` raises :py:obj:`TypeError` if called with zero
1254 arguments or more than one argument or if passed anything other than a
1255 :py:obj:`PKey` instance as its single argument.
1256 """
1257 request = X509Req()
1258 self.assertRaises(TypeError, request.verify)
1259 self.assertRaises(TypeError, request.verify, object())
1260 self.assertRaises(TypeError, request.verify, PKey(), object())
1261
1262
1263 def test_verify_uninitialized_key(self):
1264 """
1265 :py:obj:`X509Req.verify` raises :py:obj:`OpenSSL.crypto.Error` if called
1266 with a :py:obj:`OpenSSL.crypto.PKey` which contains no key data.
1267 """
1268 request = X509Req()
1269 pkey = PKey()
1270 self.assertRaises(Error, request.verify, pkey)
1271
1272
1273 def test_verify_wrong_key(self):
1274 """
1275 :py:obj:`X509Req.verify` raises :py:obj:`OpenSSL.crypto.Error` if called
1276 with a :py:obj:`OpenSSL.crypto.PKey` which does not represent the public
1277 part of the key which signed the request.
1278 """
1279 request = X509Req()
1280 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001281 request.sign(pkey, GOOD_DIGEST)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001282 another_pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
1283 self.assertRaises(Error, request.verify, another_pkey)
1284
1285
1286 def test_verify_success(self):
1287 """
1288 :py:obj:`X509Req.verify` returns :py:obj:`True` if called with a
Alex Gaynor3b0ee972014-11-15 09:17:33 -08001289 :py:obj:`OpenSSL.crypto.PKey` which represents the public part of the key
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001290 which signed the request.
1291 """
1292 request = X509Req()
1293 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001294 request.sign(pkey, GOOD_DIGEST)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001295 self.assertEqual(True, request.verify(pkey))
1296
1297
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001298
Jean-Paul Calderone18808652009-07-05 12:54:05 -04001299class X509Tests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001300 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001301 Tests for :py:obj:`OpenSSL.crypto.X509`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001302 """
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001303 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
Jean-Paul Calderone8114b452008-03-25 15:27:59 -04001304
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001305 extpem = """
1306-----BEGIN CERTIFICATE-----
1307MIIC3jCCAkegAwIBAgIJAJHFjlcCgnQzMA0GCSqGSIb3DQEBBQUAMEcxCzAJBgNV
1308BAYTAlNFMRUwEwYDVQQIEwxXZXN0ZXJib3R0b20xEjAQBgNVBAoTCUNhdGFsb2dp
1309eDENMAsGA1UEAxMEUm9vdDAeFw0wODA0MjIxNDQ1MzhaFw0wOTA0MjIxNDQ1Mzha
1310MFQxCzAJBgNVBAYTAlNFMQswCQYDVQQIEwJXQjEUMBIGA1UEChMLT3Blbk1ldGFk
1311aXIxIjAgBgNVBAMTGW5vZGUxLm9tMi5vcGVubWV0YWRpci5vcmcwgZ8wDQYJKoZI
1312hvcNAQEBBQADgY0AMIGJAoGBAPIcQMrwbk2nESF/0JKibj9i1x95XYAOwP+LarwT
1313Op4EQbdlI9SY+uqYqlERhF19w7CS+S6oyqx0DRZSk4Y9dZ9j9/xgm2u/f136YS1u
1314zgYFPvfUs6PqYLPSM8Bw+SjJ+7+2+TN+Tkiof9WP1cMjodQwOmdsiRbR0/J7+b1B
1315hec1AgMBAAGjgcQwgcEwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNT
1316TCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFIdHsBcMVVMbAO7j6NCj
131703HgLnHaMB8GA1UdIwQYMBaAFL2h9Bf9Mre4vTdOiHTGAt7BRY/8MEYGA1UdEQQ/
1318MD2CDSouZXhhbXBsZS5vcmeCESoub20yLmV4bWFwbGUuY29thwSC7wgKgRNvbTJA
1319b3Blbm1ldGFkaXIub3JnMA0GCSqGSIb3DQEBBQUAA4GBALd7WdXkp2KvZ7/PuWZA
1320MPlIxyjS+Ly11+BNE0xGQRp9Wz+2lABtpgNqssvU156+HkKd02rGheb2tj7MX9hG
1321uZzbwDAZzJPjzDQDD7d3cWsrVcfIdqVU7epHqIadnOF+X0ghJ39pAm6VVadnSXCt
1322WpOdIpB8KksUTCzV591Nr1wd
1323-----END CERTIFICATE-----
1324 """
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001325 def signable(self):
1326 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001327 Create and return a new :py:obj:`X509`.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001328 """
1329 return X509()
1330
1331
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001332 def test_type(self):
1333 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001334 :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 -04001335 to create instances of that type.
1336 """
1337 self.assertIdentical(X509, X509Type)
1338 self.assertConsistentType(X509, 'X509')
1339
1340
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001341 def test_construction(self):
1342 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001343 :py:obj:`X509` takes no arguments and returns an instance of :py:obj:`X509Type`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001344 """
1345 certificate = X509()
1346 self.assertTrue(
1347 isinstance(certificate, X509Type),
1348 "%r is of type %r, should be %r" % (certificate,
1349 type(certificate),
1350 X509Type))
Rick Deane15b1472009-07-09 15:53:42 -05001351 self.assertEqual(type(X509Type).__name__, 'type')
1352 self.assertEqual(type(certificate).__name__, 'X509')
1353 self.assertEqual(type(certificate), X509Type)
Rick Dean04113e72009-07-16 12:06:35 -05001354 self.assertEqual(type(certificate), X509)
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001355
1356
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001357 def test_get_version_wrong_args(self):
1358 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001359 :py:obj:`X509.get_version` raises :py:obj:`TypeError` if invoked with any arguments.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001360 """
1361 cert = X509()
1362 self.assertRaises(TypeError, cert.get_version, None)
1363
1364
1365 def test_set_version_wrong_args(self):
1366 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001367 :py:obj:`X509.set_version` raises :py:obj:`TypeError` if invoked with the wrong number
1368 of arguments or an argument not of type :py:obj:`int`.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001369 """
1370 cert = X509()
1371 self.assertRaises(TypeError, cert.set_version)
1372 self.assertRaises(TypeError, cert.set_version, None)
1373 self.assertRaises(TypeError, cert.set_version, 1, None)
1374
1375
1376 def test_version(self):
1377 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001378 :py:obj:`X509.set_version` sets the certificate version number.
1379 :py:obj:`X509.get_version` retrieves it.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001380 """
1381 cert = X509()
1382 cert.set_version(1234)
1383 self.assertEquals(cert.get_version(), 1234)
1384
1385
1386 def test_get_serial_number_wrong_args(self):
1387 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001388 :py:obj:`X509.get_serial_number` raises :py:obj:`TypeError` if invoked with any
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001389 arguments.
1390 """
1391 cert = X509()
1392 self.assertRaises(TypeError, cert.get_serial_number, None)
1393
1394
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001395 def test_serial_number(self):
1396 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001397 The serial number of an :py:obj:`X509Type` can be retrieved and modified with
1398 :py:obj:`X509Type.get_serial_number` and :py:obj:`X509Type.set_serial_number`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001399 """
1400 certificate = X509()
1401 self.assertRaises(TypeError, certificate.set_serial_number)
1402 self.assertRaises(TypeError, certificate.set_serial_number, 1, 2)
1403 self.assertRaises(TypeError, certificate.set_serial_number, "1")
1404 self.assertRaises(TypeError, certificate.set_serial_number, 5.5)
1405 self.assertEqual(certificate.get_serial_number(), 0)
1406 certificate.set_serial_number(1)
1407 self.assertEqual(certificate.get_serial_number(), 1)
1408 certificate.set_serial_number(2 ** 32 + 1)
1409 self.assertEqual(certificate.get_serial_number(), 2 ** 32 + 1)
1410 certificate.set_serial_number(2 ** 64 + 1)
1411 self.assertEqual(certificate.get_serial_number(), 2 ** 64 + 1)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001412 certificate.set_serial_number(2 ** 128 + 1)
1413 self.assertEqual(certificate.get_serial_number(), 2 ** 128 + 1)
1414
1415
1416 def _setBoundTest(self, which):
1417 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001418 :py:obj:`X509Type.set_notBefore` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001419 GENERALIZEDTIME and sets the beginning of the certificate's validity
1420 period to it.
1421 """
1422 certificate = X509()
1423 set = getattr(certificate, 'set_not' + which)
1424 get = getattr(certificate, 'get_not' + which)
1425
Jean-Paul Calderonee0615b52008-03-09 21:44:46 -04001426 # Starts with no value.
1427 self.assertEqual(get(), None)
1428
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001429 # GMT (Or is it UTC?) -exarkun
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001430 when = b("20040203040506Z")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001431 set(when)
1432 self.assertEqual(get(), when)
1433
1434 # A plus two hours and thirty minutes offset
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001435 when = b("20040203040506+0530")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001436 set(when)
1437 self.assertEqual(get(), when)
1438
1439 # A minus one hour fifteen minutes offset
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001440 when = b("20040203040506-0115")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001441 set(when)
1442 self.assertEqual(get(), when)
1443
1444 # An invalid string results in a ValueError
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001445 self.assertRaises(ValueError, set, b("foo bar"))
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001446
Jean-Paul Calderone31ca2002010-01-30 15:14:43 -05001447 # The wrong number of arguments results in a TypeError.
1448 self.assertRaises(TypeError, set)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001449 self.assertRaises(TypeError, set, b("20040203040506Z"), b("20040203040506Z"))
1450 self.assertRaises(TypeError, get, b("foo bar"))
1451
Jean-Paul Calderone31ca2002010-01-30 15:14:43 -05001452
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001453 # XXX ASN1_TIME (not GENERALIZEDTIME)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001454
1455 def test_set_notBefore(self):
1456 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001457 :py:obj:`X509Type.set_notBefore` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001458 GENERALIZEDTIME and sets the beginning of the certificate's validity
1459 period to it.
1460 """
1461 self._setBoundTest("Before")
1462
1463
1464 def test_set_notAfter(self):
1465 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001466 :py:obj:`X509Type.set_notAfter` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001467 GENERALIZEDTIME and sets the end of the certificate's validity period
1468 to it.
1469 """
1470 self._setBoundTest("After")
Jean-Paul Calderone76576d52008-03-24 16:04:46 -04001471
1472
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001473 def test_get_notBefore(self):
1474 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001475 :py:obj:`X509Type.get_notBefore` returns a string in the format of an ASN1
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001476 GENERALIZEDTIME even for certificates which store it as UTCTIME
1477 internally.
1478 """
Jean-Paul Calderone8114b452008-03-25 15:27:59 -04001479 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001480 self.assertEqual(cert.get_notBefore(), b("20090325123658Z"))
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001481
Rick Dean38a05c82009-07-18 01:41:30 -05001482
1483 def test_get_notAfter(self):
1484 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001485 :py:obj:`X509Type.get_notAfter` returns a string in the format of an ASN1
Rick Dean38a05c82009-07-18 01:41:30 -05001486 GENERALIZEDTIME even for certificates which store it as UTCTIME
1487 internally.
1488 """
1489 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001490 self.assertEqual(cert.get_notAfter(), b("20170611123658Z"))
Rick Dean38a05c82009-07-18 01:41:30 -05001491
1492
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001493 def test_gmtime_adj_notBefore_wrong_args(self):
1494 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001495 :py:obj:`X509Type.gmtime_adj_notBefore` raises :py:obj:`TypeError` if called with the
1496 wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001497 """
1498 cert = X509()
1499 self.assertRaises(TypeError, cert.gmtime_adj_notBefore)
1500 self.assertRaises(TypeError, cert.gmtime_adj_notBefore, None)
1501 self.assertRaises(TypeError, cert.gmtime_adj_notBefore, 123, None)
1502
1503
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001504 def test_gmtime_adj_notBefore(self):
1505 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001506 :py:obj:`X509Type.gmtime_adj_notBefore` changes the not-before timestamp to be
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001507 the current time plus the number of seconds passed in.
1508 """
1509 cert = load_certificate(FILETYPE_PEM, self.pemData)
Maximilian Hilsbed25c92015-07-25 12:58:07 +02001510 not_before_min = datetime.utcnow().replace(microsecond=0) + timedelta(seconds=100)
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001511 cert.gmtime_adj_notBefore(100)
Maximilian Hilsbed25c92015-07-25 12:58:07 +02001512 not_before = datetime.strptime(cert.get_notBefore().decode(), "%Y%m%d%H%M%SZ")
1513 not_before_max = datetime.utcnow() + timedelta(seconds=100)
1514 self.assertTrue(not_before_min <= not_before <= not_before_max)
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001515
1516
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001517 def test_gmtime_adj_notAfter_wrong_args(self):
1518 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001519 :py:obj:`X509Type.gmtime_adj_notAfter` raises :py:obj:`TypeError` if called with the
1520 wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001521 """
1522 cert = X509()
1523 self.assertRaises(TypeError, cert.gmtime_adj_notAfter)
1524 self.assertRaises(TypeError, cert.gmtime_adj_notAfter, None)
1525 self.assertRaises(TypeError, cert.gmtime_adj_notAfter, 123, None)
1526
1527
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001528 def test_gmtime_adj_notAfter(self):
1529 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001530 :py:obj:`X509Type.gmtime_adj_notAfter` changes the not-after timestamp to be
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001531 the current time plus the number of seconds passed in.
1532 """
1533 cert = load_certificate(FILETYPE_PEM, self.pemData)
Maximilian Hilsbed25c92015-07-25 12:58:07 +02001534 not_after_min = datetime.utcnow().replace(microsecond=0) + timedelta(seconds=100)
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001535 cert.gmtime_adj_notAfter(100)
Maximilian Hilsbed25c92015-07-25 12:58:07 +02001536 not_after = datetime.strptime(cert.get_notAfter().decode(), "%Y%m%d%H%M%SZ")
1537 not_after_max = datetime.utcnow() + timedelta(seconds=100)
1538 self.assertTrue(not_after_min <= not_after <= not_after_max)
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001539
1540
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001541 def test_has_expired_wrong_args(self):
1542 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001543 :py:obj:`X509Type.has_expired` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001544 arguments.
1545 """
1546 cert = X509()
1547 self.assertRaises(TypeError, cert.has_expired, None)
1548
1549
1550 def test_has_expired(self):
1551 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001552 :py:obj:`X509Type.has_expired` returns :py:obj:`True` if the certificate's not-after
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001553 time is in the past.
1554 """
1555 cert = X509()
1556 cert.gmtime_adj_notAfter(-1)
1557 self.assertTrue(cert.has_expired())
1558
1559
1560 def test_has_not_expired(self):
1561 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001562 :py:obj:`X509Type.has_expired` returns :py:obj:`False` if the certificate's not-after
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001563 time is in the future.
1564 """
1565 cert = X509()
1566 cert.gmtime_adj_notAfter(2)
1567 self.assertFalse(cert.has_expired())
1568
Jeff Tangfc18f7b2015-04-15 17:42:33 -04001569 def test_root_has_not_expired(self):
1570 """
1571 :py:obj:`X509Type.has_expired` returns :py:obj:`False` if the certificate's not-after
1572 time is in the future.
1573 """
1574 cert = load_certificate(FILETYPE_PEM, root_cert_pem)
1575 self.assertFalse(cert.has_expired())
1576
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001577
Rick Dean38a05c82009-07-18 01:41:30 -05001578 def test_digest(self):
1579 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001580 :py:obj:`X509.digest` returns a string giving ":"-separated hex-encoded words
Rick Dean38a05c82009-07-18 01:41:30 -05001581 of the digest of the certificate.
1582 """
Jeff Tangfc18f7b2015-04-15 17:42:33 -04001583 cert = load_certificate(FILETYPE_PEM, root_cert_pem)
Rick Dean38a05c82009-07-18 01:41:30 -05001584 self.assertEqual(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001585 # This is MD5 instead of GOOD_DIGEST because the digest algorithm
1586 # actually matters to the assertion (ie, another arbitrary, good
1587 # digest will not product the same digest).
Jeff Tangfc18f7b2015-04-15 17:42:33 -04001588 # Digest verified with the command:
1589 # openssl x509 -in root_cert.pem -noout -fingerprint -md5
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001590 cert.digest("MD5"),
Jeff Tangfc18f7b2015-04-15 17:42:33 -04001591 b("19:B3:05:26:2B:F8:F2:FF:0B:8F:21:07:A8:28:B8:75"))
Rick Dean38a05c82009-07-18 01:41:30 -05001592
1593
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001594 def _extcert(self, pkey, extensions):
1595 cert = X509()
1596 cert.set_pubkey(pkey)
1597 cert.get_subject().commonName = "Unit Tests"
1598 cert.get_issuer().commonName = "Unit Tests"
1599 when = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
1600 cert.set_notBefore(when)
1601 cert.set_notAfter(when)
1602
1603 cert.add_extensions(extensions)
Jeff Tangfc18f7b2015-04-15 17:42:33 -04001604 cert.sign(pkey, 'sha1')
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001605 return load_certificate(
1606 FILETYPE_PEM, dump_certificate(FILETYPE_PEM, cert))
1607
1608
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001609 def test_extension_count(self):
1610 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001611 :py:obj:`X509.get_extension_count` returns the number of extensions that are
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001612 present in the certificate.
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001613 """
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001614 pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001615 ca = X509Extension(b('basicConstraints'), True, b('CA:FALSE'))
1616 key = X509Extension(b('keyUsage'), True, b('digitalSignature'))
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001617 subjectAltName = X509Extension(
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001618 b('subjectAltName'), True, b('DNS:example.com'))
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001619
1620 # Try a certificate with no extensions at all.
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001621 c = self._extcert(pkey, [])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001622 self.assertEqual(c.get_extension_count(), 0)
1623
1624 # And a certificate with one
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001625 c = self._extcert(pkey, [ca])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001626 self.assertEqual(c.get_extension_count(), 1)
1627
1628 # And a certificate with several
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001629 c = self._extcert(pkey, [ca, key, subjectAltName])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001630 self.assertEqual(c.get_extension_count(), 3)
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001631
1632
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001633 def test_get_extension(self):
1634 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001635 :py:obj:`X509.get_extension` takes an integer and returns an :py:obj:`X509Extension`
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001636 corresponding to the extension at that index.
1637 """
1638 pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001639 ca = X509Extension(b('basicConstraints'), True, b('CA:FALSE'))
1640 key = X509Extension(b('keyUsage'), True, b('digitalSignature'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001641 subjectAltName = X509Extension(
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001642 b('subjectAltName'), False, b('DNS:example.com'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001643
1644 cert = self._extcert(pkey, [ca, key, subjectAltName])
1645
1646 ext = cert.get_extension(0)
1647 self.assertTrue(isinstance(ext, X509Extension))
1648 self.assertTrue(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001649 self.assertEqual(ext.get_short_name(), b('basicConstraints'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001650
1651 ext = cert.get_extension(1)
1652 self.assertTrue(isinstance(ext, X509Extension))
1653 self.assertTrue(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001654 self.assertEqual(ext.get_short_name(), b('keyUsage'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001655
1656 ext = cert.get_extension(2)
1657 self.assertTrue(isinstance(ext, X509Extension))
1658 self.assertFalse(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001659 self.assertEqual(ext.get_short_name(), b('subjectAltName'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001660
1661 self.assertRaises(IndexError, cert.get_extension, -1)
1662 self.assertRaises(IndexError, cert.get_extension, 4)
1663 self.assertRaises(TypeError, cert.get_extension, "hello")
1664
1665
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001666 def test_nullbyte_subjectAltName(self):
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001667 """
Jean-Paul Calderone9af07b02013-08-23 16:07:31 -04001668 The fields of a `subjectAltName` extension on an X509 may contain NUL
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001669 bytes and this value is reflected in the string representation of the
1670 extension object.
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001671 """
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001672 cert = load_certificate(FILETYPE_PEM, nulbyteSubjectAltNamePEM)
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001673
1674 ext = cert.get_extension(3)
1675 self.assertEqual(ext.get_short_name(), b('subjectAltName'))
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001676 self.assertEqual(
1677 b("DNS:altnull.python.org\x00example.com, "
1678 "email:null@python.org\x00user@example.org, "
1679 "URI:http://null.python.org\x00http://example.org, "
1680 "IP Address:192.0.2.1, IP Address:2001:DB8:0:0:0:0:0:1\n"),
1681 b(str(ext)))
1682
Rick Dean38a05c82009-07-18 01:41:30 -05001683
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001684 def test_invalid_digest_algorithm(self):
1685 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001686 :py:obj:`X509.digest` raises :py:obj:`ValueError` if called with an unrecognized hash
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001687 algorithm.
1688 """
1689 cert = X509()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001690 self.assertRaises(ValueError, cert.digest, BAD_DIGEST)
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001691
1692
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001693 def test_get_subject_wrong_args(self):
1694 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001695 :py:obj:`X509.get_subject` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001696 """
1697 cert = X509()
1698 self.assertRaises(TypeError, cert.get_subject, None)
1699
1700
1701 def test_get_subject(self):
1702 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001703 :py:obj:`X509.get_subject` returns an :py:obj:`X509Name` instance.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001704 """
1705 cert = load_certificate(FILETYPE_PEM, self.pemData)
1706 subj = cert.get_subject()
1707 self.assertTrue(isinstance(subj, X509Name))
1708 self.assertEquals(
1709 subj.get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001710 [(b('C'), b('US')), (b('ST'), b('IL')), (b('L'), b('Chicago')),
1711 (b('O'), b('Testing')), (b('CN'), b('Testing Root CA'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001712
1713
1714 def test_set_subject_wrong_args(self):
1715 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001716 :py:obj:`X509.set_subject` raises a :py:obj:`TypeError` if called with the wrong
1717 number of arguments or an argument not of type :py:obj:`X509Name`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001718 """
1719 cert = X509()
1720 self.assertRaises(TypeError, cert.set_subject)
1721 self.assertRaises(TypeError, cert.set_subject, None)
1722 self.assertRaises(TypeError, cert.set_subject, cert.get_subject(), None)
1723
1724
1725 def test_set_subject(self):
1726 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001727 :py:obj:`X509.set_subject` changes the subject of the certificate to the one
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001728 passed in.
1729 """
1730 cert = X509()
1731 name = cert.get_subject()
1732 name.C = 'AU'
1733 name.O = 'Unit Tests'
1734 cert.set_subject(name)
1735 self.assertEquals(
1736 cert.get_subject().get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001737 [(b('C'), b('AU')), (b('O'), b('Unit Tests'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001738
1739
1740 def test_get_issuer_wrong_args(self):
1741 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001742 :py:obj:`X509.get_issuer` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001743 """
1744 cert = X509()
1745 self.assertRaises(TypeError, cert.get_issuer, None)
1746
1747
1748 def test_get_issuer(self):
1749 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001750 :py:obj:`X509.get_issuer` returns an :py:obj:`X509Name` instance.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001751 """
1752 cert = load_certificate(FILETYPE_PEM, self.pemData)
1753 subj = cert.get_issuer()
1754 self.assertTrue(isinstance(subj, X509Name))
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001755 comp = subj.get_components()
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001756 self.assertEquals(
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001757 comp,
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001758 [(b('C'), b('US')), (b('ST'), b('IL')), (b('L'), b('Chicago')),
1759 (b('O'), b('Testing')), (b('CN'), b('Testing Root CA'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001760
1761
1762 def test_set_issuer_wrong_args(self):
1763 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001764 :py:obj:`X509.set_issuer` raises a :py:obj:`TypeError` if called with the wrong
1765 number of arguments or an argument not of type :py:obj:`X509Name`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001766 """
1767 cert = X509()
1768 self.assertRaises(TypeError, cert.set_issuer)
1769 self.assertRaises(TypeError, cert.set_issuer, None)
1770 self.assertRaises(TypeError, cert.set_issuer, cert.get_issuer(), None)
1771
1772
1773 def test_set_issuer(self):
1774 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001775 :py:obj:`X509.set_issuer` changes the issuer of the certificate to the one
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001776 passed in.
1777 """
1778 cert = X509()
1779 name = cert.get_issuer()
1780 name.C = 'AU'
1781 name.O = 'Unit Tests'
1782 cert.set_issuer(name)
1783 self.assertEquals(
1784 cert.get_issuer().get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001785 [(b('C'), b('AU')), (b('O'), b('Unit Tests'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001786
1787
1788 def test_get_pubkey_uninitialized(self):
1789 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001790 When called on a certificate with no public key, :py:obj:`X509.get_pubkey`
1791 raises :py:obj:`OpenSSL.crypto.Error`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001792 """
1793 cert = X509()
1794 self.assertRaises(Error, cert.get_pubkey)
1795
1796
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001797 def test_subject_name_hash_wrong_args(self):
1798 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001799 :py:obj:`X509.subject_name_hash` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001800 arguments.
1801 """
1802 cert = X509()
1803 self.assertRaises(TypeError, cert.subject_name_hash, None)
1804
1805
1806 def test_subject_name_hash(self):
1807 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001808 :py:obj:`X509.subject_name_hash` returns the hash of the certificate's subject
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001809 name.
1810 """
1811 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -04001812 self.assertIn(
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001813 cert.subject_name_hash(),
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -04001814 [3350047874, # OpenSSL 0.9.8, MD5
1815 3278919224, # OpenSSL 1.0.0, SHA1
1816 ])
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001817
1818
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001819 def test_get_signature_algorithm(self):
1820 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001821 :py:obj:`X509Type.get_signature_algorithm` returns a string which means
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001822 the algorithm used to sign the certificate.
1823 """
1824 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001825 self.assertEqual(
1826 b("sha1WithRSAEncryption"), cert.get_signature_algorithm())
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001827
1828
1829 def test_get_undefined_signature_algorithm(self):
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001830 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001831 :py:obj:`X509Type.get_signature_algorithm` raises :py:obj:`ValueError` if the
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001832 signature algorithm is undefined or unknown.
1833 """
1834 # This certificate has been modified to indicate a bogus OID in the
1835 # signature algorithm field so that OpenSSL does not recognize it.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001836 certPEM = b("""\
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001837-----BEGIN CERTIFICATE-----
1838MIIC/zCCAmigAwIBAgIBATAGBgJ8BQUAMHsxCzAJBgNVBAYTAlNHMREwDwYDVQQK
1839EwhNMkNyeXB0bzEUMBIGA1UECxMLTTJDcnlwdG8gQ0ExJDAiBgNVBAMTG00yQ3J5
1840cHRvIENlcnRpZmljYXRlIE1hc3RlcjEdMBsGCSqGSIb3DQEJARYObmdwc0Bwb3N0
1841MS5jb20wHhcNMDAwOTEwMDk1MTMwWhcNMDIwOTEwMDk1MTMwWjBTMQswCQYDVQQG
1842EwJTRzERMA8GA1UEChMITTJDcnlwdG8xEjAQBgNVBAMTCWxvY2FsaG9zdDEdMBsG
1843CSqGSIb3DQEJARYObmdwc0Bwb3N0MS5jb20wXDANBgkqhkiG9w0BAQEFAANLADBI
1844AkEArL57d26W9fNXvOhNlZzlPOACmvwOZ5AdNgLzJ1/MfsQQJ7hHVeHmTAjM664V
1845+fXvwUGJLziCeBo1ysWLRnl8CQIDAQABo4IBBDCCAQAwCQYDVR0TBAIwADAsBglg
1846hkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0O
1847BBYEFM+EgpK+eyZiwFU1aOPSbczbPSpVMIGlBgNVHSMEgZ0wgZqAFPuHI2nrnDqT
1848FeXFvylRT/7tKDgBoX+kfTB7MQswCQYDVQQGEwJTRzERMA8GA1UEChMITTJDcnlw
1849dG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtNMkNyeXB0byBDZXJ0
1850aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tggEA
1851MA0GCSqGSIb3DQEBBAUAA4GBADv8KpPo+gfJxN2ERK1Y1l17sz/ZhzoGgm5XCdbx
1852jEY7xKfpQngV599k1xhl11IMqizDwu0855agrckg2MCTmOI9DZzDD77tAYb+Dk0O
1853PEVk0Mk/V0aIsDE9bolfCi/i/QWZ3N8s5nTWMNyBBBmoSliWCm4jkkRZRD0ejgTN
1854tgI5
1855-----END CERTIFICATE-----
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001856""")
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001857 cert = load_certificate(FILETYPE_PEM, certPEM)
1858 self.assertRaises(ValueError, cert.get_signature_algorithm)
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001859
1860
Rick Dean38a05c82009-07-18 01:41:30 -05001861
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001862class X509StoreTests(TestCase):
1863 """
1864 Test for :py:obj:`OpenSSL.crypto.X509Store`.
1865 """
1866 def test_type(self):
1867 """
1868 :py:obj:`X509StoreType` is a type object.
1869 """
1870 self.assertIdentical(X509Store, X509StoreType)
1871 self.assertConsistentType(X509Store, 'X509Store')
1872
1873
1874 def test_add_cert_wrong_args(self):
1875 store = X509Store()
1876 self.assertRaises(TypeError, store.add_cert)
1877 self.assertRaises(TypeError, store.add_cert, object())
1878 self.assertRaises(TypeError, store.add_cert, X509(), object())
1879
1880
1881 def test_add_cert(self):
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001882 """
1883 :py:obj:`X509Store.add_cert` adds a :py:obj:`X509` instance to the
1884 certificate store.
1885 """
1886 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001887 store = X509Store()
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001888 store.add_cert(cert)
1889
1890
1891 def test_add_cert_rejects_duplicate(self):
1892 """
1893 :py:obj:`X509Store.add_cert` raises :py:obj:`OpenSSL.crypto.Error` if an
1894 attempt is made to add the same certificate to the store more than once.
1895 """
1896 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
1897 store = X509Store()
1898 store.add_cert(cert)
1899 self.assertRaises(Error, store.add_cert, cert)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001900
1901
1902
Rick Dean623ee362009-07-17 12:22:16 -05001903class PKCS12Tests(TestCase):
1904 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001905 Test for :py:obj:`OpenSSL.crypto.PKCS12` and :py:obj:`OpenSSL.crypto.load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001906 """
1907 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
1908
Jean-Paul Calderonec3a41f72009-07-25 12:36:02 -04001909 def test_type(self):
1910 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001911 :py:obj:`PKCS12Type` is a type object.
Jean-Paul Calderonec3a41f72009-07-25 12:36:02 -04001912 """
1913 self.assertIdentical(PKCS12, PKCS12Type)
1914 self.assertConsistentType(PKCS12, 'PKCS12')
1915
1916
Rick Deanf94096c2009-07-18 14:23:06 -05001917 def test_empty_construction(self):
Rick Dean38a05c82009-07-18 01:41:30 -05001918 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001919 :py:obj:`PKCS12` returns a new instance of :py:obj:`PKCS12` with no certificate,
Jean-Paul Calderonedc857b52009-07-25 12:25:07 -04001920 private key, CA certificates, or friendly name.
Rick Dean38a05c82009-07-18 01:41:30 -05001921 """
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001922 p12 = PKCS12()
Rick Dean623ee362009-07-17 12:22:16 -05001923 self.assertEqual(None, p12.get_certificate())
1924 self.assertEqual(None, p12.get_privatekey())
1925 self.assertEqual(None, p12.get_ca_certificates())
Rick Dean42d69e12009-07-20 11:36:08 -05001926 self.assertEqual(None, p12.get_friendlyname())
Rick Dean623ee362009-07-17 12:22:16 -05001927
Rick Dean38a05c82009-07-18 01:41:30 -05001928
Rick Dean623ee362009-07-17 12:22:16 -05001929 def test_type_errors(self):
Rick Dean38a05c82009-07-18 01:41:30 -05001930 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001931 The :py:obj:`PKCS12` setter functions (:py:obj:`set_certificate`, :py:obj:`set_privatekey`,
1932 :py:obj:`set_ca_certificates`, and :py:obj:`set_friendlyname`) raise :py:obj:`TypeError`
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001933 when passed objects of types other than those expected.
Rick Dean38a05c82009-07-18 01:41:30 -05001934 """
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001935 p12 = PKCS12()
Rick Dean623ee362009-07-17 12:22:16 -05001936 self.assertRaises(TypeError, p12.set_certificate, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05001937 self.assertRaises(TypeError, p12.set_certificate, PKey())
1938 self.assertRaises(TypeError, p12.set_certificate, X509)
Rick Dean623ee362009-07-17 12:22:16 -05001939 self.assertRaises(TypeError, p12.set_privatekey, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05001940 self.assertRaises(TypeError, p12.set_privatekey, 'legbone')
1941 self.assertRaises(TypeError, p12.set_privatekey, X509())
Rick Dean623ee362009-07-17 12:22:16 -05001942 self.assertRaises(TypeError, p12.set_ca_certificates, 3)
1943 self.assertRaises(TypeError, p12.set_ca_certificates, X509())
1944 self.assertRaises(TypeError, p12.set_ca_certificates, (3, 4))
Rick Deanf94096c2009-07-18 14:23:06 -05001945 self.assertRaises(TypeError, p12.set_ca_certificates, ( PKey(), ))
Rick Dean42d69e12009-07-20 11:36:08 -05001946 self.assertRaises(TypeError, p12.set_friendlyname, 6)
1947 self.assertRaises(TypeError, p12.set_friendlyname, ('foo', 'bar'))
Rick Dean623ee362009-07-17 12:22:16 -05001948
Rick Dean38a05c82009-07-18 01:41:30 -05001949
Rick Dean623ee362009-07-17 12:22:16 -05001950 def test_key_only(self):
1951 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001952 A :py:obj:`PKCS12` with only a private key can be exported using
1953 :py:obj:`PKCS12.export` and loaded again using :py:obj:`load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001954 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001955 passwd = b"blah"
Rick Dean623ee362009-07-17 12:22:16 -05001956 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001957 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001958 p12.set_privatekey(pkey)
Rick Dean623ee362009-07-17 12:22:16 -05001959 self.assertEqual(None, p12.get_certificate())
1960 self.assertEqual(pkey, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05001961 try:
1962 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
1963 except Error:
1964 # Some versions of OpenSSL will throw an exception
1965 # for this nearly useless PKCS12 we tried to generate:
1966 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
1967 return
Rick Dean623ee362009-07-17 12:22:16 -05001968 p12 = load_pkcs12(dumped_p12, passwd)
1969 self.assertEqual(None, p12.get_ca_certificates())
1970 self.assertEqual(None, p12.get_certificate())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001971
1972 # OpenSSL fails to bring the key back to us. So sad. Perhaps in the
1973 # future this will be improved.
1974 self.assertTrue(isinstance(p12.get_privatekey(), (PKey, type(None))))
Rick Dean623ee362009-07-17 12:22:16 -05001975
Rick Dean38a05c82009-07-18 01:41:30 -05001976
Rick Dean623ee362009-07-17 12:22:16 -05001977 def test_cert_only(self):
1978 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001979 A :py:obj:`PKCS12` with only a certificate can be exported using
1980 :py:obj:`PKCS12.export` and loaded again using :py:obj:`load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001981 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001982 passwd = b"blah"
Rick Dean623ee362009-07-17 12:22:16 -05001983 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001984 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001985 p12.set_certificate(cert)
Rick Dean623ee362009-07-17 12:22:16 -05001986 self.assertEqual(cert, p12.get_certificate())
1987 self.assertEqual(None, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05001988 try:
1989 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
1990 except Error:
1991 # Some versions of OpenSSL will throw an exception
1992 # for this nearly useless PKCS12 we tried to generate:
1993 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
1994 return
Rick Dean623ee362009-07-17 12:22:16 -05001995 p12 = load_pkcs12(dumped_p12, passwd)
1996 self.assertEqual(None, p12.get_privatekey())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001997
1998 # OpenSSL fails to bring the cert back to us. Groany mcgroan.
1999 self.assertTrue(isinstance(p12.get_certificate(), (X509, type(None))))
2000
2001 # Oh ho. It puts the certificate into the ca certificates list, in
2002 # fact. Totally bogus, I would think. Nevertheless, let's exploit
2003 # that to check to see if it reconstructed the certificate we expected
2004 # it to. At some point, hopefully this will change so that
2005 # p12.get_certificate() is actually what returns the loaded
2006 # certificate.
2007 self.assertEqual(
2008 cleartextCertificatePEM,
2009 dump_certificate(FILETYPE_PEM, p12.get_ca_certificates()[0]))
Rick Dean623ee362009-07-17 12:22:16 -05002010
2011
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002012 def gen_pkcs12(self, cert_pem=None, key_pem=None, ca_pem=None, friendly_name=None):
Rick Dean623ee362009-07-17 12:22:16 -05002013 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002014 Generate a PKCS12 object with components from PEM. Verify that the set
2015 functions return None.
Rick Dean623ee362009-07-17 12:22:16 -05002016 """
Rick Deanf94096c2009-07-18 14:23:06 -05002017 p12 = PKCS12()
2018 if cert_pem:
2019 ret = p12.set_certificate(load_certificate(FILETYPE_PEM, cert_pem))
2020 self.assertEqual(ret, None)
2021 if key_pem:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002022 ret = p12.set_privatekey(load_privatekey(FILETYPE_PEM, key_pem))
Rick Deanf94096c2009-07-18 14:23:06 -05002023 self.assertEqual(ret, None)
2024 if ca_pem:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002025 ret = p12.set_ca_certificates((load_certificate(FILETYPE_PEM, ca_pem),))
Rick Deanf94096c2009-07-18 14:23:06 -05002026 self.assertEqual(ret, None)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002027 if friendly_name:
2028 ret = p12.set_friendlyname(friendly_name)
Rick Dean42d69e12009-07-20 11:36:08 -05002029 self.assertEqual(ret, None)
Rick Deanf94096c2009-07-18 14:23:06 -05002030 return p12
2031
2032
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002033 def check_recovery(self, p12_str, key=None, cert=None, ca=None, passwd=b"",
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002034 extra=()):
Rick Deanf94096c2009-07-18 14:23:06 -05002035 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002036 Use openssl program to confirm three components are recoverable from a
2037 PKCS12 string.
Rick Deanf94096c2009-07-18 14:23:06 -05002038 """
2039 if key:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002040 recovered_key = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002041 p12_str, b"pkcs12", b"-nocerts", b"-nodes", b"-passin",
2042 b"pass:" + passwd, *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05002043 self.assertEqual(recovered_key[-len(key):], key)
2044 if cert:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002045 recovered_cert = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002046 p12_str, b"pkcs12", b"-clcerts", b"-nodes", b"-passin",
2047 b"pass:" + passwd, b"-nokeys", *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05002048 self.assertEqual(recovered_cert[-len(cert):], cert)
2049 if ca:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002050 recovered_cert = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002051 p12_str, b"pkcs12", b"-cacerts", b"-nodes", b"-passin",
2052 b"pass:" + passwd, b"-nokeys", *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05002053 self.assertEqual(recovered_cert[-len(ca):], ca)
2054
2055
Stephen Holsapple38482622014-04-05 20:29:34 -07002056 def verify_pkcs12_container(self, p12):
2057 """
2058 Verify that the PKCS#12 container contains the correct client
2059 certificate and private key.
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002060
2061 :param p12: The PKCS12 instance to verify.
2062 :type p12: :py:class:`PKCS12`
Stephen Holsapple38482622014-04-05 20:29:34 -07002063 """
2064 cert_pem = dump_certificate(FILETYPE_PEM, p12.get_certificate())
2065 key_pem = dump_privatekey(FILETYPE_PEM, p12.get_privatekey())
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002066 self.assertEqual(
2067 (client_cert_pem, client_key_pem, None),
2068 (cert_pem, key_pem, p12.get_ca_certificates()))
Stephen Holsapple38482622014-04-05 20:29:34 -07002069
2070
Rick Deanf94096c2009-07-18 14:23:06 -05002071 def test_load_pkcs12(self):
2072 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002073 A PKCS12 string generated using the openssl command line can be loaded
Jonathan Ballet648875f2011-07-16 14:14:58 +09002074 with :py:obj:`load_pkcs12` and its components extracted and examined.
Rick Deanf94096c2009-07-18 14:23:06 -05002075 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002076 passwd = b"whatever"
Rick Dean623ee362009-07-17 12:22:16 -05002077 pem = client_key_pem + client_cert_pem
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002078 p12_str = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002079 pem, b"pkcs12", b"-export", b"-clcerts", b"-passout", b"pass:" + passwd)
Stephen Holsapple38482622014-04-05 20:29:34 -07002080 p12 = load_pkcs12(p12_str, passphrase=passwd)
2081 self.verify_pkcs12_container(p12)
2082
2083
Abraham Martinc5484ba2015-03-25 15:33:05 +00002084 def test_load_pkcs12_text_passphrase(self):
2085 """
2086 A PKCS12 string generated using the openssl command line can be loaded
2087 with :py:obj:`load_pkcs12` and its components extracted and examined.
2088 Using text as passphrase instead of bytes. DeprecationWarning expected.
2089 """
2090 pem = client_key_pem + client_cert_pem
2091 passwd = b"whatever"
2092 p12_str = _runopenssl(pem, b"pkcs12", b"-export", b"-clcerts",
2093 b"-passout", b"pass:" + passwd)
2094 with catch_warnings(record=True) as w:
2095 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002096 p12 = load_pkcs12(p12_str, passphrase=b"whatever".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002097
2098 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002099 "{0} for passphrase is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002100 WARNING_TYPE_EXPECTED
2101 ),
2102 str(w[-1].message)
2103 )
2104 self.assertIs(w[-1].category, DeprecationWarning)
2105
Abraham Martinc5484ba2015-03-25 15:33:05 +00002106 self.verify_pkcs12_container(p12)
2107
2108
Stephen Holsapple38482622014-04-05 20:29:34 -07002109 def test_load_pkcs12_no_passphrase(self):
2110 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002111 A PKCS12 string generated using openssl command line can be loaded with
2112 :py:obj:`load_pkcs12` without a passphrase and its components extracted
2113 and examined.
Stephen Holsapple38482622014-04-05 20:29:34 -07002114 """
2115 pem = client_key_pem + client_cert_pem
2116 p12_str = _runopenssl(
2117 pem, b"pkcs12", b"-export", b"-clcerts", b"-passout", b"pass:")
2118 p12 = load_pkcs12(p12_str)
2119 self.verify_pkcs12_container(p12)
2120
2121
2122 def _dump_and_load(self, dump_passphrase, load_passphrase):
2123 """
2124 A helper method to dump and load a PKCS12 object.
2125 """
2126 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem)
2127 dumped_p12 = p12.export(passphrase=dump_passphrase, iter=2, maciter=3)
2128 return load_pkcs12(dumped_p12, passphrase=load_passphrase)
2129
2130
2131 def test_load_pkcs12_null_passphrase_load_empty(self):
2132 """
2133 A PKCS12 string can be dumped with a null passphrase, loaded with an
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002134 empty passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002135 extracted and examined.
2136 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002137 self.verify_pkcs12_container(
2138 self._dump_and_load(dump_passphrase=None, load_passphrase=b''))
Stephen Holsapple38482622014-04-05 20:29:34 -07002139
2140
2141 def test_load_pkcs12_null_passphrase_load_null(self):
2142 """
2143 A PKCS12 string can be dumped with a null passphrase, loaded with a
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002144 null passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002145 extracted and examined.
2146 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002147 self.verify_pkcs12_container(
2148 self._dump_and_load(dump_passphrase=None, load_passphrase=None))
Stephen Holsapple38482622014-04-05 20:29:34 -07002149
2150
2151 def test_load_pkcs12_empty_passphrase_load_empty(self):
2152 """
2153 A PKCS12 string can be dumped with an empty passphrase, loaded with an
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002154 empty passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002155 extracted and examined.
2156 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002157 self.verify_pkcs12_container(
2158 self._dump_and_load(dump_passphrase=b'', load_passphrase=b''))
Stephen Holsapple38482622014-04-05 20:29:34 -07002159
2160
2161 def test_load_pkcs12_empty_passphrase_load_null(self):
2162 """
2163 A PKCS12 string can be dumped with an empty passphrase, loaded with a
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002164 null passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002165 extracted and examined.
2166 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002167 self.verify_pkcs12_container(
2168 self._dump_and_load(dump_passphrase=b'', load_passphrase=None))
Rick Deanf94096c2009-07-18 14:23:06 -05002169
Rick Deanee568302009-07-24 09:56:29 -05002170
2171 def test_load_pkcs12_garbage(self):
2172 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002173 :py:obj:`load_pkcs12` raises :py:obj:`OpenSSL.crypto.Error` when passed a string
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002174 which is not a PKCS12 dump.
Rick Deanee568302009-07-24 09:56:29 -05002175 """
2176 passwd = 'whatever'
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002177 e = self.assertRaises(Error, load_pkcs12, b'fruit loops', passwd)
Jean-Paul Calderonede075462014-01-18 10:34:12 -05002178 self.assertEqual( e.args[0][0][0], 'asn1 encoding routines')
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -04002179 self.assertEqual( len(e.args[0][0]), 3)
Rick Deanee568302009-07-24 09:56:29 -05002180
2181
Rick Deanf94096c2009-07-18 14:23:06 -05002182 def test_replace(self):
2183 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002184 :py:obj:`PKCS12.set_certificate` replaces the certificate in a PKCS12 cluster.
2185 :py:obj:`PKCS12.set_privatekey` replaces the private key.
2186 :py:obj:`PKCS12.set_ca_certificates` replaces the CA certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05002187 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002188 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
2189 p12.set_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2190 p12.set_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002191 root_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05002192 client_cert = load_certificate(FILETYPE_PEM, client_cert_pem)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002193 p12.set_ca_certificates([root_cert]) # not a tuple
Rick Dean623ee362009-07-17 12:22:16 -05002194 self.assertEqual(1, len(p12.get_ca_certificates()))
2195 self.assertEqual(root_cert, p12.get_ca_certificates()[0])
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002196 p12.set_ca_certificates([client_cert, root_cert])
Rick Deanf94096c2009-07-18 14:23:06 -05002197 self.assertEqual(2, len(p12.get_ca_certificates()))
2198 self.assertEqual(client_cert, p12.get_ca_certificates()[0])
2199 self.assertEqual(root_cert, p12.get_ca_certificates()[1])
2200
2201
2202 def test_friendly_name(self):
2203 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002204 The *friendlyName* of a PKCS12 can be set and retrieved via
Jonathan Ballet648875f2011-07-16 14:14:58 +09002205 :py:obj:`PKCS12.get_friendlyname` and :py:obj:`PKCS12_set_friendlyname`, and a
2206 :py:obj:`PKCS12` with a friendly name set can be dumped with :py:obj:`PKCS12.export`.
Rick Deanf94096c2009-07-18 14:23:06 -05002207 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002208 passwd = b'Dogmeat[]{}!@#$%^&*()~`?/.,<>-_+=";:'
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002209 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -04002210 for friendly_name in [b('Serverlicious'), None, b('###')]:
Rick Dean42d69e12009-07-20 11:36:08 -05002211 p12.set_friendlyname(friendly_name)
2212 self.assertEqual(p12.get_friendlyname(), friendly_name)
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002213 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
Rick Dean42d69e12009-07-20 11:36:08 -05002214 reloaded_p12 = load_pkcs12(dumped_p12, passwd)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002215 self.assertEqual(
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -04002216 p12.get_friendlyname(), reloaded_p12.get_friendlyname())
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002217 # We would use the openssl program to confirm the friendly
2218 # name, but it is not possible. The pkcs12 command
2219 # does not store the friendly name in the cert's
Rick Dean42d69e12009-07-20 11:36:08 -05002220 # alias, which we could then extract.
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002221 self.check_recovery(
2222 dumped_p12, key=server_key_pem, cert=server_cert_pem,
2223 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05002224
2225
2226 def test_various_empty_passphrases(self):
2227 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002228 Test that missing, None, and '' passphrases are identical for PKCS12
2229 export.
Rick Deanf94096c2009-07-18 14:23:06 -05002230 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002231 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002232 passwd = b""
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002233 dumped_p12_empty = p12.export(iter=2, maciter=0, passphrase=passwd)
2234 dumped_p12_none = p12.export(iter=3, maciter=2, passphrase=None)
2235 dumped_p12_nopw = p12.export(iter=9, maciter=4)
2236 for dumped_p12 in [dumped_p12_empty, dumped_p12_none, dumped_p12_nopw]:
2237 self.check_recovery(
2238 dumped_p12, key=client_key_pem, cert=client_cert_pem,
2239 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05002240
2241
2242 def test_removing_ca_cert(self):
2243 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002244 Passing :py:obj:`None` to :py:obj:`PKCS12.set_ca_certificates` removes all CA
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002245 certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05002246 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002247 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
2248 p12.set_ca_certificates(None)
Rick Dean623ee362009-07-17 12:22:16 -05002249 self.assertEqual(None, p12.get_ca_certificates())
Rick Deanf94096c2009-07-18 14:23:06 -05002250
2251
2252 def test_export_without_mac(self):
2253 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002254 Exporting a PKCS12 with a :py:obj:`maciter` of ``-1`` excludes the MAC
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002255 entirely.
Rick Deanf94096c2009-07-18 14:23:06 -05002256 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002257 passwd = b"Lake Michigan"
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002258 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Dean623ee362009-07-17 12:22:16 -05002259 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002260 self.check_recovery(
2261 dumped_p12, key=server_key_pem, cert=server_cert_pem,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002262 passwd=passwd, extra=(b"-nomacver",))
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002263
2264
2265 def test_load_without_mac(self):
2266 """
2267 Loading a PKCS12 without a MAC does something other than crash.
2268 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002269 passwd = b"Lake Michigan"
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002270 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
2271 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Rick Dean321a0512009-08-13 17:21:29 -05002272 try:
2273 recovered_p12 = load_pkcs12(dumped_p12, passwd)
2274 # The person who generated this PCKS12 should be flogged,
2275 # or better yet we should have a means to determine
2276 # whether a PCKS12 had a MAC that was verified.
2277 # Anyway, libopenssl chooses to allow it, so the
2278 # pyopenssl binding does as well.
2279 self.assertTrue(isinstance(recovered_p12, PKCS12))
2280 except Error:
2281 # Failing here with an exception is preferred as some openssl
2282 # versions do.
2283 pass
Rick Dean623ee362009-07-17 12:22:16 -05002284
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002285
Rick Dean25bcc1f2009-07-20 11:53:13 -05002286 def test_zero_len_list_for_ca(self):
2287 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002288 A PKCS12 with an empty CA certificates list can be exported.
Rick Dean25bcc1f2009-07-20 11:53:13 -05002289 """
2290 passwd = 'Hobie 18'
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002291 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002292 # p12.set_ca_certificates([])
2293 # self.assertEqual((), p12.get_ca_certificates())
2294 # dumped_p12 = p12.export(passphrase=passwd, iter=3)
2295 # self.check_recovery(
2296 # dumped_p12, key=server_key_pem, cert=server_cert_pem,
2297 # passwd=passwd)
Rick Dean25bcc1f2009-07-20 11:53:13 -05002298
2299
Rick Deanf94096c2009-07-18 14:23:06 -05002300 def test_export_without_args(self):
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002301 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002302 All the arguments to :py:obj:`PKCS12.export` are optional.
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002303 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002304 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05002305 dumped_p12 = p12.export() # no args
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002306 self.check_recovery(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002307 dumped_p12, key=server_key_pem, cert=server_cert_pem, passwd=b"")
Rick Deanf94096c2009-07-18 14:23:06 -05002308
2309
Abraham Martinc5484ba2015-03-25 15:33:05 +00002310 def test_export_without_bytes(self):
2311 """
2312 Test :py:obj:`PKCS12.export` with text not bytes as passphrase
2313 """
2314 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
2315
2316 with catch_warnings(record=True) as w:
2317 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002318 dumped_p12 = p12.export(passphrase=b"randomtext".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002319 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002320 "{0} for passphrase is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002321 WARNING_TYPE_EXPECTED
2322 ),
2323 str(w[-1].message)
2324 )
2325 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinc5484ba2015-03-25 15:33:05 +00002326 self.check_recovery(
2327 dumped_p12, key=server_key_pem, cert=server_cert_pem, passwd=b"randomtext")
2328
2329
Rick Deanf94096c2009-07-18 14:23:06 -05002330 def test_key_cert_mismatch(self):
2331 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002332 :py:obj:`PKCS12.export` raises an exception when a key and certificate
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002333 mismatch.
Rick Deanf94096c2009-07-18 14:23:06 -05002334 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002335 p12 = self.gen_pkcs12(server_cert_pem, client_key_pem, root_cert_pem)
2336 self.assertRaises(Error, p12.export)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002337
2338
2339
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002340# These quoting functions taken directly from Twisted's twisted.python.win32.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002341_cmdLineQuoteRe = re.compile(br'(\\*)"')
2342_cmdLineQuoteRe2 = re.compile(br'(\\+)\Z')
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002343def cmdLineQuote(s):
2344 """
2345 Internal method for quoting a single command-line argument.
2346
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002347 See http://www.perlmonks.org/?node_id=764004
2348
Jonathan Ballet648875f2011-07-16 14:14:58 +09002349 :type: :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002350 :param s: A single unquoted string to quote for something that is expecting
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002351 cmd.exe-style quoting
2352
Jonathan Ballet648875f2011-07-16 14:14:58 +09002353 :rtype: :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002354 :return: A cmd.exe-style quoted string
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002355 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002356 s = _cmdLineQuoteRe2.sub(br"\1\1", _cmdLineQuoteRe.sub(br'\1\1\\"', s))
2357 return b'"' + s + b'"'
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002358
2359
2360
2361def quoteArguments(arguments):
2362 """
2363 Quote an iterable of command-line arguments for passing to CreateProcess or
Jonathan Ballet648875f2011-07-16 14:14:58 +09002364 a similar API. This allows the list passed to :py:obj:`reactor.spawnProcess` to
2365 match the child process's :py:obj:`sys.argv` properly.
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002366
Jonathan Ballet648875f2011-07-16 14:14:58 +09002367 :type arguments: :py:obj:`iterable` of :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002368 :param arguments: An iterable of unquoted arguments to quote
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002369
Jonathan Ballet648875f2011-07-16 14:14:58 +09002370 :rtype: :py:obj:`str`
2371 :return: A space-delimited string containing quoted versions of :py:obj:`arguments`
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002372 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002373 return b' '.join(map(cmdLineQuote, arguments))
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002374
2375
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002376
Rick Dean4c9ad612009-07-17 15:05:22 -05002377def _runopenssl(pem, *args):
2378 """
2379 Run the command line openssl tool with the given arguments and write
Rick Dean55d1ce62009-08-13 17:40:24 -05002380 the given PEM to its stdin. Not safe for quotes.
Rick Dean4c9ad612009-07-17 15:05:22 -05002381 """
Jean-Paul Calderone038de952009-08-21 12:16:06 -04002382 if os.name == 'posix':
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002383 command = b"openssl " + b" ".join([
2384 (b"'" + arg.replace(b"'", b"'\\''") + b"'")
2385 for arg in args])
Rick Dean55d1ce62009-08-13 17:40:24 -05002386 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002387 command = b"openssl " + quoteArguments(args)
2388 proc = Popen(native(command), shell=True, stdin=PIPE, stdout=PIPE)
Jean-Paul Calderone62ca8da2010-08-11 19:58:08 -04002389 proc.stdin.write(pem)
2390 proc.stdin.close()
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002391 output = proc.stdout.read()
2392 proc.stdout.close()
2393 proc.wait()
2394 return output
Rick Dean4c9ad612009-07-17 15:05:22 -05002395
2396
2397
Jean-Paul Calderone18808652009-07-05 12:54:05 -04002398class FunctionTests(TestCase):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002399 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002400 Tests for free-functions in the :py:obj:`OpenSSL.crypto` module.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002401 """
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002402
2403 def test_load_privatekey_invalid_format(self):
2404 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002405 :py:obj:`load_privatekey` raises :py:obj:`ValueError` if passed an unknown filetype.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002406 """
2407 self.assertRaises(ValueError, load_privatekey, 100, root_key_pem)
2408
2409
2410 def test_load_privatekey_invalid_passphrase_type(self):
2411 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002412 :py:obj:`load_privatekey` raises :py:obj:`TypeError` if passed a passphrase that is
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002413 neither a :py:obj:`str` nor a callable.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002414 """
2415 self.assertRaises(
2416 TypeError,
2417 load_privatekey,
2418 FILETYPE_PEM, encryptedPrivateKeyPEMPassphrase, object())
2419
2420
2421 def test_load_privatekey_wrong_args(self):
2422 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002423 :py:obj:`load_privatekey` raises :py:obj:`TypeError` if called with the wrong number
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002424 of arguments.
2425 """
2426 self.assertRaises(TypeError, load_privatekey)
2427
2428
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002429 def test_load_privatekey_wrongPassphrase(self):
2430 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002431 :py:obj:`load_privatekey` raises :py:obj:`OpenSSL.crypto.Error` when it is passed an
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002432 encrypted PEM and an incorrect passphrase.
2433 """
2434 self.assertRaises(
2435 Error,
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002436 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, b("quack"))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002437
2438
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002439 def test_load_privatekey_passphraseWrongType(self):
2440 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002441 :py:obj:`load_privatekey` raises :py:obj:`ValueError` when it is passed a passphrase
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002442 with a private key encoded in a format, that doesn't support
2443 encryption.
2444 """
2445 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2446 blob = dump_privatekey(FILETYPE_ASN1, key)
2447 self.assertRaises(ValueError,
2448 load_privatekey, FILETYPE_ASN1, blob, "secret")
2449
2450
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002451 def test_load_privatekey_passphrase(self):
2452 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002453 :py:obj:`load_privatekey` can create a :py:obj:`PKey` object from an encrypted PEM
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002454 string if given the passphrase.
2455 """
2456 key = load_privatekey(
2457 FILETYPE_PEM, encryptedPrivateKeyPEM,
2458 encryptedPrivateKeyPEMPassphrase)
2459 self.assertTrue(isinstance(key, PKeyType))
2460
2461
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002462 def test_load_privatekey_passphrase_exception(self):
2463 """
2464 If the passphrase callback raises an exception, that exception is raised
2465 by :py:obj:`load_privatekey`.
2466 """
2467 def cb(ignored):
2468 raise ArithmeticError
2469
2470 self.assertRaises(ArithmeticError,
2471 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2472
2473
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002474 def test_load_privatekey_wrongPassphraseCallback(self):
2475 """
Jean-Paul Calderoned440a082011-09-14 11:02:05 -04002476 :py:obj:`load_privatekey` raises :py:obj:`OpenSSL.crypto.Error` when it
2477 is passed an encrypted PEM and a passphrase callback which returns an
2478 incorrect passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002479 """
2480 called = []
2481 def cb(*a):
2482 called.append(None)
Jean-Paul Calderoned440a082011-09-14 11:02:05 -04002483 return b("quack")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002484 self.assertRaises(
2485 Error,
2486 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2487 self.assertTrue(called)
2488
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002489
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002490 def test_load_privatekey_passphraseCallback(self):
2491 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002492 :py:obj:`load_privatekey` can create a :py:obj:`PKey` object from an encrypted PEM
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002493 string if given a passphrase callback which returns the correct
2494 password.
2495 """
2496 called = []
2497 def cb(writing):
2498 called.append(writing)
2499 return encryptedPrivateKeyPEMPassphrase
2500 key = load_privatekey(FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2501 self.assertTrue(isinstance(key, PKeyType))
2502 self.assertEqual(called, [False])
2503
2504
Jean-Paul Calderone105cb952011-09-14 10:16:46 -04002505 def test_load_privatekey_passphrase_wrong_return_type(self):
2506 """
2507 :py:obj:`load_privatekey` raises :py:obj:`ValueError` if the passphrase
2508 callback returns something other than a byte string.
2509 """
2510 self.assertRaises(
2511 ValueError,
2512 load_privatekey,
2513 FILETYPE_PEM, encryptedPrivateKeyPEM, lambda *args: 3)
2514
2515
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002516 def test_dump_privatekey_wrong_args(self):
2517 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002518 :py:obj:`dump_privatekey` raises :py:obj:`TypeError` if called with the wrong number
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002519 of arguments.
2520 """
2521 self.assertRaises(TypeError, dump_privatekey)
Jean-Paul Calderone1eeccd82011-09-14 10:18:52 -04002522 # If cipher name is given, password is required.
2523 self.assertRaises(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002524 TypeError, dump_privatekey, FILETYPE_PEM, PKey(), GOOD_CIPHER)
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002525
2526
2527 def test_dump_privatekey_unknown_cipher(self):
2528 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002529 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` if called with an unrecognized
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002530 cipher name.
2531 """
2532 key = PKey()
2533 key.generate_key(TYPE_RSA, 512)
2534 self.assertRaises(
2535 ValueError, dump_privatekey,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002536 FILETYPE_PEM, key, BAD_CIPHER, "passphrase")
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002537
2538
2539 def test_dump_privatekey_invalid_passphrase_type(self):
2540 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002541 :py:obj:`dump_privatekey` raises :py:obj:`TypeError` if called with a passphrase which
2542 is neither a :py:obj:`str` nor a callable.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002543 """
2544 key = PKey()
2545 key.generate_key(TYPE_RSA, 512)
2546 self.assertRaises(
2547 TypeError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002548 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, object())
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002549
2550
2551 def test_dump_privatekey_invalid_filetype(self):
2552 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002553 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` if called with an unrecognized
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002554 filetype.
2555 """
2556 key = PKey()
2557 key.generate_key(TYPE_RSA, 512)
2558 self.assertRaises(ValueError, dump_privatekey, 100, key)
2559
2560
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002561 def test_load_privatekey_passphraseCallbackLength(self):
2562 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002563 :py:obj:`crypto.load_privatekey` should raise an error when the passphrase
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002564 provided by the callback is too long, not silently truncate it.
2565 """
2566 def cb(ignored):
2567 return "a" * 1025
2568
2569 self.assertRaises(ValueError,
2570 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2571
2572
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002573 def test_dump_privatekey_passphrase(self):
2574 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002575 :py:obj:`dump_privatekey` writes an encrypted PEM when given a passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002576 """
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002577 passphrase = b("foo")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002578 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002579 pem = dump_privatekey(FILETYPE_PEM, key, GOOD_CIPHER, passphrase)
2580 self.assertTrue(isinstance(pem, binary_type))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002581 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
2582 self.assertTrue(isinstance(loadedKey, PKeyType))
2583 self.assertEqual(loadedKey.type(), key.type())
2584 self.assertEqual(loadedKey.bits(), key.bits())
2585
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002586
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002587 def test_dump_privatekey_passphraseWrongType(self):
2588 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002589 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` when it is passed a passphrase
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002590 with a private key encoded in a format, that doesn't support
2591 encryption.
2592 """
2593 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2594 self.assertRaises(ValueError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002595 dump_privatekey, FILETYPE_ASN1, key, GOOD_CIPHER, "secret")
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002596
2597
Rick Dean5b7b6372009-04-01 11:34:06 -05002598 def test_dump_certificate(self):
2599 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002600 :py:obj:`dump_certificate` writes PEM, DER, and text.
Rick Dean5b7b6372009-04-01 11:34:06 -05002601 """
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002602 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
Rick Dean5b7b6372009-04-01 11:34:06 -05002603 cert = load_certificate(FILETYPE_PEM, pemData)
2604 dumped_pem = dump_certificate(FILETYPE_PEM, cert)
2605 self.assertEqual(dumped_pem, cleartextCertificatePEM)
2606 dumped_der = dump_certificate(FILETYPE_ASN1, cert)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002607 good_der = _runopenssl(dumped_pem, b"x509", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002608 self.assertEqual(dumped_der, good_der)
2609 cert2 = load_certificate(FILETYPE_ASN1, dumped_der)
2610 dumped_pem2 = dump_certificate(FILETYPE_PEM, cert2)
2611 self.assertEqual(dumped_pem2, cleartextCertificatePEM)
2612 dumped_text = dump_certificate(FILETYPE_TEXT, cert)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002613 good_text = _runopenssl(dumped_pem, b"x509", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002614 self.assertEqual(dumped_text, good_text)
2615
2616
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002617 def test_dump_privatekey_pem(self):
Rick Dean5b7b6372009-04-01 11:34:06 -05002618 """
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002619 :py:obj:`dump_privatekey` writes a PEM
Rick Dean5b7b6372009-04-01 11:34:06 -05002620 """
2621 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -04002622 self.assertTrue(key.check())
Rick Dean5b7b6372009-04-01 11:34:06 -05002623 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2624 self.assertEqual(dumped_pem, cleartextPrivateKeyPEM)
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002625
2626
2627 def test_dump_privatekey_asn1(self):
2628 """
2629 :py:obj:`dump_privatekey` writes a DER
2630 """
2631 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2632 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2633
Rick Dean5b7b6372009-04-01 11:34:06 -05002634 dumped_der = dump_privatekey(FILETYPE_ASN1, key)
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002635 # XXX This OpenSSL call writes "writing RSA key" to standard out. Sad.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002636 good_der = _runopenssl(dumped_pem, b"rsa", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002637 self.assertEqual(dumped_der, good_der)
2638 key2 = load_privatekey(FILETYPE_ASN1, dumped_der)
2639 dumped_pem2 = dump_privatekey(FILETYPE_PEM, key2)
2640 self.assertEqual(dumped_pem2, cleartextPrivateKeyPEM)
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002641
2642
2643 def test_dump_privatekey_text(self):
2644 """
2645 :py:obj:`dump_privatekey` writes a text
2646 """
2647 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2648 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2649
Rick Dean5b7b6372009-04-01 11:34:06 -05002650 dumped_text = dump_privatekey(FILETYPE_TEXT, key)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002651 good_text = _runopenssl(dumped_pem, b"rsa", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002652 self.assertEqual(dumped_text, good_text)
2653
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002654
Rick Dean5b7b6372009-04-01 11:34:06 -05002655 def test_dump_certificate_request(self):
2656 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002657 :py:obj:`dump_certificate_request` writes a PEM, DER, and text.
Rick Dean5b7b6372009-04-01 11:34:06 -05002658 """
2659 req = load_certificate_request(FILETYPE_PEM, cleartextCertificateRequestPEM)
2660 dumped_pem = dump_certificate_request(FILETYPE_PEM, req)
2661 self.assertEqual(dumped_pem, cleartextCertificateRequestPEM)
2662 dumped_der = dump_certificate_request(FILETYPE_ASN1, req)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002663 good_der = _runopenssl(dumped_pem, b"req", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002664 self.assertEqual(dumped_der, good_der)
2665 req2 = load_certificate_request(FILETYPE_ASN1, dumped_der)
2666 dumped_pem2 = dump_certificate_request(FILETYPE_PEM, req2)
2667 self.assertEqual(dumped_pem2, cleartextCertificateRequestPEM)
2668 dumped_text = dump_certificate_request(FILETYPE_TEXT, req)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002669 good_text = _runopenssl(dumped_pem, b"req", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002670 self.assertEqual(dumped_text, good_text)
Jean-Paul Calderoneaf43cdf2010-08-03 18:40:52 -04002671 self.assertRaises(ValueError, dump_certificate_request, 100, req)
Rick Dean5b7b6372009-04-01 11:34:06 -05002672
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002673
2674 def test_dump_privatekey_passphraseCallback(self):
2675 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002676 :py:obj:`dump_privatekey` writes an encrypted PEM when given a callback which
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002677 returns the correct passphrase.
2678 """
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002679 passphrase = b("foo")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002680 called = []
2681 def cb(writing):
2682 called.append(writing)
2683 return passphrase
2684 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002685 pem = dump_privatekey(FILETYPE_PEM, key, GOOD_CIPHER, cb)
2686 self.assertTrue(isinstance(pem, binary_type))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002687 self.assertEqual(called, [True])
2688 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
2689 self.assertTrue(isinstance(loadedKey, PKeyType))
2690 self.assertEqual(loadedKey.type(), key.type())
2691 self.assertEqual(loadedKey.bits(), key.bits())
Rick Dean5b7b6372009-04-01 11:34:06 -05002692
2693
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002694 def test_dump_privatekey_passphrase_exception(self):
2695 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002696 :py:obj:`dump_privatekey` should not overwrite the exception raised
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002697 by the passphrase callback.
2698 """
2699 def cb(ignored):
2700 raise ArithmeticError
2701
2702 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2703 self.assertRaises(ArithmeticError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002704 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, cb)
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002705
2706
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002707 def test_dump_privatekey_passphraseCallbackLength(self):
2708 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002709 :py:obj:`crypto.dump_privatekey` should raise an error when the passphrase
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002710 provided by the callback is too long, not silently truncate it.
2711 """
2712 def cb(ignored):
2713 return "a" * 1025
2714
2715 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2716 self.assertRaises(ValueError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002717 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, cb)
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002718
2719
Alex Gaynor4b9c96a2014-08-14 09:51:48 -07002720 def test_load_pkcs7_data_pem(self):
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002721 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002722 :py:obj:`load_pkcs7_data` accepts a PKCS#7 string and returns an instance of
2723 :py:obj:`PKCS7Type`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002724 """
2725 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2726 self.assertTrue(isinstance(pkcs7, PKCS7Type))
2727
2728
Alex Gaynor4b9c96a2014-08-14 09:51:48 -07002729 def test_load_pkcs7_data_asn1(self):
Alex Gaynor9875a912014-08-14 13:35:05 -07002730 """
2731 :py:obj:`load_pkcs7_data` accepts a bytes containing ASN1 data
2732 representing PKCS#7 and returns an instance of :py:obj`PKCS7Type`.
2733 """
Alex Gaynor4b9c96a2014-08-14 09:51:48 -07002734 pkcs7 = load_pkcs7_data(FILETYPE_ASN1, pkcs7DataASN1)
2735 self.assertTrue(isinstance(pkcs7, PKCS7Type))
2736
2737
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002738 def test_load_pkcs7_data_invalid(self):
2739 """
2740 If the data passed to :py:obj:`load_pkcs7_data` is invalid,
2741 :py:obj:`Error` is raised.
2742 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002743 self.assertRaises(Error, load_pkcs7_data, FILETYPE_PEM, b"foo")
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002744
2745
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002746
Jean-Paul Calderone4a68b402013-12-29 16:54:58 -05002747class LoadCertificateTests(TestCase):
2748 """
2749 Tests for :py:obj:`load_certificate_request`.
2750 """
2751 def test_badFileType(self):
2752 """
2753 If the file type passed to :py:obj:`load_certificate_request` is
2754 neither :py:obj:`FILETYPE_PEM` nor :py:obj:`FILETYPE_ASN1` then
2755 :py:class:`ValueError` is raised.
2756 """
2757 self.assertRaises(ValueError, load_certificate_request, object(), b"")
2758
2759
2760
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002761class PKCS7Tests(TestCase):
2762 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002763 Tests for :py:obj:`PKCS7Type`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002764 """
2765 def test_type(self):
2766 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002767 :py:obj:`PKCS7Type` is a type object.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002768 """
2769 self.assertTrue(isinstance(PKCS7Type, type))
2770 self.assertEqual(PKCS7Type.__name__, 'PKCS7')
2771
2772 # XXX This doesn't currently work.
2773 # self.assertIdentical(PKCS7, PKCS7Type)
2774
2775
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002776 # XXX Opposite results for all these following methods
2777
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002778 def test_type_is_signed_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002779 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002780 :py:obj:`PKCS7Type.type_is_signed` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002781 arguments.
2782 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002783 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2784 self.assertRaises(TypeError, pkcs7.type_is_signed, None)
2785
2786
2787 def test_type_is_signed(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002788 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002789 :py:obj:`PKCS7Type.type_is_signed` returns :py:obj:`True` if the PKCS7 object is of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002790 the type *signed*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002791 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002792 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2793 self.assertTrue(pkcs7.type_is_signed())
2794
2795
2796 def test_type_is_enveloped_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002797 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002798 :py:obj:`PKCS7Type.type_is_enveloped` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002799 arguments.
2800 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002801 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2802 self.assertRaises(TypeError, pkcs7.type_is_enveloped, None)
2803
2804
2805 def test_type_is_enveloped(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002806 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002807 :py:obj:`PKCS7Type.type_is_enveloped` returns :py:obj:`False` if the PKCS7 object is
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002808 not of the type *enveloped*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002809 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002810 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2811 self.assertFalse(pkcs7.type_is_enveloped())
2812
2813
2814 def test_type_is_signedAndEnveloped_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002815 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002816 :py:obj:`PKCS7Type.type_is_signedAndEnveloped` raises :py:obj:`TypeError` if called
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002817 with any arguments.
2818 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002819 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2820 self.assertRaises(TypeError, pkcs7.type_is_signedAndEnveloped, None)
2821
2822
2823 def test_type_is_signedAndEnveloped(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002824 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002825 :py:obj:`PKCS7Type.type_is_signedAndEnveloped` returns :py:obj:`False` if the PKCS7
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002826 object is not of the type *signed and enveloped*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002827 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002828 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2829 self.assertFalse(pkcs7.type_is_signedAndEnveloped())
2830
2831
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002832 def test_type_is_data(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002833 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002834 :py:obj:`PKCS7Type.type_is_data` returns :py:obj:`False` if the PKCS7 object is not of
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002835 the type data.
2836 """
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002837 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2838 self.assertFalse(pkcs7.type_is_data())
2839
2840
2841 def test_type_is_data_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002842 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002843 :py:obj:`PKCS7Type.type_is_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002844 arguments.
2845 """
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002846 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2847 self.assertRaises(TypeError, pkcs7.type_is_data, None)
2848
2849
Jean-Paul Calderone97b28ca2010-07-30 10:56:07 -04002850 def test_get_type_name_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002851 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002852 :py:obj:`PKCS7Type.get_type_name` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002853 arguments.
2854 """
Jean-Paul Calderone97b28ca2010-07-30 10:56:07 -04002855 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2856 self.assertRaises(TypeError, pkcs7.get_type_name, None)
2857
2858
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002859 def test_get_type_name(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002860 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002861 :py:obj:`PKCS7Type.get_type_name` returns a :py:obj:`str` giving the type name.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002862 """
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002863 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
Jean-Paul Calderone07640f12010-08-22 17:14:43 -04002864 self.assertEquals(pkcs7.get_type_name(), b('pkcs7-signedData'))
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002865
2866
2867 def test_attribute(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002868 """
2869 If an attribute other than one of the methods tested here is accessed on
Jonathan Ballet648875f2011-07-16 14:14:58 +09002870 an instance of :py:obj:`PKCS7Type`, :py:obj:`AttributeError` is raised.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002871 """
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002872 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2873 self.assertRaises(AttributeError, getattr, pkcs7, "foo")
2874
2875
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002876
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002877class NetscapeSPKITests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002878 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002879 Tests for :py:obj:`OpenSSL.crypto.NetscapeSPKI`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002880 """
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002881 def signable(self):
2882 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002883 Return a new :py:obj:`NetscapeSPKI` for use with signing tests.
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002884 """
2885 return NetscapeSPKI()
2886
2887
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002888 def test_type(self):
2889 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002890 :py:obj:`NetscapeSPKI` and :py:obj:`NetscapeSPKIType` refer to the same type object
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002891 and can be used to create instances of that type.
2892 """
2893 self.assertIdentical(NetscapeSPKI, NetscapeSPKIType)
2894 self.assertConsistentType(NetscapeSPKI, 'NetscapeSPKI')
2895
2896
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002897 def test_construction(self):
2898 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002899 :py:obj:`NetscapeSPKI` returns an instance of :py:obj:`NetscapeSPKIType`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002900 """
2901 nspki = NetscapeSPKI()
2902 self.assertTrue(isinstance(nspki, NetscapeSPKIType))
2903
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002904
Jean-Paul Calderone969efaa2010-08-03 18:19:19 -04002905 def test_invalid_attribute(self):
2906 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002907 Accessing a non-existent attribute of a :py:obj:`NetscapeSPKI` instance causes
2908 an :py:obj:`AttributeError` to be raised.
Jean-Paul Calderone969efaa2010-08-03 18:19:19 -04002909 """
2910 nspki = NetscapeSPKI()
2911 self.assertRaises(AttributeError, lambda: nspki.foo)
2912
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002913
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002914 def test_b64_encode(self):
2915 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002916 :py:obj:`NetscapeSPKI.b64_encode` encodes the certificate to a base64 blob.
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002917 """
2918 nspki = NetscapeSPKI()
2919 blob = nspki.b64_encode()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002920 self.assertTrue(isinstance(blob, binary_type))
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002921
2922
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002923
Rick Dean536ba022009-07-24 23:57:27 -05002924class RevokedTests(TestCase):
2925 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002926 Tests for :py:obj:`OpenSSL.crypto.Revoked`
Rick Dean536ba022009-07-24 23:57:27 -05002927 """
2928 def test_construction(self):
2929 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002930 Confirm we can create :py:obj:`OpenSSL.crypto.Revoked`. Check
Rick Dean536ba022009-07-24 23:57:27 -05002931 that it is empty.
2932 """
2933 revoked = Revoked()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002934 self.assertTrue(isinstance(revoked, Revoked))
2935 self.assertEquals(type(revoked), Revoked)
2936 self.assertEquals(revoked.get_serial(), b('00'))
2937 self.assertEquals(revoked.get_rev_date(), None)
2938 self.assertEquals(revoked.get_reason(), None)
Rick Dean536ba022009-07-24 23:57:27 -05002939
2940
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002941 def test_construction_wrong_args(self):
2942 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002943 Calling :py:obj:`OpenSSL.crypto.Revoked` with any arguments results
2944 in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002945 """
2946 self.assertRaises(TypeError, Revoked, None)
2947 self.assertRaises(TypeError, Revoked, 1)
2948 self.assertRaises(TypeError, Revoked, "foo")
2949
2950
Rick Dean536ba022009-07-24 23:57:27 -05002951 def test_serial(self):
2952 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002953 Confirm we can set and get serial numbers from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002954 :py:obj:`OpenSSL.crypto.Revoked`. Confirm errors are handled
Rick Dean536ba022009-07-24 23:57:27 -05002955 with grace.
2956 """
2957 revoked = Revoked()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002958 ret = revoked.set_serial(b('10b'))
2959 self.assertEquals(ret, None)
Rick Dean536ba022009-07-24 23:57:27 -05002960 ser = revoked.get_serial()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002961 self.assertEquals(ser, b('010B'))
Rick Dean536ba022009-07-24 23:57:27 -05002962
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002963 revoked.set_serial(b('31ppp')) # a type error would be nice
Rick Dean536ba022009-07-24 23:57:27 -05002964 ser = revoked.get_serial()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002965 self.assertEquals(ser, b('31'))
Rick Dean536ba022009-07-24 23:57:27 -05002966
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002967 self.assertRaises(ValueError, revoked.set_serial, b('pqrst'))
Rick Dean536ba022009-07-24 23:57:27 -05002968 self.assertRaises(TypeError, revoked.set_serial, 100)
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002969 self.assertRaises(TypeError, revoked.get_serial, 1)
2970 self.assertRaises(TypeError, revoked.get_serial, None)
2971 self.assertRaises(TypeError, revoked.get_serial, "")
Rick Dean536ba022009-07-24 23:57:27 -05002972
2973
2974 def test_date(self):
2975 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002976 Confirm we can set and get revocation dates from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002977 :py:obj:`OpenSSL.crypto.Revoked`. Confirm errors are handled
Rick Dean536ba022009-07-24 23:57:27 -05002978 with grace.
2979 """
2980 revoked = Revoked()
2981 date = revoked.get_rev_date()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002982 self.assertEquals(date, None)
Rick Dean536ba022009-07-24 23:57:27 -05002983
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002984 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05002985 ret = revoked.set_rev_date(now)
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002986 self.assertEqual(ret, None)
Rick Dean536ba022009-07-24 23:57:27 -05002987 date = revoked.get_rev_date()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002988 self.assertEqual(date, now)
Rick Dean536ba022009-07-24 23:57:27 -05002989
2990
Rick Dean6385faf2009-07-26 00:07:47 -05002991 def test_reason(self):
2992 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002993 Confirm we can set and get revocation reasons from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002994 :py:obj:`OpenSSL.crypto.Revoked`. The "get" need to work
Rick Dean6385faf2009-07-26 00:07:47 -05002995 as "set". Likewise, each reason of all_reasons() must work.
2996 """
2997 revoked = Revoked()
2998 for r in revoked.all_reasons():
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002999 for x in range(2):
Rick Dean6385faf2009-07-26 00:07:47 -05003000 ret = revoked.set_reason(r)
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04003001 self.assertEquals(ret, None)
Rick Dean6385faf2009-07-26 00:07:47 -05003002 reason = revoked.get_reason()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04003003 self.assertEquals(
3004 reason.lower().replace(b(' '), b('')),
3005 r.lower().replace(b(' '), b('')))
Rick Dean6385faf2009-07-26 00:07:47 -05003006 r = reason # again with the resp of get
3007
3008 revoked.set_reason(None)
3009 self.assertEqual(revoked.get_reason(), None)
3010
3011
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05003012 def test_set_reason_wrong_arguments(self):
Rick Dean6385faf2009-07-26 00:07:47 -05003013 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003014 Calling :py:obj:`OpenSSL.crypto.Revoked.set_reason` with other than
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05003015 one argument, or an argument which isn't a valid reason,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003016 results in :py:obj:`TypeError` or :py:obj:`ValueError` being raised.
Rick Dean6385faf2009-07-26 00:07:47 -05003017 """
3018 revoked = Revoked()
3019 self.assertRaises(TypeError, revoked.set_reason, 100)
Jean-Paul Calderone281b62b2010-08-28 14:22:29 -04003020 self.assertRaises(ValueError, revoked.set_reason, b('blue'))
Rick Dean6385faf2009-07-26 00:07:47 -05003021
Rick Dean536ba022009-07-24 23:57:27 -05003022
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05003023 def test_get_reason_wrong_arguments(self):
3024 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003025 Calling :py:obj:`OpenSSL.crypto.Revoked.get_reason` with any
3026 arguments results in :py:obj:`TypeError` being raised.
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05003027 """
3028 revoked = Revoked()
3029 self.assertRaises(TypeError, revoked.get_reason, None)
3030 self.assertRaises(TypeError, revoked.get_reason, 1)
3031 self.assertRaises(TypeError, revoked.get_reason, "foo")
3032
3033
3034
Rick Dean536ba022009-07-24 23:57:27 -05003035class CRLTests(TestCase):
3036 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003037 Tests for :py:obj:`OpenSSL.crypto.CRL`
Rick Dean536ba022009-07-24 23:57:27 -05003038 """
3039 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
3040 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
3041
3042 def test_construction(self):
3043 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003044 Confirm we can create :py:obj:`OpenSSL.crypto.CRL`. Check
Rick Dean536ba022009-07-24 23:57:27 -05003045 that it is empty
3046 """
3047 crl = CRL()
3048 self.assertTrue( isinstance(crl, CRL) )
3049 self.assertEqual(crl.get_revoked(), None)
3050
3051
Jean-Paul Calderone2efd03e2010-01-30 13:59:55 -05003052 def test_construction_wrong_args(self):
3053 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003054 Calling :py:obj:`OpenSSL.crypto.CRL` with any number of arguments
3055 results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone2efd03e2010-01-30 13:59:55 -05003056 """
3057 self.assertRaises(TypeError, CRL, 1)
3058 self.assertRaises(TypeError, CRL, "")
3059 self.assertRaises(TypeError, CRL, None)
3060
3061
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003062 def _get_crl(self):
Rick Dean536ba022009-07-24 23:57:27 -05003063 """
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003064 Get a new ``CRL`` with a revocation.
Rick Dean536ba022009-07-24 23:57:27 -05003065 """
3066 crl = CRL()
3067 revoked = Revoked()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003068 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05003069 revoked.set_rev_date(now)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003070 revoked.set_serial(b('3ab'))
3071 revoked.set_reason(b('sUpErSeDEd'))
Rick Dean536ba022009-07-24 23:57:27 -05003072 crl.add_revoked(revoked)
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003073 return crl
Rick Dean536ba022009-07-24 23:57:27 -05003074
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003075
3076 def test_export_pem(self):
3077 """
3078 If not passed a format, ``CRL.export`` returns a "PEM" format string
3079 representing a serial number, a revoked reason, and certificate issuer
3080 information.
3081 """
3082 crl = self._get_crl()
Rick Dean536ba022009-07-24 23:57:27 -05003083 # PEM format
3084 dumped_crl = crl.export(self.cert, self.pkey, days=20)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003085 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003086
3087 # These magic values are based on the way the CRL above was constructed
3088 # and with what certificate it was exported.
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003089 text.index(b('Serial Number: 03AB'))
3090 text.index(b('Superseded'))
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003091 text.index(
3092 b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA')
3093 )
3094
3095
3096 def test_export_der(self):
3097 """
3098 If passed ``FILETYPE_ASN1`` for the format, ``CRL.export`` returns a
3099 "DER" format string representing a serial number, a revoked reason, and
3100 certificate issuer information.
3101 """
3102 crl = self._get_crl()
Rick Dean536ba022009-07-24 23:57:27 -05003103
3104 # DER format
3105 dumped_crl = crl.export(self.cert, self.pkey, FILETYPE_ASN1)
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003106 text = _runopenssl(
3107 dumped_crl, b"crl", b"-noout", b"-text", b"-inform", b"DER"
3108 )
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003109 text.index(b('Serial Number: 03AB'))
3110 text.index(b('Superseded'))
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003111 text.index(
3112 b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA')
3113 )
3114
3115
3116 def test_export_text(self):
3117 """
3118 If passed ``FILETYPE_TEXT`` for the format, ``CRL.export`` returns a
3119 text format string like the one produced by the openssl command line
3120 tool.
3121 """
3122 crl = self._get_crl()
3123
3124 dumped_crl = crl.export(self.cert, self.pkey, FILETYPE_ASN1)
3125 text = _runopenssl(
3126 dumped_crl, b"crl", b"-noout", b"-text", b"-inform", b"DER"
3127 )
Rick Dean536ba022009-07-24 23:57:27 -05003128
3129 # text format
3130 dumped_text = crl.export(self.cert, self.pkey, type=FILETYPE_TEXT)
3131 self.assertEqual(text, dumped_text)
3132
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003133
3134 def test_export_custom_digest(self):
3135 """
3136 If passed the name of a digest function, ``CRL.export`` uses a
3137 signature algorithm based on that digest function.
3138 """
3139 crl = self._get_crl()
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04003140 dumped_crl = crl.export(self.cert, self.pkey, digest=b"sha1")
Bulat Gaifullin1966c972014-09-22 09:47:20 +04003141 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
3142 text.index(b('Signature Algorithm: sha1'))
3143
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003144
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04003145 def test_export_md5_digest(self):
3146 """
3147 If passed md5 as the digest function, ``CRL.export`` uses md5 and does
3148 not emit a deprecation warning.
3149 """
3150 crl = self._get_crl()
3151 with catch_warnings(record=True) as catcher:
3152 simplefilter("always")
3153 self.assertEqual(0, len(catcher))
3154 dumped_crl = crl.export(self.cert, self.pkey, digest=b"md5")
3155 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
3156 text.index(b('Signature Algorithm: md5'))
3157
3158
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003159 def test_export_default_digest(self):
3160 """
3161 If not passed the name of a digest function, ``CRL.export`` uses a
3162 signature algorithm based on MD5 and emits a deprecation warning.
3163 """
3164 crl = self._get_crl()
3165 with catch_warnings(record=True) as catcher:
3166 simplefilter("always")
3167 dumped_crl = crl.export(self.cert, self.pkey)
3168 self.assertEqual(
3169 "The default message digest (md5) is deprecated. "
3170 "Pass the name of a message digest explicitly.",
3171 str(catcher[0].message),
3172 )
Bulat Gaifullin1966c972014-09-22 09:47:20 +04003173 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
3174 text.index(b('Signature Algorithm: md5'))
3175
Rick Dean536ba022009-07-24 23:57:27 -05003176
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -04003177 def test_export_invalid(self):
3178 """
3179 If :py:obj:`CRL.export` is used with an uninitialized :py:obj:`X509`
Jean-Paul Calderoneb5871072012-03-09 14:58:00 -08003180 instance, :py:obj:`OpenSSL.crypto.Error` is raised.
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -04003181 """
3182 crl = CRL()
3183 self.assertRaises(Error, crl.export, X509(), PKey())
3184
3185
Jean-Paul Calderone56515342010-01-30 13:49:38 -05003186 def test_add_revoked_keyword(self):
3187 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003188 :py:obj:`OpenSSL.CRL.add_revoked` accepts its single argument as the
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003189 ``revoked`` keyword argument.
Jean-Paul Calderone56515342010-01-30 13:49:38 -05003190 """
3191 crl = CRL()
3192 revoked = Revoked()
3193 crl.add_revoked(revoked=revoked)
3194 self.assertTrue(isinstance(crl.get_revoked()[0], Revoked))
3195
Rick Dean6385faf2009-07-26 00:07:47 -05003196
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05003197 def test_export_wrong_args(self):
3198 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003199 Calling :py:obj:`OpenSSL.CRL.export` with fewer than two or more than
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05003200 four arguments, or with arguments other than the certificate,
3201 private key, integer file type, and integer number of days it
Jonathan Ballet648875f2011-07-16 14:14:58 +09003202 expects, results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05003203 """
3204 crl = CRL()
3205 self.assertRaises(TypeError, crl.export)
3206 self.assertRaises(TypeError, crl.export, self.cert)
Bulat Gaifullin925f7862014-09-22 10:10:44 +04003207 self.assertRaises(TypeError, crl.export, self.cert, self.pkey, FILETYPE_PEM, 10, "md5", "foo")
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05003208
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05003209 self.assertRaises(TypeError, crl.export, None, self.pkey, FILETYPE_PEM, 10)
3210 self.assertRaises(TypeError, crl.export, self.cert, None, FILETYPE_PEM, 10)
3211 self.assertRaises(TypeError, crl.export, self.cert, self.pkey, None, 10)
3212 self.assertRaises(TypeError, crl.export, self.cert, FILETYPE_PEM, None)
3213
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05003214
Jean-Paul Calderoneea198422010-01-30 13:58:23 -05003215 def test_export_unknown_filetype(self):
3216 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003217 Calling :py:obj:`OpenSSL.CRL.export` with a file type other than
3218 :py:obj:`FILETYPE_PEM`, :py:obj:`FILETYPE_ASN1`, or :py:obj:`FILETYPE_TEXT` results
3219 in a :py:obj:`ValueError` being raised.
Jean-Paul Calderoneea198422010-01-30 13:58:23 -05003220 """
3221 crl = CRL()
3222 self.assertRaises(ValueError, crl.export, self.cert, self.pkey, 100, 10)
3223
3224
Bulat Gaifullin925f7862014-09-22 10:10:44 +04003225 def test_export_unknown_digest(self):
Bulat Gaifullin5f9eea42014-09-23 19:35:15 +04003226 """
3227 Calling :py:obj:`OpenSSL.CRL.export` with a unsupported digest results
3228 in a :py:obj:`ValueError` being raised.
3229 """
Bulat Gaifullin925f7862014-09-22 10:10:44 +04003230 crl = CRL()
Jean-Paul Calderone9be85192015-04-13 21:20:51 -04003231 self.assertRaises(
3232 ValueError,
3233 crl.export,
3234 self.cert, self.pkey, FILETYPE_PEM, 10, b"strange-digest"
3235 )
Bulat Gaifullin925f7862014-09-22 10:10:44 +04003236
3237
Rick Dean536ba022009-07-24 23:57:27 -05003238 def test_get_revoked(self):
3239 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05003240 Use python to create a simple CRL with two revocations.
Jonathan Ballet648875f2011-07-16 14:14:58 +09003241 Get back the :py:obj:`Revoked` using :py:obj:`OpenSSL.CRL.get_revoked` and
Rick Dean536ba022009-07-24 23:57:27 -05003242 verify them.
3243 """
3244 crl = CRL()
3245
3246 revoked = Revoked()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003247 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05003248 revoked.set_rev_date(now)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003249 revoked.set_serial(b('3ab'))
Rick Dean536ba022009-07-24 23:57:27 -05003250 crl.add_revoked(revoked)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003251 revoked.set_serial(b('100'))
3252 revoked.set_reason(b('sUpErSeDEd'))
Rick Dean536ba022009-07-24 23:57:27 -05003253 crl.add_revoked(revoked)
3254
3255 revs = crl.get_revoked()
3256 self.assertEqual(len(revs), 2)
3257 self.assertEqual(type(revs[0]), Revoked)
3258 self.assertEqual(type(revs[1]), Revoked)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003259 self.assertEqual(revs[0].get_serial(), b('03AB'))
3260 self.assertEqual(revs[1].get_serial(), b('0100'))
Rick Dean536ba022009-07-24 23:57:27 -05003261 self.assertEqual(revs[0].get_rev_date(), now)
3262 self.assertEqual(revs[1].get_rev_date(), now)
3263
3264
Jean-Paul Calderone46bdce42010-01-30 13:44:16 -05003265 def test_get_revoked_wrong_args(self):
3266 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003267 Calling :py:obj:`OpenSSL.CRL.get_revoked` with any arguments results
3268 in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone46bdce42010-01-30 13:44:16 -05003269 """
3270 crl = CRL()
3271 self.assertRaises(TypeError, crl.get_revoked, None)
3272 self.assertRaises(TypeError, crl.get_revoked, 1)
3273 self.assertRaises(TypeError, crl.get_revoked, "")
3274 self.assertRaises(TypeError, crl.get_revoked, "", 1, None)
3275
3276
Jean-Paul Calderoneecef6fa2010-01-30 13:47:18 -05003277 def test_add_revoked_wrong_args(self):
3278 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003279 Calling :py:obj:`OpenSSL.CRL.add_revoked` with other than one
3280 argument results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderoneecef6fa2010-01-30 13:47:18 -05003281 """
3282 crl = CRL()
3283 self.assertRaises(TypeError, crl.add_revoked)
3284 self.assertRaises(TypeError, crl.add_revoked, 1, 2)
3285 self.assertRaises(TypeError, crl.add_revoked, "foo", "bar")
3286
3287
Rick Dean536ba022009-07-24 23:57:27 -05003288 def test_load_crl(self):
3289 """
3290 Load a known CRL and inspect its revocations. Both
3291 PEM and DER formats are loaded.
3292 """
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003293 crl = load_crl(FILETYPE_PEM, crlData)
Rick Dean536ba022009-07-24 23:57:27 -05003294 revs = crl.get_revoked()
3295 self.assertEqual(len(revs), 2)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003296 self.assertEqual(revs[0].get_serial(), b('03AB'))
Rick Dean6385faf2009-07-26 00:07:47 -05003297 self.assertEqual(revs[0].get_reason(), None)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003298 self.assertEqual(revs[1].get_serial(), b('0100'))
3299 self.assertEqual(revs[1].get_reason(), b('Superseded'))
Rick Dean536ba022009-07-24 23:57:27 -05003300
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003301 der = _runopenssl(crlData, b"crl", b"-outform", b"DER")
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05003302 crl = load_crl(FILETYPE_ASN1, der)
Rick Dean536ba022009-07-24 23:57:27 -05003303 revs = crl.get_revoked()
3304 self.assertEqual(len(revs), 2)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003305 self.assertEqual(revs[0].get_serial(), b('03AB'))
Rick Dean6385faf2009-07-26 00:07:47 -05003306 self.assertEqual(revs[0].get_reason(), None)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003307 self.assertEqual(revs[1].get_serial(), b('0100'))
3308 self.assertEqual(revs[1].get_reason(), b('Superseded'))
Rick Dean536ba022009-07-24 23:57:27 -05003309
3310
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003311 def test_load_crl_wrong_args(self):
3312 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003313 Calling :py:obj:`OpenSSL.crypto.load_crl` with other than two
3314 arguments results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003315 """
3316 self.assertRaises(TypeError, load_crl)
3317 self.assertRaises(TypeError, load_crl, FILETYPE_PEM)
3318 self.assertRaises(TypeError, load_crl, FILETYPE_PEM, crlData, None)
3319
3320
3321 def test_load_crl_bad_filetype(self):
3322 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003323 Calling :py:obj:`OpenSSL.crypto.load_crl` with an unknown file type
3324 raises a :py:obj:`ValueError`.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003325 """
3326 self.assertRaises(ValueError, load_crl, 100, crlData)
3327
3328
3329 def test_load_crl_bad_data(self):
3330 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003331 Calling :py:obj:`OpenSSL.crypto.load_crl` with file data which can't
3332 be loaded raises a :py:obj:`OpenSSL.crypto.Error`.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003333 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003334 self.assertRaises(Error, load_crl, FILETYPE_PEM, b"hello, world")
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003335
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04003336
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -05003337
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003338class X509StoreContextTests(TestCase):
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003339 """
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003340 Tests for :py:obj:`OpenSSL.crypto.X509StoreContext`.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003341 """
3342 root_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3343 intermediate_cert = load_certificate(FILETYPE_PEM, intermediate_cert_pem)
3344 intermediate_server_cert = load_certificate(FILETYPE_PEM, intermediate_server_cert_pem)
3345
3346 def test_valid(self):
3347 """
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003348 :py:obj:`verify_certificate` returns ``None`` when called with a certificate
Jean-Paul Calderone06e01b92015-01-18 15:43:13 -05003349 and valid chain.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003350 """
3351 store = X509Store()
3352 store.add_cert(self.root_cert)
3353 store.add_cert(self.intermediate_cert)
3354 store_ctx = X509StoreContext(store, self.intermediate_server_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003355 self.assertEqual(store_ctx.verify_certificate(), None)
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003356
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003357
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003358 def test_reuse(self):
3359 """
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003360 :py:obj:`verify_certificate` can be called multiple times with the same
Jean-Paul Calderone06e01b92015-01-18 15:43:13 -05003361 ``X509StoreContext`` instance to produce the same result.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003362 """
3363 store = X509Store()
3364 store.add_cert(self.root_cert)
3365 store.add_cert(self.intermediate_cert)
3366 store_ctx = X509StoreContext(store, self.intermediate_server_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003367 self.assertEqual(store_ctx.verify_certificate(), None)
3368 self.assertEqual(store_ctx.verify_certificate(), None)
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003369
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003370
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003371 def test_trusted_self_signed(self):
3372 """
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003373 :py:obj:`verify_certificate` returns ``None`` when called with a self-signed
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003374 certificate and itself in the chain.
3375 """
3376 store = X509Store()
3377 store.add_cert(self.root_cert)
3378 store_ctx = X509StoreContext(store, self.root_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003379 self.assertEqual(store_ctx.verify_certificate(), None)
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003380
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003381
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003382 def test_untrusted_self_signed(self):
3383 """
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003384 :py:obj:`verify_certificate` raises error when a self-signed certificate is
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003385 verified without itself in the chain.
3386 """
3387 store = X509Store()
3388 store_ctx = X509StoreContext(store, self.root_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003389 e = self.assertRaises(X509StoreContextError, store_ctx.verify_certificate)
Jean-Paul Calderone4c10a1e2015-01-18 16:31:27 -05003390 self.assertEqual(e.args[0][2], 'self signed certificate')
Jean-Paul Calderone06e01b92015-01-18 15:43:13 -05003391 self.assertEqual(e.certificate.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003392
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003393
3394 def test_invalid_chain_no_root(self):
3395 """
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003396 :py:obj:`verify_certificate` raises error when a root certificate is missing
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003397 from the chain.
3398 """
3399 store = X509Store()
3400 store.add_cert(self.intermediate_cert)
3401 store_ctx = X509StoreContext(store, self.intermediate_server_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003402 e = self.assertRaises(X509StoreContextError, store_ctx.verify_certificate)
Jean-Paul Calderone4c10a1e2015-01-18 16:31:27 -05003403 self.assertEqual(e.args[0][2], 'unable to get issuer certificate')
Jean-Paul Calderone06e01b92015-01-18 15:43:13 -05003404 self.assertEqual(e.certificate.get_subject().CN, 'intermediate')
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003405
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003406
3407 def test_invalid_chain_no_intermediate(self):
3408 """
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003409 :py:obj:`verify_certificate` raises error when an intermediate certificate is
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003410 missing from the chain.
3411 """
3412 store = X509Store()
3413 store.add_cert(self.root_cert)
3414 store_ctx = X509StoreContext(store, self.intermediate_server_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003415 e = self.assertRaises(X509StoreContextError, store_ctx.verify_certificate)
Jean-Paul Calderone4c10a1e2015-01-18 16:31:27 -05003416 self.assertEqual(e.args[0][2], 'unable to get local issuer certificate')
Jean-Paul Calderone06e01b92015-01-18 15:43:13 -05003417 self.assertEqual(e.certificate.get_subject().CN, 'intermediate-service')
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003418
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003419
Stephen Holsapple46a09252015-02-12 14:45:43 -08003420 def test_modification_pre_verify(self):
3421 """
3422 :py:obj:`verify_certificate` can use a store context modified after
3423 instantiation.
3424 """
3425 store_bad = X509Store()
3426 store_bad.add_cert(self.intermediate_cert)
3427 store_good = X509Store()
3428 store_good.add_cert(self.root_cert)
3429 store_good.add_cert(self.intermediate_cert)
3430 store_ctx = X509StoreContext(store_bad, self.intermediate_server_cert)
3431 e = self.assertRaises(X509StoreContextError, store_ctx.verify_certificate)
3432 self.assertEqual(e.args[0][2], 'unable to get issuer certificate')
3433 self.assertEqual(e.certificate.get_subject().CN, 'intermediate')
3434 store_ctx.set_store(store_good)
3435 self.assertEqual(store_ctx.verify_certificate(), None)
3436
3437
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04003438
3439class SignVerifyTests(TestCase):
3440 """
3441 Tests for :py:obj:`OpenSSL.crypto.sign` and :py:obj:`OpenSSL.crypto.verify`.
3442 """
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04003443 def test_sign_verify(self):
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04003444 """
3445 :py:obj:`sign` generates a cryptographic signature which :py:obj:`verify` can check.
3446 """
3447 content = b(
James Yonan7c2e5d32010-02-27 05:45:50 -07003448 "It was a bright cold day in April, and the clocks were striking "
Jean-Paul Calderoned08feb02010-10-12 21:53:24 -04003449 "thirteen. Winston Smith, his chin nuzzled into his breast in an "
James Yonan7c2e5d32010-02-27 05:45:50 -07003450 "effort to escape the vile wind, slipped quickly through the "
3451 "glass doors of Victory Mansions, though not quickly enough to "
3452 "prevent a swirl of gritty dust from entering along with him.")
3453
3454 # sign the content with this private key
3455 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
3456 # verify the content with this cert
3457 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3458 # certificate unrelated to priv_key, used to trigger an error
3459 bad_cert = load_certificate(FILETYPE_PEM, server_cert_pem)
3460
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003461 for digest in ['md5', 'sha1']:
3462 sig = sign(priv_key, content, digest)
3463
James Yonan7c2e5d32010-02-27 05:45:50 -07003464 # Verify the signature of content, will throw an exception if error.
3465 verify(good_cert, sig, content, digest)
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003466
Jean-Paul Calderone9538f142010-10-13 22:13:40 -04003467 # This should fail because the certificate doesn't match the
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003468 # private key that was used to sign the content.
Jean-Paul Calderone9538f142010-10-13 22:13:40 -04003469 self.assertRaises(Error, verify, bad_cert, sig, content, digest)
James Yonan7c2e5d32010-02-27 05:45:50 -07003470
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04003471 # This should fail because we've "tainted" the content after
Jean-Paul Calderone9828f662010-12-08 22:57:26 -05003472 # signing it.
3473 self.assertRaises(
Jonathan Ballet648875f2011-07-16 14:14:58 +09003474 Error, verify,
Jean-Paul Calderone9828f662010-12-08 22:57:26 -05003475 good_cert, sig, content + b("tainted"), digest)
3476
3477 # test that unknown digest types fail
3478 self.assertRaises(
3479 ValueError, sign, priv_key, content, "strange-digest")
3480 self.assertRaises(
3481 ValueError, verify, good_cert, sig, content, "strange-digest")
3482
Rick Dean5b7b6372009-04-01 11:34:06 -05003483
Abraham Martinc5484ba2015-03-25 15:33:05 +00003484 def test_sign_verify_with_text(self):
3485 """
3486 :py:obj:`sign` generates a cryptographic signature which :py:obj:`verify` can check.
3487 Deprecation warnings raised because using text instead of bytes as content
3488 """
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003489 content = (
Jean-Paul Calderone362c1f52015-03-29 08:01:39 -04003490 b"It was a bright cold day in April, and the clocks were striking "
3491 b"thirteen. Winston Smith, his chin nuzzled into his breast in an "
3492 b"effort to escape the vile wind, slipped quickly through the "
3493 b"glass doors of Victory Mansions, though not quickly enough to "
3494 b"prevent a swirl of gritty dust from entering along with him."
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003495 ).decode("ascii")
Abraham Martinc5484ba2015-03-25 15:33:05 +00003496
3497 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
3498 cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3499 for digest in ['md5', 'sha1']:
3500 with catch_warnings(record=True) as w:
3501 simplefilter("always")
3502 sig = sign(priv_key, content, digest)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003503
3504 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003505 "{0} for data is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003506 WARNING_TYPE_EXPECTED
3507 ),
3508 str(w[-1].message)
3509 )
3510 self.assertIs(w[-1].category, DeprecationWarning)
3511
Abraham Martinc5484ba2015-03-25 15:33:05 +00003512 with catch_warnings(record=True) as w:
3513 simplefilter("always")
3514 verify(cert, sig, content, digest)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003515
3516 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003517 "{0} for data is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003518 WARNING_TYPE_EXPECTED
3519 ),
3520 str(w[-1].message)
3521 )
3522 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinc5484ba2015-03-25 15:33:05 +00003523
3524
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -05003525 def test_sign_nulls(self):
3526 """
3527 :py:obj:`sign` produces a signature for a string with embedded nulls.
3528 """
3529 content = b("Watch out! \0 Did you see it?")
3530 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
3531 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3532 sig = sign(priv_key, content, "sha1")
3533 verify(good_cert, sig, content, "sha1")
3534
3535
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003536
3537class EllipticCurveTests(TestCase):
3538 """
3539 Tests for :py:class:`_EllipticCurve`, :py:obj:`get_elliptic_curve`, and
3540 :py:obj:`get_elliptic_curves`.
3541 """
3542 def test_set(self):
3543 """
3544 :py:obj:`get_elliptic_curves` returns a :py:obj:`set`.
3545 """
3546 self.assertIsInstance(get_elliptic_curves(), set)
3547
3548
3549 def test_some_curves(self):
3550 """
3551 If :py:mod:`cryptography` has elliptic curve support then the set
3552 returned by :py:obj:`get_elliptic_curves` has some elliptic curves in
3553 it.
3554
3555 There could be an OpenSSL that violates this assumption. If so, this
3556 test will fail and we'll find out.
3557 """
3558 curves = get_elliptic_curves()
3559 if lib.Cryptography_HAS_EC:
3560 self.assertTrue(curves)
3561 else:
3562 self.assertFalse(curves)
3563
3564
3565 def test_a_curve(self):
3566 """
3567 :py:obj:`get_elliptic_curve` can be used to retrieve a particular
3568 supported curve.
3569 """
3570 curves = get_elliptic_curves()
3571 if curves:
3572 curve = next(iter(curves))
3573 self.assertEqual(curve.name, get_elliptic_curve(curve.name).name)
3574 else:
Jean-Paul Calderoneeb86f3a2014-04-19 09:45:57 -04003575 self.assertRaises(ValueError, get_elliptic_curve, u("prime256v1"))
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003576
3577
3578 def test_not_a_curve(self):
3579 """
3580 :py:obj:`get_elliptic_curve` raises :py:class:`ValueError` if called
3581 with a name which does not identify a supported curve.
3582 """
3583 self.assertRaises(
Jean-Paul Calderone5a82db92014-04-19 09:51:29 -04003584 ValueError, get_elliptic_curve, u("this curve was just invented"))
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003585
3586
3587 def test_repr(self):
3588 """
3589 The string representation of a curve object includes simply states the
3590 object is a curve and what its name is.
3591 """
3592 curves = get_elliptic_curves()
3593 if curves:
3594 curve = next(iter(curves))
3595 self.assertEqual("<Curve %r>" % (curve.name,), repr(curve))
3596
3597
3598 def test_to_EC_KEY(self):
3599 """
3600 The curve object can export a version of itself as an EC_KEY* via the
3601 private :py:meth:`_EllipticCurve._to_EC_KEY`.
3602 """
3603 curves = get_elliptic_curves()
3604 if curves:
3605 curve = next(iter(curves))
3606 # It's not easy to assert anything about this object. However, see
3607 # leakcheck/crypto.py for a test that demonstrates it at least does
3608 # not leak memory.
3609 curve._to_EC_KEY()
3610
3611
Jean-Paul Calderone1be77082014-04-30 18:17:41 -04003612
3613class EllipticCurveFactory(object):
3614 """
3615 A helper to get the names of two curves.
3616 """
3617 def __init__(self):
3618 curves = iter(get_elliptic_curves())
3619 try:
3620 self.curve_name = next(curves).name
3621 self.another_curve_name = next(curves).name
3622 except StopIteration:
3623 self.curve_name = self.another_curve_name = None
3624
3625
3626
3627class EllipticCurveEqualityTests(TestCase, EqualityTestsMixin):
3628 """
3629 Tests :py:type:`_EllipticCurve`\ 's implementation of ``==`` and ``!=``.
3630 """
3631 curve_factory = EllipticCurveFactory()
3632
3633 if curve_factory.curve_name is None:
3634 skip = "There are no curves available there can be no curve objects."
3635
3636
3637 def anInstance(self):
3638 """
3639 Get the curve object for an arbitrary curve supported by the system.
3640 """
3641 return get_elliptic_curve(self.curve_factory.curve_name)
3642
3643
3644 def anotherInstance(self):
3645 """
3646 Get the curve object for an arbitrary curve supported by the system -
3647 but not the one returned by C{anInstance}.
3648 """
3649 return get_elliptic_curve(self.curve_factory.another_curve_name)
3650
3651
3652
Jean-Paul Calderone22c31242014-05-01 07:49:47 -04003653class EllipticCurveHashTests(TestCase):
3654 """
3655 Tests for :py:type:`_EllipticCurve`\ 's implementation of hashing (thus use
3656 as an item in a :py:type:`dict` or :py:type:`set`).
3657 """
3658 curve_factory = EllipticCurveFactory()
3659
3660 if curve_factory.curve_name is None:
3661 skip = "There are no curves available there can be no curve objects."
3662
3663
3664 def test_contains(self):
3665 """
3666 The ``in`` operator reports that a :py:type:`set` containing a curve
3667 does contain that curve.
3668 """
3669 curve = get_elliptic_curve(self.curve_factory.curve_name)
3670 curves = set([curve])
3671 self.assertIn(curve, curves)
3672
3673
3674 def test_does_not_contain(self):
3675 """
3676 The ``in`` operator reports that a :py:type:`set` not containing a
3677 curve does not contain that curve.
3678 """
3679 curve = get_elliptic_curve(self.curve_factory.curve_name)
3680 curves = set([get_elliptic_curve(self.curve_factory.another_curve_name)])
3681 self.assertNotIn(curve, curves)
3682
3683
3684
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -05003685if __name__ == '__main__':
3686 main()