blob: fc6350cbd89111bf05906b3846246ec5f0f4fdb1 [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
9
Alex Gaynor4b9c96a2014-08-14 09:51:48 -070010import base64
11import os
12import re
Jean-Paul Calderone62ca8da2010-08-11 19:58:08 -040013from subprocess import PIPE, Popen
Rick Dean47262da2009-07-08 16:17:17 -050014from datetime import datetime, timedelta
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -050015
Jean-Paul Calderoneeb86f3a2014-04-19 09:45:57 -040016from six import u, b, binary_type
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050017
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -050018from OpenSSL.crypto import TYPE_RSA, TYPE_DSA, Error, PKey, PKeyType
Jean-Paul Calderone78381d22008-03-06 23:35:22 -050019from OpenSSL.crypto import X509, X509Type, X509Name, X509NameType
Stephen Holsapple0d9815f2014-08-27 19:36:53 -070020from OpenSSL.crypto import X509Store, X509StoreType, X509StoreContext
21from OpenSSL.crypto import X509Req, X509ReqType
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -050022from OpenSSL.crypto import X509Extension, X509ExtensionType
Rick Dean5b7b6372009-04-01 11:34:06 -050023from OpenSSL.crypto import load_certificate, load_privatekey
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -040024from OpenSSL.crypto import FILETYPE_PEM, FILETYPE_ASN1, FILETYPE_TEXT
Jean-Paul Calderone71919862009-04-01 13:01:19 -040025from OpenSSL.crypto import dump_certificate, load_certificate_request
26from OpenSSL.crypto import dump_certificate_request, dump_privatekey
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -040027from OpenSSL.crypto import PKCS7Type, load_pkcs7_data
Jean-Paul Calderone9178ee62010-01-25 17:55:30 -050028from OpenSSL.crypto import PKCS12, PKCS12Type, load_pkcs12
Rick Dean536ba022009-07-24 23:57:27 -050029from OpenSSL.crypto import CRL, Revoked, load_crl
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -040030from OpenSSL.crypto import NetscapeSPKI, NetscapeSPKIType
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040031from OpenSSL.crypto import (
Stephen Holsapple0d9815f2014-08-27 19:36:53 -070032 sign, verify, verify_cert, get_elliptic_curve, get_elliptic_curves)
Jean-Paul Calderone1be77082014-04-30 18:17:41 -040033from OpenSSL.test.util import EqualityTestsMixin, TestCase
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040034from OpenSSL._util import native, lib
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040035
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -040036def normalize_certificate_pem(pem):
37 return dump_certificate(FILETYPE_PEM, load_certificate(FILETYPE_PEM, pem))
38
39
40def normalize_privatekey_pem(pem):
41 return dump_privatekey(FILETYPE_PEM, load_privatekey(FILETYPE_PEM, pem))
42
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040043
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050044GOOD_CIPHER = "blowfish"
45BAD_CIPHER = "zippers"
46
47GOOD_DIGEST = "MD5"
48BAD_DIGEST = "monkeys"
49
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040050root_cert_pem = b("""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -050051MIIC7TCCAlagAwIBAgIIPQzE4MbeufQwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE
52BhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdU
53ZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwIhgPMjAwOTAzMjUxMjM2
54NThaGA8yMDE3MDYxMTEyMzY1OFowWDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklM
55MRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9U
56ZXN0aW5nIFJvb3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPmaQumL
57urpE527uSEHdL1pqcDRmWzu+98Y6YHzT/J7KWEamyMCNZ6fRW1JCR782UQ8a07fy
582xXsKy4WdKaxyG8CcatwmXvpvRQ44dSANMihHELpANTdyVp6DCysED6wkQFurHlF
591dshEaJw8b/ypDhmbVIo6Ci1xvCJqivbLFnbAgMBAAGjgbswgbgwHQYDVR0OBBYE
60FINVdy1eIfFJDAkk51QJEo3IfgSuMIGIBgNVHSMEgYAwfoAUg1V3LV4h8UkMCSTn
61VAkSjch+BK6hXKRaMFgxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UE
62BxMHQ2hpY2FnbzEQMA4GA1UEChMHVGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBS
63b290IENBggg9DMTgxt659DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB
64AGGCDazMJGoWNBpc03u6+smc95dEead2KlZXBATOdFT1VesY3+nUOqZhEhTGlDMi
65hkgaZnzoIq/Uamidegk4hirsCT/R+6vsKAAxNTcBjUeZjlykCJWy5ojShGftXIKY
66w/njVbKMXrvc83qmTdGl3TAM0fxQIpqgcglFLveEBgzn
67-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040068""")
Rick Dean94e46fd2009-07-18 14:51:24 -050069
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040070root_key_pem = b("""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -050071MIICXQIBAAKBgQD5mkLpi7q6ROdu7khB3S9aanA0Zls7vvfGOmB80/yeylhGpsjA
72jWen0VtSQke/NlEPGtO38tsV7CsuFnSmschvAnGrcJl76b0UOOHUgDTIoRxC6QDU
733claegwsrBA+sJEBbqx5RdXbIRGicPG/8qQ4Zm1SKOgotcbwiaor2yxZ2wIDAQAB
74AoGBAPCgMpmLxzwDaUmcFbTJUvlLW1hoxNNYSu2jIZm1k/hRAcE60JYwvBkgz3UB
75yMEh0AtLxYe0bFk6EHah11tMUPgscbCq73snJ++8koUw+csk22G65hOs51bVb7Aa
766JBe67oLzdtvgCUFAA2qfrKzWRZzAdhUirQUZgySZk+Xq1pBAkEA/kZG0A6roTSM
77BVnx7LnPfsycKUsTumorpXiylZJjTi9XtmzxhrYN6wgZlDOOwOLgSQhszGpxVoMD
78u3gByT1b2QJBAPtL3mSKdvwRu/+40zaZLwvSJRxaj0mcE4BJOS6Oqs/hS1xRlrNk
79PpQ7WJ4yM6ZOLnXzm2mKyxm50Mv64109FtMCQQDOqS2KkjHaLowTGVxwC0DijMfr
80I9Lf8sSQk32J5VWCySWf5gGTfEnpmUa41gKTMJIbqZZLucNuDcOtzUaeWZlZAkA8
81ttXigLnCqR486JDPTi9ZscoZkZ+w7y6e/hH8t6d5Vjt48JVyfjPIaJY+km58LcN3
826AWSeGAdtRFHVzR7oHjVAkB4hutvxiOeiIVQNBhM6RSI9aBPMI21DoX2JRoxvNW2
83cbvAhow217X9V0dVerEOKxnNYspXRrh36h7k4mQA+sDq
84-----END RSA PRIVATE KEY-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040085""")
Rick Dean94e46fd2009-07-18 14:51:24 -050086
Stephen Holsapple0d9815f2014-08-27 19:36:53 -070087intermediate_cert_pem = b("""-----BEGIN CERTIFICATE-----
88MIICVzCCAcCgAwIBAgIRAMPzhm6//0Y/g2pmnHR2C4cwDQYJKoZIhvcNAQENBQAw
89WDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAw
90DgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwHhcNMTQw
91ODI4MDIwNDA4WhcNMjQwODI1MDIwNDA4WjBmMRUwEwYDVQQDEwxpbnRlcm1lZGlh
92dGUxDDAKBgNVBAoTA29yZzERMA8GA1UECxMIb3JnLXVuaXQxCzAJBgNVBAYTAlVT
93MQswCQYDVQQIEwJDQTESMBAGA1UEBxMJU2FuIERpZWdvMIGfMA0GCSqGSIb3DQEB
94AQUAA4GNADCBiQKBgQDYcEQw5lfbEQRjr5Yy4yxAHGV0b9Al+Lmu7wLHMkZ/ZMmK
95FGIbljbviiD1Nz97Oh2cpB91YwOXOTN2vXHq26S+A5xe8z/QJbBsyghMur88CjdT
9621H2qwMa+r5dCQwEhuGIiZ3KbzB/n4DTMYI5zy4IYPv0pjxShZn4aZTCCK2IUwID
97AQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBDQUAA4GBAPIWSkLX
98QRMApOjjyC+tMxumT5e2pMqChHmxobQK4NMdrf2VCx+cRT6EmY8sK3/Xl/X8UBQ+
999n5zXb1ZwhW/sTWgUvmOceJ4/XVs9FkdWOOn1J0XBch9ZIiFe/s5ASIgG7fUdcUF
1009mAWS6FK2ca3xIh5kIupCXOFa0dPvlw/YUFT
101-----END CERTIFICATE-----
102""")
103
104intermediate_key_pem = b("""-----BEGIN RSA PRIVATE KEY-----
105MIICWwIBAAKBgQDYcEQw5lfbEQRjr5Yy4yxAHGV0b9Al+Lmu7wLHMkZ/ZMmKFGIb
106ljbviiD1Nz97Oh2cpB91YwOXOTN2vXHq26S+A5xe8z/QJbBsyghMur88CjdT21H2
107qwMa+r5dCQwEhuGIiZ3KbzB/n4DTMYI5zy4IYPv0pjxShZn4aZTCCK2IUwIDAQAB
108AoGAfSZVV80pSeOKHTYfbGdNY/jHdU9eFUa/33YWriXU+77EhpIItJjkRRgivIfo
109rhFJpBSGmDLblaqepm8emsXMeH4+2QzOYIf0QGGP6E6scjTt1PLqdqKfVJ1a2REN
110147cujNcmFJb/5VQHHMpaPTgttEjlzuww4+BCDPsVRABWrkCQQD3loH36nLoQTtf
111+kQq0T6Bs9/UWkTAGo0ND81ALj0F8Ie1oeZg6RNT96RxZ3aVuFTESTv6/TbjWywO
112wdzlmV1vAkEA38rTJ6PTwaJlw5OttdDzAXGPB9tDmzh9oSi7cHwQQXizYd8MBYx4
113sjHUKD3dCQnb1dxJFhd3BT5HsnkRMbVZXQJAbXduH17ZTzcIOXc9jHDXYiFVZV5D
11452vV0WCbLzVCZc3jMrtSUKa8lPN5EWrdU3UchWybyG0MR5mX8S5lrF4SoQJAIyUD
115DBKaSqpqONCUUx1BTFS9FYrFjzbL4+c1qHCTTPTblt8kUCrDOZjBrKAqeiTmNSum
116/qUot9YUBF8m6BuGsQJATHHmdFy/fG1VLkyBp49CAa8tN3Z5r/CgTznI4DfMTf4C
117NbRHn2UmYlwQBa+L5lg9phewNe8aEwpPyPLoV85U8Q==
118-----END RSA PRIVATE KEY-----
119""")
120
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400121server_cert_pem = b("""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500122MIICKDCCAZGgAwIBAgIJAJn/HpR21r/8MA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
123BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
124VGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBSb290IENBMCIYDzIwMDkwMzI1MTIz
125NzUzWhgPMjAxNzA2MTExMjM3NTNaMBgxFjAUBgNVBAMTDWxvdmVseSBzZXJ2ZXIw
126gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAL6m+G653V0tpBC/OKl22VxOi2Cv
127lK4TYu9LHSDP9uDVTe7V5D5Tl6qzFoRRx5pfmnkqT5B+W9byp2NU3FC5hLm5zSAr
128b45meUhjEJ/ifkZgbNUjHdBIGP9MAQUHZa5WKdkGIJvGAvs8UzUqlr4TBWQIB24+
129lJ+Ukk/CRgasrYwdAgMBAAGjNjA0MB0GA1UdDgQWBBS4kC7Ij0W1TZXZqXQFAM2e
130gKEG2DATBgNVHSUEDDAKBggrBgEFBQcDATANBgkqhkiG9w0BAQUFAAOBgQBh30Li
131dJ+NlxIOx5343WqIBka3UbsOb2kxWrbkVCrvRapCMLCASO4FqiKWM+L0VDBprqIp
1322mgpFQ6FHpoIENGvJhdEKpptQ5i7KaGhnDNTfdy3x1+h852G99f1iyj0RmbuFcM8
133uzujnS8YXWvM7DM1Ilozk4MzPug8jzFp5uhKCQ==
134-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400135""")
Rick Dean94e46fd2009-07-18 14:51:24 -0500136
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -0400137server_key_pem = normalize_privatekey_pem(b("""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500138MIICWwIBAAKBgQC+pvhuud1dLaQQvzipdtlcTotgr5SuE2LvSx0gz/bg1U3u1eQ+
139U5eqsxaEUceaX5p5Kk+QflvW8qdjVNxQuYS5uc0gK2+OZnlIYxCf4n5GYGzVIx3Q
140SBj/TAEFB2WuVinZBiCbxgL7PFM1Kpa+EwVkCAduPpSflJJPwkYGrK2MHQIDAQAB
141AoGAbwuZ0AR6JveahBaczjfnSpiFHf+mve2UxoQdpyr6ROJ4zg/PLW5K/KXrC48G
142j6f3tXMrfKHcpEoZrQWUfYBRCUsGD5DCazEhD8zlxEHahIsqpwA0WWssJA2VOLEN
143j6DuV2pCFbw67rfTBkTSo32ahfXxEKev5KswZk0JIzH3ooECQQDgzS9AI89h0gs8
144Dt+1m11Rzqo3vZML7ZIyGApUzVan+a7hbc33nbGRkAXjHaUBJO31it/H6dTO+uwX
145msWwNG5ZAkEA2RyFKs5xR5USTFaKLWCgpH/ydV96KPOpBND7TKQx62snDenFNNbn
146FwwOhpahld+vqhYk+pfuWWUpQciE+Bu7ZQJASjfT4sQv4qbbKK/scePicnDdx9th
1474e1EeB9xwb+tXXXUo/6Bor/AcUNwfiQ6Zt9PZOK9sR3lMZSsP7rMi7kzuQJABie6
1481sXXjFH7nNJvRG4S39cIxq8YRYTy68II/dlB2QzGpKxV/POCxbJ/zu0CU79tuYK7
149NaeNCFfH3aeTrX0LyQJAMBWjWmeKM2G2sCExheeQK0ROnaBC8itCECD4Jsve4nqf
150r50+LF74iLXFwqysVCebPKMOpDWp/qQ1BbJQIPs7/A==
151-----END RSA PRIVATE KEY-----
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -0400152"""))
Rick Dean94e46fd2009-07-18 14:51:24 -0500153
Stephen Holsapple0d9815f2014-08-27 19:36:53 -0700154intermediate_server_cert_pem = b("""-----BEGIN CERTIFICATE-----
155MIICWDCCAcGgAwIBAgIRAPQFY9jfskSihdiNSNdt6GswDQYJKoZIhvcNAQENBQAw
156ZjEVMBMGA1UEAxMMaW50ZXJtZWRpYXRlMQwwCgYDVQQKEwNvcmcxETAPBgNVBAsT
157CG9yZy11bml0MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVNh
158biBEaWVnbzAeFw0xNDA4MjgwMjEwNDhaFw0yNDA4MjUwMjEwNDhaMG4xHTAbBgNV
159BAMTFGludGVybWVkaWF0ZS1zZXJ2aWNlMQwwCgYDVQQKEwNvcmcxETAPBgNVBAsT
160CG9yZy11bml0MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVNh
161biBEaWVnbzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqpJZygd+w1faLOr1
162iOAmbBhx5SZWcTCZ/ZjHQTJM7GuPT624QkqsixFghRKdDROwpwnAP7gMRukLqiy4
163+kRuGT5OfyGggL95i2xqA+zehjj08lSTlvGHpePJgCyTavIy5+Ljsj4DKnKyuhxm
164biXTRrH83NDgixVkObTEmh/OVK0CAwEAATANBgkqhkiG9w0BAQ0FAAOBgQBa0Npw
165UkzjaYEo1OUE1sTI6Mm4riTIHMak4/nswKh9hYup//WVOlr/RBSBtZ7Q/BwbjobN
1663bfAtV7eSAqBsfxYXyof7G1ALANQERkq3+oyLP1iVt08W1WOUlIMPhdCF/QuCwy6
167x9MJLhUCGLJPM+O2rAPWVD9wCmvq10ALsiH3yA==
168-----END CERTIFICATE-----
169""")
170
171intermediate_server_key_pem = b("""-----BEGIN RSA PRIVATE KEY-----
172MIICXAIBAAKBgQCqklnKB37DV9os6vWI4CZsGHHlJlZxMJn9mMdBMkzsa49PrbhC
173SqyLEWCFEp0NE7CnCcA/uAxG6QuqLLj6RG4ZPk5/IaCAv3mLbGoD7N6GOPTyVJOW
1748Yel48mALJNq8jLn4uOyPgMqcrK6HGZuJdNGsfzc0OCLFWQ5tMSaH85UrQIDAQAB
175AoGAIQ594j5zna3/9WaPsTgnmhlesVctt4AAx/n827DA4ayyuHFlXUuVhtoWR5Pk
1765ezj9mtYW8DyeCegABnsu2vZni/CdvU6uiS1Hv6qM1GyYDm9KWgovIP9rQCDSGaz
177d57IWVGxx7ODFkm3gN5nxnSBOFVHytuW1J7FBRnEsehRroECQQDXHFOv82JuXDcz
178z3+4c74IEURdOHcbycxlppmK9kFqm5lsUdydnnGW+mvwDk0APOB7Wg7vyFyr393e
179dpmBDCzNAkEAyv6tVbTKUYhSjW+QhabJo896/EqQEYUmtMXxk4cQnKeR/Ao84Rkf
180EqD5IykMUfUI0jJU4DGX+gWZ10a7kNbHYQJAVFCuHNFxS4Cpwo0aqtnzKoZaHY/8
181X9ABZfafSHCtw3Op92M+7ikkrOELXdS9KdKyyqbKJAKNEHF3LbOfB44WIQJAA2N4
1829UNNVUsXRbElEnYUS529CdUczo4QdVgQjkvk5RiPAUwSdBd9Q0xYnFOlFwEmIowg
183ipWJWe0aAlP18ZcEQQJBAL+5lekZ/GUdQoZ4HAsN5a9syrzavJ9VvU1KOOPorPZK
184nMRZbbQgP+aSB7yl6K0gaLaZ8XaK0pjxNBh6ASqg9f4=
185-----END RSA PRIVATE KEY-----
186""")
187
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400188client_cert_pem = b("""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500189MIICJjCCAY+gAwIBAgIJAKxpFI5lODkjMA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
190BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
191VGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBSb290IENBMCIYDzIwMDkwMzI1MTIz
192ODA1WhgPMjAxNzA2MTExMjM4MDVaMBYxFDASBgNVBAMTC3VnbHkgY2xpZW50MIGf
193MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDAZh/SRtNm5ntMT4qb6YzEpTroMlq2
194rn+GrRHRiZ+xkCw/CGNhbtPir7/QxaUj26BSmQrHw1bGKEbPsWiW7bdXSespl+xK
195iku4G/KvnnmWdeJHqsiXeUZtqurMELcPQAw9xPHEuhqqUJvvEoMTsnCEqGM+7Dtb
196oCRajYyHfluARQIDAQABozYwNDAdBgNVHQ4EFgQUNQB+qkaOaEVecf1J3TTUtAff
1970fAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQEFBQADgYEAyv/Jh7gM
198Q3OHvmsFEEvRI+hsW8y66zK4K5de239Y44iZrFYkt7Q5nBPMEWDj4F2hLYWL/qtI
1999Zdr0U4UDCU9SmmGYh4o7R4TZ5pGFvBYvjhHbkSFYFQXZxKUi+WUxplP6I0wr2KJ
200PSTJCjJOn3xo2NTKRgV1gaoTf2EhL+RG8TQ=
201-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400202""")
Rick Dean94e46fd2009-07-18 14:51:24 -0500203
Jean-Paul Calderone22cbe502011-05-04 17:01:43 -0400204client_key_pem = normalize_privatekey_pem(b("""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500205MIICXgIBAAKBgQDAZh/SRtNm5ntMT4qb6YzEpTroMlq2rn+GrRHRiZ+xkCw/CGNh
206btPir7/QxaUj26BSmQrHw1bGKEbPsWiW7bdXSespl+xKiku4G/KvnnmWdeJHqsiX
207eUZtqurMELcPQAw9xPHEuhqqUJvvEoMTsnCEqGM+7DtboCRajYyHfluARQIDAQAB
208AoGATkZ+NceY5Glqyl4mD06SdcKfV65814vg2EL7V9t8+/mi9rYL8KztSXGlQWPX
209zuHgtRoMl78yQ4ZJYOBVo+nsx8KZNRCEBlE19bamSbQLCeQMenWnpeYyQUZ908gF
210h6L9qsFVJepgA9RDgAjyDoS5CaWCdCCPCH2lDkdcqC54SVUCQQDseuduc4wi8h4t
211V8AahUn9fn9gYfhoNuM0gdguTA0nPLVWz4hy1yJiWYQe0H7NLNNTmCKiLQaJpAbb
212TC6vE8C7AkEA0Ee8CMJUc20BnGEmxwgWcVuqFWaKCo8jTH1X38FlATUsyR3krjW2
213dL3yDD9NwHxsYP7nTKp/U8MV7U9IBn4y/wJBAJl7H0/BcLeRmuJk7IqJ7b635iYB
214D/9beFUw3MUXmQXZUfyYz39xf6CDZsu1GEdEC5haykeln3Of4M9d/4Kj+FcCQQCY
215si6xwT7GzMDkk/ko684AV3KPc/h6G0yGtFIrMg7J3uExpR/VdH2KgwMkZXisSMvw
216JJEQjOMCVsEJlRk54WWjAkEAzoZNH6UhDdBK5F38rVt/y4SEHgbSfJHIAmPS32Kq
217f6GGcfNpip0Uk7q7udTKuX7Q/buZi/C4YW7u3VKAquv9NA==
218-----END RSA PRIVATE KEY-----
Jean-Paul Calderone22cbe502011-05-04 17:01:43 -0400219"""))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400220
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400221cleartextCertificatePEM = b("""-----BEGIN CERTIFICATE-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400222MIIC7TCCAlagAwIBAgIIPQzE4MbeufQwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE
223BhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdU
224ZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwIhgPMjAwOTAzMjUxMjM2
225NThaGA8yMDE3MDYxMTEyMzY1OFowWDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklM
226MRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9U
227ZXN0aW5nIFJvb3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPmaQumL
228urpE527uSEHdL1pqcDRmWzu+98Y6YHzT/J7KWEamyMCNZ6fRW1JCR782UQ8a07fy
2292xXsKy4WdKaxyG8CcatwmXvpvRQ44dSANMihHELpANTdyVp6DCysED6wkQFurHlF
2301dshEaJw8b/ypDhmbVIo6Ci1xvCJqivbLFnbAgMBAAGjgbswgbgwHQYDVR0OBBYE
231FINVdy1eIfFJDAkk51QJEo3IfgSuMIGIBgNVHSMEgYAwfoAUg1V3LV4h8UkMCSTn
232VAkSjch+BK6hXKRaMFgxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UE
233BxMHQ2hpY2FnbzEQMA4GA1UEChMHVGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBS
234b290IENBggg9DMTgxt659DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB
235AGGCDazMJGoWNBpc03u6+smc95dEead2KlZXBATOdFT1VesY3+nUOqZhEhTGlDMi
236hkgaZnzoIq/Uamidegk4hirsCT/R+6vsKAAxNTcBjUeZjlykCJWy5ojShGftXIKY
237w/njVbKMXrvc83qmTdGl3TAM0fxQIpqgcglFLveEBgzn
238-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400239""")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400240
Jean-Paul Calderoned50d2042011-05-04 17:00:49 -0400241cleartextPrivateKeyPEM = normalize_privatekey_pem(b("""\
242-----BEGIN RSA PRIVATE KEY-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400243MIICXQIBAAKBgQD5mkLpi7q6ROdu7khB3S9aanA0Zls7vvfGOmB80/yeylhGpsjA
244jWen0VtSQke/NlEPGtO38tsV7CsuFnSmschvAnGrcJl76b0UOOHUgDTIoRxC6QDU
2453claegwsrBA+sJEBbqx5RdXbIRGicPG/8qQ4Zm1SKOgotcbwiaor2yxZ2wIDAQAB
246AoGBAPCgMpmLxzwDaUmcFbTJUvlLW1hoxNNYSu2jIZm1k/hRAcE60JYwvBkgz3UB
247yMEh0AtLxYe0bFk6EHah11tMUPgscbCq73snJ++8koUw+csk22G65hOs51bVb7Aa
2486JBe67oLzdtvgCUFAA2qfrKzWRZzAdhUirQUZgySZk+Xq1pBAkEA/kZG0A6roTSM
249BVnx7LnPfsycKUsTumorpXiylZJjTi9XtmzxhrYN6wgZlDOOwOLgSQhszGpxVoMD
250u3gByT1b2QJBAPtL3mSKdvwRu/+40zaZLwvSJRxaj0mcE4BJOS6Oqs/hS1xRlrNk
251PpQ7WJ4yM6ZOLnXzm2mKyxm50Mv64109FtMCQQDOqS2KkjHaLowTGVxwC0DijMfr
252I9Lf8sSQk32J5VWCySWf5gGTfEnpmUa41gKTMJIbqZZLucNuDcOtzUaeWZlZAkA8
253ttXigLnCqR486JDPTi9ZscoZkZ+w7y6e/hH8t6d5Vjt48JVyfjPIaJY+km58LcN3
2546AWSeGAdtRFHVzR7oHjVAkB4hutvxiOeiIVQNBhM6RSI9aBPMI21DoX2JRoxvNW2
255cbvAhow217X9V0dVerEOKxnNYspXRrh36h7k4mQA+sDq
256-----END RSA PRIVATE KEY-----
Jean-Paul Calderoned50d2042011-05-04 17:00:49 -0400257"""))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400258
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400259cleartextCertificateRequestPEM = b("""-----BEGIN CERTIFICATE REQUEST-----
260MIIBnjCCAQcCAQAwXjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQH
261EwdDaGljYWdvMRcwFQYDVQQKEw5NeSBDb21wYW55IEx0ZDEXMBUGA1UEAxMORnJl
262ZGVyaWNrIERlYW4wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANp6Y17WzKSw
263BsUWkXdqg6tnXy8H8hA1msCMWpc+/2KJ4mbv5NyD6UD+/SqagQqulPbF/DFea9nA
264E0zhmHJELcM8gUTIlXv/cgDWnmK4xj8YkjVUiCdqKRAKeuzLG1pGmwwF5lGeJpXN
265xQn5ecR0UYSOWj6TTGXB9VyUMQzCClcBAgMBAAGgADANBgkqhkiG9w0BAQUFAAOB
266gQAAJGuF/R/GGbeC7FbFW+aJgr9ee0Xbl6nlhu7pTe67k+iiKT2dsl2ti68MVTnu
267Vrb3HUNqOkiwsJf6kCtq5oPn3QVYzTa76Dt2y3Rtzv6boRSlmlfrgS92GNma8JfR
268oICQk3nAudi6zl1Dix3BCv1pUp5KMtGn3MeDEi6QFGy2rA==
269-----END CERTIFICATE REQUEST-----
270""")
Rick Dean5b7b6372009-04-01 11:34:06 -0500271
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400272encryptedPrivateKeyPEM = b("""-----BEGIN RSA PRIVATE KEY-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400273Proc-Type: 4,ENCRYPTED
274DEK-Info: DES-EDE3-CBC,9573604A18579E9E
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400275
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400276SHOho56WxDkT0ht10UTeKc0F5u8cqIa01kzFAmETw0MAs8ezYtK15NPdCXUm3X/2
277a17G7LSF5bkxOgZ7vpXyMzun/owrj7CzvLxyncyEFZWvtvzaAhPhvTJtTIB3kf8B
2788+qRcpTGK7NgXEgYBW5bj1y4qZkD4zCL9o9NQzsKI3Ie8i0239jsDOWR38AxjXBH
279mGwAQ4Z6ZN5dnmM4fhMIWsmFf19sNyAML4gHenQCHhmXbjXeVq47aC2ProInJbrm
280+00TcisbAQ40V9aehVbcDKtS4ZbMVDwncAjpXpcncC54G76N6j7F7wL7L/FuXa3A
281fvSVy9n2VfF/pJ3kYSflLHH2G/DFxjF7dl0GxhKPxJjp3IJi9VtuvmN9R2jZWLQF
282tfC8dXgy/P9CfFQhlinqBTEwgH0oZ/d4k4NVFDSdEMaSdmBAjlHpc+Vfdty3HVnV
283rKXj//wslsFNm9kIwJGIgKUa/n2jsOiydrsk1mgH7SmNCb3YHgZhbbnq0qLat/HC
284gHDt3FHpNQ31QzzL3yrenFB2L9osIsnRsDTPFNi4RX4SpDgNroxOQmyzCCV6H+d4
285o1mcnNiZSdxLZxVKccq0AfRpHqpPAFnJcQHP6xyT9MZp6fBa0XkxDnt9kNU8H3Qw
2867SJWZ69VXjBUzMlQViLuaWMgTnL+ZVyFZf9hTF7U/ef4HMLMAVNdiaGG+G+AjCV/
287MbzjS007Oe4qqBnCWaFPSnJX6uLApeTbqAxAeyCql56ULW5x6vDMNC3dwjvS/CEh
28811n8RkgFIQA0AhuKSIg3CbuartRsJnWOLwgLTzsrKYL4yRog1RJrtw==
289-----END RSA PRIVATE KEY-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400290""")
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400291
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400292encryptedPrivateKeyPEMPassphrase = b("foobar")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400293
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400294# Some PKCS#7 stuff. Generated with the openssl command line:
295#
296# openssl crl2pkcs7 -inform pem -outform pem -certfile s.pem -nocrl
297#
298# with a certificate and key (but the key should be irrelevant) in s.pem
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400299pkcs7Data = b("""\
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400300-----BEGIN PKCS7-----
301MIIDNwYJKoZIhvcNAQcCoIIDKDCCAyQCAQExADALBgkqhkiG9w0BBwGgggMKMIID
302BjCCAm+gAwIBAgIBATANBgkqhkiG9w0BAQQFADB7MQswCQYDVQQGEwJTRzERMA8G
303A1UEChMITTJDcnlwdG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtN
304MkNyeXB0byBDZXJ0aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNA
305cG9zdDEuY29tMB4XDTAwMDkxMDA5NTEzMFoXDTAyMDkxMDA5NTEzMFowUzELMAkG
306A1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwlsb2NhbGhvc3Qx
307HTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tMFwwDQYJKoZIhvcNAQEBBQAD
308SwAwSAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh5kwI
309zOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEAAaOCAQQwggEAMAkGA1UdEwQCMAAw
310LAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0G
311A1UdDgQWBBTPhIKSvnsmYsBVNWjj0m3M2z0qVTCBpQYDVR0jBIGdMIGagBT7hyNp
31265w6kxXlxb8pUU/+7Sg4AaF/pH0wezELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0y
313Q3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlwdG8g
314Q2VydGlmaWNhdGUgTWFzdGVyMR0wGwYJKoZIhvcNAQkBFg5uZ3BzQHBvc3QxLmNv
315bYIBADANBgkqhkiG9w0BAQQFAAOBgQA7/CqT6PoHycTdhEStWNZde7M/2Yc6BoJu
316VwnW8YxGO8Sn6UJ4FeffZNcYZddSDKosw8LtPOeWoK3JINjAk5jiPQ2cww++7QGG
317/g5NDjxFZNDJP1dGiLAxPW6JXwov4v0FmdzfLOZ01jDcgQQZqEpYlgpuI5JEWUQ9
318Ho4EzbYCOaEAMQA=
319-----END PKCS7-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400320""")
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400321
Alex Gaynor8fa1dd62014-08-14 09:57:51 -0700322pkcs7DataASN1 = base64.b64decode(b"""
Alex Gaynor4b9c96a2014-08-14 09:51:48 -0700323MIIDNwYJKoZIhvcNAQcCoIIDKDCCAyQCAQExADALBgkqhkiG9w0BBwGgggMKMIID
324BjCCAm+gAwIBAgIBATANBgkqhkiG9w0BAQQFADB7MQswCQYDVQQGEwJTRzERMA8G
325A1UEChMITTJDcnlwdG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtN
326MkNyeXB0byBDZXJ0aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNA
327cG9zdDEuY29tMB4XDTAwMDkxMDA5NTEzMFoXDTAyMDkxMDA5NTEzMFowUzELMAkG
328A1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwlsb2NhbGhvc3Qx
329HTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tMFwwDQYJKoZIhvcNAQEBBQAD
330SwAwSAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh5kwI
331zOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEAAaOCAQQwggEAMAkGA1UdEwQCMAAw
332LAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0G
333A1UdDgQWBBTPhIKSvnsmYsBVNWjj0m3M2z0qVTCBpQYDVR0jBIGdMIGagBT7hyNp
33465w6kxXlxb8pUU/+7Sg4AaF/pH0wezELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0y
335Q3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlwdG8g
336Q2VydGlmaWNhdGUgTWFzdGVyMR0wGwYJKoZIhvcNAQkBFg5uZ3BzQHBvc3QxLmNv
337bYIBADANBgkqhkiG9w0BAQQFAAOBgQA7/CqT6PoHycTdhEStWNZde7M/2Yc6BoJu
338VwnW8YxGO8Sn6UJ4FeffZNcYZddSDKosw8LtPOeWoK3JINjAk5jiPQ2cww++7QGG
339/g5NDjxFZNDJP1dGiLAxPW6JXwov4v0FmdzfLOZ01jDcgQQZqEpYlgpuI5JEWUQ9
340Ho4EzbYCOaEAMQA=
Alex Gaynor8fa1dd62014-08-14 09:57:51 -0700341""")
Alex Gaynor4b9c96a2014-08-14 09:51:48 -0700342
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400343crlData = b("""\
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -0500344-----BEGIN X509 CRL-----
345MIIBWzCBxTANBgkqhkiG9w0BAQQFADBYMQswCQYDVQQGEwJVUzELMAkGA1UECBMC
346SUwxEDAOBgNVBAcTB0NoaWNhZ28xEDAOBgNVBAoTB1Rlc3RpbmcxGDAWBgNVBAMT
347D1Rlc3RpbmcgUm9vdCBDQRcNMDkwNzI2MDQzNDU2WhcNMTIwOTI3MDI0MTUyWjA8
348MBUCAgOrGA8yMDA5MDcyNTIzMzQ1NlowIwICAQAYDzIwMDkwNzI1MjMzNDU2WjAM
349MAoGA1UdFQQDCgEEMA0GCSqGSIb3DQEBBAUAA4GBAEBt7xTs2htdD3d4ErrcGAw1
3504dKcVnIWTutoI7xxen26Wwvh8VCsT7i/UeP+rBl9rC/kfjWjzQk3/zleaarGTpBT
3510yp4HXRFFoRhhSE/hP+eteaPXRgrsNRLHe9ZDd69wmh7J1wMDb0m81RG7kqcbsid
352vrzEeLDRiiPl92dyyWmu
353-----END X509 CRL-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400354""")
Jean-Paul Calderonee890db32010-08-22 16:55:15 -0400355
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400356
357# A broken RSA private key which can be used to test the error path through
358# PKey.check.
359inconsistentPrivateKeyPEM = b("""-----BEGIN RSA PRIVATE KEY-----
360MIIBPAIBAAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh
3615kwIzOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEaAQJBAIqm/bz4NA1H++Vx5Ewx
362OcKp3w19QSaZAwlGRtsUxrP7436QjnREM3Bm8ygU11BjkPVmtrKm6AayQfCHqJoT
363zIECIQDW0BoMoL0HOYM/mrTLhaykYAVqgIeJsPjvkEhTFXWBuQIhAM3deFAvWNu4
364nklUQ37XsCT2c9tmNt1LAT+slG2JOTTRAiAuXDtC/m3NYVwyHfFm+zKHRzHkClk2
365HjubeEgjpj32AQIhAJqMGTaZVOwevTXvvHwNeH+vRWsAYU/gbx+OQB+7VOcBAiEA
366oolb6NMg/R3enNPvS1O4UU1H8wpaF77L4yiSWlE0p4w=
367-----END RSA PRIVATE KEY-----
368""")
369
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -0400370# certificate with NULL bytes in subjectAltName and common name
371
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400372nulbyteSubjectAltNamePEM = b("""-----BEGIN CERTIFICATE-----
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -0400373MIIE2DCCA8CgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBxTELMAkGA1UEBhMCVVMx
374DzANBgNVBAgMBk9yZWdvbjESMBAGA1UEBwwJQmVhdmVydG9uMSMwIQYDVQQKDBpQ
375eXRob24gU29mdHdhcmUgRm91bmRhdGlvbjEgMB4GA1UECwwXUHl0aG9uIENvcmUg
376RGV2ZWxvcG1lbnQxJDAiBgNVBAMMG251bGwucHl0aG9uLm9yZwBleGFtcGxlLm9y
377ZzEkMCIGCSqGSIb3DQEJARYVcHl0aG9uLWRldkBweXRob24ub3JnMB4XDTEzMDgw
378NzEzMTE1MloXDTEzMDgwNzEzMTI1MlowgcUxCzAJBgNVBAYTAlVTMQ8wDQYDVQQI
379DAZPcmVnb24xEjAQBgNVBAcMCUJlYXZlcnRvbjEjMCEGA1UECgwaUHl0aG9uIFNv
380ZnR3YXJlIEZvdW5kYXRpb24xIDAeBgNVBAsMF1B5dGhvbiBDb3JlIERldmVsb3Bt
381ZW50MSQwIgYDVQQDDBtudWxsLnB5dGhvbi5vcmcAZXhhbXBsZS5vcmcxJDAiBgkq
382hkiG9w0BCQEWFXB5dGhvbi1kZXZAcHl0aG9uLm9yZzCCASIwDQYJKoZIhvcNAQEB
383BQADggEPADCCAQoCggEBALXq7cn7Rn1vO3aA3TrzA5QLp6bb7B3f/yN0CJ2XFj+j
384pHs+Gw6WWSUDpybiiKnPec33BFawq3kyblnBMjBU61ioy5HwQqVkJ8vUVjGIUq3P
385vX/wBmQfzCe4o4uM89gpHyUL9UYGG8oCRa17dgqcv7u5rg0Wq2B1rgY+nHwx3JIv
386KRrgSwyRkGzpN8WQ1yrXlxWjgI9de0mPVDDUlywcWze1q2kwaEPTM3hLAmD1PESA
387oY/n8A/RXoeeRs9i/Pm/DGUS8ZPINXk/yOzsR/XvvkTVroIeLZqfmFpnZeF0cHzL
38808LODkVJJ9zjLdT7SA4vnne4FEbAxDbKAq5qkYzaL4UCAwEAAaOB0DCBzTAMBgNV
389HRMBAf8EAjAAMB0GA1UdDgQWBBSIWlXAUv9hzVKjNQ/qWpwkOCL3XDALBgNVHQ8E
390BAMCBeAwgZAGA1UdEQSBiDCBhYIeYWx0bnVsbC5weXRob24ub3JnAGV4YW1wbGUu
391Y29tgSBudWxsQHB5dGhvbi5vcmcAdXNlckBleGFtcGxlLm9yZ4YpaHR0cDovL251
392bGwucHl0aG9uLm9yZwBodHRwOi8vZXhhbXBsZS5vcmeHBMAAAgGHECABDbgAAAAA
393AAAAAAAAAAEwDQYJKoZIhvcNAQEFBQADggEBAKxPRe99SaghcI6IWT7UNkJw9aO9
394i9eo0Fj2MUqxpKbdb9noRDy2CnHWf7EIYZ1gznXPdwzSN4YCjV5d+Q9xtBaowT0j
395HPERs1ZuytCNNJTmhyqZ8q6uzMLoht4IqH/FBfpvgaeC5tBTnTT0rD5A/olXeimk
396kX4LxlEx5RAvpGB2zZVRGr6LobD9rVK91xuHYNIxxxfEGE8tCCWjp0+3ksri9SXx
397VHWBnbM9YaL32u3hxm8sYB/Yb8WSBavJCWJJqRStVRHM1koZlJmXNx2BX4vPo6iW
398RFEIPQsFZRLrtnCAiEhyT8bC2s/Njlu6ly9gtJZWSV46Q3ZjBL4q9sHKqZQ=
399-----END CERTIFICATE-----""")
400
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400401
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400402class X509ExtTests(TestCase):
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400403 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900404 Tests for :py:class:`OpenSSL.crypto.X509Extension`.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400405 """
406
407 def setUp(self):
408 """
409 Create a new private key and start a certificate request (for a test
410 method to finish in one way or another).
411 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -0800412 super(X509ExtTests, self).setUp()
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400413 # Basic setup stuff to generate a certificate
414 self.pkey = PKey()
415 self.pkey.generate_key(TYPE_RSA, 384)
416 self.req = X509Req()
417 self.req.set_pubkey(self.pkey)
418 # Authority good you have.
419 self.req.get_subject().commonName = "Yoda root CA"
420 self.x509 = X509()
421 self.subject = self.x509.get_subject()
422 self.subject.commonName = self.req.get_subject().commonName
423 self.x509.set_issuer(self.subject)
424 self.x509.set_pubkey(self.pkey)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400425 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
426 expire = b((datetime.now() + timedelta(days=100)).strftime("%Y%m%d%H%M%SZ"))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400427 self.x509.set_notBefore(now)
428 self.x509.set_notAfter(expire)
429
430
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -0800431 def tearDown(self):
432 """
433 Forget all of the pyOpenSSL objects so they can be garbage collected,
434 their memory released, and not interfere with the leak detection code.
435 """
436 self.pkey = self.req = self.x509 = self.subject = None
437 super(X509ExtTests, self).tearDown()
438
439
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400440 def test_str(self):
441 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900442 The string representation of :py:class:`X509Extension` instances as returned by
443 :py:data:`str` includes stuff.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400444 """
445 # This isn't necessarily the best string representation. Perhaps it
446 # will be changed/improved in the future.
447 self.assertEquals(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400448 str(X509Extension(b('basicConstraints'), True, b('CA:false'))),
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400449 'CA:FALSE')
450
451
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400452 def test_type(self):
453 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900454 :py:class:`X509Extension` and :py:class:`X509ExtensionType` refer to the same type object
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400455 and can be used to create instances of that type.
456 """
457 self.assertIdentical(X509Extension, X509ExtensionType)
458 self.assertConsistentType(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400459 X509Extension,
460 'X509Extension', b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400461
462
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500463 def test_construction(self):
464 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900465 :py:class:`X509Extension` accepts an extension type name, a critical flag,
466 and an extension value and returns an :py:class:`X509ExtensionType` instance.
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500467 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400468 basic = X509Extension(b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500469 self.assertTrue(
470 isinstance(basic, X509ExtensionType),
471 "%r is of type %r, should be %r" % (
472 basic, type(basic), X509ExtensionType))
473
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400474 comment = X509Extension(
475 b('nsComment'), False, b('pyOpenSSL unit test'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500476 self.assertTrue(
477 isinstance(comment, X509ExtensionType),
478 "%r is of type %r, should be %r" % (
479 comment, type(comment), X509ExtensionType))
480
481
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500482 def test_invalid_extension(self):
483 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900484 :py:class:`X509Extension` raises something if it is passed a bad extension
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500485 name or value.
486 """
487 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400488 Error, X509Extension, b('thisIsMadeUp'), False, b('hi'))
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500489 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400490 Error, X509Extension, b('basicConstraints'), False, b('blah blah'))
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500491
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500492 # Exercise a weird one (an extension which uses the r2i method). This
493 # exercises the codepath that requires a non-NULL ctx to be passed to
494 # X509V3_EXT_nconf. It can't work now because we provide no
495 # configuration database. It might be made to work in the future.
496 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400497 Error, X509Extension, b('proxyCertInfo'), True,
498 b('language:id-ppl-anyLanguage,pathlen:1,policy:text:AB'))
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500499
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500500
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500501 def test_get_critical(self):
502 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900503 :py:meth:`X509ExtensionType.get_critical` returns the value of the
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500504 extension's critical flag.
505 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400506 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500507 self.assertTrue(ext.get_critical())
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400508 ext = X509Extension(b('basicConstraints'), False, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500509 self.assertFalse(ext.get_critical())
510
Jean-Paul Calderone7535dab2008-03-06 18:53:11 -0500511
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500512 def test_get_short_name(self):
513 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900514 :py:meth:`X509ExtensionType.get_short_name` returns a string giving the short
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500515 type name of the extension.
516 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400517 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
518 self.assertEqual(ext.get_short_name(), b('basicConstraints'))
519 ext = X509Extension(b('nsComment'), True, b('foo bar'))
520 self.assertEqual(ext.get_short_name(), b('nsComment'))
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500521
522
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400523 def test_get_data(self):
524 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900525 :py:meth:`X509Extension.get_data` returns a string giving the data of the
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400526 extension.
527 """
528 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
529 # Expect to get back the DER encoded form of CA:true.
530 self.assertEqual(ext.get_data(), b('0\x03\x01\x01\xff'))
531
532
533 def test_get_data_wrong_args(self):
534 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900535 :py:meth:`X509Extension.get_data` raises :py:exc:`TypeError` if passed any arguments.
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400536 """
537 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
538 self.assertRaises(TypeError, ext.get_data, None)
539 self.assertRaises(TypeError, ext.get_data, "foo")
540 self.assertRaises(TypeError, ext.get_data, 7)
541
542
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400543 def test_unused_subject(self):
Rick Dean47262da2009-07-08 16:17:17 -0500544 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900545 The :py:data:`subject` parameter to :py:class:`X509Extension` may be provided for an
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400546 extension which does not use it and is ignored in this case.
Rick Dean47262da2009-07-08 16:17:17 -0500547 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400548 ext1 = X509Extension(
549 b('basicConstraints'), False, b('CA:TRUE'), subject=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400550 self.x509.add_extensions([ext1])
551 self.x509.sign(self.pkey, 'sha1')
552 # This is a little lame. Can we think of a better way?
553 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400554 self.assertTrue(b('X509v3 Basic Constraints:') in text)
555 self.assertTrue(b('CA:TRUE') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400556
557
558 def test_subject(self):
559 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900560 If an extension requires a subject, the :py:data:`subject` parameter to
561 :py:class:`X509Extension` provides its value.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400562 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400563 ext3 = X509Extension(
564 b('subjectKeyIdentifier'), False, b('hash'), subject=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400565 self.x509.add_extensions([ext3])
566 self.x509.sign(self.pkey, 'sha1')
567 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400568 self.assertTrue(b('X509v3 Subject Key Identifier:') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400569
570
571 def test_missing_subject(self):
572 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900573 If an extension requires a subject and the :py:data:`subject` parameter is
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400574 given no value, something happens.
575 """
576 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400577 Error, X509Extension, b('subjectKeyIdentifier'), False, b('hash'))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400578
579
580 def test_invalid_subject(self):
581 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900582 If the :py:data:`subject` parameter is given a value which is not an
583 :py:class:`X509` instance, :py:exc:`TypeError` is raised.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400584 """
585 for badObj in [True, object(), "hello", [], self]:
586 self.assertRaises(
587 TypeError,
588 X509Extension,
589 'basicConstraints', False, 'CA:TRUE', subject=badObj)
590
591
592 def test_unused_issuer(self):
593 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900594 The :py:data:`issuer` parameter to :py:class:`X509Extension` may be provided for an
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400595 extension which does not use it and is ignored in this case.
596 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400597 ext1 = X509Extension(
598 b('basicConstraints'), False, b('CA:TRUE'), issuer=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400599 self.x509.add_extensions([ext1])
600 self.x509.sign(self.pkey, 'sha1')
601 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400602 self.assertTrue(b('X509v3 Basic Constraints:') in text)
603 self.assertTrue(b('CA:TRUE') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400604
605
606 def test_issuer(self):
607 """
Alex Gaynor3b0ee972014-11-15 09:17:33 -0800608 If an extension requires an issuer, the :py:data:`issuer` parameter to
Jonathan Ballet648875f2011-07-16 14:14:58 +0900609 :py:class:`X509Extension` provides its value.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400610 """
611 ext2 = X509Extension(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400612 b('authorityKeyIdentifier'), False, b('issuer:always'),
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400613 issuer=self.x509)
614 self.x509.add_extensions([ext2])
615 self.x509.sign(self.pkey, 'sha1')
616 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400617 self.assertTrue(b('X509v3 Authority Key Identifier:') in text)
618 self.assertTrue(b('DirName:/CN=Yoda root CA') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400619
620
621 def test_missing_issuer(self):
622 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900623 If an extension requires an issue and the :py:data:`issuer` parameter is given
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400624 no value, something happens.
625 """
626 self.assertRaises(
627 Error,
628 X509Extension,
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400629 b('authorityKeyIdentifier'), False,
630 b('keyid:always,issuer:always'))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400631
632
633 def test_invalid_issuer(self):
634 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900635 If the :py:data:`issuer` parameter is given a value which is not an
636 :py:class:`X509` instance, :py:exc:`TypeError` is raised.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400637 """
638 for badObj in [True, object(), "hello", [], self]:
639 self.assertRaises(
640 TypeError,
641 X509Extension,
642 'authorityKeyIdentifier', False, 'keyid:always,issuer:always',
643 issuer=badObj)
Rick Dean47262da2009-07-08 16:17:17 -0500644
645
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500646
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400647class PKeyTests(TestCase):
Jean-Paul Calderoneac930e12008-03-06 18:50:51 -0500648 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900649 Unit tests for :py:class:`OpenSSL.crypto.PKey`.
Jean-Paul Calderoneac930e12008-03-06 18:50:51 -0500650 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400651 def test_type(self):
652 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900653 :py:class:`PKey` and :py:class:`PKeyType` refer to the same type object
654 and can be used to create instances of that type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400655 """
656 self.assertIdentical(PKey, PKeyType)
657 self.assertConsistentType(PKey, 'PKey')
658
659
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500660 def test_construction(self):
661 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900662 :py:class:`PKey` takes no arguments and returns a new :py:class:`PKey` instance.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500663 """
664 self.assertRaises(TypeError, PKey, None)
665 key = PKey()
666 self.assertTrue(
667 isinstance(key, PKeyType),
668 "%r is of type %r, should be %r" % (key, type(key), PKeyType))
669
670
671 def test_pregeneration(self):
672 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900673 :py:attr:`PKeyType.bits` and :py:attr:`PKeyType.type` return :py:data:`0` before the key is
674 generated. :py:attr:`PKeyType.check` raises :py:exc:`TypeError` before the key is
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500675 generated.
676 """
677 key = PKey()
678 self.assertEqual(key.type(), 0)
679 self.assertEqual(key.bits(), 0)
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400680 self.assertRaises(TypeError, key.check)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500681
682
683 def test_failedGeneration(self):
684 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900685 :py:meth:`PKeyType.generate_key` takes two arguments, the first giving the key
686 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 -0500687 number of bits to generate. If an invalid type is specified or
Jonathan Ballet648875f2011-07-16 14:14:58 +0900688 generation fails, :py:exc:`Error` is raised. If an invalid number of bits is
689 specified, :py:exc:`ValueError` or :py:exc:`Error` is raised.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500690 """
691 key = PKey()
692 self.assertRaises(TypeError, key.generate_key)
693 self.assertRaises(TypeError, key.generate_key, 1, 2, 3)
694 self.assertRaises(TypeError, key.generate_key, "foo", "bar")
695 self.assertRaises(Error, key.generate_key, -1, 0)
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500696
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500697 self.assertRaises(ValueError, key.generate_key, TYPE_RSA, -1)
698 self.assertRaises(ValueError, key.generate_key, TYPE_RSA, 0)
Jean-Paul Calderoned71fe982008-03-06 00:31:50 -0500699
700 # XXX RSA generation for small values of bits is fairly buggy in a wide
701 # range of OpenSSL versions. I need to figure out what the safe lower
702 # bound for a reasonable number of OpenSSL versions is and explicitly
703 # check for that in the wrapper. The failure behavior is typically an
704 # infinite loop inside OpenSSL.
705
706 # self.assertRaises(Error, key.generate_key, TYPE_RSA, 2)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500707
708 # XXX DSA generation seems happy with any number of bits. The DSS
709 # says bits must be between 512 and 1024 inclusive. OpenSSL's DSA
710 # generator doesn't seem to care about the upper limit at all. For
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500711 # the lower limit, it uses 512 if anything smaller is specified.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500712 # So, it doesn't seem possible to make generate_key fail for
713 # TYPE_DSA with a bits argument which is at least an int.
714
715 # self.assertRaises(Error, key.generate_key, TYPE_DSA, -7)
716
717
718 def test_rsaGeneration(self):
719 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900720 :py:meth:`PKeyType.generate_key` generates an RSA key when passed
721 :py:data:`TYPE_RSA` as a type and a reasonable number of bits.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500722 """
723 bits = 128
724 key = PKey()
725 key.generate_key(TYPE_RSA, bits)
726 self.assertEqual(key.type(), TYPE_RSA)
727 self.assertEqual(key.bits(), bits)
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -0400728 self.assertTrue(key.check())
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500729
730
731 def test_dsaGeneration(self):
732 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900733 :py:meth:`PKeyType.generate_key` generates a DSA key when passed
734 :py:data:`TYPE_DSA` as a type and a reasonable number of bits.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500735 """
736 # 512 is a magic number. The DSS (Digital Signature Standard)
737 # allows a minimum of 512 bits for DSA. DSA_generate_parameters
738 # will silently promote any value below 512 to 512.
739 bits = 512
740 key = PKey()
741 key.generate_key(TYPE_DSA, bits)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800742 # self.assertEqual(key.type(), TYPE_DSA)
743 # self.assertEqual(key.bits(), bits)
744 # self.assertRaises(TypeError, key.check)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500745
746
747 def test_regeneration(self):
748 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900749 :py:meth:`PKeyType.generate_key` can be called multiple times on the same
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500750 key to generate new keys.
751 """
752 key = PKey()
753 for type, bits in [(TYPE_RSA, 512), (TYPE_DSA, 576)]:
754 key.generate_key(type, bits)
755 self.assertEqual(key.type(), type)
756 self.assertEqual(key.bits(), bits)
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500757
758
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400759 def test_inconsistentKey(self):
760 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900761 :py:`PKeyType.check` returns :py:exc:`Error` if the key is not consistent.
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400762 """
763 key = load_privatekey(FILETYPE_PEM, inconsistentPrivateKeyPEM)
Jean-Paul Calderoned338e4e2009-05-13 15:45:07 -0400764 self.assertRaises(Error, key.check)
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400765
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500766
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400767 def test_check_wrong_args(self):
768 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900769 :py:meth:`PKeyType.check` raises :py:exc:`TypeError` if called with any arguments.
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400770 """
771 self.assertRaises(TypeError, PKey().check, None)
772 self.assertRaises(TypeError, PKey().check, object())
773 self.assertRaises(TypeError, PKey().check, 1)
774
775
Jean-Paul Calderone02d01972011-10-31 10:39:29 -0400776 def test_check_public_key(self):
777 """
778 :py:meth:`PKeyType.check` raises :py:exc:`TypeError` if only the public
779 part of the key is available.
780 """
781 # A trick to get a public-only key
782 key = PKey()
783 key.generate_key(TYPE_RSA, 512)
784 cert = X509()
785 cert.set_pubkey(key)
786 pub = cert.get_pubkey()
787 self.assertRaises(TypeError, pub.check)
788
789
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400790
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400791class X509NameTests(TestCase):
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500792 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900793 Unit tests for :py:class:`OpenSSL.crypto.X509Name`.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500794 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500795 def _x509name(self, **attrs):
796 # XXX There's no other way to get a new X509Name yet.
797 name = X509().get_subject()
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400798 attrs = list(attrs.items())
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500799 # Make the order stable - order matters!
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400800 def key(attr):
801 return attr[1]
802 attrs.sort(key=key)
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500803 for k, v in attrs:
804 setattr(name, k, v)
805 return name
806
807
Rick Deane15b1472009-07-09 15:53:42 -0500808 def test_type(self):
809 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900810 The type of X509Name objects is :py:class:`X509NameType`.
Rick Deane15b1472009-07-09 15:53:42 -0500811 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400812 self.assertIdentical(X509Name, X509NameType)
813 self.assertEqual(X509NameType.__name__, 'X509Name')
814 self.assertTrue(isinstance(X509NameType, type))
815
Rick Deane15b1472009-07-09 15:53:42 -0500816 name = self._x509name()
817 self.assertTrue(
818 isinstance(name, X509NameType),
819 "%r is of type %r, should be %r" % (
820 name, type(name), X509NameType))
Rick Deane15b1472009-07-09 15:53:42 -0500821
822
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400823 def test_onlyStringAttributes(self):
824 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900825 Attempting to set a non-:py:data:`str` attribute name on an :py:class:`X509NameType`
826 instance causes :py:exc:`TypeError` to be raised.
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400827 """
828 name = self._x509name()
829 # Beyond these cases, you may also think that unicode should be
830 # rejected. Sorry, you're wrong. unicode is automatically converted to
831 # str outside of the control of X509Name, so there's no way to reject
832 # it.
Jean-Paul Calderoneff363be2013-03-03 10:21:23 -0800833
834 # Also, this used to test str subclasses, but that test is less relevant
835 # now that the implementation is in Python instead of C. Also PyPy
836 # automatically converts str subclasses to str when they are passed to
837 # setattr, so we can't test it on PyPy. Apparently CPython does this
838 # sometimes as well.
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400839 self.assertRaises(TypeError, setattr, name, None, "hello")
840 self.assertRaises(TypeError, setattr, name, 30, "hello")
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400841
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -0500842
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400843 def test_setInvalidAttribute(self):
844 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900845 Attempting to set any attribute name on an :py:class:`X509NameType` instance for
846 which no corresponding NID is defined causes :py:exc:`AttributeError` to be
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400847 raised.
848 """
849 name = self._x509name()
850 self.assertRaises(AttributeError, setattr, name, "no such thing", None)
851
852
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500853 def test_attributes(self):
854 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900855 :py:class:`X509NameType` instances have attributes for each standard (?)
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500856 X509Name field.
857 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500858 name = self._x509name()
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500859 name.commonName = "foo"
860 self.assertEqual(name.commonName, "foo")
861 self.assertEqual(name.CN, "foo")
862 name.CN = "baz"
863 self.assertEqual(name.commonName, "baz")
864 self.assertEqual(name.CN, "baz")
865 name.commonName = "bar"
866 self.assertEqual(name.commonName, "bar")
867 self.assertEqual(name.CN, "bar")
868 name.CN = "quux"
869 self.assertEqual(name.commonName, "quux")
870 self.assertEqual(name.CN, "quux")
871
872
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500873 def test_copy(self):
874 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900875 :py:class:`X509Name` creates a new :py:class:`X509NameType` instance with all the same
876 attributes as an existing :py:class:`X509NameType` instance when called with
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500877 one.
878 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500879 name = self._x509name(commonName="foo", emailAddress="bar@example.com")
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500880
881 copy = X509Name(name)
882 self.assertEqual(copy.commonName, "foo")
883 self.assertEqual(copy.emailAddress, "bar@example.com")
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500884
885 # Mutate the copy and ensure the original is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500886 copy.commonName = "baz"
887 self.assertEqual(name.commonName, "foo")
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500888
889 # Mutate the original and ensure the copy is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500890 name.emailAddress = "quux@example.com"
891 self.assertEqual(copy.emailAddress, "bar@example.com")
892
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500893
894 def test_repr(self):
895 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900896 :py:func:`repr` passed an :py:class:`X509NameType` instance should return a string
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500897 containing a description of the type and the NIDs which have been set
898 on it.
899 """
900 name = self._x509name(commonName="foo", emailAddress="bar")
901 self.assertEqual(
902 repr(name),
903 "<X509Name object '/emailAddress=bar/CN=foo'>")
904
905
906 def test_comparison(self):
907 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900908 :py:class:`X509NameType` instances should compare based on their NIDs.
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500909 """
910 def _equality(a, b, assertTrue, assertFalse):
911 assertTrue(a == b, "(%r == %r) --> False" % (a, b))
912 assertFalse(a != b)
913 assertTrue(b == a)
914 assertFalse(b != a)
915
916 def assertEqual(a, b):
917 _equality(a, b, self.assertTrue, self.assertFalse)
918
919 # Instances compare equal to themselves.
920 name = self._x509name()
921 assertEqual(name, name)
922
923 # Empty instances should compare equal to each other.
924 assertEqual(self._x509name(), self._x509name())
925
926 # Instances with equal NIDs should compare equal to each other.
927 assertEqual(self._x509name(commonName="foo"),
928 self._x509name(commonName="foo"))
929
930 # Instance with equal NIDs set using different aliases should compare
931 # equal to each other.
932 assertEqual(self._x509name(commonName="foo"),
933 self._x509name(CN="foo"))
934
935 # Instances with more than one NID with the same values should compare
936 # equal to each other.
937 assertEqual(self._x509name(CN="foo", organizationalUnitName="bar"),
938 self._x509name(commonName="foo", OU="bar"))
939
940 def assertNotEqual(a, b):
941 _equality(a, b, self.assertFalse, self.assertTrue)
942
943 # Instances with different values for the same NID should not compare
944 # equal to each other.
945 assertNotEqual(self._x509name(CN="foo"),
946 self._x509name(CN="bar"))
947
948 # Instances with different NIDs should not compare equal to each other.
949 assertNotEqual(self._x509name(CN="foo"),
950 self._x509name(OU="foo"))
951
952 def _inequality(a, b, assertTrue, assertFalse):
953 assertTrue(a < b)
954 assertTrue(a <= b)
955 assertTrue(b > a)
956 assertTrue(b >= a)
957 assertFalse(a > b)
958 assertFalse(a >= b)
959 assertFalse(b < a)
960 assertFalse(b <= a)
961
962 def assertLessThan(a, b):
963 _inequality(a, b, self.assertTrue, self.assertFalse)
964
965 # An X509Name with a NID with a value which sorts less than the value
966 # of the same NID on another X509Name compares less than the other
967 # X509Name.
968 assertLessThan(self._x509name(CN="abc"),
969 self._x509name(CN="def"))
970
971 def assertGreaterThan(a, b):
972 _inequality(a, b, self.assertFalse, self.assertTrue)
973
974 # An X509Name with a NID with a value which sorts greater than the
975 # value of the same NID on another X509Name compares greater than the
976 # other X509Name.
977 assertGreaterThan(self._x509name(CN="def"),
978 self._x509name(CN="abc"))
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -0500979
980
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400981 def test_hash(self):
982 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900983 :py:meth:`X509Name.hash` returns an integer hash based on the value of the
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400984 name.
985 """
986 a = self._x509name(CN="foo")
987 b = self._x509name(CN="foo")
988 self.assertEqual(a.hash(), b.hash())
989 a.CN = "bar"
990 self.assertNotEqual(a.hash(), b.hash())
991
992
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400993 def test_der(self):
994 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900995 :py:meth:`X509Name.der` returns the DER encoded form of the name.
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400996 """
997 a = self._x509name(CN="foo", C="US")
998 self.assertEqual(
999 a.der(),
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -04001000 b('0\x1b1\x0b0\t\x06\x03U\x04\x06\x13\x02US'
1001 '1\x0c0\n\x06\x03U\x04\x03\x13\x03foo'))
Jean-Paul Calderonee957a002008-03-25 15:16:51 -04001002
1003
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -04001004 def test_get_components(self):
1005 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001006 :py:meth:`X509Name.get_components` returns a :py:data:`list` of
1007 two-tuples of :py:data:`str`
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -04001008 giving the NIDs and associated values which make up the name.
1009 """
1010 a = self._x509name()
1011 self.assertEqual(a.get_components(), [])
1012 a.CN = "foo"
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -04001013 self.assertEqual(a.get_components(), [(b("CN"), b("foo"))])
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -04001014 a.organizationalUnitName = "bar"
1015 self.assertEqual(
1016 a.get_components(),
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -04001017 [(b("CN"), b("foo")), (b("OU"), b("bar"))])
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -04001018
Jean-Paul Calderone110cd092008-03-24 17:27:42 -04001019
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001020 def test_load_nul_byte_attribute(self):
1021 """
Jean-Paul Calderone9af07b02013-08-23 16:07:31 -04001022 An :py:class:`OpenSSL.crypto.X509Name` from an
1023 :py:class:`OpenSSL.crypto.X509` instance loaded from a file can have a
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001024 NUL byte in the value of one of its attributes.
1025 """
1026 cert = load_certificate(FILETYPE_PEM, nulbyteSubjectAltNamePEM)
1027 subject = cert.get_subject()
1028 self.assertEqual(
Jean-Paul Calderone06754fc2013-08-23 15:47:47 -04001029 "null.python.org\x00example.org", subject.commonName)
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001030
1031
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -05001032 def test_setAttributeFailure(self):
1033 """
1034 If the value of an attribute cannot be set for some reason then
1035 :py:class:`OpenSSL.crypto.Error` is raised.
1036 """
1037 name = self._x509name()
1038 # This value is too long
1039 self.assertRaises(Error, setattr, name, "O", b"x" * 512)
1040
1041
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001042
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001043class _PKeyInteractionTestsMixin:
1044 """
1045 Tests which involve another thing and a PKey.
1046 """
1047 def signable(self):
1048 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001049 Return something with a :py:meth:`set_pubkey`, :py:meth:`set_pubkey`,
1050 and :py:meth:`sign` method.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001051 """
1052 raise NotImplementedError()
1053
1054
1055 def test_signWithUngenerated(self):
1056 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001057 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when pass a
1058 :py:class:`PKey` with no parts.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001059 """
1060 request = self.signable()
1061 key = PKey()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001062 self.assertRaises(ValueError, request.sign, key, GOOD_DIGEST)
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001063
1064
1065 def test_signWithPublicKey(self):
1066 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001067 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when pass a
1068 :py:class:`PKey` with no private part as the signing key.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001069 """
1070 request = self.signable()
1071 key = PKey()
1072 key.generate_key(TYPE_RSA, 512)
1073 request.set_pubkey(key)
1074 pub = request.get_pubkey()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001075 self.assertRaises(ValueError, request.sign, pub, GOOD_DIGEST)
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001076
1077
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -04001078 def test_signWithUnknownDigest(self):
1079 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001080 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when passed a digest name which is
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -04001081 not known.
1082 """
1083 request = self.signable()
1084 key = PKey()
1085 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001086 self.assertRaises(ValueError, request.sign, key, BAD_DIGEST)
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -04001087
1088
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04001089 def test_sign(self):
1090 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001091 :py:meth:`X509Req.sign` succeeds when passed a private key object and a valid
1092 digest function. :py:meth:`X509Req.verify` can be used to check the signature.
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04001093 """
1094 request = self.signable()
1095 key = PKey()
1096 key.generate_key(TYPE_RSA, 512)
1097 request.set_pubkey(key)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001098 request.sign(key, GOOD_DIGEST)
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04001099 # If the type has a verify method, cover that too.
1100 if getattr(request, 'verify', None) is not None:
1101 pub = request.get_pubkey()
1102 self.assertTrue(request.verify(pub))
1103 # Make another key that won't verify.
1104 key = PKey()
1105 key.generate_key(TYPE_RSA, 512)
1106 self.assertRaises(Error, request.verify, key)
1107
1108
1109
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001110
Jean-Paul Calderone18808652009-07-05 12:54:05 -04001111class X509ReqTests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001112 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001113 Tests for :py:class:`OpenSSL.crypto.X509Req`.
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001114 """
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001115 def signable(self):
1116 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001117 Create and return a new :py:class:`X509Req`.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001118 """
1119 return X509Req()
1120
1121
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001122 def test_type(self):
1123 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001124 :py:obj:`X509Req` and :py:obj:`X509ReqType` refer to the same type object and can be
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001125 used to create instances of that type.
1126 """
1127 self.assertIdentical(X509Req, X509ReqType)
1128 self.assertConsistentType(X509Req, 'X509Req')
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001129
1130
1131 def test_construction(self):
1132 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001133 :py:obj:`X509Req` takes no arguments and returns an :py:obj:`X509ReqType` instance.
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001134 """
1135 request = X509Req()
1136 self.assertTrue(
1137 isinstance(request, X509ReqType),
1138 "%r is of type %r, should be %r" % (request, type(request), X509ReqType))
1139
1140
Jean-Paul Calderone8dd19b82008-12-28 20:41:16 -05001141 def test_version(self):
1142 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001143 :py:obj:`X509ReqType.set_version` sets the X.509 version of the certificate
1144 request. :py:obj:`X509ReqType.get_version` returns the X.509 version of
Jean-Paul Calderone8dd19b82008-12-28 20:41:16 -05001145 the certificate request. The initial value of the version is 0.
1146 """
1147 request = X509Req()
1148 self.assertEqual(request.get_version(), 0)
1149 request.set_version(1)
1150 self.assertEqual(request.get_version(), 1)
1151 request.set_version(3)
1152 self.assertEqual(request.get_version(), 3)
1153
1154
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001155 def test_version_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001156 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001157 :py:obj:`X509ReqType.set_version` raises :py:obj:`TypeError` if called with the wrong
1158 number of arguments or with a non-:py:obj:`int` argument.
1159 :py:obj:`X509ReqType.get_version` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001160 arguments.
1161 """
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001162 request = X509Req()
1163 self.assertRaises(TypeError, request.set_version)
1164 self.assertRaises(TypeError, request.set_version, "foo")
1165 self.assertRaises(TypeError, request.set_version, 1, 2)
1166 self.assertRaises(TypeError, request.get_version, None)
1167
1168
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001169 def test_get_subject(self):
1170 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001171 :py:obj:`X509ReqType.get_subject` returns an :py:obj:`X509Name` for the subject of
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001172 the request and which is valid even after the request object is
1173 otherwise dead.
1174 """
1175 request = X509Req()
1176 subject = request.get_subject()
1177 self.assertTrue(
1178 isinstance(subject, X509NameType),
1179 "%r is of type %r, should be %r" % (subject, type(subject), X509NameType))
1180 subject.commonName = "foo"
1181 self.assertEqual(request.get_subject().commonName, "foo")
1182 del request
1183 subject.commonName = "bar"
1184 self.assertEqual(subject.commonName, "bar")
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001185
1186
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001187 def test_get_subject_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001188 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001189 :py:obj:`X509ReqType.get_subject` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001190 arguments.
1191 """
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001192 request = X509Req()
1193 self.assertRaises(TypeError, request.get_subject, None)
1194
1195
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001196 def test_add_extensions(self):
1197 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001198 :py:obj:`X509Req.add_extensions` accepts a :py:obj:`list` of :py:obj:`X509Extension`
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001199 instances and adds them to the X509 request.
1200 """
1201 request = X509Req()
1202 request.add_extensions([
Jean-Paul Calderonee16f9f32010-08-22 19:20:37 -04001203 X509Extension(b('basicConstraints'), True, b('CA:false'))])
Stephen Holsappleca545b72014-01-28 21:43:25 -08001204 exts = request.get_extensions()
Stephen Holsapple7fbdf642014-03-01 20:05:47 -08001205 self.assertEqual(len(exts), 1)
1206 self.assertEqual(exts[0].get_short_name(), b('basicConstraints'))
1207 self.assertEqual(exts[0].get_critical(), 1)
1208 self.assertEqual(exts[0].get_data(), b('0\x00'))
1209
1210
1211 def test_get_extensions(self):
1212 """
1213 :py:obj:`X509Req.get_extensions` returns a :py:obj:`list` of
1214 extensions added to this X509 request.
1215 """
1216 request = X509Req()
1217 exts = request.get_extensions()
1218 self.assertEqual(exts, [])
1219 request.add_extensions([
1220 X509Extension(b('basicConstraints'), True, b('CA:true')),
1221 X509Extension(b('keyUsage'), False, b('digitalSignature'))])
1222 exts = request.get_extensions()
1223 self.assertEqual(len(exts), 2)
1224 self.assertEqual(exts[0].get_short_name(), b('basicConstraints'))
1225 self.assertEqual(exts[0].get_critical(), 1)
1226 self.assertEqual(exts[0].get_data(), b('0\x03\x01\x01\xff'))
1227 self.assertEqual(exts[1].get_short_name(), b('keyUsage'))
1228 self.assertEqual(exts[1].get_critical(), 0)
1229 self.assertEqual(exts[1].get_data(), b('\x03\x02\x07\x80'))
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001230
1231
1232 def test_add_extensions_wrong_args(self):
1233 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001234 :py:obj:`X509Req.add_extensions` raises :py:obj:`TypeError` if called with the wrong
1235 number of arguments or with a non-:py:obj:`list`. Or it raises :py:obj:`ValueError`
1236 if called with a :py:obj:`list` containing objects other than :py:obj:`X509Extension`
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001237 instances.
1238 """
1239 request = X509Req()
1240 self.assertRaises(TypeError, request.add_extensions)
1241 self.assertRaises(TypeError, request.add_extensions, object())
1242 self.assertRaises(ValueError, request.add_extensions, [object()])
1243 self.assertRaises(TypeError, request.add_extensions, [], None)
1244
1245
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001246 def test_verify_wrong_args(self):
1247 """
1248 :py:obj:`X509Req.verify` raises :py:obj:`TypeError` if called with zero
1249 arguments or more than one argument or if passed anything other than a
1250 :py:obj:`PKey` instance as its single argument.
1251 """
1252 request = X509Req()
1253 self.assertRaises(TypeError, request.verify)
1254 self.assertRaises(TypeError, request.verify, object())
1255 self.assertRaises(TypeError, request.verify, PKey(), object())
1256
1257
1258 def test_verify_uninitialized_key(self):
1259 """
1260 :py:obj:`X509Req.verify` raises :py:obj:`OpenSSL.crypto.Error` if called
1261 with a :py:obj:`OpenSSL.crypto.PKey` which contains no key data.
1262 """
1263 request = X509Req()
1264 pkey = PKey()
1265 self.assertRaises(Error, request.verify, pkey)
1266
1267
1268 def test_verify_wrong_key(self):
1269 """
1270 :py:obj:`X509Req.verify` raises :py:obj:`OpenSSL.crypto.Error` if called
1271 with a :py:obj:`OpenSSL.crypto.PKey` which does not represent the public
1272 part of the key which signed the request.
1273 """
1274 request = X509Req()
1275 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001276 request.sign(pkey, GOOD_DIGEST)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001277 another_pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
1278 self.assertRaises(Error, request.verify, another_pkey)
1279
1280
1281 def test_verify_success(self):
1282 """
1283 :py:obj:`X509Req.verify` returns :py:obj:`True` if called with a
Alex Gaynor3b0ee972014-11-15 09:17:33 -08001284 :py:obj:`OpenSSL.crypto.PKey` which represents the public part of the key
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001285 which signed the request.
1286 """
1287 request = X509Req()
1288 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001289 request.sign(pkey, GOOD_DIGEST)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001290 self.assertEqual(True, request.verify(pkey))
1291
1292
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001293
Jean-Paul Calderone18808652009-07-05 12:54:05 -04001294class X509Tests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001295 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001296 Tests for :py:obj:`OpenSSL.crypto.X509`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001297 """
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001298 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
Jean-Paul Calderone8114b452008-03-25 15:27:59 -04001299
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001300 extpem = """
1301-----BEGIN CERTIFICATE-----
1302MIIC3jCCAkegAwIBAgIJAJHFjlcCgnQzMA0GCSqGSIb3DQEBBQUAMEcxCzAJBgNV
1303BAYTAlNFMRUwEwYDVQQIEwxXZXN0ZXJib3R0b20xEjAQBgNVBAoTCUNhdGFsb2dp
1304eDENMAsGA1UEAxMEUm9vdDAeFw0wODA0MjIxNDQ1MzhaFw0wOTA0MjIxNDQ1Mzha
1305MFQxCzAJBgNVBAYTAlNFMQswCQYDVQQIEwJXQjEUMBIGA1UEChMLT3Blbk1ldGFk
1306aXIxIjAgBgNVBAMTGW5vZGUxLm9tMi5vcGVubWV0YWRpci5vcmcwgZ8wDQYJKoZI
1307hvcNAQEBBQADgY0AMIGJAoGBAPIcQMrwbk2nESF/0JKibj9i1x95XYAOwP+LarwT
1308Op4EQbdlI9SY+uqYqlERhF19w7CS+S6oyqx0DRZSk4Y9dZ9j9/xgm2u/f136YS1u
1309zgYFPvfUs6PqYLPSM8Bw+SjJ+7+2+TN+Tkiof9WP1cMjodQwOmdsiRbR0/J7+b1B
1310hec1AgMBAAGjgcQwgcEwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNT
1311TCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFIdHsBcMVVMbAO7j6NCj
131203HgLnHaMB8GA1UdIwQYMBaAFL2h9Bf9Mre4vTdOiHTGAt7BRY/8MEYGA1UdEQQ/
1313MD2CDSouZXhhbXBsZS5vcmeCESoub20yLmV4bWFwbGUuY29thwSC7wgKgRNvbTJA
1314b3Blbm1ldGFkaXIub3JnMA0GCSqGSIb3DQEBBQUAA4GBALd7WdXkp2KvZ7/PuWZA
1315MPlIxyjS+Ly11+BNE0xGQRp9Wz+2lABtpgNqssvU156+HkKd02rGheb2tj7MX9hG
1316uZzbwDAZzJPjzDQDD7d3cWsrVcfIdqVU7epHqIadnOF+X0ghJ39pAm6VVadnSXCt
1317WpOdIpB8KksUTCzV591Nr1wd
1318-----END CERTIFICATE-----
1319 """
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001320 def signable(self):
1321 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001322 Create and return a new :py:obj:`X509`.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001323 """
1324 return X509()
1325
1326
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001327 def test_type(self):
1328 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001329 :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 -04001330 to create instances of that type.
1331 """
1332 self.assertIdentical(X509, X509Type)
1333 self.assertConsistentType(X509, 'X509')
1334
1335
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001336 def test_construction(self):
1337 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001338 :py:obj:`X509` takes no arguments and returns an instance of :py:obj:`X509Type`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001339 """
1340 certificate = X509()
1341 self.assertTrue(
1342 isinstance(certificate, X509Type),
1343 "%r is of type %r, should be %r" % (certificate,
1344 type(certificate),
1345 X509Type))
Rick Deane15b1472009-07-09 15:53:42 -05001346 self.assertEqual(type(X509Type).__name__, 'type')
1347 self.assertEqual(type(certificate).__name__, 'X509')
1348 self.assertEqual(type(certificate), X509Type)
Rick Dean04113e72009-07-16 12:06:35 -05001349 self.assertEqual(type(certificate), X509)
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001350
1351
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001352 def test_get_version_wrong_args(self):
1353 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001354 :py:obj:`X509.get_version` raises :py:obj:`TypeError` if invoked with any arguments.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001355 """
1356 cert = X509()
1357 self.assertRaises(TypeError, cert.get_version, None)
1358
1359
1360 def test_set_version_wrong_args(self):
1361 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001362 :py:obj:`X509.set_version` raises :py:obj:`TypeError` if invoked with the wrong number
1363 of arguments or an argument not of type :py:obj:`int`.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001364 """
1365 cert = X509()
1366 self.assertRaises(TypeError, cert.set_version)
1367 self.assertRaises(TypeError, cert.set_version, None)
1368 self.assertRaises(TypeError, cert.set_version, 1, None)
1369
1370
1371 def test_version(self):
1372 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001373 :py:obj:`X509.set_version` sets the certificate version number.
1374 :py:obj:`X509.get_version` retrieves it.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001375 """
1376 cert = X509()
1377 cert.set_version(1234)
1378 self.assertEquals(cert.get_version(), 1234)
1379
1380
1381 def test_get_serial_number_wrong_args(self):
1382 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001383 :py:obj:`X509.get_serial_number` raises :py:obj:`TypeError` if invoked with any
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001384 arguments.
1385 """
1386 cert = X509()
1387 self.assertRaises(TypeError, cert.get_serial_number, None)
1388
1389
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001390 def test_serial_number(self):
1391 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001392 The serial number of an :py:obj:`X509Type` can be retrieved and modified with
1393 :py:obj:`X509Type.get_serial_number` and :py:obj:`X509Type.set_serial_number`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001394 """
1395 certificate = X509()
1396 self.assertRaises(TypeError, certificate.set_serial_number)
1397 self.assertRaises(TypeError, certificate.set_serial_number, 1, 2)
1398 self.assertRaises(TypeError, certificate.set_serial_number, "1")
1399 self.assertRaises(TypeError, certificate.set_serial_number, 5.5)
1400 self.assertEqual(certificate.get_serial_number(), 0)
1401 certificate.set_serial_number(1)
1402 self.assertEqual(certificate.get_serial_number(), 1)
1403 certificate.set_serial_number(2 ** 32 + 1)
1404 self.assertEqual(certificate.get_serial_number(), 2 ** 32 + 1)
1405 certificate.set_serial_number(2 ** 64 + 1)
1406 self.assertEqual(certificate.get_serial_number(), 2 ** 64 + 1)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001407 certificate.set_serial_number(2 ** 128 + 1)
1408 self.assertEqual(certificate.get_serial_number(), 2 ** 128 + 1)
1409
1410
1411 def _setBoundTest(self, which):
1412 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001413 :py:obj:`X509Type.set_notBefore` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001414 GENERALIZEDTIME and sets the beginning of the certificate's validity
1415 period to it.
1416 """
1417 certificate = X509()
1418 set = getattr(certificate, 'set_not' + which)
1419 get = getattr(certificate, 'get_not' + which)
1420
Jean-Paul Calderonee0615b52008-03-09 21:44:46 -04001421 # Starts with no value.
1422 self.assertEqual(get(), None)
1423
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001424 # GMT (Or is it UTC?) -exarkun
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001425 when = b("20040203040506Z")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001426 set(when)
1427 self.assertEqual(get(), when)
1428
1429 # A plus two hours and thirty minutes offset
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001430 when = b("20040203040506+0530")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001431 set(when)
1432 self.assertEqual(get(), when)
1433
1434 # A minus one hour fifteen minutes offset
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001435 when = b("20040203040506-0115")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001436 set(when)
1437 self.assertEqual(get(), when)
1438
1439 # An invalid string results in a ValueError
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001440 self.assertRaises(ValueError, set, b("foo bar"))
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001441
Jean-Paul Calderone31ca2002010-01-30 15:14:43 -05001442 # The wrong number of arguments results in a TypeError.
1443 self.assertRaises(TypeError, set)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001444 self.assertRaises(TypeError, set, b("20040203040506Z"), b("20040203040506Z"))
1445 self.assertRaises(TypeError, get, b("foo bar"))
1446
Jean-Paul Calderone31ca2002010-01-30 15:14:43 -05001447
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001448 # XXX ASN1_TIME (not GENERALIZEDTIME)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001449
1450 def test_set_notBefore(self):
1451 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001452 :py:obj:`X509Type.set_notBefore` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001453 GENERALIZEDTIME and sets the beginning of the certificate's validity
1454 period to it.
1455 """
1456 self._setBoundTest("Before")
1457
1458
1459 def test_set_notAfter(self):
1460 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001461 :py:obj:`X509Type.set_notAfter` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001462 GENERALIZEDTIME and sets the end of the certificate's validity period
1463 to it.
1464 """
1465 self._setBoundTest("After")
Jean-Paul Calderone76576d52008-03-24 16:04:46 -04001466
1467
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001468 def test_get_notBefore(self):
1469 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001470 :py:obj:`X509Type.get_notBefore` returns a string in the format of an ASN1
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001471 GENERALIZEDTIME even for certificates which store it as UTCTIME
1472 internally.
1473 """
Jean-Paul Calderone8114b452008-03-25 15:27:59 -04001474 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001475 self.assertEqual(cert.get_notBefore(), b("20090325123658Z"))
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001476
Rick Dean38a05c82009-07-18 01:41:30 -05001477
1478 def test_get_notAfter(self):
1479 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001480 :py:obj:`X509Type.get_notAfter` returns a string in the format of an ASN1
Rick Dean38a05c82009-07-18 01:41:30 -05001481 GENERALIZEDTIME even for certificates which store it as UTCTIME
1482 internally.
1483 """
1484 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001485 self.assertEqual(cert.get_notAfter(), b("20170611123658Z"))
Rick Dean38a05c82009-07-18 01:41:30 -05001486
1487
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001488 def test_gmtime_adj_notBefore_wrong_args(self):
1489 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001490 :py:obj:`X509Type.gmtime_adj_notBefore` raises :py:obj:`TypeError` if called with the
1491 wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001492 """
1493 cert = X509()
1494 self.assertRaises(TypeError, cert.gmtime_adj_notBefore)
1495 self.assertRaises(TypeError, cert.gmtime_adj_notBefore, None)
1496 self.assertRaises(TypeError, cert.gmtime_adj_notBefore, 123, None)
1497
1498
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001499 def test_gmtime_adj_notBefore(self):
1500 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001501 :py:obj:`X509Type.gmtime_adj_notBefore` changes the not-before timestamp to be
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001502 the current time plus the number of seconds passed in.
1503 """
1504 cert = load_certificate(FILETYPE_PEM, self.pemData)
1505 now = datetime.utcnow() + timedelta(seconds=100)
1506 cert.gmtime_adj_notBefore(100)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001507 self.assertEqual(cert.get_notBefore(), b(now.strftime("%Y%m%d%H%M%SZ")))
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001508
1509
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001510 def test_gmtime_adj_notAfter_wrong_args(self):
1511 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001512 :py:obj:`X509Type.gmtime_adj_notAfter` raises :py:obj:`TypeError` if called with the
1513 wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001514 """
1515 cert = X509()
1516 self.assertRaises(TypeError, cert.gmtime_adj_notAfter)
1517 self.assertRaises(TypeError, cert.gmtime_adj_notAfter, None)
1518 self.assertRaises(TypeError, cert.gmtime_adj_notAfter, 123, None)
1519
1520
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001521 def test_gmtime_adj_notAfter(self):
1522 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001523 :py:obj:`X509Type.gmtime_adj_notAfter` changes the not-after timestamp to be
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001524 the current time plus the number of seconds passed in.
1525 """
1526 cert = load_certificate(FILETYPE_PEM, self.pemData)
1527 now = datetime.utcnow() + timedelta(seconds=100)
1528 cert.gmtime_adj_notAfter(100)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001529 self.assertEqual(cert.get_notAfter(), b(now.strftime("%Y%m%d%H%M%SZ")))
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001530
1531
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001532 def test_has_expired_wrong_args(self):
1533 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001534 :py:obj:`X509Type.has_expired` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001535 arguments.
1536 """
1537 cert = X509()
1538 self.assertRaises(TypeError, cert.has_expired, None)
1539
1540
1541 def test_has_expired(self):
1542 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001543 :py:obj:`X509Type.has_expired` returns :py:obj:`True` if the certificate's not-after
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001544 time is in the past.
1545 """
1546 cert = X509()
1547 cert.gmtime_adj_notAfter(-1)
1548 self.assertTrue(cert.has_expired())
1549
1550
1551 def test_has_not_expired(self):
1552 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001553 :py:obj:`X509Type.has_expired` returns :py:obj:`False` if the certificate's not-after
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001554 time is in the future.
1555 """
1556 cert = X509()
1557 cert.gmtime_adj_notAfter(2)
1558 self.assertFalse(cert.has_expired())
1559
1560
Rick Dean38a05c82009-07-18 01:41:30 -05001561 def test_digest(self):
1562 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001563 :py:obj:`X509.digest` returns a string giving ":"-separated hex-encoded words
Rick Dean38a05c82009-07-18 01:41:30 -05001564 of the digest of the certificate.
1565 """
1566 cert = X509()
1567 self.assertEqual(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001568 # This is MD5 instead of GOOD_DIGEST because the digest algorithm
1569 # actually matters to the assertion (ie, another arbitrary, good
1570 # digest will not product the same digest).
1571 cert.digest("MD5"),
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001572 b("A8:EB:07:F8:53:25:0A:F2:56:05:C5:A5:C4:C4:C7:15"))
Rick Dean38a05c82009-07-18 01:41:30 -05001573
1574
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001575 def _extcert(self, pkey, extensions):
1576 cert = X509()
1577 cert.set_pubkey(pkey)
1578 cert.get_subject().commonName = "Unit Tests"
1579 cert.get_issuer().commonName = "Unit Tests"
1580 when = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
1581 cert.set_notBefore(when)
1582 cert.set_notAfter(when)
1583
1584 cert.add_extensions(extensions)
1585 return load_certificate(
1586 FILETYPE_PEM, dump_certificate(FILETYPE_PEM, cert))
1587
1588
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001589 def test_extension_count(self):
1590 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001591 :py:obj:`X509.get_extension_count` returns the number of extensions that are
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001592 present in the certificate.
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001593 """
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001594 pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001595 ca = X509Extension(b('basicConstraints'), True, b('CA:FALSE'))
1596 key = X509Extension(b('keyUsage'), True, b('digitalSignature'))
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001597 subjectAltName = X509Extension(
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001598 b('subjectAltName'), True, b('DNS:example.com'))
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001599
1600 # Try a certificate with no extensions at all.
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001601 c = self._extcert(pkey, [])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001602 self.assertEqual(c.get_extension_count(), 0)
1603
1604 # And a certificate with one
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001605 c = self._extcert(pkey, [ca])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001606 self.assertEqual(c.get_extension_count(), 1)
1607
1608 # And a certificate with several
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001609 c = self._extcert(pkey, [ca, key, subjectAltName])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001610 self.assertEqual(c.get_extension_count(), 3)
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001611
1612
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001613 def test_get_extension(self):
1614 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001615 :py:obj:`X509.get_extension` takes an integer and returns an :py:obj:`X509Extension`
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001616 corresponding to the extension at that index.
1617 """
1618 pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001619 ca = X509Extension(b('basicConstraints'), True, b('CA:FALSE'))
1620 key = X509Extension(b('keyUsage'), True, b('digitalSignature'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001621 subjectAltName = X509Extension(
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001622 b('subjectAltName'), False, b('DNS:example.com'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001623
1624 cert = self._extcert(pkey, [ca, key, subjectAltName])
1625
1626 ext = cert.get_extension(0)
1627 self.assertTrue(isinstance(ext, X509Extension))
1628 self.assertTrue(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001629 self.assertEqual(ext.get_short_name(), b('basicConstraints'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001630
1631 ext = cert.get_extension(1)
1632 self.assertTrue(isinstance(ext, X509Extension))
1633 self.assertTrue(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001634 self.assertEqual(ext.get_short_name(), b('keyUsage'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001635
1636 ext = cert.get_extension(2)
1637 self.assertTrue(isinstance(ext, X509Extension))
1638 self.assertFalse(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001639 self.assertEqual(ext.get_short_name(), b('subjectAltName'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001640
1641 self.assertRaises(IndexError, cert.get_extension, -1)
1642 self.assertRaises(IndexError, cert.get_extension, 4)
1643 self.assertRaises(TypeError, cert.get_extension, "hello")
1644
1645
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001646 def test_nullbyte_subjectAltName(self):
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001647 """
Jean-Paul Calderone9af07b02013-08-23 16:07:31 -04001648 The fields of a `subjectAltName` extension on an X509 may contain NUL
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001649 bytes and this value is reflected in the string representation of the
1650 extension object.
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001651 """
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001652 cert = load_certificate(FILETYPE_PEM, nulbyteSubjectAltNamePEM)
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001653
1654 ext = cert.get_extension(3)
1655 self.assertEqual(ext.get_short_name(), b('subjectAltName'))
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001656 self.assertEqual(
1657 b("DNS:altnull.python.org\x00example.com, "
1658 "email:null@python.org\x00user@example.org, "
1659 "URI:http://null.python.org\x00http://example.org, "
1660 "IP Address:192.0.2.1, IP Address:2001:DB8:0:0:0:0:0:1\n"),
1661 b(str(ext)))
1662
Rick Dean38a05c82009-07-18 01:41:30 -05001663
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001664 def test_invalid_digest_algorithm(self):
1665 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001666 :py:obj:`X509.digest` raises :py:obj:`ValueError` if called with an unrecognized hash
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001667 algorithm.
1668 """
1669 cert = X509()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001670 self.assertRaises(ValueError, cert.digest, BAD_DIGEST)
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001671
1672
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001673 def test_get_subject_wrong_args(self):
1674 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001675 :py:obj:`X509.get_subject` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001676 """
1677 cert = X509()
1678 self.assertRaises(TypeError, cert.get_subject, None)
1679
1680
1681 def test_get_subject(self):
1682 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001683 :py:obj:`X509.get_subject` returns an :py:obj:`X509Name` instance.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001684 """
1685 cert = load_certificate(FILETYPE_PEM, self.pemData)
1686 subj = cert.get_subject()
1687 self.assertTrue(isinstance(subj, X509Name))
1688 self.assertEquals(
1689 subj.get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001690 [(b('C'), b('US')), (b('ST'), b('IL')), (b('L'), b('Chicago')),
1691 (b('O'), b('Testing')), (b('CN'), b('Testing Root CA'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001692
1693
1694 def test_set_subject_wrong_args(self):
1695 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001696 :py:obj:`X509.set_subject` raises a :py:obj:`TypeError` if called with the wrong
1697 number of arguments or an argument not of type :py:obj:`X509Name`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001698 """
1699 cert = X509()
1700 self.assertRaises(TypeError, cert.set_subject)
1701 self.assertRaises(TypeError, cert.set_subject, None)
1702 self.assertRaises(TypeError, cert.set_subject, cert.get_subject(), None)
1703
1704
1705 def test_set_subject(self):
1706 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001707 :py:obj:`X509.set_subject` changes the subject of the certificate to the one
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001708 passed in.
1709 """
1710 cert = X509()
1711 name = cert.get_subject()
1712 name.C = 'AU'
1713 name.O = 'Unit Tests'
1714 cert.set_subject(name)
1715 self.assertEquals(
1716 cert.get_subject().get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001717 [(b('C'), b('AU')), (b('O'), b('Unit Tests'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001718
1719
1720 def test_get_issuer_wrong_args(self):
1721 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001722 :py:obj:`X509.get_issuer` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001723 """
1724 cert = X509()
1725 self.assertRaises(TypeError, cert.get_issuer, None)
1726
1727
1728 def test_get_issuer(self):
1729 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001730 :py:obj:`X509.get_issuer` returns an :py:obj:`X509Name` instance.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001731 """
1732 cert = load_certificate(FILETYPE_PEM, self.pemData)
1733 subj = cert.get_issuer()
1734 self.assertTrue(isinstance(subj, X509Name))
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001735 comp = subj.get_components()
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001736 self.assertEquals(
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001737 comp,
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001738 [(b('C'), b('US')), (b('ST'), b('IL')), (b('L'), b('Chicago')),
1739 (b('O'), b('Testing')), (b('CN'), b('Testing Root CA'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001740
1741
1742 def test_set_issuer_wrong_args(self):
1743 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001744 :py:obj:`X509.set_issuer` raises a :py:obj:`TypeError` if called with the wrong
1745 number of arguments or an argument not of type :py:obj:`X509Name`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001746 """
1747 cert = X509()
1748 self.assertRaises(TypeError, cert.set_issuer)
1749 self.assertRaises(TypeError, cert.set_issuer, None)
1750 self.assertRaises(TypeError, cert.set_issuer, cert.get_issuer(), None)
1751
1752
1753 def test_set_issuer(self):
1754 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001755 :py:obj:`X509.set_issuer` changes the issuer of the certificate to the one
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001756 passed in.
1757 """
1758 cert = X509()
1759 name = cert.get_issuer()
1760 name.C = 'AU'
1761 name.O = 'Unit Tests'
1762 cert.set_issuer(name)
1763 self.assertEquals(
1764 cert.get_issuer().get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001765 [(b('C'), b('AU')), (b('O'), b('Unit Tests'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001766
1767
1768 def test_get_pubkey_uninitialized(self):
1769 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001770 When called on a certificate with no public key, :py:obj:`X509.get_pubkey`
1771 raises :py:obj:`OpenSSL.crypto.Error`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001772 """
1773 cert = X509()
1774 self.assertRaises(Error, cert.get_pubkey)
1775
1776
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001777 def test_subject_name_hash_wrong_args(self):
1778 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001779 :py:obj:`X509.subject_name_hash` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001780 arguments.
1781 """
1782 cert = X509()
1783 self.assertRaises(TypeError, cert.subject_name_hash, None)
1784
1785
1786 def test_subject_name_hash(self):
1787 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001788 :py:obj:`X509.subject_name_hash` returns the hash of the certificate's subject
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001789 name.
1790 """
1791 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -04001792 self.assertIn(
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001793 cert.subject_name_hash(),
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -04001794 [3350047874, # OpenSSL 0.9.8, MD5
1795 3278919224, # OpenSSL 1.0.0, SHA1
1796 ])
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001797
1798
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001799 def test_get_signature_algorithm(self):
1800 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001801 :py:obj:`X509Type.get_signature_algorithm` returns a string which means
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001802 the algorithm used to sign the certificate.
1803 """
1804 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001805 self.assertEqual(
1806 b("sha1WithRSAEncryption"), cert.get_signature_algorithm())
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001807
1808
1809 def test_get_undefined_signature_algorithm(self):
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001810 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001811 :py:obj:`X509Type.get_signature_algorithm` raises :py:obj:`ValueError` if the
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001812 signature algorithm is undefined or unknown.
1813 """
1814 # This certificate has been modified to indicate a bogus OID in the
1815 # signature algorithm field so that OpenSSL does not recognize it.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001816 certPEM = b("""\
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001817-----BEGIN CERTIFICATE-----
1818MIIC/zCCAmigAwIBAgIBATAGBgJ8BQUAMHsxCzAJBgNVBAYTAlNHMREwDwYDVQQK
1819EwhNMkNyeXB0bzEUMBIGA1UECxMLTTJDcnlwdG8gQ0ExJDAiBgNVBAMTG00yQ3J5
1820cHRvIENlcnRpZmljYXRlIE1hc3RlcjEdMBsGCSqGSIb3DQEJARYObmdwc0Bwb3N0
1821MS5jb20wHhcNMDAwOTEwMDk1MTMwWhcNMDIwOTEwMDk1MTMwWjBTMQswCQYDVQQG
1822EwJTRzERMA8GA1UEChMITTJDcnlwdG8xEjAQBgNVBAMTCWxvY2FsaG9zdDEdMBsG
1823CSqGSIb3DQEJARYObmdwc0Bwb3N0MS5jb20wXDANBgkqhkiG9w0BAQEFAANLADBI
1824AkEArL57d26W9fNXvOhNlZzlPOACmvwOZ5AdNgLzJ1/MfsQQJ7hHVeHmTAjM664V
1825+fXvwUGJLziCeBo1ysWLRnl8CQIDAQABo4IBBDCCAQAwCQYDVR0TBAIwADAsBglg
1826hkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0O
1827BBYEFM+EgpK+eyZiwFU1aOPSbczbPSpVMIGlBgNVHSMEgZ0wgZqAFPuHI2nrnDqT
1828FeXFvylRT/7tKDgBoX+kfTB7MQswCQYDVQQGEwJTRzERMA8GA1UEChMITTJDcnlw
1829dG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtNMkNyeXB0byBDZXJ0
1830aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tggEA
1831MA0GCSqGSIb3DQEBBAUAA4GBADv8KpPo+gfJxN2ERK1Y1l17sz/ZhzoGgm5XCdbx
1832jEY7xKfpQngV599k1xhl11IMqizDwu0855agrckg2MCTmOI9DZzDD77tAYb+Dk0O
1833PEVk0Mk/V0aIsDE9bolfCi/i/QWZ3N8s5nTWMNyBBBmoSliWCm4jkkRZRD0ejgTN
1834tgI5
1835-----END CERTIFICATE-----
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001836""")
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001837 cert = load_certificate(FILETYPE_PEM, certPEM)
1838 self.assertRaises(ValueError, cert.get_signature_algorithm)
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001839
1840
Rick Dean38a05c82009-07-18 01:41:30 -05001841
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001842class X509StoreTests(TestCase):
1843 """
1844 Test for :py:obj:`OpenSSL.crypto.X509Store`.
1845 """
1846 def test_type(self):
1847 """
1848 :py:obj:`X509StoreType` is a type object.
1849 """
1850 self.assertIdentical(X509Store, X509StoreType)
1851 self.assertConsistentType(X509Store, 'X509Store')
1852
1853
1854 def test_add_cert_wrong_args(self):
1855 store = X509Store()
1856 self.assertRaises(TypeError, store.add_cert)
1857 self.assertRaises(TypeError, store.add_cert, object())
1858 self.assertRaises(TypeError, store.add_cert, X509(), object())
1859
1860
1861 def test_add_cert(self):
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001862 """
1863 :py:obj:`X509Store.add_cert` adds a :py:obj:`X509` instance to the
1864 certificate store.
1865 """
1866 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001867 store = X509Store()
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001868 store.add_cert(cert)
1869
1870
1871 def test_add_cert_rejects_duplicate(self):
1872 """
1873 :py:obj:`X509Store.add_cert` raises :py:obj:`OpenSSL.crypto.Error` if an
1874 attempt is made to add the same certificate to the store more than once.
1875 """
1876 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
1877 store = X509Store()
1878 store.add_cert(cert)
1879 self.assertRaises(Error, store.add_cert, cert)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001880
1881
1882
Rick Dean623ee362009-07-17 12:22:16 -05001883class PKCS12Tests(TestCase):
1884 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001885 Test for :py:obj:`OpenSSL.crypto.PKCS12` and :py:obj:`OpenSSL.crypto.load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001886 """
1887 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
1888
Jean-Paul Calderonec3a41f72009-07-25 12:36:02 -04001889 def test_type(self):
1890 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001891 :py:obj:`PKCS12Type` is a type object.
Jean-Paul Calderonec3a41f72009-07-25 12:36:02 -04001892 """
1893 self.assertIdentical(PKCS12, PKCS12Type)
1894 self.assertConsistentType(PKCS12, 'PKCS12')
1895
1896
Rick Deanf94096c2009-07-18 14:23:06 -05001897 def test_empty_construction(self):
Rick Dean38a05c82009-07-18 01:41:30 -05001898 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001899 :py:obj:`PKCS12` returns a new instance of :py:obj:`PKCS12` with no certificate,
Jean-Paul Calderonedc857b52009-07-25 12:25:07 -04001900 private key, CA certificates, or friendly name.
Rick Dean38a05c82009-07-18 01:41:30 -05001901 """
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001902 p12 = PKCS12()
Rick Dean623ee362009-07-17 12:22:16 -05001903 self.assertEqual(None, p12.get_certificate())
1904 self.assertEqual(None, p12.get_privatekey())
1905 self.assertEqual(None, p12.get_ca_certificates())
Rick Dean42d69e12009-07-20 11:36:08 -05001906 self.assertEqual(None, p12.get_friendlyname())
Rick Dean623ee362009-07-17 12:22:16 -05001907
Rick Dean38a05c82009-07-18 01:41:30 -05001908
Rick Dean623ee362009-07-17 12:22:16 -05001909 def test_type_errors(self):
Rick Dean38a05c82009-07-18 01:41:30 -05001910 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001911 The :py:obj:`PKCS12` setter functions (:py:obj:`set_certificate`, :py:obj:`set_privatekey`,
1912 :py:obj:`set_ca_certificates`, and :py:obj:`set_friendlyname`) raise :py:obj:`TypeError`
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001913 when passed objects of types other than those expected.
Rick Dean38a05c82009-07-18 01:41:30 -05001914 """
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001915 p12 = PKCS12()
Rick Dean623ee362009-07-17 12:22:16 -05001916 self.assertRaises(TypeError, p12.set_certificate, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05001917 self.assertRaises(TypeError, p12.set_certificate, PKey())
1918 self.assertRaises(TypeError, p12.set_certificate, X509)
Rick Dean623ee362009-07-17 12:22:16 -05001919 self.assertRaises(TypeError, p12.set_privatekey, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05001920 self.assertRaises(TypeError, p12.set_privatekey, 'legbone')
1921 self.assertRaises(TypeError, p12.set_privatekey, X509())
Rick Dean623ee362009-07-17 12:22:16 -05001922 self.assertRaises(TypeError, p12.set_ca_certificates, 3)
1923 self.assertRaises(TypeError, p12.set_ca_certificates, X509())
1924 self.assertRaises(TypeError, p12.set_ca_certificates, (3, 4))
Rick Deanf94096c2009-07-18 14:23:06 -05001925 self.assertRaises(TypeError, p12.set_ca_certificates, ( PKey(), ))
Rick Dean42d69e12009-07-20 11:36:08 -05001926 self.assertRaises(TypeError, p12.set_friendlyname, 6)
1927 self.assertRaises(TypeError, p12.set_friendlyname, ('foo', 'bar'))
Rick Dean623ee362009-07-17 12:22:16 -05001928
Rick Dean38a05c82009-07-18 01:41:30 -05001929
Rick Dean623ee362009-07-17 12:22:16 -05001930 def test_key_only(self):
1931 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001932 A :py:obj:`PKCS12` with only a private key can be exported using
1933 :py:obj:`PKCS12.export` and loaded again using :py:obj:`load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001934 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001935 passwd = b"blah"
Rick Dean623ee362009-07-17 12:22:16 -05001936 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001937 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001938 p12.set_privatekey(pkey)
Rick Dean623ee362009-07-17 12:22:16 -05001939 self.assertEqual(None, p12.get_certificate())
1940 self.assertEqual(pkey, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05001941 try:
1942 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
1943 except Error:
1944 # Some versions of OpenSSL will throw an exception
1945 # for this nearly useless PKCS12 we tried to generate:
1946 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
1947 return
Rick Dean623ee362009-07-17 12:22:16 -05001948 p12 = load_pkcs12(dumped_p12, passwd)
1949 self.assertEqual(None, p12.get_ca_certificates())
1950 self.assertEqual(None, p12.get_certificate())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001951
1952 # OpenSSL fails to bring the key back to us. So sad. Perhaps in the
1953 # future this will be improved.
1954 self.assertTrue(isinstance(p12.get_privatekey(), (PKey, type(None))))
Rick Dean623ee362009-07-17 12:22:16 -05001955
Rick Dean38a05c82009-07-18 01:41:30 -05001956
Rick Dean623ee362009-07-17 12:22:16 -05001957 def test_cert_only(self):
1958 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001959 A :py:obj:`PKCS12` with only a certificate can be exported using
1960 :py:obj:`PKCS12.export` and loaded again using :py:obj:`load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001961 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001962 passwd = b"blah"
Rick Dean623ee362009-07-17 12:22:16 -05001963 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001964 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001965 p12.set_certificate(cert)
Rick Dean623ee362009-07-17 12:22:16 -05001966 self.assertEqual(cert, p12.get_certificate())
1967 self.assertEqual(None, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05001968 try:
1969 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
1970 except Error:
1971 # Some versions of OpenSSL will throw an exception
1972 # for this nearly useless PKCS12 we tried to generate:
1973 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
1974 return
Rick Dean623ee362009-07-17 12:22:16 -05001975 p12 = load_pkcs12(dumped_p12, passwd)
1976 self.assertEqual(None, p12.get_privatekey())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001977
1978 # OpenSSL fails to bring the cert back to us. Groany mcgroan.
1979 self.assertTrue(isinstance(p12.get_certificate(), (X509, type(None))))
1980
1981 # Oh ho. It puts the certificate into the ca certificates list, in
1982 # fact. Totally bogus, I would think. Nevertheless, let's exploit
1983 # that to check to see if it reconstructed the certificate we expected
1984 # it to. At some point, hopefully this will change so that
1985 # p12.get_certificate() is actually what returns the loaded
1986 # certificate.
1987 self.assertEqual(
1988 cleartextCertificatePEM,
1989 dump_certificate(FILETYPE_PEM, p12.get_ca_certificates()[0]))
Rick Dean623ee362009-07-17 12:22:16 -05001990
1991
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001992 def gen_pkcs12(self, cert_pem=None, key_pem=None, ca_pem=None, friendly_name=None):
Rick Dean623ee362009-07-17 12:22:16 -05001993 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001994 Generate a PKCS12 object with components from PEM. Verify that the set
1995 functions return None.
Rick Dean623ee362009-07-17 12:22:16 -05001996 """
Rick Deanf94096c2009-07-18 14:23:06 -05001997 p12 = PKCS12()
1998 if cert_pem:
1999 ret = p12.set_certificate(load_certificate(FILETYPE_PEM, cert_pem))
2000 self.assertEqual(ret, None)
2001 if key_pem:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002002 ret = p12.set_privatekey(load_privatekey(FILETYPE_PEM, key_pem))
Rick Deanf94096c2009-07-18 14:23:06 -05002003 self.assertEqual(ret, None)
2004 if ca_pem:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002005 ret = p12.set_ca_certificates((load_certificate(FILETYPE_PEM, ca_pem),))
Rick Deanf94096c2009-07-18 14:23:06 -05002006 self.assertEqual(ret, None)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002007 if friendly_name:
2008 ret = p12.set_friendlyname(friendly_name)
Rick Dean42d69e12009-07-20 11:36:08 -05002009 self.assertEqual(ret, None)
Rick Deanf94096c2009-07-18 14:23:06 -05002010 return p12
2011
2012
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002013 def check_recovery(self, p12_str, key=None, cert=None, ca=None, passwd=b"",
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002014 extra=()):
Rick Deanf94096c2009-07-18 14:23:06 -05002015 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002016 Use openssl program to confirm three components are recoverable from a
2017 PKCS12 string.
Rick Deanf94096c2009-07-18 14:23:06 -05002018 """
2019 if key:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002020 recovered_key = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002021 p12_str, b"pkcs12", b"-nocerts", b"-nodes", b"-passin",
2022 b"pass:" + passwd, *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05002023 self.assertEqual(recovered_key[-len(key):], key)
2024 if cert:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002025 recovered_cert = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002026 p12_str, b"pkcs12", b"-clcerts", b"-nodes", b"-passin",
2027 b"pass:" + passwd, b"-nokeys", *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05002028 self.assertEqual(recovered_cert[-len(cert):], cert)
2029 if ca:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002030 recovered_cert = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002031 p12_str, b"pkcs12", b"-cacerts", b"-nodes", b"-passin",
2032 b"pass:" + passwd, b"-nokeys", *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05002033 self.assertEqual(recovered_cert[-len(ca):], ca)
2034
2035
Stephen Holsapple38482622014-04-05 20:29:34 -07002036 def verify_pkcs12_container(self, p12):
2037 """
2038 Verify that the PKCS#12 container contains the correct client
2039 certificate and private key.
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002040
2041 :param p12: The PKCS12 instance to verify.
2042 :type p12: :py:class:`PKCS12`
Stephen Holsapple38482622014-04-05 20:29:34 -07002043 """
2044 cert_pem = dump_certificate(FILETYPE_PEM, p12.get_certificate())
2045 key_pem = dump_privatekey(FILETYPE_PEM, p12.get_privatekey())
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002046 self.assertEqual(
2047 (client_cert_pem, client_key_pem, None),
2048 (cert_pem, key_pem, p12.get_ca_certificates()))
Stephen Holsapple38482622014-04-05 20:29:34 -07002049
2050
Rick Deanf94096c2009-07-18 14:23:06 -05002051 def test_load_pkcs12(self):
2052 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002053 A PKCS12 string generated using the openssl command line can be loaded
Jonathan Ballet648875f2011-07-16 14:14:58 +09002054 with :py:obj:`load_pkcs12` and its components extracted and examined.
Rick Deanf94096c2009-07-18 14:23:06 -05002055 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002056 passwd = b"whatever"
Rick Dean623ee362009-07-17 12:22:16 -05002057 pem = client_key_pem + client_cert_pem
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002058 p12_str = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002059 pem, b"pkcs12", b"-export", b"-clcerts", b"-passout", b"pass:" + passwd)
Stephen Holsapple38482622014-04-05 20:29:34 -07002060 p12 = load_pkcs12(p12_str, passphrase=passwd)
2061 self.verify_pkcs12_container(p12)
2062
2063
2064 def test_load_pkcs12_no_passphrase(self):
2065 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002066 A PKCS12 string generated using openssl command line can be loaded with
2067 :py:obj:`load_pkcs12` without a passphrase and its components extracted
2068 and examined.
Stephen Holsapple38482622014-04-05 20:29:34 -07002069 """
2070 pem = client_key_pem + client_cert_pem
2071 p12_str = _runopenssl(
2072 pem, b"pkcs12", b"-export", b"-clcerts", b"-passout", b"pass:")
2073 p12 = load_pkcs12(p12_str)
2074 self.verify_pkcs12_container(p12)
2075
2076
2077 def _dump_and_load(self, dump_passphrase, load_passphrase):
2078 """
2079 A helper method to dump and load a PKCS12 object.
2080 """
2081 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem)
2082 dumped_p12 = p12.export(passphrase=dump_passphrase, iter=2, maciter=3)
2083 return load_pkcs12(dumped_p12, passphrase=load_passphrase)
2084
2085
2086 def test_load_pkcs12_null_passphrase_load_empty(self):
2087 """
2088 A PKCS12 string can be dumped with a null passphrase, loaded with an
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002089 empty passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002090 extracted and examined.
2091 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002092 self.verify_pkcs12_container(
2093 self._dump_and_load(dump_passphrase=None, load_passphrase=b''))
Stephen Holsapple38482622014-04-05 20:29:34 -07002094
2095
2096 def test_load_pkcs12_null_passphrase_load_null(self):
2097 """
2098 A PKCS12 string can be dumped with a null passphrase, loaded with a
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002099 null passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002100 extracted and examined.
2101 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002102 self.verify_pkcs12_container(
2103 self._dump_and_load(dump_passphrase=None, load_passphrase=None))
Stephen Holsapple38482622014-04-05 20:29:34 -07002104
2105
2106 def test_load_pkcs12_empty_passphrase_load_empty(self):
2107 """
2108 A PKCS12 string can be dumped with an empty passphrase, loaded with an
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002109 empty passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002110 extracted and examined.
2111 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002112 self.verify_pkcs12_container(
2113 self._dump_and_load(dump_passphrase=b'', load_passphrase=b''))
Stephen Holsapple38482622014-04-05 20:29:34 -07002114
2115
2116 def test_load_pkcs12_empty_passphrase_load_null(self):
2117 """
2118 A PKCS12 string can be dumped with an empty passphrase, loaded with a
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002119 null passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002120 extracted and examined.
2121 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002122 self.verify_pkcs12_container(
2123 self._dump_and_load(dump_passphrase=b'', load_passphrase=None))
Rick Deanf94096c2009-07-18 14:23:06 -05002124
Rick Deanee568302009-07-24 09:56:29 -05002125
2126 def test_load_pkcs12_garbage(self):
2127 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002128 :py:obj:`load_pkcs12` raises :py:obj:`OpenSSL.crypto.Error` when passed a string
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002129 which is not a PKCS12 dump.
Rick Deanee568302009-07-24 09:56:29 -05002130 """
2131 passwd = 'whatever'
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002132 e = self.assertRaises(Error, load_pkcs12, b'fruit loops', passwd)
Jean-Paul Calderonede075462014-01-18 10:34:12 -05002133 self.assertEqual( e.args[0][0][0], 'asn1 encoding routines')
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -04002134 self.assertEqual( len(e.args[0][0]), 3)
Rick Deanee568302009-07-24 09:56:29 -05002135
2136
Rick Deanf94096c2009-07-18 14:23:06 -05002137 def test_replace(self):
2138 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002139 :py:obj:`PKCS12.set_certificate` replaces the certificate in a PKCS12 cluster.
2140 :py:obj:`PKCS12.set_privatekey` replaces the private key.
2141 :py:obj:`PKCS12.set_ca_certificates` replaces the CA certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05002142 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002143 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
2144 p12.set_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2145 p12.set_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002146 root_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05002147 client_cert = load_certificate(FILETYPE_PEM, client_cert_pem)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002148 p12.set_ca_certificates([root_cert]) # not a tuple
Rick Dean623ee362009-07-17 12:22:16 -05002149 self.assertEqual(1, len(p12.get_ca_certificates()))
2150 self.assertEqual(root_cert, p12.get_ca_certificates()[0])
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002151 p12.set_ca_certificates([client_cert, root_cert])
Rick Deanf94096c2009-07-18 14:23:06 -05002152 self.assertEqual(2, len(p12.get_ca_certificates()))
2153 self.assertEqual(client_cert, p12.get_ca_certificates()[0])
2154 self.assertEqual(root_cert, p12.get_ca_certificates()[1])
2155
2156
2157 def test_friendly_name(self):
2158 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002159 The *friendlyName* of a PKCS12 can be set and retrieved via
Jonathan Ballet648875f2011-07-16 14:14:58 +09002160 :py:obj:`PKCS12.get_friendlyname` and :py:obj:`PKCS12_set_friendlyname`, and a
2161 :py:obj:`PKCS12` with a friendly name set can be dumped with :py:obj:`PKCS12.export`.
Rick Deanf94096c2009-07-18 14:23:06 -05002162 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002163 passwd = b'Dogmeat[]{}!@#$%^&*()~`?/.,<>-_+=";:'
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002164 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -04002165 for friendly_name in [b('Serverlicious'), None, b('###')]:
Rick Dean42d69e12009-07-20 11:36:08 -05002166 p12.set_friendlyname(friendly_name)
2167 self.assertEqual(p12.get_friendlyname(), friendly_name)
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002168 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
Rick Dean42d69e12009-07-20 11:36:08 -05002169 reloaded_p12 = load_pkcs12(dumped_p12, passwd)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002170 self.assertEqual(
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -04002171 p12.get_friendlyname(), reloaded_p12.get_friendlyname())
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002172 # We would use the openssl program to confirm the friendly
2173 # name, but it is not possible. The pkcs12 command
2174 # does not store the friendly name in the cert's
Rick Dean42d69e12009-07-20 11:36:08 -05002175 # alias, which we could then extract.
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002176 self.check_recovery(
2177 dumped_p12, key=server_key_pem, cert=server_cert_pem,
2178 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05002179
2180
2181 def test_various_empty_passphrases(self):
2182 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002183 Test that missing, None, and '' passphrases are identical for PKCS12
2184 export.
Rick Deanf94096c2009-07-18 14:23:06 -05002185 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002186 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002187 passwd = b""
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002188 dumped_p12_empty = p12.export(iter=2, maciter=0, passphrase=passwd)
2189 dumped_p12_none = p12.export(iter=3, maciter=2, passphrase=None)
2190 dumped_p12_nopw = p12.export(iter=9, maciter=4)
2191 for dumped_p12 in [dumped_p12_empty, dumped_p12_none, dumped_p12_nopw]:
2192 self.check_recovery(
2193 dumped_p12, key=client_key_pem, cert=client_cert_pem,
2194 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05002195
2196
2197 def test_removing_ca_cert(self):
2198 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002199 Passing :py:obj:`None` to :py:obj:`PKCS12.set_ca_certificates` removes all CA
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002200 certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05002201 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002202 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
2203 p12.set_ca_certificates(None)
Rick Dean623ee362009-07-17 12:22:16 -05002204 self.assertEqual(None, p12.get_ca_certificates())
Rick Deanf94096c2009-07-18 14:23:06 -05002205
2206
2207 def test_export_without_mac(self):
2208 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002209 Exporting a PKCS12 with a :py:obj:`maciter` of ``-1`` excludes the MAC
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002210 entirely.
Rick Deanf94096c2009-07-18 14:23:06 -05002211 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002212 passwd = b"Lake Michigan"
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002213 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Dean623ee362009-07-17 12:22:16 -05002214 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002215 self.check_recovery(
2216 dumped_p12, key=server_key_pem, cert=server_cert_pem,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002217 passwd=passwd, extra=(b"-nomacver",))
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002218
2219
2220 def test_load_without_mac(self):
2221 """
2222 Loading a PKCS12 without a MAC does something other than crash.
2223 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002224 passwd = b"Lake Michigan"
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002225 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
2226 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Rick Dean321a0512009-08-13 17:21:29 -05002227 try:
2228 recovered_p12 = load_pkcs12(dumped_p12, passwd)
2229 # The person who generated this PCKS12 should be flogged,
2230 # or better yet we should have a means to determine
2231 # whether a PCKS12 had a MAC that was verified.
2232 # Anyway, libopenssl chooses to allow it, so the
2233 # pyopenssl binding does as well.
2234 self.assertTrue(isinstance(recovered_p12, PKCS12))
2235 except Error:
2236 # Failing here with an exception is preferred as some openssl
2237 # versions do.
2238 pass
Rick Dean623ee362009-07-17 12:22:16 -05002239
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002240
Rick Dean25bcc1f2009-07-20 11:53:13 -05002241 def test_zero_len_list_for_ca(self):
2242 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002243 A PKCS12 with an empty CA certificates list can be exported.
Rick Dean25bcc1f2009-07-20 11:53:13 -05002244 """
2245 passwd = 'Hobie 18'
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002246 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002247 # p12.set_ca_certificates([])
2248 # self.assertEqual((), p12.get_ca_certificates())
2249 # dumped_p12 = p12.export(passphrase=passwd, iter=3)
2250 # self.check_recovery(
2251 # dumped_p12, key=server_key_pem, cert=server_cert_pem,
2252 # passwd=passwd)
Rick Dean25bcc1f2009-07-20 11:53:13 -05002253
2254
Rick Deanf94096c2009-07-18 14:23:06 -05002255 def test_export_without_args(self):
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002256 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002257 All the arguments to :py:obj:`PKCS12.export` are optional.
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002258 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002259 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05002260 dumped_p12 = p12.export() # no args
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002261 self.check_recovery(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002262 dumped_p12, key=server_key_pem, cert=server_cert_pem, passwd=b"")
Rick Deanf94096c2009-07-18 14:23:06 -05002263
2264
2265 def test_key_cert_mismatch(self):
2266 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002267 :py:obj:`PKCS12.export` raises an exception when a key and certificate
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002268 mismatch.
Rick Deanf94096c2009-07-18 14:23:06 -05002269 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002270 p12 = self.gen_pkcs12(server_cert_pem, client_key_pem, root_cert_pem)
2271 self.assertRaises(Error, p12.export)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002272
2273
2274
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002275# These quoting functions taken directly from Twisted's twisted.python.win32.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002276_cmdLineQuoteRe = re.compile(br'(\\*)"')
2277_cmdLineQuoteRe2 = re.compile(br'(\\+)\Z')
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002278def cmdLineQuote(s):
2279 """
2280 Internal method for quoting a single command-line argument.
2281
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002282 See http://www.perlmonks.org/?node_id=764004
2283
Jonathan Ballet648875f2011-07-16 14:14:58 +09002284 :type: :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002285 :param s: A single unquoted string to quote for something that is expecting
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002286 cmd.exe-style quoting
2287
Jonathan Ballet648875f2011-07-16 14:14:58 +09002288 :rtype: :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002289 :return: A cmd.exe-style quoted string
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002290 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002291 s = _cmdLineQuoteRe2.sub(br"\1\1", _cmdLineQuoteRe.sub(br'\1\1\\"', s))
2292 return b'"' + s + b'"'
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002293
2294
2295
2296def quoteArguments(arguments):
2297 """
2298 Quote an iterable of command-line arguments for passing to CreateProcess or
Jonathan Ballet648875f2011-07-16 14:14:58 +09002299 a similar API. This allows the list passed to :py:obj:`reactor.spawnProcess` to
2300 match the child process's :py:obj:`sys.argv` properly.
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002301
Jonathan Ballet648875f2011-07-16 14:14:58 +09002302 :type arguments: :py:obj:`iterable` of :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002303 :param arguments: An iterable of unquoted arguments to quote
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002304
Jonathan Ballet648875f2011-07-16 14:14:58 +09002305 :rtype: :py:obj:`str`
2306 :return: A space-delimited string containing quoted versions of :py:obj:`arguments`
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002307 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002308 return b' '.join(map(cmdLineQuote, arguments))
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002309
2310
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002311
Rick Dean4c9ad612009-07-17 15:05:22 -05002312def _runopenssl(pem, *args):
2313 """
2314 Run the command line openssl tool with the given arguments and write
Rick Dean55d1ce62009-08-13 17:40:24 -05002315 the given PEM to its stdin. Not safe for quotes.
Rick Dean4c9ad612009-07-17 15:05:22 -05002316 """
Jean-Paul Calderone038de952009-08-21 12:16:06 -04002317 if os.name == 'posix':
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002318 command = b"openssl " + b" ".join([
2319 (b"'" + arg.replace(b"'", b"'\\''") + b"'")
2320 for arg in args])
Rick Dean55d1ce62009-08-13 17:40:24 -05002321 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002322 command = b"openssl " + quoteArguments(args)
2323 proc = Popen(native(command), shell=True, stdin=PIPE, stdout=PIPE)
Jean-Paul Calderone62ca8da2010-08-11 19:58:08 -04002324 proc.stdin.write(pem)
2325 proc.stdin.close()
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002326 output = proc.stdout.read()
2327 proc.stdout.close()
2328 proc.wait()
2329 return output
Rick Dean4c9ad612009-07-17 15:05:22 -05002330
2331
2332
Jean-Paul Calderone18808652009-07-05 12:54:05 -04002333class FunctionTests(TestCase):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002334 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002335 Tests for free-functions in the :py:obj:`OpenSSL.crypto` module.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002336 """
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002337
2338 def test_load_privatekey_invalid_format(self):
2339 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002340 :py:obj:`load_privatekey` raises :py:obj:`ValueError` if passed an unknown filetype.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002341 """
2342 self.assertRaises(ValueError, load_privatekey, 100, root_key_pem)
2343
2344
2345 def test_load_privatekey_invalid_passphrase_type(self):
2346 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002347 :py:obj:`load_privatekey` raises :py:obj:`TypeError` if passed a passphrase that is
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002348 neither a :py:obj:`str` nor a callable.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002349 """
2350 self.assertRaises(
2351 TypeError,
2352 load_privatekey,
2353 FILETYPE_PEM, encryptedPrivateKeyPEMPassphrase, object())
2354
2355
2356 def test_load_privatekey_wrong_args(self):
2357 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002358 :py:obj:`load_privatekey` raises :py:obj:`TypeError` if called with the wrong number
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002359 of arguments.
2360 """
2361 self.assertRaises(TypeError, load_privatekey)
2362
2363
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002364 def test_load_privatekey_wrongPassphrase(self):
2365 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002366 :py:obj:`load_privatekey` raises :py:obj:`OpenSSL.crypto.Error` when it is passed an
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002367 encrypted PEM and an incorrect passphrase.
2368 """
2369 self.assertRaises(
2370 Error,
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002371 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, b("quack"))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002372
2373
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002374 def test_load_privatekey_passphraseWrongType(self):
2375 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002376 :py:obj:`load_privatekey` raises :py:obj:`ValueError` when it is passed a passphrase
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002377 with a private key encoded in a format, that doesn't support
2378 encryption.
2379 """
2380 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2381 blob = dump_privatekey(FILETYPE_ASN1, key)
2382 self.assertRaises(ValueError,
2383 load_privatekey, FILETYPE_ASN1, blob, "secret")
2384
2385
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002386 def test_load_privatekey_passphrase(self):
2387 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002388 :py:obj:`load_privatekey` can create a :py:obj:`PKey` object from an encrypted PEM
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002389 string if given the passphrase.
2390 """
2391 key = load_privatekey(
2392 FILETYPE_PEM, encryptedPrivateKeyPEM,
2393 encryptedPrivateKeyPEMPassphrase)
2394 self.assertTrue(isinstance(key, PKeyType))
2395
2396
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002397 def test_load_privatekey_passphrase_exception(self):
2398 """
2399 If the passphrase callback raises an exception, that exception is raised
2400 by :py:obj:`load_privatekey`.
2401 """
2402 def cb(ignored):
2403 raise ArithmeticError
2404
2405 self.assertRaises(ArithmeticError,
2406 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2407
2408
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002409 def test_load_privatekey_wrongPassphraseCallback(self):
2410 """
Jean-Paul Calderoned440a082011-09-14 11:02:05 -04002411 :py:obj:`load_privatekey` raises :py:obj:`OpenSSL.crypto.Error` when it
2412 is passed an encrypted PEM and a passphrase callback which returns an
2413 incorrect passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002414 """
2415 called = []
2416 def cb(*a):
2417 called.append(None)
Jean-Paul Calderoned440a082011-09-14 11:02:05 -04002418 return b("quack")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002419 self.assertRaises(
2420 Error,
2421 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2422 self.assertTrue(called)
2423
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002424
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002425 def test_load_privatekey_passphraseCallback(self):
2426 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002427 :py:obj:`load_privatekey` can create a :py:obj:`PKey` object from an encrypted PEM
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002428 string if given a passphrase callback which returns the correct
2429 password.
2430 """
2431 called = []
2432 def cb(writing):
2433 called.append(writing)
2434 return encryptedPrivateKeyPEMPassphrase
2435 key = load_privatekey(FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2436 self.assertTrue(isinstance(key, PKeyType))
2437 self.assertEqual(called, [False])
2438
2439
Jean-Paul Calderone105cb952011-09-14 10:16:46 -04002440 def test_load_privatekey_passphrase_wrong_return_type(self):
2441 """
2442 :py:obj:`load_privatekey` raises :py:obj:`ValueError` if the passphrase
2443 callback returns something other than a byte string.
2444 """
2445 self.assertRaises(
2446 ValueError,
2447 load_privatekey,
2448 FILETYPE_PEM, encryptedPrivateKeyPEM, lambda *args: 3)
2449
2450
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002451 def test_dump_privatekey_wrong_args(self):
2452 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002453 :py:obj:`dump_privatekey` raises :py:obj:`TypeError` if called with the wrong number
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002454 of arguments.
2455 """
2456 self.assertRaises(TypeError, dump_privatekey)
Jean-Paul Calderone1eeccd82011-09-14 10:18:52 -04002457 # If cipher name is given, password is required.
2458 self.assertRaises(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002459 TypeError, dump_privatekey, FILETYPE_PEM, PKey(), GOOD_CIPHER)
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002460
2461
2462 def test_dump_privatekey_unknown_cipher(self):
2463 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002464 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` if called with an unrecognized
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002465 cipher name.
2466 """
2467 key = PKey()
2468 key.generate_key(TYPE_RSA, 512)
2469 self.assertRaises(
2470 ValueError, dump_privatekey,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002471 FILETYPE_PEM, key, BAD_CIPHER, "passphrase")
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002472
2473
2474 def test_dump_privatekey_invalid_passphrase_type(self):
2475 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002476 :py:obj:`dump_privatekey` raises :py:obj:`TypeError` if called with a passphrase which
2477 is neither a :py:obj:`str` nor a callable.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002478 """
2479 key = PKey()
2480 key.generate_key(TYPE_RSA, 512)
2481 self.assertRaises(
2482 TypeError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002483 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, object())
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002484
2485
2486 def test_dump_privatekey_invalid_filetype(self):
2487 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002488 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` if called with an unrecognized
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002489 filetype.
2490 """
2491 key = PKey()
2492 key.generate_key(TYPE_RSA, 512)
2493 self.assertRaises(ValueError, dump_privatekey, 100, key)
2494
2495
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002496 def test_load_privatekey_passphraseCallbackLength(self):
2497 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002498 :py:obj:`crypto.load_privatekey` should raise an error when the passphrase
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002499 provided by the callback is too long, not silently truncate it.
2500 """
2501 def cb(ignored):
2502 return "a" * 1025
2503
2504 self.assertRaises(ValueError,
2505 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2506
2507
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002508 def test_dump_privatekey_passphrase(self):
2509 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002510 :py:obj:`dump_privatekey` writes an encrypted PEM when given a passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002511 """
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002512 passphrase = b("foo")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002513 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002514 pem = dump_privatekey(FILETYPE_PEM, key, GOOD_CIPHER, passphrase)
2515 self.assertTrue(isinstance(pem, binary_type))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002516 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
2517 self.assertTrue(isinstance(loadedKey, PKeyType))
2518 self.assertEqual(loadedKey.type(), key.type())
2519 self.assertEqual(loadedKey.bits(), key.bits())
2520
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002521
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002522 def test_dump_privatekey_passphraseWrongType(self):
2523 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002524 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` when it is passed a passphrase
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002525 with a private key encoded in a format, that doesn't support
2526 encryption.
2527 """
2528 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2529 self.assertRaises(ValueError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002530 dump_privatekey, FILETYPE_ASN1, key, GOOD_CIPHER, "secret")
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002531
2532
Rick Dean5b7b6372009-04-01 11:34:06 -05002533 def test_dump_certificate(self):
2534 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002535 :py:obj:`dump_certificate` writes PEM, DER, and text.
Rick Dean5b7b6372009-04-01 11:34:06 -05002536 """
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002537 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
Rick Dean5b7b6372009-04-01 11:34:06 -05002538 cert = load_certificate(FILETYPE_PEM, pemData)
2539 dumped_pem = dump_certificate(FILETYPE_PEM, cert)
2540 self.assertEqual(dumped_pem, cleartextCertificatePEM)
2541 dumped_der = dump_certificate(FILETYPE_ASN1, cert)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002542 good_der = _runopenssl(dumped_pem, b"x509", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002543 self.assertEqual(dumped_der, good_der)
2544 cert2 = load_certificate(FILETYPE_ASN1, dumped_der)
2545 dumped_pem2 = dump_certificate(FILETYPE_PEM, cert2)
2546 self.assertEqual(dumped_pem2, cleartextCertificatePEM)
2547 dumped_text = dump_certificate(FILETYPE_TEXT, cert)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002548 good_text = _runopenssl(dumped_pem, b"x509", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002549 self.assertEqual(dumped_text, good_text)
2550
2551
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002552 def test_dump_privatekey_pem(self):
Rick Dean5b7b6372009-04-01 11:34:06 -05002553 """
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002554 :py:obj:`dump_privatekey` writes a PEM
Rick Dean5b7b6372009-04-01 11:34:06 -05002555 """
2556 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -04002557 self.assertTrue(key.check())
Rick Dean5b7b6372009-04-01 11:34:06 -05002558 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2559 self.assertEqual(dumped_pem, cleartextPrivateKeyPEM)
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002560
2561
2562 def test_dump_privatekey_asn1(self):
2563 """
2564 :py:obj:`dump_privatekey` writes a DER
2565 """
2566 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2567 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2568
Rick Dean5b7b6372009-04-01 11:34:06 -05002569 dumped_der = dump_privatekey(FILETYPE_ASN1, key)
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002570 # XXX This OpenSSL call writes "writing RSA key" to standard out. Sad.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002571 good_der = _runopenssl(dumped_pem, b"rsa", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002572 self.assertEqual(dumped_der, good_der)
2573 key2 = load_privatekey(FILETYPE_ASN1, dumped_der)
2574 dumped_pem2 = dump_privatekey(FILETYPE_PEM, key2)
2575 self.assertEqual(dumped_pem2, cleartextPrivateKeyPEM)
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002576
2577
2578 def test_dump_privatekey_text(self):
2579 """
2580 :py:obj:`dump_privatekey` writes a text
2581 """
2582 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2583 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2584
Rick Dean5b7b6372009-04-01 11:34:06 -05002585 dumped_text = dump_privatekey(FILETYPE_TEXT, key)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002586 good_text = _runopenssl(dumped_pem, b"rsa", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002587 self.assertEqual(dumped_text, good_text)
2588
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002589
Rick Dean5b7b6372009-04-01 11:34:06 -05002590 def test_dump_certificate_request(self):
2591 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002592 :py:obj:`dump_certificate_request` writes a PEM, DER, and text.
Rick Dean5b7b6372009-04-01 11:34:06 -05002593 """
2594 req = load_certificate_request(FILETYPE_PEM, cleartextCertificateRequestPEM)
2595 dumped_pem = dump_certificate_request(FILETYPE_PEM, req)
2596 self.assertEqual(dumped_pem, cleartextCertificateRequestPEM)
2597 dumped_der = dump_certificate_request(FILETYPE_ASN1, req)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002598 good_der = _runopenssl(dumped_pem, b"req", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002599 self.assertEqual(dumped_der, good_der)
2600 req2 = load_certificate_request(FILETYPE_ASN1, dumped_der)
2601 dumped_pem2 = dump_certificate_request(FILETYPE_PEM, req2)
2602 self.assertEqual(dumped_pem2, cleartextCertificateRequestPEM)
2603 dumped_text = dump_certificate_request(FILETYPE_TEXT, req)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002604 good_text = _runopenssl(dumped_pem, b"req", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002605 self.assertEqual(dumped_text, good_text)
Jean-Paul Calderoneaf43cdf2010-08-03 18:40:52 -04002606 self.assertRaises(ValueError, dump_certificate_request, 100, req)
Rick Dean5b7b6372009-04-01 11:34:06 -05002607
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002608
2609 def test_dump_privatekey_passphraseCallback(self):
2610 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002611 :py:obj:`dump_privatekey` writes an encrypted PEM when given a callback which
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002612 returns the correct passphrase.
2613 """
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002614 passphrase = b("foo")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002615 called = []
2616 def cb(writing):
2617 called.append(writing)
2618 return passphrase
2619 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002620 pem = dump_privatekey(FILETYPE_PEM, key, GOOD_CIPHER, cb)
2621 self.assertTrue(isinstance(pem, binary_type))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002622 self.assertEqual(called, [True])
2623 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
2624 self.assertTrue(isinstance(loadedKey, PKeyType))
2625 self.assertEqual(loadedKey.type(), key.type())
2626 self.assertEqual(loadedKey.bits(), key.bits())
Rick Dean5b7b6372009-04-01 11:34:06 -05002627
2628
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002629 def test_dump_privatekey_passphrase_exception(self):
2630 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002631 :py:obj:`dump_privatekey` should not overwrite the exception raised
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002632 by the passphrase callback.
2633 """
2634 def cb(ignored):
2635 raise ArithmeticError
2636
2637 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2638 self.assertRaises(ArithmeticError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002639 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, cb)
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002640
2641
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002642 def test_dump_privatekey_passphraseCallbackLength(self):
2643 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002644 :py:obj:`crypto.dump_privatekey` should raise an error when the passphrase
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002645 provided by the callback is too long, not silently truncate it.
2646 """
2647 def cb(ignored):
2648 return "a" * 1025
2649
2650 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2651 self.assertRaises(ValueError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002652 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, cb)
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002653
2654
Alex Gaynor4b9c96a2014-08-14 09:51:48 -07002655 def test_load_pkcs7_data_pem(self):
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002656 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002657 :py:obj:`load_pkcs7_data` accepts a PKCS#7 string and returns an instance of
2658 :py:obj:`PKCS7Type`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002659 """
2660 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2661 self.assertTrue(isinstance(pkcs7, PKCS7Type))
2662
2663
Alex Gaynor4b9c96a2014-08-14 09:51:48 -07002664 def test_load_pkcs7_data_asn1(self):
Alex Gaynor9875a912014-08-14 13:35:05 -07002665 """
2666 :py:obj:`load_pkcs7_data` accepts a bytes containing ASN1 data
2667 representing PKCS#7 and returns an instance of :py:obj`PKCS7Type`.
2668 """
Alex Gaynor4b9c96a2014-08-14 09:51:48 -07002669 pkcs7 = load_pkcs7_data(FILETYPE_ASN1, pkcs7DataASN1)
2670 self.assertTrue(isinstance(pkcs7, PKCS7Type))
2671
2672
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002673 def test_load_pkcs7_data_invalid(self):
2674 """
2675 If the data passed to :py:obj:`load_pkcs7_data` is invalid,
2676 :py:obj:`Error` is raised.
2677 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002678 self.assertRaises(Error, load_pkcs7_data, FILETYPE_PEM, b"foo")
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002679
2680
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002681
Jean-Paul Calderone4a68b402013-12-29 16:54:58 -05002682class LoadCertificateTests(TestCase):
2683 """
2684 Tests for :py:obj:`load_certificate_request`.
2685 """
2686 def test_badFileType(self):
2687 """
2688 If the file type passed to :py:obj:`load_certificate_request` is
2689 neither :py:obj:`FILETYPE_PEM` nor :py:obj:`FILETYPE_ASN1` then
2690 :py:class:`ValueError` is raised.
2691 """
2692 self.assertRaises(ValueError, load_certificate_request, object(), b"")
2693
2694
2695
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002696class PKCS7Tests(TestCase):
2697 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002698 Tests for :py:obj:`PKCS7Type`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002699 """
2700 def test_type(self):
2701 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002702 :py:obj:`PKCS7Type` is a type object.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002703 """
2704 self.assertTrue(isinstance(PKCS7Type, type))
2705 self.assertEqual(PKCS7Type.__name__, 'PKCS7')
2706
2707 # XXX This doesn't currently work.
2708 # self.assertIdentical(PKCS7, PKCS7Type)
2709
2710
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002711 # XXX Opposite results for all these following methods
2712
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002713 def test_type_is_signed_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002714 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002715 :py:obj:`PKCS7Type.type_is_signed` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002716 arguments.
2717 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002718 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2719 self.assertRaises(TypeError, pkcs7.type_is_signed, None)
2720
2721
2722 def test_type_is_signed(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002723 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002724 :py:obj:`PKCS7Type.type_is_signed` returns :py:obj:`True` if the PKCS7 object is of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002725 the type *signed*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002726 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002727 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2728 self.assertTrue(pkcs7.type_is_signed())
2729
2730
2731 def test_type_is_enveloped_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002732 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002733 :py:obj:`PKCS7Type.type_is_enveloped` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002734 arguments.
2735 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002736 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2737 self.assertRaises(TypeError, pkcs7.type_is_enveloped, None)
2738
2739
2740 def test_type_is_enveloped(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002741 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002742 :py:obj:`PKCS7Type.type_is_enveloped` returns :py:obj:`False` if the PKCS7 object is
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002743 not of the type *enveloped*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002744 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002745 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2746 self.assertFalse(pkcs7.type_is_enveloped())
2747
2748
2749 def test_type_is_signedAndEnveloped_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002750 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002751 :py:obj:`PKCS7Type.type_is_signedAndEnveloped` raises :py:obj:`TypeError` if called
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002752 with any arguments.
2753 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002754 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2755 self.assertRaises(TypeError, pkcs7.type_is_signedAndEnveloped, None)
2756
2757
2758 def test_type_is_signedAndEnveloped(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002759 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002760 :py:obj:`PKCS7Type.type_is_signedAndEnveloped` returns :py:obj:`False` if the PKCS7
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002761 object is not of the type *signed and enveloped*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002762 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002763 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2764 self.assertFalse(pkcs7.type_is_signedAndEnveloped())
2765
2766
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002767 def test_type_is_data(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002768 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002769 :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 -04002770 the type data.
2771 """
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002772 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2773 self.assertFalse(pkcs7.type_is_data())
2774
2775
2776 def test_type_is_data_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002777 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002778 :py:obj:`PKCS7Type.type_is_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002779 arguments.
2780 """
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002781 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2782 self.assertRaises(TypeError, pkcs7.type_is_data, None)
2783
2784
Jean-Paul Calderone97b28ca2010-07-30 10:56:07 -04002785 def test_get_type_name_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002786 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002787 :py:obj:`PKCS7Type.get_type_name` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002788 arguments.
2789 """
Jean-Paul Calderone97b28ca2010-07-30 10:56:07 -04002790 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2791 self.assertRaises(TypeError, pkcs7.get_type_name, None)
2792
2793
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002794 def test_get_type_name(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002795 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002796 :py:obj:`PKCS7Type.get_type_name` returns a :py:obj:`str` giving the type name.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002797 """
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002798 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
Jean-Paul Calderone07640f12010-08-22 17:14:43 -04002799 self.assertEquals(pkcs7.get_type_name(), b('pkcs7-signedData'))
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002800
2801
2802 def test_attribute(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002803 """
2804 If an attribute other than one of the methods tested here is accessed on
Jonathan Ballet648875f2011-07-16 14:14:58 +09002805 an instance of :py:obj:`PKCS7Type`, :py:obj:`AttributeError` is raised.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002806 """
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002807 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2808 self.assertRaises(AttributeError, getattr, pkcs7, "foo")
2809
2810
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002811
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002812class NetscapeSPKITests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002813 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002814 Tests for :py:obj:`OpenSSL.crypto.NetscapeSPKI`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002815 """
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002816 def signable(self):
2817 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002818 Return a new :py:obj:`NetscapeSPKI` for use with signing tests.
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002819 """
2820 return NetscapeSPKI()
2821
2822
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002823 def test_type(self):
2824 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002825 :py:obj:`NetscapeSPKI` and :py:obj:`NetscapeSPKIType` refer to the same type object
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002826 and can be used to create instances of that type.
2827 """
2828 self.assertIdentical(NetscapeSPKI, NetscapeSPKIType)
2829 self.assertConsistentType(NetscapeSPKI, 'NetscapeSPKI')
2830
2831
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002832 def test_construction(self):
2833 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002834 :py:obj:`NetscapeSPKI` returns an instance of :py:obj:`NetscapeSPKIType`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002835 """
2836 nspki = NetscapeSPKI()
2837 self.assertTrue(isinstance(nspki, NetscapeSPKIType))
2838
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002839
Jean-Paul Calderone969efaa2010-08-03 18:19:19 -04002840 def test_invalid_attribute(self):
2841 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002842 Accessing a non-existent attribute of a :py:obj:`NetscapeSPKI` instance causes
2843 an :py:obj:`AttributeError` to be raised.
Jean-Paul Calderone969efaa2010-08-03 18:19:19 -04002844 """
2845 nspki = NetscapeSPKI()
2846 self.assertRaises(AttributeError, lambda: nspki.foo)
2847
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002848
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002849 def test_b64_encode(self):
2850 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002851 :py:obj:`NetscapeSPKI.b64_encode` encodes the certificate to a base64 blob.
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002852 """
2853 nspki = NetscapeSPKI()
2854 blob = nspki.b64_encode()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002855 self.assertTrue(isinstance(blob, binary_type))
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002856
2857
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002858
Rick Dean536ba022009-07-24 23:57:27 -05002859class RevokedTests(TestCase):
2860 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002861 Tests for :py:obj:`OpenSSL.crypto.Revoked`
Rick Dean536ba022009-07-24 23:57:27 -05002862 """
2863 def test_construction(self):
2864 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002865 Confirm we can create :py:obj:`OpenSSL.crypto.Revoked`. Check
Rick Dean536ba022009-07-24 23:57:27 -05002866 that it is empty.
2867 """
2868 revoked = Revoked()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002869 self.assertTrue(isinstance(revoked, Revoked))
2870 self.assertEquals(type(revoked), Revoked)
2871 self.assertEquals(revoked.get_serial(), b('00'))
2872 self.assertEquals(revoked.get_rev_date(), None)
2873 self.assertEquals(revoked.get_reason(), None)
Rick Dean536ba022009-07-24 23:57:27 -05002874
2875
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002876 def test_construction_wrong_args(self):
2877 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002878 Calling :py:obj:`OpenSSL.crypto.Revoked` with any arguments results
2879 in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002880 """
2881 self.assertRaises(TypeError, Revoked, None)
2882 self.assertRaises(TypeError, Revoked, 1)
2883 self.assertRaises(TypeError, Revoked, "foo")
2884
2885
Rick Dean536ba022009-07-24 23:57:27 -05002886 def test_serial(self):
2887 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002888 Confirm we can set and get serial numbers from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002889 :py:obj:`OpenSSL.crypto.Revoked`. Confirm errors are handled
Rick Dean536ba022009-07-24 23:57:27 -05002890 with grace.
2891 """
2892 revoked = Revoked()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002893 ret = revoked.set_serial(b('10b'))
2894 self.assertEquals(ret, None)
Rick Dean536ba022009-07-24 23:57:27 -05002895 ser = revoked.get_serial()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002896 self.assertEquals(ser, b('010B'))
Rick Dean536ba022009-07-24 23:57:27 -05002897
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002898 revoked.set_serial(b('31ppp')) # a type error would be nice
Rick Dean536ba022009-07-24 23:57:27 -05002899 ser = revoked.get_serial()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002900 self.assertEquals(ser, b('31'))
Rick Dean536ba022009-07-24 23:57:27 -05002901
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002902 self.assertRaises(ValueError, revoked.set_serial, b('pqrst'))
Rick Dean536ba022009-07-24 23:57:27 -05002903 self.assertRaises(TypeError, revoked.set_serial, 100)
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002904 self.assertRaises(TypeError, revoked.get_serial, 1)
2905 self.assertRaises(TypeError, revoked.get_serial, None)
2906 self.assertRaises(TypeError, revoked.get_serial, "")
Rick Dean536ba022009-07-24 23:57:27 -05002907
2908
2909 def test_date(self):
2910 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002911 Confirm we can set and get revocation dates from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002912 :py:obj:`OpenSSL.crypto.Revoked`. Confirm errors are handled
Rick Dean536ba022009-07-24 23:57:27 -05002913 with grace.
2914 """
2915 revoked = Revoked()
2916 date = revoked.get_rev_date()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002917 self.assertEquals(date, None)
Rick Dean536ba022009-07-24 23:57:27 -05002918
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002919 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05002920 ret = revoked.set_rev_date(now)
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002921 self.assertEqual(ret, None)
Rick Dean536ba022009-07-24 23:57:27 -05002922 date = revoked.get_rev_date()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002923 self.assertEqual(date, now)
Rick Dean536ba022009-07-24 23:57:27 -05002924
2925
Rick Dean6385faf2009-07-26 00:07:47 -05002926 def test_reason(self):
2927 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002928 Confirm we can set and get revocation reasons from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002929 :py:obj:`OpenSSL.crypto.Revoked`. The "get" need to work
Rick Dean6385faf2009-07-26 00:07:47 -05002930 as "set". Likewise, each reason of all_reasons() must work.
2931 """
2932 revoked = Revoked()
2933 for r in revoked.all_reasons():
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002934 for x in range(2):
Rick Dean6385faf2009-07-26 00:07:47 -05002935 ret = revoked.set_reason(r)
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002936 self.assertEquals(ret, None)
Rick Dean6385faf2009-07-26 00:07:47 -05002937 reason = revoked.get_reason()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002938 self.assertEquals(
2939 reason.lower().replace(b(' '), b('')),
2940 r.lower().replace(b(' '), b('')))
Rick Dean6385faf2009-07-26 00:07:47 -05002941 r = reason # again with the resp of get
2942
2943 revoked.set_reason(None)
2944 self.assertEqual(revoked.get_reason(), None)
2945
2946
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002947 def test_set_reason_wrong_arguments(self):
Rick Dean6385faf2009-07-26 00:07:47 -05002948 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002949 Calling :py:obj:`OpenSSL.crypto.Revoked.set_reason` with other than
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002950 one argument, or an argument which isn't a valid reason,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002951 results in :py:obj:`TypeError` or :py:obj:`ValueError` being raised.
Rick Dean6385faf2009-07-26 00:07:47 -05002952 """
2953 revoked = Revoked()
2954 self.assertRaises(TypeError, revoked.set_reason, 100)
Jean-Paul Calderone281b62b2010-08-28 14:22:29 -04002955 self.assertRaises(ValueError, revoked.set_reason, b('blue'))
Rick Dean6385faf2009-07-26 00:07:47 -05002956
Rick Dean536ba022009-07-24 23:57:27 -05002957
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002958 def test_get_reason_wrong_arguments(self):
2959 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002960 Calling :py:obj:`OpenSSL.crypto.Revoked.get_reason` with any
2961 arguments results in :py:obj:`TypeError` being raised.
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002962 """
2963 revoked = Revoked()
2964 self.assertRaises(TypeError, revoked.get_reason, None)
2965 self.assertRaises(TypeError, revoked.get_reason, 1)
2966 self.assertRaises(TypeError, revoked.get_reason, "foo")
2967
2968
2969
Rick Dean536ba022009-07-24 23:57:27 -05002970class CRLTests(TestCase):
2971 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002972 Tests for :py:obj:`OpenSSL.crypto.CRL`
Rick Dean536ba022009-07-24 23:57:27 -05002973 """
2974 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
2975 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2976
2977 def test_construction(self):
2978 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002979 Confirm we can create :py:obj:`OpenSSL.crypto.CRL`. Check
Rick Dean536ba022009-07-24 23:57:27 -05002980 that it is empty
2981 """
2982 crl = CRL()
2983 self.assertTrue( isinstance(crl, CRL) )
2984 self.assertEqual(crl.get_revoked(), None)
2985
2986
Jean-Paul Calderone2efd03e2010-01-30 13:59:55 -05002987 def test_construction_wrong_args(self):
2988 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002989 Calling :py:obj:`OpenSSL.crypto.CRL` with any number of arguments
2990 results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone2efd03e2010-01-30 13:59:55 -05002991 """
2992 self.assertRaises(TypeError, CRL, 1)
2993 self.assertRaises(TypeError, CRL, "")
2994 self.assertRaises(TypeError, CRL, None)
2995
2996
Rick Dean536ba022009-07-24 23:57:27 -05002997 def test_export(self):
2998 """
2999 Use python to create a simple CRL with a revocation, and export
3000 the CRL in formats of PEM, DER and text. Those outputs are verified
3001 with the openssl program.
3002 """
3003 crl = CRL()
3004 revoked = Revoked()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003005 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05003006 revoked.set_rev_date(now)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003007 revoked.set_serial(b('3ab'))
3008 revoked.set_reason(b('sUpErSeDEd'))
Rick Dean536ba022009-07-24 23:57:27 -05003009 crl.add_revoked(revoked)
3010
3011 # PEM format
3012 dumped_crl = crl.export(self.cert, self.pkey, days=20)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003013 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003014 text.index(b('Serial Number: 03AB'))
3015 text.index(b('Superseded'))
3016 text.index(b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA'))
Rick Dean536ba022009-07-24 23:57:27 -05003017
3018 # DER format
3019 dumped_crl = crl.export(self.cert, self.pkey, FILETYPE_ASN1)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003020 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text", b"-inform", b"DER")
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003021 text.index(b('Serial Number: 03AB'))
3022 text.index(b('Superseded'))
3023 text.index(b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA'))
Rick Dean536ba022009-07-24 23:57:27 -05003024
3025 # text format
3026 dumped_text = crl.export(self.cert, self.pkey, type=FILETYPE_TEXT)
3027 self.assertEqual(text, dumped_text)
3028
3029
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -04003030 def test_export_invalid(self):
3031 """
3032 If :py:obj:`CRL.export` is used with an uninitialized :py:obj:`X509`
Jean-Paul Calderoneb5871072012-03-09 14:58:00 -08003033 instance, :py:obj:`OpenSSL.crypto.Error` is raised.
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -04003034 """
3035 crl = CRL()
3036 self.assertRaises(Error, crl.export, X509(), PKey())
3037
3038
Jean-Paul Calderone56515342010-01-30 13:49:38 -05003039 def test_add_revoked_keyword(self):
3040 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003041 :py:obj:`OpenSSL.CRL.add_revoked` accepts its single argument as the
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003042 ``revoked`` keyword argument.
Jean-Paul Calderone56515342010-01-30 13:49:38 -05003043 """
3044 crl = CRL()
3045 revoked = Revoked()
3046 crl.add_revoked(revoked=revoked)
3047 self.assertTrue(isinstance(crl.get_revoked()[0], Revoked))
3048
Rick Dean6385faf2009-07-26 00:07:47 -05003049
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05003050 def test_export_wrong_args(self):
3051 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003052 Calling :py:obj:`OpenSSL.CRL.export` with fewer than two or more than
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05003053 four arguments, or with arguments other than the certificate,
3054 private key, integer file type, and integer number of days it
Jonathan Ballet648875f2011-07-16 14:14:58 +09003055 expects, results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05003056 """
3057 crl = CRL()
3058 self.assertRaises(TypeError, crl.export)
3059 self.assertRaises(TypeError, crl.export, self.cert)
3060 self.assertRaises(TypeError, crl.export, self.cert, self.pkey, FILETYPE_PEM, 10, "foo")
3061
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05003062 self.assertRaises(TypeError, crl.export, None, self.pkey, FILETYPE_PEM, 10)
3063 self.assertRaises(TypeError, crl.export, self.cert, None, FILETYPE_PEM, 10)
3064 self.assertRaises(TypeError, crl.export, self.cert, self.pkey, None, 10)
3065 self.assertRaises(TypeError, crl.export, self.cert, FILETYPE_PEM, None)
3066
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05003067
Jean-Paul Calderoneea198422010-01-30 13:58:23 -05003068 def test_export_unknown_filetype(self):
3069 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003070 Calling :py:obj:`OpenSSL.CRL.export` with a file type other than
3071 :py:obj:`FILETYPE_PEM`, :py:obj:`FILETYPE_ASN1`, or :py:obj:`FILETYPE_TEXT` results
3072 in a :py:obj:`ValueError` being raised.
Jean-Paul Calderoneea198422010-01-30 13:58:23 -05003073 """
3074 crl = CRL()
3075 self.assertRaises(ValueError, crl.export, self.cert, self.pkey, 100, 10)
3076
3077
Rick Dean536ba022009-07-24 23:57:27 -05003078 def test_get_revoked(self):
3079 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05003080 Use python to create a simple CRL with two revocations.
Jonathan Ballet648875f2011-07-16 14:14:58 +09003081 Get back the :py:obj:`Revoked` using :py:obj:`OpenSSL.CRL.get_revoked` and
Rick Dean536ba022009-07-24 23:57:27 -05003082 verify them.
3083 """
3084 crl = CRL()
3085
3086 revoked = Revoked()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003087 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05003088 revoked.set_rev_date(now)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003089 revoked.set_serial(b('3ab'))
Rick Dean536ba022009-07-24 23:57:27 -05003090 crl.add_revoked(revoked)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003091 revoked.set_serial(b('100'))
3092 revoked.set_reason(b('sUpErSeDEd'))
Rick Dean536ba022009-07-24 23:57:27 -05003093 crl.add_revoked(revoked)
3094
3095 revs = crl.get_revoked()
3096 self.assertEqual(len(revs), 2)
3097 self.assertEqual(type(revs[0]), Revoked)
3098 self.assertEqual(type(revs[1]), Revoked)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003099 self.assertEqual(revs[0].get_serial(), b('03AB'))
3100 self.assertEqual(revs[1].get_serial(), b('0100'))
Rick Dean536ba022009-07-24 23:57:27 -05003101 self.assertEqual(revs[0].get_rev_date(), now)
3102 self.assertEqual(revs[1].get_rev_date(), now)
3103
3104
Jean-Paul Calderone46bdce42010-01-30 13:44:16 -05003105 def test_get_revoked_wrong_args(self):
3106 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003107 Calling :py:obj:`OpenSSL.CRL.get_revoked` with any arguments results
3108 in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone46bdce42010-01-30 13:44:16 -05003109 """
3110 crl = CRL()
3111 self.assertRaises(TypeError, crl.get_revoked, None)
3112 self.assertRaises(TypeError, crl.get_revoked, 1)
3113 self.assertRaises(TypeError, crl.get_revoked, "")
3114 self.assertRaises(TypeError, crl.get_revoked, "", 1, None)
3115
3116
Jean-Paul Calderoneecef6fa2010-01-30 13:47:18 -05003117 def test_add_revoked_wrong_args(self):
3118 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003119 Calling :py:obj:`OpenSSL.CRL.add_revoked` with other than one
3120 argument results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderoneecef6fa2010-01-30 13:47:18 -05003121 """
3122 crl = CRL()
3123 self.assertRaises(TypeError, crl.add_revoked)
3124 self.assertRaises(TypeError, crl.add_revoked, 1, 2)
3125 self.assertRaises(TypeError, crl.add_revoked, "foo", "bar")
3126
3127
Rick Dean536ba022009-07-24 23:57:27 -05003128 def test_load_crl(self):
3129 """
3130 Load a known CRL and inspect its revocations. Both
3131 PEM and DER formats are loaded.
3132 """
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003133 crl = load_crl(FILETYPE_PEM, crlData)
Rick Dean536ba022009-07-24 23:57:27 -05003134 revs = crl.get_revoked()
3135 self.assertEqual(len(revs), 2)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003136 self.assertEqual(revs[0].get_serial(), b('03AB'))
Rick Dean6385faf2009-07-26 00:07:47 -05003137 self.assertEqual(revs[0].get_reason(), None)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003138 self.assertEqual(revs[1].get_serial(), b('0100'))
3139 self.assertEqual(revs[1].get_reason(), b('Superseded'))
Rick Dean536ba022009-07-24 23:57:27 -05003140
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003141 der = _runopenssl(crlData, b"crl", b"-outform", b"DER")
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05003142 crl = load_crl(FILETYPE_ASN1, der)
Rick Dean536ba022009-07-24 23:57:27 -05003143 revs = crl.get_revoked()
3144 self.assertEqual(len(revs), 2)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003145 self.assertEqual(revs[0].get_serial(), b('03AB'))
Rick Dean6385faf2009-07-26 00:07:47 -05003146 self.assertEqual(revs[0].get_reason(), None)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003147 self.assertEqual(revs[1].get_serial(), b('0100'))
3148 self.assertEqual(revs[1].get_reason(), b('Superseded'))
Rick Dean536ba022009-07-24 23:57:27 -05003149
3150
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003151 def test_load_crl_wrong_args(self):
3152 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003153 Calling :py:obj:`OpenSSL.crypto.load_crl` with other than two
3154 arguments results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003155 """
3156 self.assertRaises(TypeError, load_crl)
3157 self.assertRaises(TypeError, load_crl, FILETYPE_PEM)
3158 self.assertRaises(TypeError, load_crl, FILETYPE_PEM, crlData, None)
3159
3160
3161 def test_load_crl_bad_filetype(self):
3162 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003163 Calling :py:obj:`OpenSSL.crypto.load_crl` with an unknown file type
3164 raises a :py:obj:`ValueError`.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003165 """
3166 self.assertRaises(ValueError, load_crl, 100, crlData)
3167
3168
3169 def test_load_crl_bad_data(self):
3170 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003171 Calling :py:obj:`OpenSSL.crypto.load_crl` with file data which can't
3172 be loaded raises a :py:obj:`OpenSSL.crypto.Error`.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003173 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003174 self.assertRaises(Error, load_crl, FILETYPE_PEM, b"hello, world")
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003175
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04003176
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003177
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003178class VerifyCertTests(TestCase):
3179 """
3180 Tests for :py:obj:`OpenSSL.crypto.verify_cert`.
3181 """
3182 root_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3183 intermediate_cert = load_certificate(FILETYPE_PEM, intermediate_cert_pem)
3184 intermediate_server_cert = load_certificate(FILETYPE_PEM, intermediate_server_cert_pem)
3185
3186 def test_valid(self):
3187 """
Jean-Paul Calderone06e01b92015-01-18 15:43:13 -05003188 :py:obj:`verify_cert` returns ``None`` when called with a certificate
3189 and valid chain.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003190 """
3191 store = X509Store()
3192 store.add_cert(self.root_cert)
3193 store.add_cert(self.intermediate_cert)
3194 store_ctx = X509StoreContext(store, self.intermediate_server_cert)
3195 self.assertEqual(verify_cert(store_ctx), None)
3196
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003197
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003198 def test_reuse(self):
3199 """
Jean-Paul Calderone06e01b92015-01-18 15:43:13 -05003200 :py:obj:`verify_cert` can be called multiple times with the same
3201 ``X509StoreContext`` instance to produce the same result.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003202 """
3203 store = X509Store()
3204 store.add_cert(self.root_cert)
3205 store.add_cert(self.intermediate_cert)
3206 store_ctx = X509StoreContext(store, self.intermediate_server_cert)
3207 self.assertEqual(verify_cert(store_ctx), None)
3208 self.assertEqual(verify_cert(store_ctx), None)
3209
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003210
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003211 def test_trusted_self_signed(self):
3212 """
Jean-Paul Calderone06e01b92015-01-18 15:43:13 -05003213 :py:obj:`verify_cert` returns ``None`` when called with a self-signed
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003214 certificate and itself in the chain.
3215 """
3216 store = X509Store()
3217 store.add_cert(self.root_cert)
3218 store_ctx = X509StoreContext(store, self.root_cert)
3219 self.assertEqual(verify_cert(store_ctx), None)
3220
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003221
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003222 def test_untrusted_self_signed(self):
3223 """
3224 :py:obj:`verify_cert` raises error when a self-signed certificate is
3225 verified without itself in the chain.
3226 """
3227 store = X509Store()
3228 store_ctx = X509StoreContext(store, self.root_cert)
Jean-Paul Calderone06e01b92015-01-18 15:43:13 -05003229 e = self.assertRaises(Error, verify_cert, store_ctx)
Jean-Paul Calderone4c10a1e2015-01-18 16:31:27 -05003230 self.assertEqual(e.args[0][2], 'self signed certificate')
Jean-Paul Calderone06e01b92015-01-18 15:43:13 -05003231 self.assertEqual(e.certificate.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003232
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003233
3234 def test_invalid_chain_no_root(self):
3235 """
3236 :py:obj:`verify_cert` raises error when a root certificate is missing
3237 from the chain.
3238 """
3239 store = X509Store()
3240 store.add_cert(self.intermediate_cert)
3241 store_ctx = X509StoreContext(store, self.intermediate_server_cert)
Jean-Paul Calderone06e01b92015-01-18 15:43:13 -05003242 e = self.assertRaises(Error, verify_cert, store_ctx)
Jean-Paul Calderone4c10a1e2015-01-18 16:31:27 -05003243 self.assertEqual(e.args[0][2], 'unable to get issuer certificate')
Jean-Paul Calderone06e01b92015-01-18 15:43:13 -05003244 self.assertEqual(e.certificate.get_subject().CN, 'intermediate')
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003245
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003246
3247 def test_invalid_chain_no_intermediate(self):
3248 """
3249 :py:obj:`verify_cert` raises error when an intermediate certificate is
3250 missing from the chain.
3251 """
3252 store = X509Store()
3253 store.add_cert(self.root_cert)
3254 store_ctx = X509StoreContext(store, self.intermediate_server_cert)
Jean-Paul Calderone06e01b92015-01-18 15:43:13 -05003255 e = self.assertRaises(Error, verify_cert, store_ctx)
Jean-Paul Calderone4c10a1e2015-01-18 16:31:27 -05003256 self.assertEqual(e.args[0][2], 'unable to get local issuer certificate')
Jean-Paul Calderone06e01b92015-01-18 15:43:13 -05003257 self.assertEqual(e.certificate.get_subject().CN, 'intermediate-service')
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003258
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003259
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -05003260
James Yonan7c2e5d32010-02-27 05:45:50 -07003261class SignVerifyTests(TestCase):
3262 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003263 Tests for :py:obj:`OpenSSL.crypto.sign` and :py:obj:`OpenSSL.crypto.verify`.
James Yonan7c2e5d32010-02-27 05:45:50 -07003264 """
3265 def test_sign_verify(self):
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04003266 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003267 :py:obj:`sign` generates a cryptographic signature which :py:obj:`verify` can check.
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04003268 """
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003269 content = b(
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04003270 "It was a bright cold day in April, and the clocks were striking "
3271 "thirteen. Winston Smith, his chin nuzzled into his breast in an "
3272 "effort to escape the vile wind, slipped quickly through the "
3273 "glass doors of Victory Mansions, though not quickly enough to "
3274 "prevent a swirl of gritty dust from entering along with him.")
3275
3276 # sign the content with this private key
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04003277 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04003278 # verify the content with this cert
3279 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3280 # certificate unrelated to priv_key, used to trigger an error
3281 bad_cert = load_certificate(FILETYPE_PEM, server_cert_pem)
James Yonan7c2e5d32010-02-27 05:45:50 -07003282
Jean-Paul Calderoned08feb02010-10-12 21:53:24 -04003283 for digest in ['md5', 'sha1']:
James Yonan7c2e5d32010-02-27 05:45:50 -07003284 sig = sign(priv_key, content, digest)
3285
3286 # Verify the signature of content, will throw an exception if error.
3287 verify(good_cert, sig, content, digest)
3288
3289 # This should fail because the certificate doesn't match the
3290 # private key that was used to sign the content.
3291 self.assertRaises(Error, verify, bad_cert, sig, content, digest)
3292
3293 # This should fail because we've "tainted" the content after
3294 # signing it.
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003295 self.assertRaises(
3296 Error, verify,
3297 good_cert, sig, content + b("tainted"), digest)
James Yonan7c2e5d32010-02-27 05:45:50 -07003298
3299 # test that unknown digest types fail
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003300 self.assertRaises(
Jean-Paul Calderone9538f142010-10-13 22:13:40 -04003301 ValueError, sign, priv_key, content, "strange-digest")
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003302 self.assertRaises(
Jean-Paul Calderone9538f142010-10-13 22:13:40 -04003303 ValueError, verify, good_cert, sig, content, "strange-digest")
James Yonan7c2e5d32010-02-27 05:45:50 -07003304
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04003305
Jean-Paul Calderone9828f662010-12-08 22:57:26 -05003306 def test_sign_nulls(self):
3307 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003308 :py:obj:`sign` produces a signature for a string with embedded nulls.
Jean-Paul Calderone9828f662010-12-08 22:57:26 -05003309 """
3310 content = b("Watch out! \0 Did you see it?")
3311 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
3312 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3313 sig = sign(priv_key, content, "sha1")
3314 verify(good_cert, sig, content, "sha1")
3315
3316
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003317
3318class EllipticCurveTests(TestCase):
3319 """
3320 Tests for :py:class:`_EllipticCurve`, :py:obj:`get_elliptic_curve`, and
3321 :py:obj:`get_elliptic_curves`.
3322 """
3323 def test_set(self):
3324 """
3325 :py:obj:`get_elliptic_curves` returns a :py:obj:`set`.
3326 """
3327 self.assertIsInstance(get_elliptic_curves(), set)
3328
3329
3330 def test_some_curves(self):
3331 """
3332 If :py:mod:`cryptography` has elliptic curve support then the set
3333 returned by :py:obj:`get_elliptic_curves` has some elliptic curves in
3334 it.
3335
3336 There could be an OpenSSL that violates this assumption. If so, this
3337 test will fail and we'll find out.
3338 """
3339 curves = get_elliptic_curves()
3340 if lib.Cryptography_HAS_EC:
3341 self.assertTrue(curves)
3342 else:
3343 self.assertFalse(curves)
3344
3345
3346 def test_a_curve(self):
3347 """
3348 :py:obj:`get_elliptic_curve` can be used to retrieve a particular
3349 supported curve.
3350 """
3351 curves = get_elliptic_curves()
3352 if curves:
3353 curve = next(iter(curves))
3354 self.assertEqual(curve.name, get_elliptic_curve(curve.name).name)
3355 else:
Jean-Paul Calderoneeb86f3a2014-04-19 09:45:57 -04003356 self.assertRaises(ValueError, get_elliptic_curve, u("prime256v1"))
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003357
3358
3359 def test_not_a_curve(self):
3360 """
3361 :py:obj:`get_elliptic_curve` raises :py:class:`ValueError` if called
3362 with a name which does not identify a supported curve.
3363 """
3364 self.assertRaises(
Jean-Paul Calderone5a82db92014-04-19 09:51:29 -04003365 ValueError, get_elliptic_curve, u("this curve was just invented"))
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003366
3367
3368 def test_repr(self):
3369 """
3370 The string representation of a curve object includes simply states the
3371 object is a curve and what its name is.
3372 """
3373 curves = get_elliptic_curves()
3374 if curves:
3375 curve = next(iter(curves))
3376 self.assertEqual("<Curve %r>" % (curve.name,), repr(curve))
3377
3378
3379 def test_to_EC_KEY(self):
3380 """
3381 The curve object can export a version of itself as an EC_KEY* via the
3382 private :py:meth:`_EllipticCurve._to_EC_KEY`.
3383 """
3384 curves = get_elliptic_curves()
3385 if curves:
3386 curve = next(iter(curves))
3387 # It's not easy to assert anything about this object. However, see
3388 # leakcheck/crypto.py for a test that demonstrates it at least does
3389 # not leak memory.
3390 curve._to_EC_KEY()
3391
3392
Jean-Paul Calderone1be77082014-04-30 18:17:41 -04003393
3394class EllipticCurveFactory(object):
3395 """
3396 A helper to get the names of two curves.
3397 """
3398 def __init__(self):
3399 curves = iter(get_elliptic_curves())
3400 try:
3401 self.curve_name = next(curves).name
3402 self.another_curve_name = next(curves).name
3403 except StopIteration:
3404 self.curve_name = self.another_curve_name = None
3405
3406
3407
3408class EllipticCurveEqualityTests(TestCase, EqualityTestsMixin):
3409 """
3410 Tests :py:type:`_EllipticCurve`\ 's implementation of ``==`` and ``!=``.
3411 """
3412 curve_factory = EllipticCurveFactory()
3413
3414 if curve_factory.curve_name is None:
3415 skip = "There are no curves available there can be no curve objects."
3416
3417
3418 def anInstance(self):
3419 """
3420 Get the curve object for an arbitrary curve supported by the system.
3421 """
3422 return get_elliptic_curve(self.curve_factory.curve_name)
3423
3424
3425 def anotherInstance(self):
3426 """
3427 Get the curve object for an arbitrary curve supported by the system -
3428 but not the one returned by C{anInstance}.
3429 """
3430 return get_elliptic_curve(self.curve_factory.another_curve_name)
3431
3432
3433
Jean-Paul Calderone22c31242014-05-01 07:49:47 -04003434class EllipticCurveHashTests(TestCase):
3435 """
3436 Tests for :py:type:`_EllipticCurve`\ 's implementation of hashing (thus use
3437 as an item in a :py:type:`dict` or :py:type:`set`).
3438 """
3439 curve_factory = EllipticCurveFactory()
3440
3441 if curve_factory.curve_name is None:
3442 skip = "There are no curves available there can be no curve objects."
3443
3444
3445 def test_contains(self):
3446 """
3447 The ``in`` operator reports that a :py:type:`set` containing a curve
3448 does contain that curve.
3449 """
3450 curve = get_elliptic_curve(self.curve_factory.curve_name)
3451 curves = set([curve])
3452 self.assertIn(curve, curves)
3453
3454
3455 def test_does_not_contain(self):
3456 """
3457 The ``in`` operator reports that a :py:type:`set` not containing a
3458 curve does not contain that curve.
3459 """
3460 curve = get_elliptic_curve(self.curve_factory.curve_name)
3461 curves = set([get_elliptic_curve(self.curve_factory.another_curve_name)])
3462 self.assertNotIn(curve, curves)
3463
3464
3465
Rick Dean5b7b6372009-04-01 11:34:06 -05003466if __name__ == '__main__':
3467 main()