blob: b81745138fdff7d2a13deaef14a289b3c2390c31 [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)
1510 now = datetime.utcnow() + timedelta(seconds=100)
1511 cert.gmtime_adj_notBefore(100)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001512 self.assertEqual(cert.get_notBefore(), b(now.strftime("%Y%m%d%H%M%SZ")))
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001513
1514
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001515 def test_gmtime_adj_notAfter_wrong_args(self):
1516 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001517 :py:obj:`X509Type.gmtime_adj_notAfter` raises :py:obj:`TypeError` if called with the
1518 wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001519 """
1520 cert = X509()
1521 self.assertRaises(TypeError, cert.gmtime_adj_notAfter)
1522 self.assertRaises(TypeError, cert.gmtime_adj_notAfter, None)
1523 self.assertRaises(TypeError, cert.gmtime_adj_notAfter, 123, None)
1524
1525
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001526 def test_gmtime_adj_notAfter(self):
1527 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001528 :py:obj:`X509Type.gmtime_adj_notAfter` changes the not-after timestamp to be
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001529 the current time plus the number of seconds passed in.
1530 """
1531 cert = load_certificate(FILETYPE_PEM, self.pemData)
1532 now = datetime.utcnow() + timedelta(seconds=100)
1533 cert.gmtime_adj_notAfter(100)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001534 self.assertEqual(cert.get_notAfter(), b(now.strftime("%Y%m%d%H%M%SZ")))
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001535
1536
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001537 def test_has_expired_wrong_args(self):
1538 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001539 :py:obj:`X509Type.has_expired` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001540 arguments.
1541 """
1542 cert = X509()
1543 self.assertRaises(TypeError, cert.has_expired, None)
1544
1545
1546 def test_has_expired(self):
1547 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001548 :py:obj:`X509Type.has_expired` returns :py:obj:`True` if the certificate's not-after
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001549 time is in the past.
1550 """
1551 cert = X509()
1552 cert.gmtime_adj_notAfter(-1)
1553 self.assertTrue(cert.has_expired())
1554
1555
1556 def test_has_not_expired(self):
1557 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001558 :py:obj:`X509Type.has_expired` returns :py:obj:`False` if the certificate's not-after
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001559 time is in the future.
1560 """
1561 cert = X509()
1562 cert.gmtime_adj_notAfter(2)
1563 self.assertFalse(cert.has_expired())
1564
Jeff Tangfc18f7b2015-04-15 17:42:33 -04001565 def test_root_has_not_expired(self):
1566 """
1567 :py:obj:`X509Type.has_expired` returns :py:obj:`False` if the certificate's not-after
1568 time is in the future.
1569 """
1570 cert = load_certificate(FILETYPE_PEM, root_cert_pem)
1571 self.assertFalse(cert.has_expired())
1572
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001573
Rick Dean38a05c82009-07-18 01:41:30 -05001574 def test_digest(self):
1575 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001576 :py:obj:`X509.digest` returns a string giving ":"-separated hex-encoded words
Rick Dean38a05c82009-07-18 01:41:30 -05001577 of the digest of the certificate.
1578 """
Jeff Tangfc18f7b2015-04-15 17:42:33 -04001579 cert = load_certificate(FILETYPE_PEM, root_cert_pem)
Rick Dean38a05c82009-07-18 01:41:30 -05001580 self.assertEqual(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001581 # This is MD5 instead of GOOD_DIGEST because the digest algorithm
1582 # actually matters to the assertion (ie, another arbitrary, good
1583 # digest will not product the same digest).
Jeff Tangfc18f7b2015-04-15 17:42:33 -04001584 # Digest verified with the command:
1585 # openssl x509 -in root_cert.pem -noout -fingerprint -md5
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001586 cert.digest("MD5"),
Jeff Tangfc18f7b2015-04-15 17:42:33 -04001587 b("19:B3:05:26:2B:F8:F2:FF:0B:8F:21:07:A8:28:B8:75"))
Rick Dean38a05c82009-07-18 01:41:30 -05001588
1589
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001590 def _extcert(self, pkey, extensions):
1591 cert = X509()
1592 cert.set_pubkey(pkey)
1593 cert.get_subject().commonName = "Unit Tests"
1594 cert.get_issuer().commonName = "Unit Tests"
1595 when = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
1596 cert.set_notBefore(when)
1597 cert.set_notAfter(when)
1598
1599 cert.add_extensions(extensions)
Jeff Tangfc18f7b2015-04-15 17:42:33 -04001600 cert.sign(pkey, 'sha1')
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001601 return load_certificate(
1602 FILETYPE_PEM, dump_certificate(FILETYPE_PEM, cert))
1603
1604
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001605 def test_extension_count(self):
1606 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001607 :py:obj:`X509.get_extension_count` returns the number of extensions that are
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001608 present in the certificate.
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001609 """
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001610 pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001611 ca = X509Extension(b('basicConstraints'), True, b('CA:FALSE'))
1612 key = X509Extension(b('keyUsage'), True, b('digitalSignature'))
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001613 subjectAltName = X509Extension(
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001614 b('subjectAltName'), True, b('DNS:example.com'))
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001615
1616 # Try a certificate with no extensions at all.
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001617 c = self._extcert(pkey, [])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001618 self.assertEqual(c.get_extension_count(), 0)
1619
1620 # And a certificate with one
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001621 c = self._extcert(pkey, [ca])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001622 self.assertEqual(c.get_extension_count(), 1)
1623
1624 # And a certificate with several
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001625 c = self._extcert(pkey, [ca, key, subjectAltName])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001626 self.assertEqual(c.get_extension_count(), 3)
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001627
1628
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001629 def test_get_extension(self):
1630 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001631 :py:obj:`X509.get_extension` takes an integer and returns an :py:obj:`X509Extension`
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001632 corresponding to the extension at that index.
1633 """
1634 pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001635 ca = X509Extension(b('basicConstraints'), True, b('CA:FALSE'))
1636 key = X509Extension(b('keyUsage'), True, b('digitalSignature'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001637 subjectAltName = X509Extension(
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001638 b('subjectAltName'), False, b('DNS:example.com'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001639
1640 cert = self._extcert(pkey, [ca, key, subjectAltName])
1641
1642 ext = cert.get_extension(0)
1643 self.assertTrue(isinstance(ext, X509Extension))
1644 self.assertTrue(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001645 self.assertEqual(ext.get_short_name(), b('basicConstraints'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001646
1647 ext = cert.get_extension(1)
1648 self.assertTrue(isinstance(ext, X509Extension))
1649 self.assertTrue(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001650 self.assertEqual(ext.get_short_name(), b('keyUsage'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001651
1652 ext = cert.get_extension(2)
1653 self.assertTrue(isinstance(ext, X509Extension))
1654 self.assertFalse(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001655 self.assertEqual(ext.get_short_name(), b('subjectAltName'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001656
1657 self.assertRaises(IndexError, cert.get_extension, -1)
1658 self.assertRaises(IndexError, cert.get_extension, 4)
1659 self.assertRaises(TypeError, cert.get_extension, "hello")
1660
1661
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001662 def test_nullbyte_subjectAltName(self):
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001663 """
Jean-Paul Calderone9af07b02013-08-23 16:07:31 -04001664 The fields of a `subjectAltName` extension on an X509 may contain NUL
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001665 bytes and this value is reflected in the string representation of the
1666 extension object.
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001667 """
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001668 cert = load_certificate(FILETYPE_PEM, nulbyteSubjectAltNamePEM)
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001669
1670 ext = cert.get_extension(3)
1671 self.assertEqual(ext.get_short_name(), b('subjectAltName'))
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001672 self.assertEqual(
1673 b("DNS:altnull.python.org\x00example.com, "
1674 "email:null@python.org\x00user@example.org, "
1675 "URI:http://null.python.org\x00http://example.org, "
1676 "IP Address:192.0.2.1, IP Address:2001:DB8:0:0:0:0:0:1\n"),
1677 b(str(ext)))
1678
Rick Dean38a05c82009-07-18 01:41:30 -05001679
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001680 def test_invalid_digest_algorithm(self):
1681 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001682 :py:obj:`X509.digest` raises :py:obj:`ValueError` if called with an unrecognized hash
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001683 algorithm.
1684 """
1685 cert = X509()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001686 self.assertRaises(ValueError, cert.digest, BAD_DIGEST)
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001687
1688
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001689 def test_get_subject_wrong_args(self):
1690 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001691 :py:obj:`X509.get_subject` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001692 """
1693 cert = X509()
1694 self.assertRaises(TypeError, cert.get_subject, None)
1695
1696
1697 def test_get_subject(self):
1698 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001699 :py:obj:`X509.get_subject` returns an :py:obj:`X509Name` instance.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001700 """
1701 cert = load_certificate(FILETYPE_PEM, self.pemData)
1702 subj = cert.get_subject()
1703 self.assertTrue(isinstance(subj, X509Name))
1704 self.assertEquals(
1705 subj.get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001706 [(b('C'), b('US')), (b('ST'), b('IL')), (b('L'), b('Chicago')),
1707 (b('O'), b('Testing')), (b('CN'), b('Testing Root CA'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001708
1709
1710 def test_set_subject_wrong_args(self):
1711 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001712 :py:obj:`X509.set_subject` raises a :py:obj:`TypeError` if called with the wrong
1713 number of arguments or an argument not of type :py:obj:`X509Name`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001714 """
1715 cert = X509()
1716 self.assertRaises(TypeError, cert.set_subject)
1717 self.assertRaises(TypeError, cert.set_subject, None)
1718 self.assertRaises(TypeError, cert.set_subject, cert.get_subject(), None)
1719
1720
1721 def test_set_subject(self):
1722 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001723 :py:obj:`X509.set_subject` changes the subject of the certificate to the one
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001724 passed in.
1725 """
1726 cert = X509()
1727 name = cert.get_subject()
1728 name.C = 'AU'
1729 name.O = 'Unit Tests'
1730 cert.set_subject(name)
1731 self.assertEquals(
1732 cert.get_subject().get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001733 [(b('C'), b('AU')), (b('O'), b('Unit Tests'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001734
1735
1736 def test_get_issuer_wrong_args(self):
1737 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001738 :py:obj:`X509.get_issuer` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001739 """
1740 cert = X509()
1741 self.assertRaises(TypeError, cert.get_issuer, None)
1742
1743
1744 def test_get_issuer(self):
1745 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001746 :py:obj:`X509.get_issuer` returns an :py:obj:`X509Name` instance.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001747 """
1748 cert = load_certificate(FILETYPE_PEM, self.pemData)
1749 subj = cert.get_issuer()
1750 self.assertTrue(isinstance(subj, X509Name))
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001751 comp = subj.get_components()
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001752 self.assertEquals(
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001753 comp,
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001754 [(b('C'), b('US')), (b('ST'), b('IL')), (b('L'), b('Chicago')),
1755 (b('O'), b('Testing')), (b('CN'), b('Testing Root CA'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001756
1757
1758 def test_set_issuer_wrong_args(self):
1759 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001760 :py:obj:`X509.set_issuer` raises a :py:obj:`TypeError` if called with the wrong
1761 number of arguments or an argument not of type :py:obj:`X509Name`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001762 """
1763 cert = X509()
1764 self.assertRaises(TypeError, cert.set_issuer)
1765 self.assertRaises(TypeError, cert.set_issuer, None)
1766 self.assertRaises(TypeError, cert.set_issuer, cert.get_issuer(), None)
1767
1768
1769 def test_set_issuer(self):
1770 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001771 :py:obj:`X509.set_issuer` changes the issuer of the certificate to the one
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001772 passed in.
1773 """
1774 cert = X509()
1775 name = cert.get_issuer()
1776 name.C = 'AU'
1777 name.O = 'Unit Tests'
1778 cert.set_issuer(name)
1779 self.assertEquals(
1780 cert.get_issuer().get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001781 [(b('C'), b('AU')), (b('O'), b('Unit Tests'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001782
1783
1784 def test_get_pubkey_uninitialized(self):
1785 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001786 When called on a certificate with no public key, :py:obj:`X509.get_pubkey`
1787 raises :py:obj:`OpenSSL.crypto.Error`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001788 """
1789 cert = X509()
1790 self.assertRaises(Error, cert.get_pubkey)
1791
1792
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001793 def test_subject_name_hash_wrong_args(self):
1794 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001795 :py:obj:`X509.subject_name_hash` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001796 arguments.
1797 """
1798 cert = X509()
1799 self.assertRaises(TypeError, cert.subject_name_hash, None)
1800
1801
1802 def test_subject_name_hash(self):
1803 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001804 :py:obj:`X509.subject_name_hash` returns the hash of the certificate's subject
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001805 name.
1806 """
1807 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -04001808 self.assertIn(
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001809 cert.subject_name_hash(),
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -04001810 [3350047874, # OpenSSL 0.9.8, MD5
1811 3278919224, # OpenSSL 1.0.0, SHA1
1812 ])
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001813
1814
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001815 def test_get_signature_algorithm(self):
1816 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001817 :py:obj:`X509Type.get_signature_algorithm` returns a string which means
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001818 the algorithm used to sign the certificate.
1819 """
1820 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001821 self.assertEqual(
1822 b("sha1WithRSAEncryption"), cert.get_signature_algorithm())
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001823
1824
1825 def test_get_undefined_signature_algorithm(self):
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001826 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001827 :py:obj:`X509Type.get_signature_algorithm` raises :py:obj:`ValueError` if the
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001828 signature algorithm is undefined or unknown.
1829 """
1830 # This certificate has been modified to indicate a bogus OID in the
1831 # signature algorithm field so that OpenSSL does not recognize it.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001832 certPEM = b("""\
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001833-----BEGIN CERTIFICATE-----
1834MIIC/zCCAmigAwIBAgIBATAGBgJ8BQUAMHsxCzAJBgNVBAYTAlNHMREwDwYDVQQK
1835EwhNMkNyeXB0bzEUMBIGA1UECxMLTTJDcnlwdG8gQ0ExJDAiBgNVBAMTG00yQ3J5
1836cHRvIENlcnRpZmljYXRlIE1hc3RlcjEdMBsGCSqGSIb3DQEJARYObmdwc0Bwb3N0
1837MS5jb20wHhcNMDAwOTEwMDk1MTMwWhcNMDIwOTEwMDk1MTMwWjBTMQswCQYDVQQG
1838EwJTRzERMA8GA1UEChMITTJDcnlwdG8xEjAQBgNVBAMTCWxvY2FsaG9zdDEdMBsG
1839CSqGSIb3DQEJARYObmdwc0Bwb3N0MS5jb20wXDANBgkqhkiG9w0BAQEFAANLADBI
1840AkEArL57d26W9fNXvOhNlZzlPOACmvwOZ5AdNgLzJ1/MfsQQJ7hHVeHmTAjM664V
1841+fXvwUGJLziCeBo1ysWLRnl8CQIDAQABo4IBBDCCAQAwCQYDVR0TBAIwADAsBglg
1842hkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0O
1843BBYEFM+EgpK+eyZiwFU1aOPSbczbPSpVMIGlBgNVHSMEgZ0wgZqAFPuHI2nrnDqT
1844FeXFvylRT/7tKDgBoX+kfTB7MQswCQYDVQQGEwJTRzERMA8GA1UEChMITTJDcnlw
1845dG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtNMkNyeXB0byBDZXJ0
1846aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tggEA
1847MA0GCSqGSIb3DQEBBAUAA4GBADv8KpPo+gfJxN2ERK1Y1l17sz/ZhzoGgm5XCdbx
1848jEY7xKfpQngV599k1xhl11IMqizDwu0855agrckg2MCTmOI9DZzDD77tAYb+Dk0O
1849PEVk0Mk/V0aIsDE9bolfCi/i/QWZ3N8s5nTWMNyBBBmoSliWCm4jkkRZRD0ejgTN
1850tgI5
1851-----END CERTIFICATE-----
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001852""")
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001853 cert = load_certificate(FILETYPE_PEM, certPEM)
1854 self.assertRaises(ValueError, cert.get_signature_algorithm)
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001855
1856
Rick Dean38a05c82009-07-18 01:41:30 -05001857
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001858class X509StoreTests(TestCase):
1859 """
1860 Test for :py:obj:`OpenSSL.crypto.X509Store`.
1861 """
1862 def test_type(self):
1863 """
1864 :py:obj:`X509StoreType` is a type object.
1865 """
1866 self.assertIdentical(X509Store, X509StoreType)
1867 self.assertConsistentType(X509Store, 'X509Store')
1868
1869
1870 def test_add_cert_wrong_args(self):
1871 store = X509Store()
1872 self.assertRaises(TypeError, store.add_cert)
1873 self.assertRaises(TypeError, store.add_cert, object())
1874 self.assertRaises(TypeError, store.add_cert, X509(), object())
1875
1876
1877 def test_add_cert(self):
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001878 """
1879 :py:obj:`X509Store.add_cert` adds a :py:obj:`X509` instance to the
1880 certificate store.
1881 """
1882 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001883 store = X509Store()
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001884 store.add_cert(cert)
1885
1886
1887 def test_add_cert_rejects_duplicate(self):
1888 """
1889 :py:obj:`X509Store.add_cert` raises :py:obj:`OpenSSL.crypto.Error` if an
1890 attempt is made to add the same certificate to the store more than once.
1891 """
1892 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
1893 store = X509Store()
1894 store.add_cert(cert)
1895 self.assertRaises(Error, store.add_cert, cert)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001896
1897
1898
Rick Dean623ee362009-07-17 12:22:16 -05001899class PKCS12Tests(TestCase):
1900 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001901 Test for :py:obj:`OpenSSL.crypto.PKCS12` and :py:obj:`OpenSSL.crypto.load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001902 """
1903 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
1904
Jean-Paul Calderonec3a41f72009-07-25 12:36:02 -04001905 def test_type(self):
1906 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001907 :py:obj:`PKCS12Type` is a type object.
Jean-Paul Calderonec3a41f72009-07-25 12:36:02 -04001908 """
1909 self.assertIdentical(PKCS12, PKCS12Type)
1910 self.assertConsistentType(PKCS12, 'PKCS12')
1911
1912
Rick Deanf94096c2009-07-18 14:23:06 -05001913 def test_empty_construction(self):
Rick Dean38a05c82009-07-18 01:41:30 -05001914 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001915 :py:obj:`PKCS12` returns a new instance of :py:obj:`PKCS12` with no certificate,
Jean-Paul Calderonedc857b52009-07-25 12:25:07 -04001916 private key, CA certificates, or friendly name.
Rick Dean38a05c82009-07-18 01:41:30 -05001917 """
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001918 p12 = PKCS12()
Rick Dean623ee362009-07-17 12:22:16 -05001919 self.assertEqual(None, p12.get_certificate())
1920 self.assertEqual(None, p12.get_privatekey())
1921 self.assertEqual(None, p12.get_ca_certificates())
Rick Dean42d69e12009-07-20 11:36:08 -05001922 self.assertEqual(None, p12.get_friendlyname())
Rick Dean623ee362009-07-17 12:22:16 -05001923
Rick Dean38a05c82009-07-18 01:41:30 -05001924
Rick Dean623ee362009-07-17 12:22:16 -05001925 def test_type_errors(self):
Rick Dean38a05c82009-07-18 01:41:30 -05001926 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001927 The :py:obj:`PKCS12` setter functions (:py:obj:`set_certificate`, :py:obj:`set_privatekey`,
1928 :py:obj:`set_ca_certificates`, and :py:obj:`set_friendlyname`) raise :py:obj:`TypeError`
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001929 when passed objects of types other than those expected.
Rick Dean38a05c82009-07-18 01:41:30 -05001930 """
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001931 p12 = PKCS12()
Rick Dean623ee362009-07-17 12:22:16 -05001932 self.assertRaises(TypeError, p12.set_certificate, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05001933 self.assertRaises(TypeError, p12.set_certificate, PKey())
1934 self.assertRaises(TypeError, p12.set_certificate, X509)
Rick Dean623ee362009-07-17 12:22:16 -05001935 self.assertRaises(TypeError, p12.set_privatekey, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05001936 self.assertRaises(TypeError, p12.set_privatekey, 'legbone')
1937 self.assertRaises(TypeError, p12.set_privatekey, X509())
Rick Dean623ee362009-07-17 12:22:16 -05001938 self.assertRaises(TypeError, p12.set_ca_certificates, 3)
1939 self.assertRaises(TypeError, p12.set_ca_certificates, X509())
1940 self.assertRaises(TypeError, p12.set_ca_certificates, (3, 4))
Rick Deanf94096c2009-07-18 14:23:06 -05001941 self.assertRaises(TypeError, p12.set_ca_certificates, ( PKey(), ))
Rick Dean42d69e12009-07-20 11:36:08 -05001942 self.assertRaises(TypeError, p12.set_friendlyname, 6)
1943 self.assertRaises(TypeError, p12.set_friendlyname, ('foo', 'bar'))
Rick Dean623ee362009-07-17 12:22:16 -05001944
Rick Dean38a05c82009-07-18 01:41:30 -05001945
Rick Dean623ee362009-07-17 12:22:16 -05001946 def test_key_only(self):
1947 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001948 A :py:obj:`PKCS12` with only a private key can be exported using
1949 :py:obj:`PKCS12.export` and loaded again using :py:obj:`load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001950 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001951 passwd = b"blah"
Rick Dean623ee362009-07-17 12:22:16 -05001952 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001953 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001954 p12.set_privatekey(pkey)
Rick Dean623ee362009-07-17 12:22:16 -05001955 self.assertEqual(None, p12.get_certificate())
1956 self.assertEqual(pkey, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05001957 try:
1958 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
1959 except Error:
1960 # Some versions of OpenSSL will throw an exception
1961 # for this nearly useless PKCS12 we tried to generate:
1962 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
1963 return
Rick Dean623ee362009-07-17 12:22:16 -05001964 p12 = load_pkcs12(dumped_p12, passwd)
1965 self.assertEqual(None, p12.get_ca_certificates())
1966 self.assertEqual(None, p12.get_certificate())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001967
1968 # OpenSSL fails to bring the key back to us. So sad. Perhaps in the
1969 # future this will be improved.
1970 self.assertTrue(isinstance(p12.get_privatekey(), (PKey, type(None))))
Rick Dean623ee362009-07-17 12:22:16 -05001971
Rick Dean38a05c82009-07-18 01:41:30 -05001972
Rick Dean623ee362009-07-17 12:22:16 -05001973 def test_cert_only(self):
1974 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001975 A :py:obj:`PKCS12` with only a certificate can be exported using
1976 :py:obj:`PKCS12.export` and loaded again using :py:obj:`load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001977 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001978 passwd = b"blah"
Rick Dean623ee362009-07-17 12:22:16 -05001979 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001980 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001981 p12.set_certificate(cert)
Rick Dean623ee362009-07-17 12:22:16 -05001982 self.assertEqual(cert, p12.get_certificate())
1983 self.assertEqual(None, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05001984 try:
1985 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
1986 except Error:
1987 # Some versions of OpenSSL will throw an exception
1988 # for this nearly useless PKCS12 we tried to generate:
1989 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
1990 return
Rick Dean623ee362009-07-17 12:22:16 -05001991 p12 = load_pkcs12(dumped_p12, passwd)
1992 self.assertEqual(None, p12.get_privatekey())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001993
1994 # OpenSSL fails to bring the cert back to us. Groany mcgroan.
1995 self.assertTrue(isinstance(p12.get_certificate(), (X509, type(None))))
1996
1997 # Oh ho. It puts the certificate into the ca certificates list, in
1998 # fact. Totally bogus, I would think. Nevertheless, let's exploit
1999 # that to check to see if it reconstructed the certificate we expected
2000 # it to. At some point, hopefully this will change so that
2001 # p12.get_certificate() is actually what returns the loaded
2002 # certificate.
2003 self.assertEqual(
2004 cleartextCertificatePEM,
2005 dump_certificate(FILETYPE_PEM, p12.get_ca_certificates()[0]))
Rick Dean623ee362009-07-17 12:22:16 -05002006
2007
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002008 def gen_pkcs12(self, cert_pem=None, key_pem=None, ca_pem=None, friendly_name=None):
Rick Dean623ee362009-07-17 12:22:16 -05002009 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002010 Generate a PKCS12 object with components from PEM. Verify that the set
2011 functions return None.
Rick Dean623ee362009-07-17 12:22:16 -05002012 """
Rick Deanf94096c2009-07-18 14:23:06 -05002013 p12 = PKCS12()
2014 if cert_pem:
2015 ret = p12.set_certificate(load_certificate(FILETYPE_PEM, cert_pem))
2016 self.assertEqual(ret, None)
2017 if key_pem:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002018 ret = p12.set_privatekey(load_privatekey(FILETYPE_PEM, key_pem))
Rick Deanf94096c2009-07-18 14:23:06 -05002019 self.assertEqual(ret, None)
2020 if ca_pem:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002021 ret = p12.set_ca_certificates((load_certificate(FILETYPE_PEM, ca_pem),))
Rick Deanf94096c2009-07-18 14:23:06 -05002022 self.assertEqual(ret, None)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002023 if friendly_name:
2024 ret = p12.set_friendlyname(friendly_name)
Rick Dean42d69e12009-07-20 11:36:08 -05002025 self.assertEqual(ret, None)
Rick Deanf94096c2009-07-18 14:23:06 -05002026 return p12
2027
2028
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002029 def check_recovery(self, p12_str, key=None, cert=None, ca=None, passwd=b"",
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002030 extra=()):
Rick Deanf94096c2009-07-18 14:23:06 -05002031 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002032 Use openssl program to confirm three components are recoverable from a
2033 PKCS12 string.
Rick Deanf94096c2009-07-18 14:23:06 -05002034 """
2035 if key:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002036 recovered_key = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002037 p12_str, b"pkcs12", b"-nocerts", b"-nodes", b"-passin",
2038 b"pass:" + passwd, *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05002039 self.assertEqual(recovered_key[-len(key):], key)
2040 if cert:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002041 recovered_cert = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002042 p12_str, b"pkcs12", b"-clcerts", b"-nodes", b"-passin",
2043 b"pass:" + passwd, b"-nokeys", *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05002044 self.assertEqual(recovered_cert[-len(cert):], cert)
2045 if ca:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002046 recovered_cert = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002047 p12_str, b"pkcs12", b"-cacerts", b"-nodes", b"-passin",
2048 b"pass:" + passwd, b"-nokeys", *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05002049 self.assertEqual(recovered_cert[-len(ca):], ca)
2050
2051
Stephen Holsapple38482622014-04-05 20:29:34 -07002052 def verify_pkcs12_container(self, p12):
2053 """
2054 Verify that the PKCS#12 container contains the correct client
2055 certificate and private key.
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002056
2057 :param p12: The PKCS12 instance to verify.
2058 :type p12: :py:class:`PKCS12`
Stephen Holsapple38482622014-04-05 20:29:34 -07002059 """
2060 cert_pem = dump_certificate(FILETYPE_PEM, p12.get_certificate())
2061 key_pem = dump_privatekey(FILETYPE_PEM, p12.get_privatekey())
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002062 self.assertEqual(
2063 (client_cert_pem, client_key_pem, None),
2064 (cert_pem, key_pem, p12.get_ca_certificates()))
Stephen Holsapple38482622014-04-05 20:29:34 -07002065
2066
Rick Deanf94096c2009-07-18 14:23:06 -05002067 def test_load_pkcs12(self):
2068 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002069 A PKCS12 string generated using the openssl command line can be loaded
Jonathan Ballet648875f2011-07-16 14:14:58 +09002070 with :py:obj:`load_pkcs12` and its components extracted and examined.
Rick Deanf94096c2009-07-18 14:23:06 -05002071 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002072 passwd = b"whatever"
Rick Dean623ee362009-07-17 12:22:16 -05002073 pem = client_key_pem + client_cert_pem
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002074 p12_str = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002075 pem, b"pkcs12", b"-export", b"-clcerts", b"-passout", b"pass:" + passwd)
Stephen Holsapple38482622014-04-05 20:29:34 -07002076 p12 = load_pkcs12(p12_str, passphrase=passwd)
2077 self.verify_pkcs12_container(p12)
2078
2079
Abraham Martinc5484ba2015-03-25 15:33:05 +00002080 def test_load_pkcs12_text_passphrase(self):
2081 """
2082 A PKCS12 string generated using the openssl command line can be loaded
2083 with :py:obj:`load_pkcs12` and its components extracted and examined.
2084 Using text as passphrase instead of bytes. DeprecationWarning expected.
2085 """
2086 pem = client_key_pem + client_cert_pem
2087 passwd = b"whatever"
2088 p12_str = _runopenssl(pem, b"pkcs12", b"-export", b"-clcerts",
2089 b"-passout", b"pass:" + passwd)
2090 with catch_warnings(record=True) as w:
2091 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002092 p12 = load_pkcs12(p12_str, passphrase=b"whatever".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002093
2094 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002095 "{0} for passphrase is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002096 WARNING_TYPE_EXPECTED
2097 ),
2098 str(w[-1].message)
2099 )
2100 self.assertIs(w[-1].category, DeprecationWarning)
2101
Abraham Martinc5484ba2015-03-25 15:33:05 +00002102 self.verify_pkcs12_container(p12)
2103
2104
Stephen Holsapple38482622014-04-05 20:29:34 -07002105 def test_load_pkcs12_no_passphrase(self):
2106 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002107 A PKCS12 string generated using openssl command line can be loaded with
2108 :py:obj:`load_pkcs12` without a passphrase and its components extracted
2109 and examined.
Stephen Holsapple38482622014-04-05 20:29:34 -07002110 """
2111 pem = client_key_pem + client_cert_pem
2112 p12_str = _runopenssl(
2113 pem, b"pkcs12", b"-export", b"-clcerts", b"-passout", b"pass:")
2114 p12 = load_pkcs12(p12_str)
2115 self.verify_pkcs12_container(p12)
2116
2117
2118 def _dump_and_load(self, dump_passphrase, load_passphrase):
2119 """
2120 A helper method to dump and load a PKCS12 object.
2121 """
2122 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem)
2123 dumped_p12 = p12.export(passphrase=dump_passphrase, iter=2, maciter=3)
2124 return load_pkcs12(dumped_p12, passphrase=load_passphrase)
2125
2126
2127 def test_load_pkcs12_null_passphrase_load_empty(self):
2128 """
2129 A PKCS12 string can be dumped with a null passphrase, loaded with an
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002130 empty passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002131 extracted and examined.
2132 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002133 self.verify_pkcs12_container(
2134 self._dump_and_load(dump_passphrase=None, load_passphrase=b''))
Stephen Holsapple38482622014-04-05 20:29:34 -07002135
2136
2137 def test_load_pkcs12_null_passphrase_load_null(self):
2138 """
2139 A PKCS12 string can be dumped with a null passphrase, loaded with a
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002140 null passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002141 extracted and examined.
2142 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002143 self.verify_pkcs12_container(
2144 self._dump_and_load(dump_passphrase=None, load_passphrase=None))
Stephen Holsapple38482622014-04-05 20:29:34 -07002145
2146
2147 def test_load_pkcs12_empty_passphrase_load_empty(self):
2148 """
2149 A PKCS12 string can be dumped with an empty passphrase, loaded with an
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002150 empty passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002151 extracted and examined.
2152 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002153 self.verify_pkcs12_container(
2154 self._dump_and_load(dump_passphrase=b'', load_passphrase=b''))
Stephen Holsapple38482622014-04-05 20:29:34 -07002155
2156
2157 def test_load_pkcs12_empty_passphrase_load_null(self):
2158 """
2159 A PKCS12 string can be dumped with an empty passphrase, loaded with a
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002160 null passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002161 extracted and examined.
2162 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002163 self.verify_pkcs12_container(
2164 self._dump_and_load(dump_passphrase=b'', load_passphrase=None))
Rick Deanf94096c2009-07-18 14:23:06 -05002165
Rick Deanee568302009-07-24 09:56:29 -05002166
2167 def test_load_pkcs12_garbage(self):
2168 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002169 :py:obj:`load_pkcs12` raises :py:obj:`OpenSSL.crypto.Error` when passed a string
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002170 which is not a PKCS12 dump.
Rick Deanee568302009-07-24 09:56:29 -05002171 """
2172 passwd = 'whatever'
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002173 e = self.assertRaises(Error, load_pkcs12, b'fruit loops', passwd)
Jean-Paul Calderonede075462014-01-18 10:34:12 -05002174 self.assertEqual( e.args[0][0][0], 'asn1 encoding routines')
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -04002175 self.assertEqual( len(e.args[0][0]), 3)
Rick Deanee568302009-07-24 09:56:29 -05002176
2177
Rick Deanf94096c2009-07-18 14:23:06 -05002178 def test_replace(self):
2179 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002180 :py:obj:`PKCS12.set_certificate` replaces the certificate in a PKCS12 cluster.
2181 :py:obj:`PKCS12.set_privatekey` replaces the private key.
2182 :py:obj:`PKCS12.set_ca_certificates` replaces the CA certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05002183 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002184 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
2185 p12.set_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2186 p12.set_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002187 root_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05002188 client_cert = load_certificate(FILETYPE_PEM, client_cert_pem)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002189 p12.set_ca_certificates([root_cert]) # not a tuple
Rick Dean623ee362009-07-17 12:22:16 -05002190 self.assertEqual(1, len(p12.get_ca_certificates()))
2191 self.assertEqual(root_cert, p12.get_ca_certificates()[0])
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002192 p12.set_ca_certificates([client_cert, root_cert])
Rick Deanf94096c2009-07-18 14:23:06 -05002193 self.assertEqual(2, len(p12.get_ca_certificates()))
2194 self.assertEqual(client_cert, p12.get_ca_certificates()[0])
2195 self.assertEqual(root_cert, p12.get_ca_certificates()[1])
2196
2197
2198 def test_friendly_name(self):
2199 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002200 The *friendlyName* of a PKCS12 can be set and retrieved via
Jonathan Ballet648875f2011-07-16 14:14:58 +09002201 :py:obj:`PKCS12.get_friendlyname` and :py:obj:`PKCS12_set_friendlyname`, and a
2202 :py:obj:`PKCS12` with a friendly name set can be dumped with :py:obj:`PKCS12.export`.
Rick Deanf94096c2009-07-18 14:23:06 -05002203 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002204 passwd = b'Dogmeat[]{}!@#$%^&*()~`?/.,<>-_+=";:'
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002205 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -04002206 for friendly_name in [b('Serverlicious'), None, b('###')]:
Rick Dean42d69e12009-07-20 11:36:08 -05002207 p12.set_friendlyname(friendly_name)
2208 self.assertEqual(p12.get_friendlyname(), friendly_name)
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002209 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
Rick Dean42d69e12009-07-20 11:36:08 -05002210 reloaded_p12 = load_pkcs12(dumped_p12, passwd)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002211 self.assertEqual(
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -04002212 p12.get_friendlyname(), reloaded_p12.get_friendlyname())
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002213 # We would use the openssl program to confirm the friendly
2214 # name, but it is not possible. The pkcs12 command
2215 # does not store the friendly name in the cert's
Rick Dean42d69e12009-07-20 11:36:08 -05002216 # alias, which we could then extract.
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002217 self.check_recovery(
2218 dumped_p12, key=server_key_pem, cert=server_cert_pem,
2219 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05002220
2221
2222 def test_various_empty_passphrases(self):
2223 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002224 Test that missing, None, and '' passphrases are identical for PKCS12
2225 export.
Rick Deanf94096c2009-07-18 14:23:06 -05002226 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002227 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002228 passwd = b""
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002229 dumped_p12_empty = p12.export(iter=2, maciter=0, passphrase=passwd)
2230 dumped_p12_none = p12.export(iter=3, maciter=2, passphrase=None)
2231 dumped_p12_nopw = p12.export(iter=9, maciter=4)
2232 for dumped_p12 in [dumped_p12_empty, dumped_p12_none, dumped_p12_nopw]:
2233 self.check_recovery(
2234 dumped_p12, key=client_key_pem, cert=client_cert_pem,
2235 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05002236
2237
2238 def test_removing_ca_cert(self):
2239 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002240 Passing :py:obj:`None` to :py:obj:`PKCS12.set_ca_certificates` removes all CA
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002241 certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05002242 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002243 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
2244 p12.set_ca_certificates(None)
Rick Dean623ee362009-07-17 12:22:16 -05002245 self.assertEqual(None, p12.get_ca_certificates())
Rick Deanf94096c2009-07-18 14:23:06 -05002246
2247
2248 def test_export_without_mac(self):
2249 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002250 Exporting a PKCS12 with a :py:obj:`maciter` of ``-1`` excludes the MAC
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002251 entirely.
Rick Deanf94096c2009-07-18 14:23:06 -05002252 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002253 passwd = b"Lake Michigan"
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002254 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Dean623ee362009-07-17 12:22:16 -05002255 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002256 self.check_recovery(
2257 dumped_p12, key=server_key_pem, cert=server_cert_pem,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002258 passwd=passwd, extra=(b"-nomacver",))
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002259
2260
2261 def test_load_without_mac(self):
2262 """
2263 Loading a PKCS12 without a MAC does something other than crash.
2264 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002265 passwd = b"Lake Michigan"
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002266 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
2267 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Rick Dean321a0512009-08-13 17:21:29 -05002268 try:
2269 recovered_p12 = load_pkcs12(dumped_p12, passwd)
2270 # The person who generated this PCKS12 should be flogged,
2271 # or better yet we should have a means to determine
2272 # whether a PCKS12 had a MAC that was verified.
2273 # Anyway, libopenssl chooses to allow it, so the
2274 # pyopenssl binding does as well.
2275 self.assertTrue(isinstance(recovered_p12, PKCS12))
2276 except Error:
2277 # Failing here with an exception is preferred as some openssl
2278 # versions do.
2279 pass
Rick Dean623ee362009-07-17 12:22:16 -05002280
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002281
Rick Dean25bcc1f2009-07-20 11:53:13 -05002282 def test_zero_len_list_for_ca(self):
2283 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002284 A PKCS12 with an empty CA certificates list can be exported.
Rick Dean25bcc1f2009-07-20 11:53:13 -05002285 """
2286 passwd = 'Hobie 18'
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002287 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002288 # p12.set_ca_certificates([])
2289 # self.assertEqual((), p12.get_ca_certificates())
2290 # dumped_p12 = p12.export(passphrase=passwd, iter=3)
2291 # self.check_recovery(
2292 # dumped_p12, key=server_key_pem, cert=server_cert_pem,
2293 # passwd=passwd)
Rick Dean25bcc1f2009-07-20 11:53:13 -05002294
2295
Rick Deanf94096c2009-07-18 14:23:06 -05002296 def test_export_without_args(self):
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002297 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002298 All the arguments to :py:obj:`PKCS12.export` are optional.
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002299 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002300 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05002301 dumped_p12 = p12.export() # no args
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002302 self.check_recovery(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002303 dumped_p12, key=server_key_pem, cert=server_cert_pem, passwd=b"")
Rick Deanf94096c2009-07-18 14:23:06 -05002304
2305
Abraham Martinc5484ba2015-03-25 15:33:05 +00002306 def test_export_without_bytes(self):
2307 """
2308 Test :py:obj:`PKCS12.export` with text not bytes as passphrase
2309 """
2310 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
2311
2312 with catch_warnings(record=True) as w:
2313 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002314 dumped_p12 = p12.export(passphrase=b"randomtext".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002315 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002316 "{0} for passphrase is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002317 WARNING_TYPE_EXPECTED
2318 ),
2319 str(w[-1].message)
2320 )
2321 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinc5484ba2015-03-25 15:33:05 +00002322 self.check_recovery(
2323 dumped_p12, key=server_key_pem, cert=server_cert_pem, passwd=b"randomtext")
2324
2325
Rick Deanf94096c2009-07-18 14:23:06 -05002326 def test_key_cert_mismatch(self):
2327 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002328 :py:obj:`PKCS12.export` raises an exception when a key and certificate
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002329 mismatch.
Rick Deanf94096c2009-07-18 14:23:06 -05002330 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002331 p12 = self.gen_pkcs12(server_cert_pem, client_key_pem, root_cert_pem)
2332 self.assertRaises(Error, p12.export)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002333
2334
2335
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002336# These quoting functions taken directly from Twisted's twisted.python.win32.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002337_cmdLineQuoteRe = re.compile(br'(\\*)"')
2338_cmdLineQuoteRe2 = re.compile(br'(\\+)\Z')
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002339def cmdLineQuote(s):
2340 """
2341 Internal method for quoting a single command-line argument.
2342
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002343 See http://www.perlmonks.org/?node_id=764004
2344
Jonathan Ballet648875f2011-07-16 14:14:58 +09002345 :type: :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002346 :param s: A single unquoted string to quote for something that is expecting
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002347 cmd.exe-style quoting
2348
Jonathan Ballet648875f2011-07-16 14:14:58 +09002349 :rtype: :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002350 :return: A cmd.exe-style quoted string
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002351 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002352 s = _cmdLineQuoteRe2.sub(br"\1\1", _cmdLineQuoteRe.sub(br'\1\1\\"', s))
2353 return b'"' + s + b'"'
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002354
2355
2356
2357def quoteArguments(arguments):
2358 """
2359 Quote an iterable of command-line arguments for passing to CreateProcess or
Jonathan Ballet648875f2011-07-16 14:14:58 +09002360 a similar API. This allows the list passed to :py:obj:`reactor.spawnProcess` to
2361 match the child process's :py:obj:`sys.argv` properly.
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002362
Jonathan Ballet648875f2011-07-16 14:14:58 +09002363 :type arguments: :py:obj:`iterable` of :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002364 :param arguments: An iterable of unquoted arguments to quote
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002365
Jonathan Ballet648875f2011-07-16 14:14:58 +09002366 :rtype: :py:obj:`str`
2367 :return: A space-delimited string containing quoted versions of :py:obj:`arguments`
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002368 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002369 return b' '.join(map(cmdLineQuote, arguments))
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002370
2371
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002372
Rick Dean4c9ad612009-07-17 15:05:22 -05002373def _runopenssl(pem, *args):
2374 """
2375 Run the command line openssl tool with the given arguments and write
Rick Dean55d1ce62009-08-13 17:40:24 -05002376 the given PEM to its stdin. Not safe for quotes.
Rick Dean4c9ad612009-07-17 15:05:22 -05002377 """
Jean-Paul Calderone038de952009-08-21 12:16:06 -04002378 if os.name == 'posix':
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002379 command = b"openssl " + b" ".join([
2380 (b"'" + arg.replace(b"'", b"'\\''") + b"'")
2381 for arg in args])
Rick Dean55d1ce62009-08-13 17:40:24 -05002382 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002383 command = b"openssl " + quoteArguments(args)
2384 proc = Popen(native(command), shell=True, stdin=PIPE, stdout=PIPE)
Jean-Paul Calderone62ca8da2010-08-11 19:58:08 -04002385 proc.stdin.write(pem)
2386 proc.stdin.close()
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002387 output = proc.stdout.read()
2388 proc.stdout.close()
2389 proc.wait()
2390 return output
Rick Dean4c9ad612009-07-17 15:05:22 -05002391
2392
2393
Jean-Paul Calderone18808652009-07-05 12:54:05 -04002394class FunctionTests(TestCase):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002395 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002396 Tests for free-functions in the :py:obj:`OpenSSL.crypto` module.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002397 """
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002398
2399 def test_load_privatekey_invalid_format(self):
2400 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002401 :py:obj:`load_privatekey` raises :py:obj:`ValueError` if passed an unknown filetype.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002402 """
2403 self.assertRaises(ValueError, load_privatekey, 100, root_key_pem)
2404
2405
2406 def test_load_privatekey_invalid_passphrase_type(self):
2407 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002408 :py:obj:`load_privatekey` raises :py:obj:`TypeError` if passed a passphrase that is
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002409 neither a :py:obj:`str` nor a callable.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002410 """
2411 self.assertRaises(
2412 TypeError,
2413 load_privatekey,
2414 FILETYPE_PEM, encryptedPrivateKeyPEMPassphrase, object())
2415
2416
2417 def test_load_privatekey_wrong_args(self):
2418 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002419 :py:obj:`load_privatekey` raises :py:obj:`TypeError` if called with the wrong number
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002420 of arguments.
2421 """
2422 self.assertRaises(TypeError, load_privatekey)
2423
2424
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002425 def test_load_privatekey_wrongPassphrase(self):
2426 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002427 :py:obj:`load_privatekey` raises :py:obj:`OpenSSL.crypto.Error` when it is passed an
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002428 encrypted PEM and an incorrect passphrase.
2429 """
2430 self.assertRaises(
2431 Error,
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002432 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, b("quack"))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002433
2434
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002435 def test_load_privatekey_passphraseWrongType(self):
2436 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002437 :py:obj:`load_privatekey` raises :py:obj:`ValueError` when it is passed a passphrase
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002438 with a private key encoded in a format, that doesn't support
2439 encryption.
2440 """
2441 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2442 blob = dump_privatekey(FILETYPE_ASN1, key)
2443 self.assertRaises(ValueError,
2444 load_privatekey, FILETYPE_ASN1, blob, "secret")
2445
2446
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002447 def test_load_privatekey_passphrase(self):
2448 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002449 :py:obj:`load_privatekey` can create a :py:obj:`PKey` object from an encrypted PEM
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002450 string if given the passphrase.
2451 """
2452 key = load_privatekey(
2453 FILETYPE_PEM, encryptedPrivateKeyPEM,
2454 encryptedPrivateKeyPEMPassphrase)
2455 self.assertTrue(isinstance(key, PKeyType))
2456
2457
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002458 def test_load_privatekey_passphrase_exception(self):
2459 """
2460 If the passphrase callback raises an exception, that exception is raised
2461 by :py:obj:`load_privatekey`.
2462 """
2463 def cb(ignored):
2464 raise ArithmeticError
2465
2466 self.assertRaises(ArithmeticError,
2467 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2468
2469
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002470 def test_load_privatekey_wrongPassphraseCallback(self):
2471 """
Jean-Paul Calderoned440a082011-09-14 11:02:05 -04002472 :py:obj:`load_privatekey` raises :py:obj:`OpenSSL.crypto.Error` when it
2473 is passed an encrypted PEM and a passphrase callback which returns an
2474 incorrect passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002475 """
2476 called = []
2477 def cb(*a):
2478 called.append(None)
Jean-Paul Calderoned440a082011-09-14 11:02:05 -04002479 return b("quack")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002480 self.assertRaises(
2481 Error,
2482 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2483 self.assertTrue(called)
2484
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002485
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002486 def test_load_privatekey_passphraseCallback(self):
2487 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002488 :py:obj:`load_privatekey` can create a :py:obj:`PKey` object from an encrypted PEM
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002489 string if given a passphrase callback which returns the correct
2490 password.
2491 """
2492 called = []
2493 def cb(writing):
2494 called.append(writing)
2495 return encryptedPrivateKeyPEMPassphrase
2496 key = load_privatekey(FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2497 self.assertTrue(isinstance(key, PKeyType))
2498 self.assertEqual(called, [False])
2499
2500
Jean-Paul Calderone105cb952011-09-14 10:16:46 -04002501 def test_load_privatekey_passphrase_wrong_return_type(self):
2502 """
2503 :py:obj:`load_privatekey` raises :py:obj:`ValueError` if the passphrase
2504 callback returns something other than a byte string.
2505 """
2506 self.assertRaises(
2507 ValueError,
2508 load_privatekey,
2509 FILETYPE_PEM, encryptedPrivateKeyPEM, lambda *args: 3)
2510
2511
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002512 def test_dump_privatekey_wrong_args(self):
2513 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002514 :py:obj:`dump_privatekey` raises :py:obj:`TypeError` if called with the wrong number
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002515 of arguments.
2516 """
2517 self.assertRaises(TypeError, dump_privatekey)
Jean-Paul Calderone1eeccd82011-09-14 10:18:52 -04002518 # If cipher name is given, password is required.
2519 self.assertRaises(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002520 TypeError, dump_privatekey, FILETYPE_PEM, PKey(), GOOD_CIPHER)
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002521
2522
2523 def test_dump_privatekey_unknown_cipher(self):
2524 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002525 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` if called with an unrecognized
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002526 cipher name.
2527 """
2528 key = PKey()
2529 key.generate_key(TYPE_RSA, 512)
2530 self.assertRaises(
2531 ValueError, dump_privatekey,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002532 FILETYPE_PEM, key, BAD_CIPHER, "passphrase")
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002533
2534
2535 def test_dump_privatekey_invalid_passphrase_type(self):
2536 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002537 :py:obj:`dump_privatekey` raises :py:obj:`TypeError` if called with a passphrase which
2538 is neither a :py:obj:`str` nor a callable.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002539 """
2540 key = PKey()
2541 key.generate_key(TYPE_RSA, 512)
2542 self.assertRaises(
2543 TypeError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002544 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, object())
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002545
2546
2547 def test_dump_privatekey_invalid_filetype(self):
2548 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002549 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` if called with an unrecognized
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002550 filetype.
2551 """
2552 key = PKey()
2553 key.generate_key(TYPE_RSA, 512)
2554 self.assertRaises(ValueError, dump_privatekey, 100, key)
2555
2556
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002557 def test_load_privatekey_passphraseCallbackLength(self):
2558 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002559 :py:obj:`crypto.load_privatekey` should raise an error when the passphrase
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002560 provided by the callback is too long, not silently truncate it.
2561 """
2562 def cb(ignored):
2563 return "a" * 1025
2564
2565 self.assertRaises(ValueError,
2566 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2567
2568
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002569 def test_dump_privatekey_passphrase(self):
2570 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002571 :py:obj:`dump_privatekey` writes an encrypted PEM when given a passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002572 """
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002573 passphrase = b("foo")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002574 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002575 pem = dump_privatekey(FILETYPE_PEM, key, GOOD_CIPHER, passphrase)
2576 self.assertTrue(isinstance(pem, binary_type))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002577 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
2578 self.assertTrue(isinstance(loadedKey, PKeyType))
2579 self.assertEqual(loadedKey.type(), key.type())
2580 self.assertEqual(loadedKey.bits(), key.bits())
2581
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002582
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002583 def test_dump_privatekey_passphraseWrongType(self):
2584 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002585 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` when it is passed a passphrase
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002586 with a private key encoded in a format, that doesn't support
2587 encryption.
2588 """
2589 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2590 self.assertRaises(ValueError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002591 dump_privatekey, FILETYPE_ASN1, key, GOOD_CIPHER, "secret")
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002592
2593
Rick Dean5b7b6372009-04-01 11:34:06 -05002594 def test_dump_certificate(self):
2595 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002596 :py:obj:`dump_certificate` writes PEM, DER, and text.
Rick Dean5b7b6372009-04-01 11:34:06 -05002597 """
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002598 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
Rick Dean5b7b6372009-04-01 11:34:06 -05002599 cert = load_certificate(FILETYPE_PEM, pemData)
2600 dumped_pem = dump_certificate(FILETYPE_PEM, cert)
2601 self.assertEqual(dumped_pem, cleartextCertificatePEM)
2602 dumped_der = dump_certificate(FILETYPE_ASN1, cert)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002603 good_der = _runopenssl(dumped_pem, b"x509", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002604 self.assertEqual(dumped_der, good_der)
2605 cert2 = load_certificate(FILETYPE_ASN1, dumped_der)
2606 dumped_pem2 = dump_certificate(FILETYPE_PEM, cert2)
2607 self.assertEqual(dumped_pem2, cleartextCertificatePEM)
2608 dumped_text = dump_certificate(FILETYPE_TEXT, cert)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002609 good_text = _runopenssl(dumped_pem, b"x509", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002610 self.assertEqual(dumped_text, good_text)
2611
2612
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002613 def test_dump_privatekey_pem(self):
Rick Dean5b7b6372009-04-01 11:34:06 -05002614 """
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002615 :py:obj:`dump_privatekey` writes a PEM
Rick Dean5b7b6372009-04-01 11:34:06 -05002616 """
2617 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -04002618 self.assertTrue(key.check())
Rick Dean5b7b6372009-04-01 11:34:06 -05002619 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2620 self.assertEqual(dumped_pem, cleartextPrivateKeyPEM)
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002621
2622
2623 def test_dump_privatekey_asn1(self):
2624 """
2625 :py:obj:`dump_privatekey` writes a DER
2626 """
2627 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2628 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2629
Rick Dean5b7b6372009-04-01 11:34:06 -05002630 dumped_der = dump_privatekey(FILETYPE_ASN1, key)
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002631 # XXX This OpenSSL call writes "writing RSA key" to standard out. Sad.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002632 good_der = _runopenssl(dumped_pem, b"rsa", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002633 self.assertEqual(dumped_der, good_der)
2634 key2 = load_privatekey(FILETYPE_ASN1, dumped_der)
2635 dumped_pem2 = dump_privatekey(FILETYPE_PEM, key2)
2636 self.assertEqual(dumped_pem2, cleartextPrivateKeyPEM)
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002637
2638
2639 def test_dump_privatekey_text(self):
2640 """
2641 :py:obj:`dump_privatekey` writes a text
2642 """
2643 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2644 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2645
Rick Dean5b7b6372009-04-01 11:34:06 -05002646 dumped_text = dump_privatekey(FILETYPE_TEXT, key)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002647 good_text = _runopenssl(dumped_pem, b"rsa", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002648 self.assertEqual(dumped_text, good_text)
2649
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002650
Rick Dean5b7b6372009-04-01 11:34:06 -05002651 def test_dump_certificate_request(self):
2652 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002653 :py:obj:`dump_certificate_request` writes a PEM, DER, and text.
Rick Dean5b7b6372009-04-01 11:34:06 -05002654 """
2655 req = load_certificate_request(FILETYPE_PEM, cleartextCertificateRequestPEM)
2656 dumped_pem = dump_certificate_request(FILETYPE_PEM, req)
2657 self.assertEqual(dumped_pem, cleartextCertificateRequestPEM)
2658 dumped_der = dump_certificate_request(FILETYPE_ASN1, req)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002659 good_der = _runopenssl(dumped_pem, b"req", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002660 self.assertEqual(dumped_der, good_der)
2661 req2 = load_certificate_request(FILETYPE_ASN1, dumped_der)
2662 dumped_pem2 = dump_certificate_request(FILETYPE_PEM, req2)
2663 self.assertEqual(dumped_pem2, cleartextCertificateRequestPEM)
2664 dumped_text = dump_certificate_request(FILETYPE_TEXT, req)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002665 good_text = _runopenssl(dumped_pem, b"req", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002666 self.assertEqual(dumped_text, good_text)
Jean-Paul Calderoneaf43cdf2010-08-03 18:40:52 -04002667 self.assertRaises(ValueError, dump_certificate_request, 100, req)
Rick Dean5b7b6372009-04-01 11:34:06 -05002668
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002669
2670 def test_dump_privatekey_passphraseCallback(self):
2671 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002672 :py:obj:`dump_privatekey` writes an encrypted PEM when given a callback which
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002673 returns the correct passphrase.
2674 """
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002675 passphrase = b("foo")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002676 called = []
2677 def cb(writing):
2678 called.append(writing)
2679 return passphrase
2680 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002681 pem = dump_privatekey(FILETYPE_PEM, key, GOOD_CIPHER, cb)
2682 self.assertTrue(isinstance(pem, binary_type))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002683 self.assertEqual(called, [True])
2684 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
2685 self.assertTrue(isinstance(loadedKey, PKeyType))
2686 self.assertEqual(loadedKey.type(), key.type())
2687 self.assertEqual(loadedKey.bits(), key.bits())
Rick Dean5b7b6372009-04-01 11:34:06 -05002688
2689
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002690 def test_dump_privatekey_passphrase_exception(self):
2691 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002692 :py:obj:`dump_privatekey` should not overwrite the exception raised
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002693 by the passphrase callback.
2694 """
2695 def cb(ignored):
2696 raise ArithmeticError
2697
2698 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2699 self.assertRaises(ArithmeticError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002700 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, cb)
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002701
2702
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002703 def test_dump_privatekey_passphraseCallbackLength(self):
2704 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002705 :py:obj:`crypto.dump_privatekey` should raise an error when the passphrase
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002706 provided by the callback is too long, not silently truncate it.
2707 """
2708 def cb(ignored):
2709 return "a" * 1025
2710
2711 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2712 self.assertRaises(ValueError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002713 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, cb)
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002714
2715
Alex Gaynor4b9c96a2014-08-14 09:51:48 -07002716 def test_load_pkcs7_data_pem(self):
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002717 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002718 :py:obj:`load_pkcs7_data` accepts a PKCS#7 string and returns an instance of
2719 :py:obj:`PKCS7Type`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002720 """
2721 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2722 self.assertTrue(isinstance(pkcs7, PKCS7Type))
2723
2724
Alex Gaynor4b9c96a2014-08-14 09:51:48 -07002725 def test_load_pkcs7_data_asn1(self):
Alex Gaynor9875a912014-08-14 13:35:05 -07002726 """
2727 :py:obj:`load_pkcs7_data` accepts a bytes containing ASN1 data
2728 representing PKCS#7 and returns an instance of :py:obj`PKCS7Type`.
2729 """
Alex Gaynor4b9c96a2014-08-14 09:51:48 -07002730 pkcs7 = load_pkcs7_data(FILETYPE_ASN1, pkcs7DataASN1)
2731 self.assertTrue(isinstance(pkcs7, PKCS7Type))
2732
2733
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002734 def test_load_pkcs7_data_invalid(self):
2735 """
2736 If the data passed to :py:obj:`load_pkcs7_data` is invalid,
2737 :py:obj:`Error` is raised.
2738 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002739 self.assertRaises(Error, load_pkcs7_data, FILETYPE_PEM, b"foo")
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002740
2741
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002742
Jean-Paul Calderone4a68b402013-12-29 16:54:58 -05002743class LoadCertificateTests(TestCase):
2744 """
2745 Tests for :py:obj:`load_certificate_request`.
2746 """
2747 def test_badFileType(self):
2748 """
2749 If the file type passed to :py:obj:`load_certificate_request` is
2750 neither :py:obj:`FILETYPE_PEM` nor :py:obj:`FILETYPE_ASN1` then
2751 :py:class:`ValueError` is raised.
2752 """
2753 self.assertRaises(ValueError, load_certificate_request, object(), b"")
2754
2755
2756
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002757class PKCS7Tests(TestCase):
2758 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002759 Tests for :py:obj:`PKCS7Type`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002760 """
2761 def test_type(self):
2762 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002763 :py:obj:`PKCS7Type` is a type object.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002764 """
2765 self.assertTrue(isinstance(PKCS7Type, type))
2766 self.assertEqual(PKCS7Type.__name__, 'PKCS7')
2767
2768 # XXX This doesn't currently work.
2769 # self.assertIdentical(PKCS7, PKCS7Type)
2770
2771
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002772 # XXX Opposite results for all these following methods
2773
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002774 def test_type_is_signed_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002775 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002776 :py:obj:`PKCS7Type.type_is_signed` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002777 arguments.
2778 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002779 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2780 self.assertRaises(TypeError, pkcs7.type_is_signed, None)
2781
2782
2783 def test_type_is_signed(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002784 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002785 :py:obj:`PKCS7Type.type_is_signed` returns :py:obj:`True` if the PKCS7 object is of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002786 the type *signed*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002787 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002788 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2789 self.assertTrue(pkcs7.type_is_signed())
2790
2791
2792 def test_type_is_enveloped_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002793 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002794 :py:obj:`PKCS7Type.type_is_enveloped` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002795 arguments.
2796 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002797 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2798 self.assertRaises(TypeError, pkcs7.type_is_enveloped, None)
2799
2800
2801 def test_type_is_enveloped(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002802 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002803 :py:obj:`PKCS7Type.type_is_enveloped` returns :py:obj:`False` if the PKCS7 object is
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002804 not of the type *enveloped*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002805 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002806 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2807 self.assertFalse(pkcs7.type_is_enveloped())
2808
2809
2810 def test_type_is_signedAndEnveloped_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002811 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002812 :py:obj:`PKCS7Type.type_is_signedAndEnveloped` raises :py:obj:`TypeError` if called
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002813 with any arguments.
2814 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002815 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2816 self.assertRaises(TypeError, pkcs7.type_is_signedAndEnveloped, None)
2817
2818
2819 def test_type_is_signedAndEnveloped(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002820 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002821 :py:obj:`PKCS7Type.type_is_signedAndEnveloped` returns :py:obj:`False` if the PKCS7
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002822 object is not of the type *signed and enveloped*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002823 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002824 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2825 self.assertFalse(pkcs7.type_is_signedAndEnveloped())
2826
2827
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002828 def test_type_is_data(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002829 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002830 :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 -04002831 the type data.
2832 """
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002833 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2834 self.assertFalse(pkcs7.type_is_data())
2835
2836
2837 def test_type_is_data_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002838 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002839 :py:obj:`PKCS7Type.type_is_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002840 arguments.
2841 """
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002842 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2843 self.assertRaises(TypeError, pkcs7.type_is_data, None)
2844
2845
Jean-Paul Calderone97b28ca2010-07-30 10:56:07 -04002846 def test_get_type_name_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002847 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002848 :py:obj:`PKCS7Type.get_type_name` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002849 arguments.
2850 """
Jean-Paul Calderone97b28ca2010-07-30 10:56:07 -04002851 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2852 self.assertRaises(TypeError, pkcs7.get_type_name, None)
2853
2854
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002855 def test_get_type_name(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002856 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002857 :py:obj:`PKCS7Type.get_type_name` returns a :py:obj:`str` giving the type name.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002858 """
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002859 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
Jean-Paul Calderone07640f12010-08-22 17:14:43 -04002860 self.assertEquals(pkcs7.get_type_name(), b('pkcs7-signedData'))
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002861
2862
2863 def test_attribute(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002864 """
2865 If an attribute other than one of the methods tested here is accessed on
Jonathan Ballet648875f2011-07-16 14:14:58 +09002866 an instance of :py:obj:`PKCS7Type`, :py:obj:`AttributeError` is raised.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002867 """
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002868 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2869 self.assertRaises(AttributeError, getattr, pkcs7, "foo")
2870
2871
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002872
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002873class NetscapeSPKITests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002874 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002875 Tests for :py:obj:`OpenSSL.crypto.NetscapeSPKI`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002876 """
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002877 def signable(self):
2878 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002879 Return a new :py:obj:`NetscapeSPKI` for use with signing tests.
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002880 """
2881 return NetscapeSPKI()
2882
2883
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002884 def test_type(self):
2885 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002886 :py:obj:`NetscapeSPKI` and :py:obj:`NetscapeSPKIType` refer to the same type object
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002887 and can be used to create instances of that type.
2888 """
2889 self.assertIdentical(NetscapeSPKI, NetscapeSPKIType)
2890 self.assertConsistentType(NetscapeSPKI, 'NetscapeSPKI')
2891
2892
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002893 def test_construction(self):
2894 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002895 :py:obj:`NetscapeSPKI` returns an instance of :py:obj:`NetscapeSPKIType`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002896 """
2897 nspki = NetscapeSPKI()
2898 self.assertTrue(isinstance(nspki, NetscapeSPKIType))
2899
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002900
Jean-Paul Calderone969efaa2010-08-03 18:19:19 -04002901 def test_invalid_attribute(self):
2902 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002903 Accessing a non-existent attribute of a :py:obj:`NetscapeSPKI` instance causes
2904 an :py:obj:`AttributeError` to be raised.
Jean-Paul Calderone969efaa2010-08-03 18:19:19 -04002905 """
2906 nspki = NetscapeSPKI()
2907 self.assertRaises(AttributeError, lambda: nspki.foo)
2908
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002909
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002910 def test_b64_encode(self):
2911 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002912 :py:obj:`NetscapeSPKI.b64_encode` encodes the certificate to a base64 blob.
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002913 """
2914 nspki = NetscapeSPKI()
2915 blob = nspki.b64_encode()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002916 self.assertTrue(isinstance(blob, binary_type))
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002917
2918
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002919
Rick Dean536ba022009-07-24 23:57:27 -05002920class RevokedTests(TestCase):
2921 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002922 Tests for :py:obj:`OpenSSL.crypto.Revoked`
Rick Dean536ba022009-07-24 23:57:27 -05002923 """
2924 def test_construction(self):
2925 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002926 Confirm we can create :py:obj:`OpenSSL.crypto.Revoked`. Check
Rick Dean536ba022009-07-24 23:57:27 -05002927 that it is empty.
2928 """
2929 revoked = Revoked()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002930 self.assertTrue(isinstance(revoked, Revoked))
2931 self.assertEquals(type(revoked), Revoked)
2932 self.assertEquals(revoked.get_serial(), b('00'))
2933 self.assertEquals(revoked.get_rev_date(), None)
2934 self.assertEquals(revoked.get_reason(), None)
Rick Dean536ba022009-07-24 23:57:27 -05002935
2936
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002937 def test_construction_wrong_args(self):
2938 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002939 Calling :py:obj:`OpenSSL.crypto.Revoked` with any arguments results
2940 in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002941 """
2942 self.assertRaises(TypeError, Revoked, None)
2943 self.assertRaises(TypeError, Revoked, 1)
2944 self.assertRaises(TypeError, Revoked, "foo")
2945
2946
Rick Dean536ba022009-07-24 23:57:27 -05002947 def test_serial(self):
2948 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002949 Confirm we can set and get serial numbers from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002950 :py:obj:`OpenSSL.crypto.Revoked`. Confirm errors are handled
Rick Dean536ba022009-07-24 23:57:27 -05002951 with grace.
2952 """
2953 revoked = Revoked()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002954 ret = revoked.set_serial(b('10b'))
2955 self.assertEquals(ret, None)
Rick Dean536ba022009-07-24 23:57:27 -05002956 ser = revoked.get_serial()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002957 self.assertEquals(ser, b('010B'))
Rick Dean536ba022009-07-24 23:57:27 -05002958
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002959 revoked.set_serial(b('31ppp')) # a type error would be nice
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('31'))
Rick Dean536ba022009-07-24 23:57:27 -05002962
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002963 self.assertRaises(ValueError, revoked.set_serial, b('pqrst'))
Rick Dean536ba022009-07-24 23:57:27 -05002964 self.assertRaises(TypeError, revoked.set_serial, 100)
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002965 self.assertRaises(TypeError, revoked.get_serial, 1)
2966 self.assertRaises(TypeError, revoked.get_serial, None)
2967 self.assertRaises(TypeError, revoked.get_serial, "")
Rick Dean536ba022009-07-24 23:57:27 -05002968
2969
2970 def test_date(self):
2971 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002972 Confirm we can set and get revocation dates from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002973 :py:obj:`OpenSSL.crypto.Revoked`. Confirm errors are handled
Rick Dean536ba022009-07-24 23:57:27 -05002974 with grace.
2975 """
2976 revoked = Revoked()
2977 date = revoked.get_rev_date()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002978 self.assertEquals(date, None)
Rick Dean536ba022009-07-24 23:57:27 -05002979
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002980 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05002981 ret = revoked.set_rev_date(now)
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002982 self.assertEqual(ret, None)
Rick Dean536ba022009-07-24 23:57:27 -05002983 date = revoked.get_rev_date()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002984 self.assertEqual(date, now)
Rick Dean536ba022009-07-24 23:57:27 -05002985
2986
Rick Dean6385faf2009-07-26 00:07:47 -05002987 def test_reason(self):
2988 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002989 Confirm we can set and get revocation reasons from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002990 :py:obj:`OpenSSL.crypto.Revoked`. The "get" need to work
Rick Dean6385faf2009-07-26 00:07:47 -05002991 as "set". Likewise, each reason of all_reasons() must work.
2992 """
2993 revoked = Revoked()
2994 for r in revoked.all_reasons():
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002995 for x in range(2):
Rick Dean6385faf2009-07-26 00:07:47 -05002996 ret = revoked.set_reason(r)
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002997 self.assertEquals(ret, None)
Rick Dean6385faf2009-07-26 00:07:47 -05002998 reason = revoked.get_reason()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002999 self.assertEquals(
3000 reason.lower().replace(b(' '), b('')),
3001 r.lower().replace(b(' '), b('')))
Rick Dean6385faf2009-07-26 00:07:47 -05003002 r = reason # again with the resp of get
3003
3004 revoked.set_reason(None)
3005 self.assertEqual(revoked.get_reason(), None)
3006
3007
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05003008 def test_set_reason_wrong_arguments(self):
Rick Dean6385faf2009-07-26 00:07:47 -05003009 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003010 Calling :py:obj:`OpenSSL.crypto.Revoked.set_reason` with other than
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05003011 one argument, or an argument which isn't a valid reason,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003012 results in :py:obj:`TypeError` or :py:obj:`ValueError` being raised.
Rick Dean6385faf2009-07-26 00:07:47 -05003013 """
3014 revoked = Revoked()
3015 self.assertRaises(TypeError, revoked.set_reason, 100)
Jean-Paul Calderone281b62b2010-08-28 14:22:29 -04003016 self.assertRaises(ValueError, revoked.set_reason, b('blue'))
Rick Dean6385faf2009-07-26 00:07:47 -05003017
Rick Dean536ba022009-07-24 23:57:27 -05003018
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05003019 def test_get_reason_wrong_arguments(self):
3020 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003021 Calling :py:obj:`OpenSSL.crypto.Revoked.get_reason` with any
3022 arguments results in :py:obj:`TypeError` being raised.
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05003023 """
3024 revoked = Revoked()
3025 self.assertRaises(TypeError, revoked.get_reason, None)
3026 self.assertRaises(TypeError, revoked.get_reason, 1)
3027 self.assertRaises(TypeError, revoked.get_reason, "foo")
3028
3029
3030
Rick Dean536ba022009-07-24 23:57:27 -05003031class CRLTests(TestCase):
3032 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003033 Tests for :py:obj:`OpenSSL.crypto.CRL`
Rick Dean536ba022009-07-24 23:57:27 -05003034 """
3035 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
3036 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
3037
3038 def test_construction(self):
3039 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003040 Confirm we can create :py:obj:`OpenSSL.crypto.CRL`. Check
Rick Dean536ba022009-07-24 23:57:27 -05003041 that it is empty
3042 """
3043 crl = CRL()
3044 self.assertTrue( isinstance(crl, CRL) )
3045 self.assertEqual(crl.get_revoked(), None)
3046
3047
Jean-Paul Calderone2efd03e2010-01-30 13:59:55 -05003048 def test_construction_wrong_args(self):
3049 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003050 Calling :py:obj:`OpenSSL.crypto.CRL` with any number of arguments
3051 results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone2efd03e2010-01-30 13:59:55 -05003052 """
3053 self.assertRaises(TypeError, CRL, 1)
3054 self.assertRaises(TypeError, CRL, "")
3055 self.assertRaises(TypeError, CRL, None)
3056
3057
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003058 def _get_crl(self):
Rick Dean536ba022009-07-24 23:57:27 -05003059 """
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003060 Get a new ``CRL`` with a revocation.
Rick Dean536ba022009-07-24 23:57:27 -05003061 """
3062 crl = CRL()
3063 revoked = Revoked()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003064 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05003065 revoked.set_rev_date(now)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003066 revoked.set_serial(b('3ab'))
3067 revoked.set_reason(b('sUpErSeDEd'))
Rick Dean536ba022009-07-24 23:57:27 -05003068 crl.add_revoked(revoked)
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003069 return crl
Rick Dean536ba022009-07-24 23:57:27 -05003070
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003071
3072 def test_export_pem(self):
3073 """
3074 If not passed a format, ``CRL.export`` returns a "PEM" format string
3075 representing a serial number, a revoked reason, and certificate issuer
3076 information.
3077 """
3078 crl = self._get_crl()
Rick Dean536ba022009-07-24 23:57:27 -05003079 # PEM format
3080 dumped_crl = crl.export(self.cert, self.pkey, days=20)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003081 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003082
3083 # These magic values are based on the way the CRL above was constructed
3084 # and with what certificate it was exported.
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003085 text.index(b('Serial Number: 03AB'))
3086 text.index(b('Superseded'))
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003087 text.index(
3088 b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA')
3089 )
3090
3091
3092 def test_export_der(self):
3093 """
3094 If passed ``FILETYPE_ASN1`` for the format, ``CRL.export`` returns a
3095 "DER" format string representing a serial number, a revoked reason, and
3096 certificate issuer information.
3097 """
3098 crl = self._get_crl()
Rick Dean536ba022009-07-24 23:57:27 -05003099
3100 # DER format
3101 dumped_crl = crl.export(self.cert, self.pkey, FILETYPE_ASN1)
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003102 text = _runopenssl(
3103 dumped_crl, b"crl", b"-noout", b"-text", b"-inform", b"DER"
3104 )
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003105 text.index(b('Serial Number: 03AB'))
3106 text.index(b('Superseded'))
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003107 text.index(
3108 b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA')
3109 )
3110
3111
3112 def test_export_text(self):
3113 """
3114 If passed ``FILETYPE_TEXT`` for the format, ``CRL.export`` returns a
3115 text format string like the one produced by the openssl command line
3116 tool.
3117 """
3118 crl = self._get_crl()
3119
3120 dumped_crl = crl.export(self.cert, self.pkey, FILETYPE_ASN1)
3121 text = _runopenssl(
3122 dumped_crl, b"crl", b"-noout", b"-text", b"-inform", b"DER"
3123 )
Rick Dean536ba022009-07-24 23:57:27 -05003124
3125 # text format
3126 dumped_text = crl.export(self.cert, self.pkey, type=FILETYPE_TEXT)
3127 self.assertEqual(text, dumped_text)
3128
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003129
3130 def test_export_custom_digest(self):
3131 """
3132 If passed the name of a digest function, ``CRL.export`` uses a
3133 signature algorithm based on that digest function.
3134 """
3135 crl = self._get_crl()
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04003136 dumped_crl = crl.export(self.cert, self.pkey, digest=b"sha1")
Bulat Gaifullin1966c972014-09-22 09:47:20 +04003137 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
3138 text.index(b('Signature Algorithm: sha1'))
3139
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003140
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04003141 def test_export_md5_digest(self):
3142 """
3143 If passed md5 as the digest function, ``CRL.export`` uses md5 and does
3144 not emit a deprecation warning.
3145 """
3146 crl = self._get_crl()
3147 with catch_warnings(record=True) as catcher:
3148 simplefilter("always")
3149 self.assertEqual(0, len(catcher))
3150 dumped_crl = crl.export(self.cert, self.pkey, digest=b"md5")
3151 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
3152 text.index(b('Signature Algorithm: md5'))
3153
3154
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003155 def test_export_default_digest(self):
3156 """
3157 If not passed the name of a digest function, ``CRL.export`` uses a
3158 signature algorithm based on MD5 and emits a deprecation warning.
3159 """
3160 crl = self._get_crl()
3161 with catch_warnings(record=True) as catcher:
3162 simplefilter("always")
3163 dumped_crl = crl.export(self.cert, self.pkey)
3164 self.assertEqual(
3165 "The default message digest (md5) is deprecated. "
3166 "Pass the name of a message digest explicitly.",
3167 str(catcher[0].message),
3168 )
Bulat Gaifullin1966c972014-09-22 09:47:20 +04003169 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
3170 text.index(b('Signature Algorithm: md5'))
3171
Rick Dean536ba022009-07-24 23:57:27 -05003172
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -04003173 def test_export_invalid(self):
3174 """
3175 If :py:obj:`CRL.export` is used with an uninitialized :py:obj:`X509`
Jean-Paul Calderoneb5871072012-03-09 14:58:00 -08003176 instance, :py:obj:`OpenSSL.crypto.Error` is raised.
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -04003177 """
3178 crl = CRL()
3179 self.assertRaises(Error, crl.export, X509(), PKey())
3180
3181
Jean-Paul Calderone56515342010-01-30 13:49:38 -05003182 def test_add_revoked_keyword(self):
3183 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003184 :py:obj:`OpenSSL.CRL.add_revoked` accepts its single argument as the
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003185 ``revoked`` keyword argument.
Jean-Paul Calderone56515342010-01-30 13:49:38 -05003186 """
3187 crl = CRL()
3188 revoked = Revoked()
3189 crl.add_revoked(revoked=revoked)
3190 self.assertTrue(isinstance(crl.get_revoked()[0], Revoked))
3191
Rick Dean6385faf2009-07-26 00:07:47 -05003192
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05003193 def test_export_wrong_args(self):
3194 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003195 Calling :py:obj:`OpenSSL.CRL.export` with fewer than two or more than
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05003196 four arguments, or with arguments other than the certificate,
3197 private key, integer file type, and integer number of days it
Jonathan Ballet648875f2011-07-16 14:14:58 +09003198 expects, results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05003199 """
3200 crl = CRL()
3201 self.assertRaises(TypeError, crl.export)
3202 self.assertRaises(TypeError, crl.export, self.cert)
Bulat Gaifullin925f7862014-09-22 10:10:44 +04003203 self.assertRaises(TypeError, crl.export, self.cert, self.pkey, FILETYPE_PEM, 10, "md5", "foo")
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05003204
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05003205 self.assertRaises(TypeError, crl.export, None, self.pkey, FILETYPE_PEM, 10)
3206 self.assertRaises(TypeError, crl.export, self.cert, None, FILETYPE_PEM, 10)
3207 self.assertRaises(TypeError, crl.export, self.cert, self.pkey, None, 10)
3208 self.assertRaises(TypeError, crl.export, self.cert, FILETYPE_PEM, None)
3209
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05003210
Jean-Paul Calderoneea198422010-01-30 13:58:23 -05003211 def test_export_unknown_filetype(self):
3212 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003213 Calling :py:obj:`OpenSSL.CRL.export` with a file type other than
3214 :py:obj:`FILETYPE_PEM`, :py:obj:`FILETYPE_ASN1`, or :py:obj:`FILETYPE_TEXT` results
3215 in a :py:obj:`ValueError` being raised.
Jean-Paul Calderoneea198422010-01-30 13:58:23 -05003216 """
3217 crl = CRL()
3218 self.assertRaises(ValueError, crl.export, self.cert, self.pkey, 100, 10)
3219
3220
Bulat Gaifullin925f7862014-09-22 10:10:44 +04003221 def test_export_unknown_digest(self):
Bulat Gaifullin5f9eea42014-09-23 19:35:15 +04003222 """
3223 Calling :py:obj:`OpenSSL.CRL.export` with a unsupported digest results
3224 in a :py:obj:`ValueError` being raised.
3225 """
Bulat Gaifullin925f7862014-09-22 10:10:44 +04003226 crl = CRL()
Jean-Paul Calderone9be85192015-04-13 21:20:51 -04003227 self.assertRaises(
3228 ValueError,
3229 crl.export,
3230 self.cert, self.pkey, FILETYPE_PEM, 10, b"strange-digest"
3231 )
Bulat Gaifullin925f7862014-09-22 10:10:44 +04003232
3233
Rick Dean536ba022009-07-24 23:57:27 -05003234 def test_get_revoked(self):
3235 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05003236 Use python to create a simple CRL with two revocations.
Jonathan Ballet648875f2011-07-16 14:14:58 +09003237 Get back the :py:obj:`Revoked` using :py:obj:`OpenSSL.CRL.get_revoked` and
Rick Dean536ba022009-07-24 23:57:27 -05003238 verify them.
3239 """
3240 crl = CRL()
3241
3242 revoked = Revoked()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003243 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05003244 revoked.set_rev_date(now)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003245 revoked.set_serial(b('3ab'))
Rick Dean536ba022009-07-24 23:57:27 -05003246 crl.add_revoked(revoked)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003247 revoked.set_serial(b('100'))
3248 revoked.set_reason(b('sUpErSeDEd'))
Rick Dean536ba022009-07-24 23:57:27 -05003249 crl.add_revoked(revoked)
3250
3251 revs = crl.get_revoked()
3252 self.assertEqual(len(revs), 2)
3253 self.assertEqual(type(revs[0]), Revoked)
3254 self.assertEqual(type(revs[1]), Revoked)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003255 self.assertEqual(revs[0].get_serial(), b('03AB'))
3256 self.assertEqual(revs[1].get_serial(), b('0100'))
Rick Dean536ba022009-07-24 23:57:27 -05003257 self.assertEqual(revs[0].get_rev_date(), now)
3258 self.assertEqual(revs[1].get_rev_date(), now)
3259
3260
Jean-Paul Calderone46bdce42010-01-30 13:44:16 -05003261 def test_get_revoked_wrong_args(self):
3262 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003263 Calling :py:obj:`OpenSSL.CRL.get_revoked` with any arguments results
3264 in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone46bdce42010-01-30 13:44:16 -05003265 """
3266 crl = CRL()
3267 self.assertRaises(TypeError, crl.get_revoked, None)
3268 self.assertRaises(TypeError, crl.get_revoked, 1)
3269 self.assertRaises(TypeError, crl.get_revoked, "")
3270 self.assertRaises(TypeError, crl.get_revoked, "", 1, None)
3271
3272
Jean-Paul Calderoneecef6fa2010-01-30 13:47:18 -05003273 def test_add_revoked_wrong_args(self):
3274 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003275 Calling :py:obj:`OpenSSL.CRL.add_revoked` with other than one
3276 argument results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderoneecef6fa2010-01-30 13:47:18 -05003277 """
3278 crl = CRL()
3279 self.assertRaises(TypeError, crl.add_revoked)
3280 self.assertRaises(TypeError, crl.add_revoked, 1, 2)
3281 self.assertRaises(TypeError, crl.add_revoked, "foo", "bar")
3282
3283
Rick Dean536ba022009-07-24 23:57:27 -05003284 def test_load_crl(self):
3285 """
3286 Load a known CRL and inspect its revocations. Both
3287 PEM and DER formats are loaded.
3288 """
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003289 crl = load_crl(FILETYPE_PEM, crlData)
Rick Dean536ba022009-07-24 23:57:27 -05003290 revs = crl.get_revoked()
3291 self.assertEqual(len(revs), 2)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003292 self.assertEqual(revs[0].get_serial(), b('03AB'))
Rick Dean6385faf2009-07-26 00:07:47 -05003293 self.assertEqual(revs[0].get_reason(), None)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003294 self.assertEqual(revs[1].get_serial(), b('0100'))
3295 self.assertEqual(revs[1].get_reason(), b('Superseded'))
Rick Dean536ba022009-07-24 23:57:27 -05003296
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003297 der = _runopenssl(crlData, b"crl", b"-outform", b"DER")
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05003298 crl = load_crl(FILETYPE_ASN1, der)
Rick Dean536ba022009-07-24 23:57:27 -05003299 revs = crl.get_revoked()
3300 self.assertEqual(len(revs), 2)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003301 self.assertEqual(revs[0].get_serial(), b('03AB'))
Rick Dean6385faf2009-07-26 00:07:47 -05003302 self.assertEqual(revs[0].get_reason(), None)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003303 self.assertEqual(revs[1].get_serial(), b('0100'))
3304 self.assertEqual(revs[1].get_reason(), b('Superseded'))
Rick Dean536ba022009-07-24 23:57:27 -05003305
3306
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003307 def test_load_crl_wrong_args(self):
3308 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003309 Calling :py:obj:`OpenSSL.crypto.load_crl` with other than two
3310 arguments results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003311 """
3312 self.assertRaises(TypeError, load_crl)
3313 self.assertRaises(TypeError, load_crl, FILETYPE_PEM)
3314 self.assertRaises(TypeError, load_crl, FILETYPE_PEM, crlData, None)
3315
3316
3317 def test_load_crl_bad_filetype(self):
3318 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003319 Calling :py:obj:`OpenSSL.crypto.load_crl` with an unknown file type
3320 raises a :py:obj:`ValueError`.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003321 """
3322 self.assertRaises(ValueError, load_crl, 100, crlData)
3323
3324
3325 def test_load_crl_bad_data(self):
3326 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003327 Calling :py:obj:`OpenSSL.crypto.load_crl` with file data which can't
3328 be loaded raises a :py:obj:`OpenSSL.crypto.Error`.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003329 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003330 self.assertRaises(Error, load_crl, FILETYPE_PEM, b"hello, world")
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003331
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04003332
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -05003333
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003334class X509StoreContextTests(TestCase):
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003335 """
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003336 Tests for :py:obj:`OpenSSL.crypto.X509StoreContext`.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003337 """
3338 root_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3339 intermediate_cert = load_certificate(FILETYPE_PEM, intermediate_cert_pem)
3340 intermediate_server_cert = load_certificate(FILETYPE_PEM, intermediate_server_cert_pem)
3341
3342 def test_valid(self):
3343 """
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003344 :py:obj:`verify_certificate` returns ``None`` when called with a certificate
Jean-Paul Calderone06e01b92015-01-18 15:43:13 -05003345 and valid chain.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003346 """
3347 store = X509Store()
3348 store.add_cert(self.root_cert)
3349 store.add_cert(self.intermediate_cert)
3350 store_ctx = X509StoreContext(store, self.intermediate_server_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003351 self.assertEqual(store_ctx.verify_certificate(), None)
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003352
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003353
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003354 def test_reuse(self):
3355 """
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003356 :py:obj:`verify_certificate` can be called multiple times with the same
Jean-Paul Calderone06e01b92015-01-18 15:43:13 -05003357 ``X509StoreContext`` instance to produce the same result.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003358 """
3359 store = X509Store()
3360 store.add_cert(self.root_cert)
3361 store.add_cert(self.intermediate_cert)
3362 store_ctx = X509StoreContext(store, self.intermediate_server_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003363 self.assertEqual(store_ctx.verify_certificate(), None)
3364 self.assertEqual(store_ctx.verify_certificate(), None)
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003365
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003366
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003367 def test_trusted_self_signed(self):
3368 """
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003369 :py:obj:`verify_certificate` returns ``None`` when called with a self-signed
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003370 certificate and itself in the chain.
3371 """
3372 store = X509Store()
3373 store.add_cert(self.root_cert)
3374 store_ctx = X509StoreContext(store, self.root_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003375 self.assertEqual(store_ctx.verify_certificate(), None)
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003376
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003377
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003378 def test_untrusted_self_signed(self):
3379 """
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003380 :py:obj:`verify_certificate` raises error when a self-signed certificate is
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003381 verified without itself in the chain.
3382 """
3383 store = X509Store()
3384 store_ctx = X509StoreContext(store, self.root_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003385 e = self.assertRaises(X509StoreContextError, store_ctx.verify_certificate)
Jean-Paul Calderone4c10a1e2015-01-18 16:31:27 -05003386 self.assertEqual(e.args[0][2], 'self signed certificate')
Jean-Paul Calderone06e01b92015-01-18 15:43:13 -05003387 self.assertEqual(e.certificate.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003388
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003389
3390 def test_invalid_chain_no_root(self):
3391 """
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003392 :py:obj:`verify_certificate` raises error when a root certificate is missing
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003393 from the chain.
3394 """
3395 store = X509Store()
3396 store.add_cert(self.intermediate_cert)
3397 store_ctx = X509StoreContext(store, self.intermediate_server_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003398 e = self.assertRaises(X509StoreContextError, store_ctx.verify_certificate)
Jean-Paul Calderone4c10a1e2015-01-18 16:31:27 -05003399 self.assertEqual(e.args[0][2], 'unable to get issuer certificate')
Jean-Paul Calderone06e01b92015-01-18 15:43:13 -05003400 self.assertEqual(e.certificate.get_subject().CN, 'intermediate')
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003401
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003402
3403 def test_invalid_chain_no_intermediate(self):
3404 """
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003405 :py:obj:`verify_certificate` raises error when an intermediate certificate is
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003406 missing from the chain.
3407 """
3408 store = X509Store()
3409 store.add_cert(self.root_cert)
3410 store_ctx = X509StoreContext(store, self.intermediate_server_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08003411 e = self.assertRaises(X509StoreContextError, store_ctx.verify_certificate)
Jean-Paul Calderone4c10a1e2015-01-18 16:31:27 -05003412 self.assertEqual(e.args[0][2], 'unable to get local issuer certificate')
Jean-Paul Calderone06e01b92015-01-18 15:43:13 -05003413 self.assertEqual(e.certificate.get_subject().CN, 'intermediate-service')
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003414
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003415
Stephen Holsapple46a09252015-02-12 14:45:43 -08003416 def test_modification_pre_verify(self):
3417 """
3418 :py:obj:`verify_certificate` can use a store context modified after
3419 instantiation.
3420 """
3421 store_bad = X509Store()
3422 store_bad.add_cert(self.intermediate_cert)
3423 store_good = X509Store()
3424 store_good.add_cert(self.root_cert)
3425 store_good.add_cert(self.intermediate_cert)
3426 store_ctx = X509StoreContext(store_bad, self.intermediate_server_cert)
3427 e = self.assertRaises(X509StoreContextError, store_ctx.verify_certificate)
3428 self.assertEqual(e.args[0][2], 'unable to get issuer certificate')
3429 self.assertEqual(e.certificate.get_subject().CN, 'intermediate')
3430 store_ctx.set_store(store_good)
3431 self.assertEqual(store_ctx.verify_certificate(), None)
3432
3433
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04003434
3435class SignVerifyTests(TestCase):
3436 """
3437 Tests for :py:obj:`OpenSSL.crypto.sign` and :py:obj:`OpenSSL.crypto.verify`.
3438 """
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04003439 def test_sign_verify(self):
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04003440 """
3441 :py:obj:`sign` generates a cryptographic signature which :py:obj:`verify` can check.
3442 """
3443 content = b(
James Yonan7c2e5d32010-02-27 05:45:50 -07003444 "It was a bright cold day in April, and the clocks were striking "
Jean-Paul Calderoned08feb02010-10-12 21:53:24 -04003445 "thirteen. Winston Smith, his chin nuzzled into his breast in an "
James Yonan7c2e5d32010-02-27 05:45:50 -07003446 "effort to escape the vile wind, slipped quickly through the "
3447 "glass doors of Victory Mansions, though not quickly enough to "
3448 "prevent a swirl of gritty dust from entering along with him.")
3449
3450 # sign the content with this private key
3451 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
3452 # verify the content with this cert
3453 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3454 # certificate unrelated to priv_key, used to trigger an error
3455 bad_cert = load_certificate(FILETYPE_PEM, server_cert_pem)
3456
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003457 for digest in ['md5', 'sha1']:
3458 sig = sign(priv_key, content, digest)
3459
James Yonan7c2e5d32010-02-27 05:45:50 -07003460 # Verify the signature of content, will throw an exception if error.
3461 verify(good_cert, sig, content, digest)
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003462
Jean-Paul Calderone9538f142010-10-13 22:13:40 -04003463 # This should fail because the certificate doesn't match the
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003464 # private key that was used to sign the content.
Jean-Paul Calderone9538f142010-10-13 22:13:40 -04003465 self.assertRaises(Error, verify, bad_cert, sig, content, digest)
James Yonan7c2e5d32010-02-27 05:45:50 -07003466
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04003467 # This should fail because we've "tainted" the content after
Jean-Paul Calderone9828f662010-12-08 22:57:26 -05003468 # signing it.
3469 self.assertRaises(
Jonathan Ballet648875f2011-07-16 14:14:58 +09003470 Error, verify,
Jean-Paul Calderone9828f662010-12-08 22:57:26 -05003471 good_cert, sig, content + b("tainted"), digest)
3472
3473 # test that unknown digest types fail
3474 self.assertRaises(
3475 ValueError, sign, priv_key, content, "strange-digest")
3476 self.assertRaises(
3477 ValueError, verify, good_cert, sig, content, "strange-digest")
3478
Rick Dean5b7b6372009-04-01 11:34:06 -05003479
Abraham Martinc5484ba2015-03-25 15:33:05 +00003480 def test_sign_verify_with_text(self):
3481 """
3482 :py:obj:`sign` generates a cryptographic signature which :py:obj:`verify` can check.
3483 Deprecation warnings raised because using text instead of bytes as content
3484 """
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003485 content = (
Jean-Paul Calderone362c1f52015-03-29 08:01:39 -04003486 b"It was a bright cold day in April, and the clocks were striking "
3487 b"thirteen. Winston Smith, his chin nuzzled into his breast in an "
3488 b"effort to escape the vile wind, slipped quickly through the "
3489 b"glass doors of Victory Mansions, though not quickly enough to "
3490 b"prevent a swirl of gritty dust from entering along with him."
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003491 ).decode("ascii")
Abraham Martinc5484ba2015-03-25 15:33:05 +00003492
3493 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
3494 cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3495 for digest in ['md5', 'sha1']:
3496 with catch_warnings(record=True) as w:
3497 simplefilter("always")
3498 sig = sign(priv_key, content, digest)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003499
3500 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003501 "{0} for data is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003502 WARNING_TYPE_EXPECTED
3503 ),
3504 str(w[-1].message)
3505 )
3506 self.assertIs(w[-1].category, DeprecationWarning)
3507
Abraham Martinc5484ba2015-03-25 15:33:05 +00003508 with catch_warnings(record=True) as w:
3509 simplefilter("always")
3510 verify(cert, sig, content, digest)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003511
3512 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003513 "{0} for data is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003514 WARNING_TYPE_EXPECTED
3515 ),
3516 str(w[-1].message)
3517 )
3518 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinc5484ba2015-03-25 15:33:05 +00003519
3520
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -05003521 def test_sign_nulls(self):
3522 """
3523 :py:obj:`sign` produces a signature for a string with embedded nulls.
3524 """
3525 content = b("Watch out! \0 Did you see it?")
3526 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
3527 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3528 sig = sign(priv_key, content, "sha1")
3529 verify(good_cert, sig, content, "sha1")
3530
3531
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003532
3533class EllipticCurveTests(TestCase):
3534 """
3535 Tests for :py:class:`_EllipticCurve`, :py:obj:`get_elliptic_curve`, and
3536 :py:obj:`get_elliptic_curves`.
3537 """
3538 def test_set(self):
3539 """
3540 :py:obj:`get_elliptic_curves` returns a :py:obj:`set`.
3541 """
3542 self.assertIsInstance(get_elliptic_curves(), set)
3543
3544
3545 def test_some_curves(self):
3546 """
3547 If :py:mod:`cryptography` has elliptic curve support then the set
3548 returned by :py:obj:`get_elliptic_curves` has some elliptic curves in
3549 it.
3550
3551 There could be an OpenSSL that violates this assumption. If so, this
3552 test will fail and we'll find out.
3553 """
3554 curves = get_elliptic_curves()
3555 if lib.Cryptography_HAS_EC:
3556 self.assertTrue(curves)
3557 else:
3558 self.assertFalse(curves)
3559
3560
3561 def test_a_curve(self):
3562 """
3563 :py:obj:`get_elliptic_curve` can be used to retrieve a particular
3564 supported curve.
3565 """
3566 curves = get_elliptic_curves()
3567 if curves:
3568 curve = next(iter(curves))
3569 self.assertEqual(curve.name, get_elliptic_curve(curve.name).name)
3570 else:
Jean-Paul Calderoneeb86f3a2014-04-19 09:45:57 -04003571 self.assertRaises(ValueError, get_elliptic_curve, u("prime256v1"))
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003572
3573
3574 def test_not_a_curve(self):
3575 """
3576 :py:obj:`get_elliptic_curve` raises :py:class:`ValueError` if called
3577 with a name which does not identify a supported curve.
3578 """
3579 self.assertRaises(
Jean-Paul Calderone5a82db92014-04-19 09:51:29 -04003580 ValueError, get_elliptic_curve, u("this curve was just invented"))
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003581
3582
3583 def test_repr(self):
3584 """
3585 The string representation of a curve object includes simply states the
3586 object is a curve and what its name is.
3587 """
3588 curves = get_elliptic_curves()
3589 if curves:
3590 curve = next(iter(curves))
3591 self.assertEqual("<Curve %r>" % (curve.name,), repr(curve))
3592
3593
3594 def test_to_EC_KEY(self):
3595 """
3596 The curve object can export a version of itself as an EC_KEY* via the
3597 private :py:meth:`_EllipticCurve._to_EC_KEY`.
3598 """
3599 curves = get_elliptic_curves()
3600 if curves:
3601 curve = next(iter(curves))
3602 # It's not easy to assert anything about this object. However, see
3603 # leakcheck/crypto.py for a test that demonstrates it at least does
3604 # not leak memory.
3605 curve._to_EC_KEY()
3606
3607
Jean-Paul Calderone1be77082014-04-30 18:17:41 -04003608
3609class EllipticCurveFactory(object):
3610 """
3611 A helper to get the names of two curves.
3612 """
3613 def __init__(self):
3614 curves = iter(get_elliptic_curves())
3615 try:
3616 self.curve_name = next(curves).name
3617 self.another_curve_name = next(curves).name
3618 except StopIteration:
3619 self.curve_name = self.another_curve_name = None
3620
3621
3622
3623class EllipticCurveEqualityTests(TestCase, EqualityTestsMixin):
3624 """
3625 Tests :py:type:`_EllipticCurve`\ 's implementation of ``==`` and ``!=``.
3626 """
3627 curve_factory = EllipticCurveFactory()
3628
3629 if curve_factory.curve_name is None:
3630 skip = "There are no curves available there can be no curve objects."
3631
3632
3633 def anInstance(self):
3634 """
3635 Get the curve object for an arbitrary curve supported by the system.
3636 """
3637 return get_elliptic_curve(self.curve_factory.curve_name)
3638
3639
3640 def anotherInstance(self):
3641 """
3642 Get the curve object for an arbitrary curve supported by the system -
3643 but not the one returned by C{anInstance}.
3644 """
3645 return get_elliptic_curve(self.curve_factory.another_curve_name)
3646
3647
3648
Jean-Paul Calderone22c31242014-05-01 07:49:47 -04003649class EllipticCurveHashTests(TestCase):
3650 """
3651 Tests for :py:type:`_EllipticCurve`\ 's implementation of hashing (thus use
3652 as an item in a :py:type:`dict` or :py:type:`set`).
3653 """
3654 curve_factory = EllipticCurveFactory()
3655
3656 if curve_factory.curve_name is None:
3657 skip = "There are no curves available there can be no curve objects."
3658
3659
3660 def test_contains(self):
3661 """
3662 The ``in`` operator reports that a :py:type:`set` containing a curve
3663 does contain that curve.
3664 """
3665 curve = get_elliptic_curve(self.curve_factory.curve_name)
3666 curves = set([curve])
3667 self.assertIn(curve, curves)
3668
3669
3670 def test_does_not_contain(self):
3671 """
3672 The ``in`` operator reports that a :py:type:`set` not containing a
3673 curve does not contain that curve.
3674 """
3675 curve = get_elliptic_curve(self.curve_factory.curve_name)
3676 curves = set([get_elliptic_curve(self.curve_factory.another_curve_name)])
3677 self.assertNotIn(curve, curves)
3678
3679
3680
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -05003681if __name__ == '__main__':
3682 main()