blob: 2f7a70d8cab9fe9efa2855bdaf39217819e58e8f [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 Calderone60432792015-04-13 12:26:07 -04008from warnings import catch_warnings, simplefilter
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04009
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
Alex Gaynor791212d2015-09-05 15:46:08 -040016import pytest
17
Alex Gaynore7f51982016-09-11 11:48:14 -040018from six import binary_type
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050019
Paul Kehrer72d968b2016-07-29 15:31:04 +080020from cryptography.hazmat.backends.openssl.backend import backend
21from cryptography.hazmat.primitives import serialization
22from cryptography.hazmat.primitives.asymmetric import rsa
23
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -050024from OpenSSL.crypto import TYPE_RSA, TYPE_DSA, Error, PKey, PKeyType
Jean-Paul Calderone78381d22008-03-06 23:35:22 -050025from OpenSSL.crypto import X509, X509Type, X509Name, X509NameType
Alex Gaynor31287502015-09-05 16:11:27 -040026from OpenSSL.crypto import (
Dan Sully44e767a2016-06-04 18:05:27 -070027 X509Store,
28 X509StoreFlags,
29 X509StoreType,
30 X509StoreContext,
31 X509StoreContextError
Alex Gaynor31287502015-09-05 16:11:27 -040032)
Stephen Holsapple0d9815f2014-08-27 19:36:53 -070033from OpenSSL.crypto import X509Req, X509ReqType
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -050034from OpenSSL.crypto import X509Extension, X509ExtensionType
Rick Dean5b7b6372009-04-01 11:34:06 -050035from OpenSSL.crypto import load_certificate, load_privatekey
Cory Benfield6492f7c2015-10-27 16:57:58 +090036from OpenSSL.crypto import load_publickey, dump_publickey
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -040037from OpenSSL.crypto import FILETYPE_PEM, FILETYPE_ASN1, FILETYPE_TEXT
Jean-Paul Calderone71919862009-04-01 13:01:19 -040038from OpenSSL.crypto import dump_certificate, load_certificate_request
39from OpenSSL.crypto import dump_certificate_request, dump_privatekey
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -040040from OpenSSL.crypto import PKCS7Type, load_pkcs7_data
Jean-Paul Calderone9178ee62010-01-25 17:55:30 -050041from OpenSSL.crypto import PKCS12, PKCS12Type, load_pkcs12
Dominic Chenf05b2122015-10-13 16:32:35 +000042from OpenSSL.crypto import CRL, Revoked, dump_crl, load_crl
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -040043from OpenSSL.crypto import NetscapeSPKI, NetscapeSPKIType
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040044from OpenSSL.crypto import (
45 sign, verify, get_elliptic_curve, get_elliptic_curves)
Alex Chan63ef9bc2016-12-19 12:02:06 +000046from OpenSSL._util import native
Hynek Schlawackf0e66852015-10-16 20:18:38 +020047
48from .util import (
Alex Chanc6077062016-11-18 13:53:39 +000049 EqualityTestsMixin, is_consistent_type, TestCase, WARNING_TYPE_EXPECTED
Jean-Paul Calderone6462b072015-03-29 07:03:11 -040050)
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040051
Alex Gaynoraceb3e22015-09-05 12:00:22 -040052
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -040053def normalize_privatekey_pem(pem):
54 return dump_privatekey(FILETYPE_PEM, load_privatekey(FILETYPE_PEM, pem))
55
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040056
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050057GOOD_CIPHER = "blowfish"
58BAD_CIPHER = "zippers"
59
Anthony Alba2ce737f2015-12-04 11:04:56 +080060GOOD_DIGEST = "SHA1"
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050061BAD_DIGEST = "monkeys"
62
Alex Gaynore7f51982016-09-11 11:48:14 -040063root_cert_pem = b"""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -050064MIIC7TCCAlagAwIBAgIIPQzE4MbeufQwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE
65BhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdU
66ZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwIhgPMjAwOTAzMjUxMjM2
67NThaGA8yMDE3MDYxMTEyMzY1OFowWDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklM
68MRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9U
69ZXN0aW5nIFJvb3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPmaQumL
70urpE527uSEHdL1pqcDRmWzu+98Y6YHzT/J7KWEamyMCNZ6fRW1JCR782UQ8a07fy
712xXsKy4WdKaxyG8CcatwmXvpvRQ44dSANMihHELpANTdyVp6DCysED6wkQFurHlF
721dshEaJw8b/ypDhmbVIo6Ci1xvCJqivbLFnbAgMBAAGjgbswgbgwHQYDVR0OBBYE
73FINVdy1eIfFJDAkk51QJEo3IfgSuMIGIBgNVHSMEgYAwfoAUg1V3LV4h8UkMCSTn
74VAkSjch+BK6hXKRaMFgxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UE
75BxMHQ2hpY2FnbzEQMA4GA1UEChMHVGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBS
76b290IENBggg9DMTgxt659DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB
77AGGCDazMJGoWNBpc03u6+smc95dEead2KlZXBATOdFT1VesY3+nUOqZhEhTGlDMi
78hkgaZnzoIq/Uamidegk4hirsCT/R+6vsKAAxNTcBjUeZjlykCJWy5ojShGftXIKY
79w/njVbKMXrvc83qmTdGl3TAM0fxQIpqgcglFLveEBgzn
80-----END CERTIFICATE-----
Alex Gaynore7f51982016-09-11 11:48:14 -040081"""
Rick Dean94e46fd2009-07-18 14:51:24 -050082
Alex Gaynore7f51982016-09-11 11:48:14 -040083root_key_pem = b"""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -050084MIICXQIBAAKBgQD5mkLpi7q6ROdu7khB3S9aanA0Zls7vvfGOmB80/yeylhGpsjA
85jWen0VtSQke/NlEPGtO38tsV7CsuFnSmschvAnGrcJl76b0UOOHUgDTIoRxC6QDU
863claegwsrBA+sJEBbqx5RdXbIRGicPG/8qQ4Zm1SKOgotcbwiaor2yxZ2wIDAQAB
87AoGBAPCgMpmLxzwDaUmcFbTJUvlLW1hoxNNYSu2jIZm1k/hRAcE60JYwvBkgz3UB
88yMEh0AtLxYe0bFk6EHah11tMUPgscbCq73snJ++8koUw+csk22G65hOs51bVb7Aa
896JBe67oLzdtvgCUFAA2qfrKzWRZzAdhUirQUZgySZk+Xq1pBAkEA/kZG0A6roTSM
90BVnx7LnPfsycKUsTumorpXiylZJjTi9XtmzxhrYN6wgZlDOOwOLgSQhszGpxVoMD
91u3gByT1b2QJBAPtL3mSKdvwRu/+40zaZLwvSJRxaj0mcE4BJOS6Oqs/hS1xRlrNk
92PpQ7WJ4yM6ZOLnXzm2mKyxm50Mv64109FtMCQQDOqS2KkjHaLowTGVxwC0DijMfr
93I9Lf8sSQk32J5VWCySWf5gGTfEnpmUa41gKTMJIbqZZLucNuDcOtzUaeWZlZAkA8
94ttXigLnCqR486JDPTi9ZscoZkZ+w7y6e/hH8t6d5Vjt48JVyfjPIaJY+km58LcN3
956AWSeGAdtRFHVzR7oHjVAkB4hutvxiOeiIVQNBhM6RSI9aBPMI21DoX2JRoxvNW2
96cbvAhow217X9V0dVerEOKxnNYspXRrh36h7k4mQA+sDq
97-----END RSA PRIVATE KEY-----
Alex Gaynore7f51982016-09-11 11:48:14 -040098"""
Rick Dean94e46fd2009-07-18 14:51:24 -050099
Alex Gaynore7f51982016-09-11 11:48:14 -0400100intermediate_cert_pem = b"""-----BEGIN CERTIFICATE-----
Stephen Holsapple0d9815f2014-08-27 19:36:53 -0700101MIICVzCCAcCgAwIBAgIRAMPzhm6//0Y/g2pmnHR2C4cwDQYJKoZIhvcNAQENBQAw
102WDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAw
103DgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwHhcNMTQw
104ODI4MDIwNDA4WhcNMjQwODI1MDIwNDA4WjBmMRUwEwYDVQQDEwxpbnRlcm1lZGlh
105dGUxDDAKBgNVBAoTA29yZzERMA8GA1UECxMIb3JnLXVuaXQxCzAJBgNVBAYTAlVT
106MQswCQYDVQQIEwJDQTESMBAGA1UEBxMJU2FuIERpZWdvMIGfMA0GCSqGSIb3DQEB
107AQUAA4GNADCBiQKBgQDYcEQw5lfbEQRjr5Yy4yxAHGV0b9Al+Lmu7wLHMkZ/ZMmK
108FGIbljbviiD1Nz97Oh2cpB91YwOXOTN2vXHq26S+A5xe8z/QJbBsyghMur88CjdT
10921H2qwMa+r5dCQwEhuGIiZ3KbzB/n4DTMYI5zy4IYPv0pjxShZn4aZTCCK2IUwID
110AQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBDQUAA4GBAPIWSkLX
111QRMApOjjyC+tMxumT5e2pMqChHmxobQK4NMdrf2VCx+cRT6EmY8sK3/Xl/X8UBQ+
1129n5zXb1ZwhW/sTWgUvmOceJ4/XVs9FkdWOOn1J0XBch9ZIiFe/s5ASIgG7fUdcUF
1139mAWS6FK2ca3xIh5kIupCXOFa0dPvlw/YUFT
114-----END CERTIFICATE-----
Alex Gaynore7f51982016-09-11 11:48:14 -0400115"""
Stephen Holsapple0d9815f2014-08-27 19:36:53 -0700116
Alex Gaynore7f51982016-09-11 11:48:14 -0400117intermediate_key_pem = b"""-----BEGIN RSA PRIVATE KEY-----
Stephen Holsapple0d9815f2014-08-27 19:36:53 -0700118MIICWwIBAAKBgQDYcEQw5lfbEQRjr5Yy4yxAHGV0b9Al+Lmu7wLHMkZ/ZMmKFGIb
119ljbviiD1Nz97Oh2cpB91YwOXOTN2vXHq26S+A5xe8z/QJbBsyghMur88CjdT21H2
120qwMa+r5dCQwEhuGIiZ3KbzB/n4DTMYI5zy4IYPv0pjxShZn4aZTCCK2IUwIDAQAB
121AoGAfSZVV80pSeOKHTYfbGdNY/jHdU9eFUa/33YWriXU+77EhpIItJjkRRgivIfo
122rhFJpBSGmDLblaqepm8emsXMeH4+2QzOYIf0QGGP6E6scjTt1PLqdqKfVJ1a2REN
123147cujNcmFJb/5VQHHMpaPTgttEjlzuww4+BCDPsVRABWrkCQQD3loH36nLoQTtf
124+kQq0T6Bs9/UWkTAGo0ND81ALj0F8Ie1oeZg6RNT96RxZ3aVuFTESTv6/TbjWywO
125wdzlmV1vAkEA38rTJ6PTwaJlw5OttdDzAXGPB9tDmzh9oSi7cHwQQXizYd8MBYx4
126sjHUKD3dCQnb1dxJFhd3BT5HsnkRMbVZXQJAbXduH17ZTzcIOXc9jHDXYiFVZV5D
12752vV0WCbLzVCZc3jMrtSUKa8lPN5EWrdU3UchWybyG0MR5mX8S5lrF4SoQJAIyUD
128DBKaSqpqONCUUx1BTFS9FYrFjzbL4+c1qHCTTPTblt8kUCrDOZjBrKAqeiTmNSum
129/qUot9YUBF8m6BuGsQJATHHmdFy/fG1VLkyBp49CAa8tN3Z5r/CgTznI4DfMTf4C
130NbRHn2UmYlwQBa+L5lg9phewNe8aEwpPyPLoV85U8Q==
131-----END RSA PRIVATE KEY-----
Alex Gaynore7f51982016-09-11 11:48:14 -0400132"""
Stephen Holsapple0d9815f2014-08-27 19:36:53 -0700133
Alex Gaynore7f51982016-09-11 11:48:14 -0400134server_cert_pem = b"""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500135MIICKDCCAZGgAwIBAgIJAJn/HpR21r/8MA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
136BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
137VGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBSb290IENBMCIYDzIwMDkwMzI1MTIz
138NzUzWhgPMjAxNzA2MTExMjM3NTNaMBgxFjAUBgNVBAMTDWxvdmVseSBzZXJ2ZXIw
139gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAL6m+G653V0tpBC/OKl22VxOi2Cv
140lK4TYu9LHSDP9uDVTe7V5D5Tl6qzFoRRx5pfmnkqT5B+W9byp2NU3FC5hLm5zSAr
141b45meUhjEJ/ifkZgbNUjHdBIGP9MAQUHZa5WKdkGIJvGAvs8UzUqlr4TBWQIB24+
142lJ+Ukk/CRgasrYwdAgMBAAGjNjA0MB0GA1UdDgQWBBS4kC7Ij0W1TZXZqXQFAM2e
143gKEG2DATBgNVHSUEDDAKBggrBgEFBQcDATANBgkqhkiG9w0BAQUFAAOBgQBh30Li
144dJ+NlxIOx5343WqIBka3UbsOb2kxWrbkVCrvRapCMLCASO4FqiKWM+L0VDBprqIp
1452mgpFQ6FHpoIENGvJhdEKpptQ5i7KaGhnDNTfdy3x1+h852G99f1iyj0RmbuFcM8
146uzujnS8YXWvM7DM1Ilozk4MzPug8jzFp5uhKCQ==
147-----END CERTIFICATE-----
Alex Gaynore7f51982016-09-11 11:48:14 -0400148"""
Rick Dean94e46fd2009-07-18 14:51:24 -0500149
Alex Gaynore7f51982016-09-11 11:48:14 -0400150server_key_pem = normalize_privatekey_pem(b"""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500151MIICWwIBAAKBgQC+pvhuud1dLaQQvzipdtlcTotgr5SuE2LvSx0gz/bg1U3u1eQ+
152U5eqsxaEUceaX5p5Kk+QflvW8qdjVNxQuYS5uc0gK2+OZnlIYxCf4n5GYGzVIx3Q
153SBj/TAEFB2WuVinZBiCbxgL7PFM1Kpa+EwVkCAduPpSflJJPwkYGrK2MHQIDAQAB
154AoGAbwuZ0AR6JveahBaczjfnSpiFHf+mve2UxoQdpyr6ROJ4zg/PLW5K/KXrC48G
155j6f3tXMrfKHcpEoZrQWUfYBRCUsGD5DCazEhD8zlxEHahIsqpwA0WWssJA2VOLEN
156j6DuV2pCFbw67rfTBkTSo32ahfXxEKev5KswZk0JIzH3ooECQQDgzS9AI89h0gs8
157Dt+1m11Rzqo3vZML7ZIyGApUzVan+a7hbc33nbGRkAXjHaUBJO31it/H6dTO+uwX
158msWwNG5ZAkEA2RyFKs5xR5USTFaKLWCgpH/ydV96KPOpBND7TKQx62snDenFNNbn
159FwwOhpahld+vqhYk+pfuWWUpQciE+Bu7ZQJASjfT4sQv4qbbKK/scePicnDdx9th
1604e1EeB9xwb+tXXXUo/6Bor/AcUNwfiQ6Zt9PZOK9sR3lMZSsP7rMi7kzuQJABie6
1611sXXjFH7nNJvRG4S39cIxq8YRYTy68II/dlB2QzGpKxV/POCxbJ/zu0CU79tuYK7
162NaeNCFfH3aeTrX0LyQJAMBWjWmeKM2G2sCExheeQK0ROnaBC8itCECD4Jsve4nqf
163r50+LF74iLXFwqysVCebPKMOpDWp/qQ1BbJQIPs7/A==
164-----END RSA PRIVATE KEY-----
Alex Gaynore7f51982016-09-11 11:48:14 -0400165""")
Rick Dean94e46fd2009-07-18 14:51:24 -0500166
Alex Gaynore7f51982016-09-11 11:48:14 -0400167intermediate_server_cert_pem = b"""-----BEGIN CERTIFICATE-----
Stephen Holsapple0d9815f2014-08-27 19:36:53 -0700168MIICWDCCAcGgAwIBAgIRAPQFY9jfskSihdiNSNdt6GswDQYJKoZIhvcNAQENBQAw
169ZjEVMBMGA1UEAxMMaW50ZXJtZWRpYXRlMQwwCgYDVQQKEwNvcmcxETAPBgNVBAsT
170CG9yZy11bml0MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVNh
171biBEaWVnbzAeFw0xNDA4MjgwMjEwNDhaFw0yNDA4MjUwMjEwNDhaMG4xHTAbBgNV
172BAMTFGludGVybWVkaWF0ZS1zZXJ2aWNlMQwwCgYDVQQKEwNvcmcxETAPBgNVBAsT
173CG9yZy11bml0MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVNh
174biBEaWVnbzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqpJZygd+w1faLOr1
175iOAmbBhx5SZWcTCZ/ZjHQTJM7GuPT624QkqsixFghRKdDROwpwnAP7gMRukLqiy4
176+kRuGT5OfyGggL95i2xqA+zehjj08lSTlvGHpePJgCyTavIy5+Ljsj4DKnKyuhxm
177biXTRrH83NDgixVkObTEmh/OVK0CAwEAATANBgkqhkiG9w0BAQ0FAAOBgQBa0Npw
178UkzjaYEo1OUE1sTI6Mm4riTIHMak4/nswKh9hYup//WVOlr/RBSBtZ7Q/BwbjobN
1793bfAtV7eSAqBsfxYXyof7G1ALANQERkq3+oyLP1iVt08W1WOUlIMPhdCF/QuCwy6
180x9MJLhUCGLJPM+O2rAPWVD9wCmvq10ALsiH3yA==
181-----END CERTIFICATE-----
Alex Gaynore7f51982016-09-11 11:48:14 -0400182"""
Stephen Holsapple0d9815f2014-08-27 19:36:53 -0700183
Alex Gaynore7f51982016-09-11 11:48:14 -0400184intermediate_server_key_pem = b"""-----BEGIN RSA PRIVATE KEY-----
Stephen Holsapple0d9815f2014-08-27 19:36:53 -0700185MIICXAIBAAKBgQCqklnKB37DV9os6vWI4CZsGHHlJlZxMJn9mMdBMkzsa49PrbhC
186SqyLEWCFEp0NE7CnCcA/uAxG6QuqLLj6RG4ZPk5/IaCAv3mLbGoD7N6GOPTyVJOW
1878Yel48mALJNq8jLn4uOyPgMqcrK6HGZuJdNGsfzc0OCLFWQ5tMSaH85UrQIDAQAB
188AoGAIQ594j5zna3/9WaPsTgnmhlesVctt4AAx/n827DA4ayyuHFlXUuVhtoWR5Pk
1895ezj9mtYW8DyeCegABnsu2vZni/CdvU6uiS1Hv6qM1GyYDm9KWgovIP9rQCDSGaz
190d57IWVGxx7ODFkm3gN5nxnSBOFVHytuW1J7FBRnEsehRroECQQDXHFOv82JuXDcz
191z3+4c74IEURdOHcbycxlppmK9kFqm5lsUdydnnGW+mvwDk0APOB7Wg7vyFyr393e
192dpmBDCzNAkEAyv6tVbTKUYhSjW+QhabJo896/EqQEYUmtMXxk4cQnKeR/Ao84Rkf
193EqD5IykMUfUI0jJU4DGX+gWZ10a7kNbHYQJAVFCuHNFxS4Cpwo0aqtnzKoZaHY/8
194X9ABZfafSHCtw3Op92M+7ikkrOELXdS9KdKyyqbKJAKNEHF3LbOfB44WIQJAA2N4
1959UNNVUsXRbElEnYUS529CdUczo4QdVgQjkvk5RiPAUwSdBd9Q0xYnFOlFwEmIowg
196ipWJWe0aAlP18ZcEQQJBAL+5lekZ/GUdQoZ4HAsN5a9syrzavJ9VvU1KOOPorPZK
197nMRZbbQgP+aSB7yl6K0gaLaZ8XaK0pjxNBh6ASqg9f4=
198-----END RSA PRIVATE KEY-----
Alex Gaynore7f51982016-09-11 11:48:14 -0400199"""
Stephen Holsapple0d9815f2014-08-27 19:36:53 -0700200
Alex Gaynore7f51982016-09-11 11:48:14 -0400201client_cert_pem = b"""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500202MIICJjCCAY+gAwIBAgIJAKxpFI5lODkjMA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
203BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
204VGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBSb290IENBMCIYDzIwMDkwMzI1MTIz
205ODA1WhgPMjAxNzA2MTExMjM4MDVaMBYxFDASBgNVBAMTC3VnbHkgY2xpZW50MIGf
206MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDAZh/SRtNm5ntMT4qb6YzEpTroMlq2
207rn+GrRHRiZ+xkCw/CGNhbtPir7/QxaUj26BSmQrHw1bGKEbPsWiW7bdXSespl+xK
208iku4G/KvnnmWdeJHqsiXeUZtqurMELcPQAw9xPHEuhqqUJvvEoMTsnCEqGM+7Dtb
209oCRajYyHfluARQIDAQABozYwNDAdBgNVHQ4EFgQUNQB+qkaOaEVecf1J3TTUtAff
2100fAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQEFBQADgYEAyv/Jh7gM
211Q3OHvmsFEEvRI+hsW8y66zK4K5de239Y44iZrFYkt7Q5nBPMEWDj4F2hLYWL/qtI
2129Zdr0U4UDCU9SmmGYh4o7R4TZ5pGFvBYvjhHbkSFYFQXZxKUi+WUxplP6I0wr2KJ
213PSTJCjJOn3xo2NTKRgV1gaoTf2EhL+RG8TQ=
214-----END CERTIFICATE-----
Alex Gaynore7f51982016-09-11 11:48:14 -0400215"""
Rick Dean94e46fd2009-07-18 14:51:24 -0500216
Alex Gaynore7f51982016-09-11 11:48:14 -0400217client_key_pem = normalize_privatekey_pem(b"""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500218MIICXgIBAAKBgQDAZh/SRtNm5ntMT4qb6YzEpTroMlq2rn+GrRHRiZ+xkCw/CGNh
219btPir7/QxaUj26BSmQrHw1bGKEbPsWiW7bdXSespl+xKiku4G/KvnnmWdeJHqsiX
220eUZtqurMELcPQAw9xPHEuhqqUJvvEoMTsnCEqGM+7DtboCRajYyHfluARQIDAQAB
221AoGATkZ+NceY5Glqyl4mD06SdcKfV65814vg2EL7V9t8+/mi9rYL8KztSXGlQWPX
222zuHgtRoMl78yQ4ZJYOBVo+nsx8KZNRCEBlE19bamSbQLCeQMenWnpeYyQUZ908gF
223h6L9qsFVJepgA9RDgAjyDoS5CaWCdCCPCH2lDkdcqC54SVUCQQDseuduc4wi8h4t
224V8AahUn9fn9gYfhoNuM0gdguTA0nPLVWz4hy1yJiWYQe0H7NLNNTmCKiLQaJpAbb
225TC6vE8C7AkEA0Ee8CMJUc20BnGEmxwgWcVuqFWaKCo8jTH1X38FlATUsyR3krjW2
226dL3yDD9NwHxsYP7nTKp/U8MV7U9IBn4y/wJBAJl7H0/BcLeRmuJk7IqJ7b635iYB
227D/9beFUw3MUXmQXZUfyYz39xf6CDZsu1GEdEC5haykeln3Of4M9d/4Kj+FcCQQCY
228si6xwT7GzMDkk/ko684AV3KPc/h6G0yGtFIrMg7J3uExpR/VdH2KgwMkZXisSMvw
229JJEQjOMCVsEJlRk54WWjAkEAzoZNH6UhDdBK5F38rVt/y4SEHgbSfJHIAmPS32Kq
230f6GGcfNpip0Uk7q7udTKuX7Q/buZi/C4YW7u3VKAquv9NA==
231-----END RSA PRIVATE KEY-----
Alex Gaynore7f51982016-09-11 11:48:14 -0400232""")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400233
Alex Gaynore7f51982016-09-11 11:48:14 -0400234cleartextCertificatePEM = b"""-----BEGIN CERTIFICATE-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400235MIIC7TCCAlagAwIBAgIIPQzE4MbeufQwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE
236BhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdU
237ZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwIhgPMjAwOTAzMjUxMjM2
238NThaGA8yMDE3MDYxMTEyMzY1OFowWDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklM
239MRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9U
240ZXN0aW5nIFJvb3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPmaQumL
241urpE527uSEHdL1pqcDRmWzu+98Y6YHzT/J7KWEamyMCNZ6fRW1JCR782UQ8a07fy
2422xXsKy4WdKaxyG8CcatwmXvpvRQ44dSANMihHELpANTdyVp6DCysED6wkQFurHlF
2431dshEaJw8b/ypDhmbVIo6Ci1xvCJqivbLFnbAgMBAAGjgbswgbgwHQYDVR0OBBYE
244FINVdy1eIfFJDAkk51QJEo3IfgSuMIGIBgNVHSMEgYAwfoAUg1V3LV4h8UkMCSTn
245VAkSjch+BK6hXKRaMFgxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UE
246BxMHQ2hpY2FnbzEQMA4GA1UEChMHVGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBS
247b290IENBggg9DMTgxt659DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB
248AGGCDazMJGoWNBpc03u6+smc95dEead2KlZXBATOdFT1VesY3+nUOqZhEhTGlDMi
249hkgaZnzoIq/Uamidegk4hirsCT/R+6vsKAAxNTcBjUeZjlykCJWy5ojShGftXIKY
250w/njVbKMXrvc83qmTdGl3TAM0fxQIpqgcglFLveEBgzn
251-----END CERTIFICATE-----
Alex Gaynore7f51982016-09-11 11:48:14 -0400252"""
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400253
Alex Gaynore7f51982016-09-11 11:48:14 -0400254cleartextPrivateKeyPEM = normalize_privatekey_pem(b"""\
Jean-Paul Calderoned50d2042011-05-04 17:00:49 -0400255-----BEGIN RSA PRIVATE KEY-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400256MIICXQIBAAKBgQD5mkLpi7q6ROdu7khB3S9aanA0Zls7vvfGOmB80/yeylhGpsjA
257jWen0VtSQke/NlEPGtO38tsV7CsuFnSmschvAnGrcJl76b0UOOHUgDTIoRxC6QDU
2583claegwsrBA+sJEBbqx5RdXbIRGicPG/8qQ4Zm1SKOgotcbwiaor2yxZ2wIDAQAB
259AoGBAPCgMpmLxzwDaUmcFbTJUvlLW1hoxNNYSu2jIZm1k/hRAcE60JYwvBkgz3UB
260yMEh0AtLxYe0bFk6EHah11tMUPgscbCq73snJ++8koUw+csk22G65hOs51bVb7Aa
2616JBe67oLzdtvgCUFAA2qfrKzWRZzAdhUirQUZgySZk+Xq1pBAkEA/kZG0A6roTSM
262BVnx7LnPfsycKUsTumorpXiylZJjTi9XtmzxhrYN6wgZlDOOwOLgSQhszGpxVoMD
263u3gByT1b2QJBAPtL3mSKdvwRu/+40zaZLwvSJRxaj0mcE4BJOS6Oqs/hS1xRlrNk
264PpQ7WJ4yM6ZOLnXzm2mKyxm50Mv64109FtMCQQDOqS2KkjHaLowTGVxwC0DijMfr
265I9Lf8sSQk32J5VWCySWf5gGTfEnpmUa41gKTMJIbqZZLucNuDcOtzUaeWZlZAkA8
266ttXigLnCqR486JDPTi9ZscoZkZ+w7y6e/hH8t6d5Vjt48JVyfjPIaJY+km58LcN3
2676AWSeGAdtRFHVzR7oHjVAkB4hutvxiOeiIVQNBhM6RSI9aBPMI21DoX2JRoxvNW2
268cbvAhow217X9V0dVerEOKxnNYspXRrh36h7k4mQA+sDq
269-----END RSA PRIVATE KEY-----
Alex Gaynore7f51982016-09-11 11:48:14 -0400270""")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400271
Alex Gaynore7f51982016-09-11 11:48:14 -0400272cleartextCertificateRequestPEM = b"""-----BEGIN CERTIFICATE REQUEST-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400273MIIBnjCCAQcCAQAwXjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQH
274EwdDaGljYWdvMRcwFQYDVQQKEw5NeSBDb21wYW55IEx0ZDEXMBUGA1UEAxMORnJl
275ZGVyaWNrIERlYW4wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANp6Y17WzKSw
276BsUWkXdqg6tnXy8H8hA1msCMWpc+/2KJ4mbv5NyD6UD+/SqagQqulPbF/DFea9nA
277E0zhmHJELcM8gUTIlXv/cgDWnmK4xj8YkjVUiCdqKRAKeuzLG1pGmwwF5lGeJpXN
278xQn5ecR0UYSOWj6TTGXB9VyUMQzCClcBAgMBAAGgADANBgkqhkiG9w0BAQUFAAOB
279gQAAJGuF/R/GGbeC7FbFW+aJgr9ee0Xbl6nlhu7pTe67k+iiKT2dsl2ti68MVTnu
280Vrb3HUNqOkiwsJf6kCtq5oPn3QVYzTa76Dt2y3Rtzv6boRSlmlfrgS92GNma8JfR
281oICQk3nAudi6zl1Dix3BCv1pUp5KMtGn3MeDEi6QFGy2rA==
282-----END CERTIFICATE REQUEST-----
Alex Gaynore7f51982016-09-11 11:48:14 -0400283"""
Rick Dean5b7b6372009-04-01 11:34:06 -0500284
Alex Gaynore7f51982016-09-11 11:48:14 -0400285encryptedPrivateKeyPEM = b"""-----BEGIN RSA PRIVATE KEY-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400286Proc-Type: 4,ENCRYPTED
287DEK-Info: DES-EDE3-CBC,9573604A18579E9E
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400288
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400289SHOho56WxDkT0ht10UTeKc0F5u8cqIa01kzFAmETw0MAs8ezYtK15NPdCXUm3X/2
290a17G7LSF5bkxOgZ7vpXyMzun/owrj7CzvLxyncyEFZWvtvzaAhPhvTJtTIB3kf8B
2918+qRcpTGK7NgXEgYBW5bj1y4qZkD4zCL9o9NQzsKI3Ie8i0239jsDOWR38AxjXBH
292mGwAQ4Z6ZN5dnmM4fhMIWsmFf19sNyAML4gHenQCHhmXbjXeVq47aC2ProInJbrm
293+00TcisbAQ40V9aehVbcDKtS4ZbMVDwncAjpXpcncC54G76N6j7F7wL7L/FuXa3A
294fvSVy9n2VfF/pJ3kYSflLHH2G/DFxjF7dl0GxhKPxJjp3IJi9VtuvmN9R2jZWLQF
295tfC8dXgy/P9CfFQhlinqBTEwgH0oZ/d4k4NVFDSdEMaSdmBAjlHpc+Vfdty3HVnV
296rKXj//wslsFNm9kIwJGIgKUa/n2jsOiydrsk1mgH7SmNCb3YHgZhbbnq0qLat/HC
297gHDt3FHpNQ31QzzL3yrenFB2L9osIsnRsDTPFNi4RX4SpDgNroxOQmyzCCV6H+d4
298o1mcnNiZSdxLZxVKccq0AfRpHqpPAFnJcQHP6xyT9MZp6fBa0XkxDnt9kNU8H3Qw
2997SJWZ69VXjBUzMlQViLuaWMgTnL+ZVyFZf9hTF7U/ef4HMLMAVNdiaGG+G+AjCV/
300MbzjS007Oe4qqBnCWaFPSnJX6uLApeTbqAxAeyCql56ULW5x6vDMNC3dwjvS/CEh
30111n8RkgFIQA0AhuKSIg3CbuartRsJnWOLwgLTzsrKYL4yRog1RJrtw==
302-----END RSA PRIVATE KEY-----
Alex Gaynore7f51982016-09-11 11:48:14 -0400303"""
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400304
Alex Gaynore7f51982016-09-11 11:48:14 -0400305encryptedPrivateKeyPEMPassphrase = b"foobar"
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400306
Cory Benfield6492f7c2015-10-27 16:57:58 +0900307
Alex Gaynore7f51982016-09-11 11:48:14 -0400308cleartextPublicKeyPEM = b"""-----BEGIN PUBLIC KEY-----
Cory Benfield6492f7c2015-10-27 16:57:58 +0900309MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxszlc+b71LvlLS0ypt/l
310gT/JzSVJtnEqw9WUNGeiChywX2mmQLHEt7KP0JikqUFZOtPclNY823Q4pErMTSWC
31190qlUxI47vNJbXGRfmO2q6Zfw6SE+E9iUb74xezbOJLjBuUIkQzEKEFV+8taiRV+
312ceg1v01yCT2+OjhQW3cxG42zxyRFmqesbQAUWgS3uhPrUQqYQUEiTmVhh4FBUKZ5
313XIneGUpX1S7mXRxTLH6YzRoGFqRoc9A0BBNcoXHTWnxV215k4TeHMFYE5RG0KYAS
3148Xk5iKICEXwnZreIt3jyygqoOKsKZMK/Zl2VhMGhJR6HXRpQCyASzEG7bgtROLhL
315ywIDAQAB
316-----END PUBLIC KEY-----
Alex Gaynore7f51982016-09-11 11:48:14 -0400317"""
Cory Benfield6492f7c2015-10-27 16:57:58 +0900318
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400319# Some PKCS#7 stuff. Generated with the openssl command line:
320#
321# openssl crl2pkcs7 -inform pem -outform pem -certfile s.pem -nocrl
322#
323# with a certificate and key (but the key should be irrelevant) in s.pem
Alex Gaynore7f51982016-09-11 11:48:14 -0400324pkcs7Data = b"""\
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400325-----BEGIN PKCS7-----
326MIIDNwYJKoZIhvcNAQcCoIIDKDCCAyQCAQExADALBgkqhkiG9w0BBwGgggMKMIID
327BjCCAm+gAwIBAgIBATANBgkqhkiG9w0BAQQFADB7MQswCQYDVQQGEwJTRzERMA8G
328A1UEChMITTJDcnlwdG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtN
329MkNyeXB0byBDZXJ0aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNA
330cG9zdDEuY29tMB4XDTAwMDkxMDA5NTEzMFoXDTAyMDkxMDA5NTEzMFowUzELMAkG
331A1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwlsb2NhbGhvc3Qx
332HTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tMFwwDQYJKoZIhvcNAQEBBQAD
333SwAwSAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh5kwI
334zOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEAAaOCAQQwggEAMAkGA1UdEwQCMAAw
335LAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0G
336A1UdDgQWBBTPhIKSvnsmYsBVNWjj0m3M2z0qVTCBpQYDVR0jBIGdMIGagBT7hyNp
33765w6kxXlxb8pUU/+7Sg4AaF/pH0wezELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0y
338Q3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlwdG8g
339Q2VydGlmaWNhdGUgTWFzdGVyMR0wGwYJKoZIhvcNAQkBFg5uZ3BzQHBvc3QxLmNv
340bYIBADANBgkqhkiG9w0BAQQFAAOBgQA7/CqT6PoHycTdhEStWNZde7M/2Yc6BoJu
341VwnW8YxGO8Sn6UJ4FeffZNcYZddSDKosw8LtPOeWoK3JINjAk5jiPQ2cww++7QGG
342/g5NDjxFZNDJP1dGiLAxPW6JXwov4v0FmdzfLOZ01jDcgQQZqEpYlgpuI5JEWUQ9
343Ho4EzbYCOaEAMQA=
344-----END PKCS7-----
Alex Gaynore7f51982016-09-11 11:48:14 -0400345"""
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400346
Alex Gaynor8fa1dd62014-08-14 09:57:51 -0700347pkcs7DataASN1 = base64.b64decode(b"""
Alex Gaynor4b9c96a2014-08-14 09:51:48 -0700348MIIDNwYJKoZIhvcNAQcCoIIDKDCCAyQCAQExADALBgkqhkiG9w0BBwGgggMKMIID
349BjCCAm+gAwIBAgIBATANBgkqhkiG9w0BAQQFADB7MQswCQYDVQQGEwJTRzERMA8G
350A1UEChMITTJDcnlwdG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtN
351MkNyeXB0byBDZXJ0aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNA
352cG9zdDEuY29tMB4XDTAwMDkxMDA5NTEzMFoXDTAyMDkxMDA5NTEzMFowUzELMAkG
353A1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwlsb2NhbGhvc3Qx
354HTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tMFwwDQYJKoZIhvcNAQEBBQAD
355SwAwSAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh5kwI
356zOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEAAaOCAQQwggEAMAkGA1UdEwQCMAAw
357LAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0G
358A1UdDgQWBBTPhIKSvnsmYsBVNWjj0m3M2z0qVTCBpQYDVR0jBIGdMIGagBT7hyNp
35965w6kxXlxb8pUU/+7Sg4AaF/pH0wezELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0y
360Q3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlwdG8g
361Q2VydGlmaWNhdGUgTWFzdGVyMR0wGwYJKoZIhvcNAQkBFg5uZ3BzQHBvc3QxLmNv
362bYIBADANBgkqhkiG9w0BAQQFAAOBgQA7/CqT6PoHycTdhEStWNZde7M/2Yc6BoJu
363VwnW8YxGO8Sn6UJ4FeffZNcYZddSDKosw8LtPOeWoK3JINjAk5jiPQ2cww++7QGG
364/g5NDjxFZNDJP1dGiLAxPW6JXwov4v0FmdzfLOZ01jDcgQQZqEpYlgpuI5JEWUQ9
365Ho4EzbYCOaEAMQA=
Alex Gaynor8fa1dd62014-08-14 09:57:51 -0700366""")
Alex Gaynor4b9c96a2014-08-14 09:51:48 -0700367
Alex Gaynore7f51982016-09-11 11:48:14 -0400368crlData = b"""\
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -0500369-----BEGIN X509 CRL-----
370MIIBWzCBxTANBgkqhkiG9w0BAQQFADBYMQswCQYDVQQGEwJVUzELMAkGA1UECBMC
371SUwxEDAOBgNVBAcTB0NoaWNhZ28xEDAOBgNVBAoTB1Rlc3RpbmcxGDAWBgNVBAMT
372D1Rlc3RpbmcgUm9vdCBDQRcNMDkwNzI2MDQzNDU2WhcNMTIwOTI3MDI0MTUyWjA8
373MBUCAgOrGA8yMDA5MDcyNTIzMzQ1NlowIwICAQAYDzIwMDkwNzI1MjMzNDU2WjAM
374MAoGA1UdFQQDCgEEMA0GCSqGSIb3DQEBBAUAA4GBAEBt7xTs2htdD3d4ErrcGAw1
3754dKcVnIWTutoI7xxen26Wwvh8VCsT7i/UeP+rBl9rC/kfjWjzQk3/zleaarGTpBT
3760yp4HXRFFoRhhSE/hP+eteaPXRgrsNRLHe9ZDd69wmh7J1wMDb0m81RG7kqcbsid
377vrzEeLDRiiPl92dyyWmu
378-----END X509 CRL-----
Alex Gaynore7f51982016-09-11 11:48:14 -0400379"""
Jean-Paul Calderonee890db32010-08-22 16:55:15 -0400380
Alex Gaynore7f51982016-09-11 11:48:14 -0400381crlDataUnsupportedExtension = b"""\
Paul Kehrer5e3dd4c2016-03-11 09:58:28 -0400382-----BEGIN X509 CRL-----
383MIIGRzCCBS8CAQIwDQYJKoZIhvcNAQELBQAwJzELMAkGA1UEBhMCVVMxGDAWBgNV
384BAMMD2NyeXB0b2dyYXBoeS5pbxgPMjAxNTAxMDEwMDAwMDBaGA8yMDE2MDEwMTAw
385MDAwMFowggTOMBQCAQAYDzIwMTUwMTAxMDAwMDAwWjByAgEBGA8yMDE1MDEwMTAw
386MDAwMFowXDAYBgNVHRgEERgPMjAxNTAxMDEwMDAwMDBaMDQGA1UdHQQtMCukKTAn
387MQswCQYDVQQGEwJVUzEYMBYGA1UEAwwPY3J5cHRvZ3JhcGh5LmlvMAoGA1UdFQQD
388CgEAMHICAQIYDzIwMTUwMTAxMDAwMDAwWjBcMBgGA1UdGAQRGA8yMDE1MDEwMTAw
389MDAwMFowNAYDVR0dBC0wK6QpMCcxCzAJBgNVBAYTAlVTMRgwFgYDVQQDDA9jcnlw
390dG9ncmFwaHkuaW8wCgYDVR0VBAMKAQEwcgIBAxgPMjAxNTAxMDEwMDAwMDBaMFww
391GAYDVR0YBBEYDzIwMTUwMTAxMDAwMDAwWjA0BgNVHR0ELTArpCkwJzELMAkGA1UE
392BhMCVVMxGDAWBgNVBAMMD2NyeXB0b2dyYXBoeS5pbzAKBgNVHRUEAwoBAjByAgEE
393GA8yMDE1MDEwMTAwMDAwMFowXDAYBgNVHRgEERgPMjAxNTAxMDEwMDAwMDBaMDQG
394A1UdHQQtMCukKTAnMQswCQYDVQQGEwJVUzEYMBYGA1UEAwwPY3J5cHRvZ3JhcGh5
395LmlvMAoGA1UdFQQDCgEDMHICAQUYDzIwMTUwMTAxMDAwMDAwWjBcMBgGA1UdGAQR
396GA8yMDE1MDEwMTAwMDAwMFowNAYDVR0dBC0wK6QpMCcxCzAJBgNVBAYTAlVTMRgw
397FgYDVQQDDA9jcnlwdG9ncmFwaHkuaW8wCgYDVR0VBAMKAQQwcgIBBhgPMjAxNTAx
398MDEwMDAwMDBaMFwwGAYDVR0YBBEYDzIwMTUwMTAxMDAwMDAwWjA0BgNVHR0ELTAr
399pCkwJzELMAkGA1UEBhMCVVMxGDAWBgNVBAMMD2NyeXB0b2dyYXBoeS5pbzAKBgNV
400HRUEAwoBBTByAgEHGA8yMDE1MDEwMTAwMDAwMFowXDAYBgNVHRgEERgPMjAxNTAx
401MDEwMDAwMDBaMDQGA1UdHQQtMCukKTAnMQswCQYDVQQGEwJVUzEYMBYGA1UEAwwP
402Y3J5cHRvZ3JhcGh5LmlvMAoGA1UdFQQDCgEGMHICAQgYDzIwMTUwMTAxMDAwMDAw
403WjBcMBgGA1UdGAQRGA8yMDE1MDEwMTAwMDAwMFowNAYDVR0dBC0wK6QpMCcxCzAJ
404BgNVBAYTAlVTMRgwFgYDVQQDDA9jcnlwdG9ncmFwaHkuaW8wCgYDVR0VBAMKAQgw
405cgIBCRgPMjAxNTAxMDEwMDAwMDBaMFwwGAYDVR0YBBEYDzIwMTUwMTAxMDAwMDAw
406WjA0BgNVHR0ELTArpCkwJzELMAkGA1UEBhMCVVMxGDAWBgNVBAMMD2NyeXB0b2dy
407YXBoeS5pbzAKBgNVHRUEAwoBCTByAgEKGA8yMDE1MDEwMTAwMDAwMFowXDAYBgNV
408HRgEERgPMjAxNTAxMDEwMDAwMDBaMDQGA1UdHQQtMCukKTAnMQswCQYDVQQGEwJV
409UzEYMBYGA1UEAwwPY3J5cHRvZ3JhcGh5LmlvMAoGA1UdFQQDCgEKMC4CAQsYDzIw
410MTUwMTAxMDAwMDAwWjAYMAoGA1UdFQQDCgEBMAoGAyoDBAQDCgEAMA0GCSqGSIb3
411DQEBCwUAA4IBAQBTaloHlPaCZzYee8LxkWej5meiqxQVNWFoVdjesroa+f1FRrH+
412drRU60Nq97KCKf7f9GNN/J3ZIlQmYhmuDqh12f+XLpotoj1ZRfBz2hjFCkJlv+2c
413oWWGNHgA70ndFoVtcmX088SYpX8E3ARATivS4q2h9WlwV6rO93mhg3HGIe3JpcK4
4147BcW6Poi/ut/zsDOkVbI00SqaujRpdmdCTht82MH3ztjyDkI9KYaD/YEweKSrWOz
415SdEILd164bfBeLuplVI+xpmTEMVNpXBlSXl7+xIw9Vk7p7Q1Pa3k/SvhOldYCm6y
416C1xAg/AAq6w78yzYt18j5Mj0s6eeHi1YpHKw
417-----END X509 CRL-----
Alex Gaynore7f51982016-09-11 11:48:14 -0400418"""
Paul Kehrer5e3dd4c2016-03-11 09:58:28 -0400419
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400420
421# A broken RSA private key which can be used to test the error path through
422# PKey.check.
Alex Gaynore7f51982016-09-11 11:48:14 -0400423inconsistentPrivateKeyPEM = b"""-----BEGIN RSA PRIVATE KEY-----
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400424MIIBPAIBAAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh
4255kwIzOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEaAQJBAIqm/bz4NA1H++Vx5Ewx
426OcKp3w19QSaZAwlGRtsUxrP7436QjnREM3Bm8ygU11BjkPVmtrKm6AayQfCHqJoT
427zIECIQDW0BoMoL0HOYM/mrTLhaykYAVqgIeJsPjvkEhTFXWBuQIhAM3deFAvWNu4
428nklUQ37XsCT2c9tmNt1LAT+slG2JOTTRAiAuXDtC/m3NYVwyHfFm+zKHRzHkClk2
429HjubeEgjpj32AQIhAJqMGTaZVOwevTXvvHwNeH+vRWsAYU/gbx+OQB+7VOcBAiEA
430oolb6NMg/R3enNPvS1O4UU1H8wpaF77L4yiSWlE0p4w=
431-----END RSA PRIVATE KEY-----
Alex Gaynore7f51982016-09-11 11:48:14 -0400432"""
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400433
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -0400434# certificate with NULL bytes in subjectAltName and common name
435
Alex Gaynore7f51982016-09-11 11:48:14 -0400436nulbyteSubjectAltNamePEM = b"""-----BEGIN CERTIFICATE-----
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -0400437MIIE2DCCA8CgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBxTELMAkGA1UEBhMCVVMx
438DzANBgNVBAgMBk9yZWdvbjESMBAGA1UEBwwJQmVhdmVydG9uMSMwIQYDVQQKDBpQ
439eXRob24gU29mdHdhcmUgRm91bmRhdGlvbjEgMB4GA1UECwwXUHl0aG9uIENvcmUg
440RGV2ZWxvcG1lbnQxJDAiBgNVBAMMG251bGwucHl0aG9uLm9yZwBleGFtcGxlLm9y
441ZzEkMCIGCSqGSIb3DQEJARYVcHl0aG9uLWRldkBweXRob24ub3JnMB4XDTEzMDgw
442NzEzMTE1MloXDTEzMDgwNzEzMTI1MlowgcUxCzAJBgNVBAYTAlVTMQ8wDQYDVQQI
443DAZPcmVnb24xEjAQBgNVBAcMCUJlYXZlcnRvbjEjMCEGA1UECgwaUHl0aG9uIFNv
444ZnR3YXJlIEZvdW5kYXRpb24xIDAeBgNVBAsMF1B5dGhvbiBDb3JlIERldmVsb3Bt
445ZW50MSQwIgYDVQQDDBtudWxsLnB5dGhvbi5vcmcAZXhhbXBsZS5vcmcxJDAiBgkq
446hkiG9w0BCQEWFXB5dGhvbi1kZXZAcHl0aG9uLm9yZzCCASIwDQYJKoZIhvcNAQEB
447BQADggEPADCCAQoCggEBALXq7cn7Rn1vO3aA3TrzA5QLp6bb7B3f/yN0CJ2XFj+j
448pHs+Gw6WWSUDpybiiKnPec33BFawq3kyblnBMjBU61ioy5HwQqVkJ8vUVjGIUq3P
449vX/wBmQfzCe4o4uM89gpHyUL9UYGG8oCRa17dgqcv7u5rg0Wq2B1rgY+nHwx3JIv
450KRrgSwyRkGzpN8WQ1yrXlxWjgI9de0mPVDDUlywcWze1q2kwaEPTM3hLAmD1PESA
451oY/n8A/RXoeeRs9i/Pm/DGUS8ZPINXk/yOzsR/XvvkTVroIeLZqfmFpnZeF0cHzL
45208LODkVJJ9zjLdT7SA4vnne4FEbAxDbKAq5qkYzaL4UCAwEAAaOB0DCBzTAMBgNV
453HRMBAf8EAjAAMB0GA1UdDgQWBBSIWlXAUv9hzVKjNQ/qWpwkOCL3XDALBgNVHQ8E
454BAMCBeAwgZAGA1UdEQSBiDCBhYIeYWx0bnVsbC5weXRob24ub3JnAGV4YW1wbGUu
455Y29tgSBudWxsQHB5dGhvbi5vcmcAdXNlckBleGFtcGxlLm9yZ4YpaHR0cDovL251
456bGwucHl0aG9uLm9yZwBodHRwOi8vZXhhbXBsZS5vcmeHBMAAAgGHECABDbgAAAAA
457AAAAAAAAAAEwDQYJKoZIhvcNAQEFBQADggEBAKxPRe99SaghcI6IWT7UNkJw9aO9
458i9eo0Fj2MUqxpKbdb9noRDy2CnHWf7EIYZ1gznXPdwzSN4YCjV5d+Q9xtBaowT0j
459HPERs1ZuytCNNJTmhyqZ8q6uzMLoht4IqH/FBfpvgaeC5tBTnTT0rD5A/olXeimk
460kX4LxlEx5RAvpGB2zZVRGr6LobD9rVK91xuHYNIxxxfEGE8tCCWjp0+3ksri9SXx
461VHWBnbM9YaL32u3hxm8sYB/Yb8WSBavJCWJJqRStVRHM1koZlJmXNx2BX4vPo6iW
462RFEIPQsFZRLrtnCAiEhyT8bC2s/Njlu6ly9gtJZWSV46Q3ZjBL4q9sHKqZQ=
Alex Gaynore7f51982016-09-11 11:48:14 -0400463-----END CERTIFICATE-----"""
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -0400464
Alex Gaynore7f51982016-09-11 11:48:14 -0400465large_key_pem = b"""-----BEGIN RSA PRIVATE KEY-----
Colleen Murphye09399b2016-03-01 17:40:49 -0800466MIIJYgIBAAKCAg4AtRua8eIeevRfsj+fkcHr1vmse7Kgb+oX1ssJAvCb1R7JQMnH
467hNDjDP6b3vEkZuPUzlDHymP+cNkXvvi4wJ4miVbO3+SeU4Sh+jmsHeHzGIXat9xW
4689PFtuPM5FQq8zvkY8aDeRYmYwN9JKu4/neMBCBqostYlTEWg+bSytO/qWnyHTHKh
469g0GfaDdqUQPsGQw+J0MgaYIjQOCVASHAPlzbDQLCtuOb587rwTLkZA2GwoHB/LyJ
470BwT0HHgBaiObE12Vs6wi2en0Uu11CiwEuK1KIBcZ2XbE6eApaZa6VH9ysEmUxPt7
471TqyZ4E2oMIYaLPNRxuvozdwTlj1svI1k1FrkaXGc5MTjbgigPMKjIb0T7b/4GNzt
472DhP1LvAeUMnrEi3hJJrcJPXHPqS8/RiytR9xQQW6Sdh4LaA3f9MQm3WSevWage3G
473P8YcCLssOVKsArDjuA52NF5LmYuAeUzXprm4ITDi2oO+0iFBpFW6VPEK4A9vO0Yk
474M/6Wt6tG8zyWhaSH1zFUTwfQ9Yvjyt5w1lrUaAJuoTpwbMVZaDJaEhjOaXU0dyPQ
475jOsePDOQcU6dkeTWsQ3LsHPEEug/X6819TLG5mb3V7bvV9nPFBfTJSCEG794kr90
476XgZfIN71FrdByxLerlbuJI21pPs/nZi9SXi9jAWeiS45/azUxMsyYgJArui+gjq7
477sV1pWiBm6/orAgMBAAECggINQp5L6Yu+oIXBqcSjgq8tfF9M5hd30pLuf/EheHZf
478LA7uAqn2fVGFI2OInIJhXIOT5OxsAXO0xXfltzawZxIFpOFMqajj4F7aYjvSpw9V
479J4EdSiJ/zgv8y1qUdbwEZbHVThRZjoSlrtSzilonBoHZAE0mHtqMz7iRFSk1zz6t
480GunRrvo/lROPentf3TsvHquVNUYI5yaapyO1S7xJhecMIIYSb8nbsHI54FBDGNas
4816mFmpPwI/47/6HTwOEWupnn3NicsjrHzUInOUpaMig4cRR+aP5bjqg/ty8xI8AoN
482evEmCytiWTc+Rvbp1ieN+1jpjN18PjUk80/W7qioHUDt4ieLic8uxWH2VD9SCEnX
483Mpi9tA/FqoZ+2A/3m1OfrY6jiZVE2g+asi9lCK7QVWL39eK82H4rPvtp0/dyo1/i
484ZZz68TXg+m8IgEZcp88hngbkuoTTzpGE73QuPKhGA1uMIimDdqPPB5WP76q+03Oi
485IRR5DfZnqPERed49by0enJ7tKa/gFPZizOV8ALKr0Dp+vfAkxGDLPLBLd2A3//tw
486xg0Q/wltihHSBujv4nYlDXdc5oYyMYZ+Lhc/VuOghHfBq3tgEQ1ECM/ofqXEIdy7
487nVcpZn3Eeq8Jl5CrqxE1ee3NxlzsJHn99yGQpr7mOhW/psJF3XNz80Meg3L4m1T8
488sMBK0GbaassuJhdzb5whAoIBBw48sx1b1WR4XxQc5O/HjHva+l16i2pjUnOUTcDF
489RWmSbIhBm2QQ2rVhO8+fak0tkl6ZnMWW4i0U/X5LOEBbC7+IS8bO3j3Revi+Vw5x
490j96LMlIe9XEub5i/saEWgiz7maCvfzLFU08e1OpT4qPDpP293V400ubA6R7WQTCv
491pBkskGwHeu0l/TuKkVqBFFUTu7KEbps8Gjg7MkJaFriAOv1zis/umK8pVS3ZAM6e
4928w5jfpRccn8Xzta2fRwTB5kCmfxdDsY0oYGxPLRAbW72bORoLGuyyPp/ojeGwoik
493JX9RttErc6FjyZtks370Pa8UL5QskyhMbDhrZW2jFD+RXYM1BrvmZRjbAoIBBwy4
494iFJpuDfytJfz1MWtaL5DqEL/kmiZYAXl6hifNhGu5GAipVIIGsDqEYW4i+VC15aa
4957kOCwz/I5zsB3vSDW96IRs4wXtqEZSibc2W/bqfVi+xcvPPl1ZhQ2EAwa4D/x035
496kyf20ffWOU+1yf2cnijzqs3IzlveUm+meLw5s3Rc+iG7DPWWeCoe1hVwANI1euNc
497pqKwKY905yFyjOje2OgiEU2kS4YME4zGeBys8yo7E42hNnN2EPK6xkkUqzdudLLQ
4988OUlKRTc8AbIf3XG1rpA4VUpTv3hhxGGwCRy6If8zgZQsNYchgNztRGk72Gcb8Dm
499vFSEN3ZtwxU64G3YZzntdcr2WPzxAoIBBw30g6Fgdb/gmVnOpL0//T0ePNDKIMPs
500jVJLaRduhoZgB1Bb9qPUPX0SzRzLZtg1tkZSDjBDoHmOHJfhxUaXt+FLCPPbrE4t
501+nq9n/nBaMM779w9ClqhqLOyGrwKoxjSmhi+TVEHyIxCbXMvPHVHfX9WzxjbcGrN
502ZvRaEVZWo+QlIX8yqdSwqxLk1WtAIRzvlcj7NKum8xBxPed6BNFep/PtgIAmoLT5
503L8wb7EWb2iUdc2KbZ4OaY51lDScqpATgXu3WjXfM+Q52G0mX6Wyd0cjlL711Zrjb
504yLbiueZT94lgIHHRRKtKc8CEqcjkQV5OzABS3P/gQSfgZXBdLKjOpTnKDUq7IBeH
505AoIBBweAOEIAPLQg1QRUrr3xRrYKRwlakgZDii9wJt1l5AgBTICzbTA1vzDJ1JM5
506AqSpCV6w9JWyYVcXK+HLdKBRZLaPPNEQDJ5lOxD6uMziWGl2rg8tj+1xNMWfxiPz
507aTCjoe4EoBUMoTq2gwzRcM2usEQNikXVhnj9Wzaivsaeb4bJ3GRPW5DkrO6JSEtT
508w+gvyMqQM2Hy5k7E7BT46sXVwaj/jZxuqGnebRixXtnp0WixdRIqYWUr1UqLf6hQ
509G7WP2BgoxCMaCmNW8+HMD/xuxucEotoIhZ+GgJKBFoNnjl3BX+qxYdSe9RbL/5Tr
5104It6Jxtj8uETJXEbv9Cg6v1agWPS9YY8RLTBAoIBBwrU2AsAUts6h1LgGLKK3UWZ
511oLH5E+4o+7HqSGRcRodVeN9NBXIYdHHOLeEG6YNGJiJ3bFP5ZQEu9iDsyoFVKJ9O
512Mw/y6dKZuxOCZ+X8FopSROg3yWfdOpAm6cnQZp3WqLNX4n/Q6WvKojfyEiPphjwT
5130ymrUJELXLWJmjUyPoAk6HgC0Gs28ZnEXbyhx7CSbZNFyCU/PNUDZwto3GisIPD3
514le7YjqHugezmjMGlA0sDw5aCXjfbl74vowRFYMO6e3ItApfSRgNV86CDoX74WI/5
515AYU/QVM4wGt8XGT2KwDFJaxYGKsGDMWmXY04dS+WPuetCbouWUusyFwRb9SzFave
516vYeU7Ab/
Alex Gaynore7f51982016-09-11 11:48:14 -0400517-----END RSA PRIVATE KEY-----"""
Colleen Murphye09399b2016-03-01 17:40:49 -0800518
Paul Kehrer72d968b2016-07-29 15:31:04 +0800519ec_private_key_pem = b"""-----BEGIN PRIVATE KEY-----
520MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgYirTZSx+5O8Y6tlG
521cka6W6btJiocdrdolfcukSoTEk+hRANCAAQkvPNu7Pa1GcsWU4v7ptNfqCJVq8Cx
522zo0MUVPQgwJ3aJtNM1QMOQUayCrRwfklg+D/rFSUwEUqtZh7fJDiFqz3
523-----END PRIVATE KEY-----
524"""
525
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400526
Alex Chanc6077062016-11-18 13:53:39 +0000527@pytest.fixture
528def x509_data():
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400529 """
Alex Chanc6077062016-11-18 13:53:39 +0000530 Create a new private key and start a certificate request (for a test
531 to finish in one way or another).
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400532 """
Alex Chanc6077062016-11-18 13:53:39 +0000533 # Basic setup stuff to generate a certificate
534 pkey = PKey()
535 pkey.generate_key(TYPE_RSA, 384)
536 req = X509Req()
537 req.set_pubkey(pkey)
538 # Authority good you have.
539 req.get_subject().commonName = "Yoda root CA"
540 x509 = X509()
541 subject = x509.get_subject()
542 subject.commonName = req.get_subject().commonName
543 x509.set_issuer(subject)
544 x509.set_pubkey(pkey)
545 now = datetime.now()
546 expire = datetime.now() + timedelta(days=100)
547 x509.set_notBefore(now.strftime("%Y%m%d%H%M%SZ").encode())
548 x509.set_notAfter(expire.strftime("%Y%m%d%H%M%SZ").encode())
549 yield pkey, x509
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400550
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400551
Alex Chanc6077062016-11-18 13:53:39 +0000552class TestX509Ext(object):
553 """
554 Tests for `OpenSSL.crypto.X509Extension`.
555 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -0800556
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400557 def test_str(self):
558 """
Alex Chanc6077062016-11-18 13:53:39 +0000559 The string representation of `X509Extension` instances as
560 returned by `str` includes stuff.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400561 """
562 # This isn't necessarily the best string representation. Perhaps it
563 # will be changed/improved in the future.
Alex Chanc6077062016-11-18 13:53:39 +0000564 assert (
565 str(X509Extension(b'basicConstraints', True, b'CA:false')) ==
566 'CA:FALSE'
567 )
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400568
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400569 def test_type(self):
570 """
Alex Chanc6077062016-11-18 13:53:39 +0000571 `X509Extension` and `X509ExtensionType` refer to the same type object
572 and can be used to create instances of that type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400573 """
Alex Chanc6077062016-11-18 13:53:39 +0000574 assert X509Extension is X509ExtensionType
575 assert is_consistent_type(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400576 X509Extension,
Alex Gaynore7f51982016-09-11 11:48:14 -0400577 'X509Extension', b'basicConstraints', True, b'CA:true')
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400578
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500579 def test_construction(self):
580 """
Alex Chanc6077062016-11-18 13:53:39 +0000581 `X509Extension` accepts an extension type name, a critical flag,
582 and an extension value and returns an `X509ExtensionType` instance.
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500583 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400584 basic = X509Extension(b'basicConstraints', True, b'CA:true')
Alex Chanc6077062016-11-18 13:53:39 +0000585 assert isinstance(basic, X509ExtensionType)
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500586
Alex Chanc6077062016-11-18 13:53:39 +0000587 comment = X509Extension(b'nsComment', False, b'pyOpenSSL unit test')
588 assert isinstance(comment, X509ExtensionType)
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500589
Alex Chanc6077062016-11-18 13:53:39 +0000590 @pytest.mark.parametrize('type_name, critical, value', [
591 (b'thisIsMadeUp', False, b'hi'),
592 (b'basicConstraints', False, b'blah blah'),
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500593
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500594 # Exercise a weird one (an extension which uses the r2i method). This
595 # exercises the codepath that requires a non-NULL ctx to be passed to
596 # X509V3_EXT_nconf. It can't work now because we provide no
597 # configuration database. It might be made to work in the future.
Alex Chanc6077062016-11-18 13:53:39 +0000598 (b'proxyCertInfo', True,
599 b'language:id-ppl-anyLanguage,pathlen:1,policy:text:AB')
600 ])
601 def test_invalid_extension(self, type_name, critical, value):
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500602 """
Alex Chanc6077062016-11-18 13:53:39 +0000603 `X509Extension` raises something if it is passed a bad
604 extension name or value.
605 """
606 with pytest.raises(Error):
607 X509Extension(type_name, critical, value)
608
609 @pytest.mark.parametrize('critical_flag', [True, False])
610 def test_get_critical(self, critical_flag):
611 """
612 `X509ExtensionType.get_critical` returns the value of the
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500613 extension's critical flag.
614 """
Alex Chanc6077062016-11-18 13:53:39 +0000615 ext = X509Extension(b'basicConstraints', critical_flag, b'CA:true')
616 assert ext.get_critical() == critical_flag
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500617
Alex Chanc6077062016-11-18 13:53:39 +0000618 @pytest.mark.parametrize('short_name, value', [
619 (b'basicConstraints', b'CA:true'),
620 (b'nsComment', b'foo bar'),
621 ])
622 def test_get_short_name(self, short_name, value):
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500623 """
Alex Chanc6077062016-11-18 13:53:39 +0000624 `X509ExtensionType.get_short_name` returns a string giving the
Alex Gaynor31287502015-09-05 16:11:27 -0400625 short type name of the extension.
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500626 """
Alex Chanc6077062016-11-18 13:53:39 +0000627 ext = X509Extension(short_name, True, value)
628 assert ext.get_short_name() == short_name
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500629
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400630 def test_get_data(self):
631 """
Alex Chanc6077062016-11-18 13:53:39 +0000632 `X509Extension.get_data` returns a string giving the data of
Alex Gaynor31287502015-09-05 16:11:27 -0400633 the extension.
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400634 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400635 ext = X509Extension(b'basicConstraints', True, b'CA:true')
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400636 # Expect to get back the DER encoded form of CA:true.
Alex Chanc6077062016-11-18 13:53:39 +0000637 assert ext.get_data() == b'0\x03\x01\x01\xff'
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400638
Alex Chanc6077062016-11-18 13:53:39 +0000639 def test_unused_subject(self, x509_data):
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400640 """
Alex Chanc6077062016-11-18 13:53:39 +0000641 The `subject` parameter to `X509Extension` may be provided for an
642 extension which does not use it and is ignored in this case.
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400643 """
Alex Chanc6077062016-11-18 13:53:39 +0000644 pkey, x509 = x509_data
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400645 ext1 = X509Extension(
Alex Chanc6077062016-11-18 13:53:39 +0000646 b'basicConstraints', False, b'CA:TRUE', subject=x509)
647 x509.add_extensions([ext1])
648 x509.sign(pkey, 'sha1')
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400649 # This is a little lame. Can we think of a better way?
Alex Chanc6077062016-11-18 13:53:39 +0000650 text = dump_certificate(FILETYPE_TEXT, x509)
651 assert b'X509v3 Basic Constraints:' in text
652 assert b'CA:TRUE' in text
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400653
Alex Chanc6077062016-11-18 13:53:39 +0000654 def test_subject(self, x509_data):
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400655 """
Alex Chanc6077062016-11-18 13:53:39 +0000656 If an extension requires a subject, the `subject` parameter to
657 `X509Extension` provides its value.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400658 """
Alex Chanc6077062016-11-18 13:53:39 +0000659 pkey, x509 = x509_data
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400660 ext3 = X509Extension(
Alex Chanc6077062016-11-18 13:53:39 +0000661 b'subjectKeyIdentifier', False, b'hash', subject=x509)
662 x509.add_extensions([ext3])
663 x509.sign(pkey, 'sha1')
664 text = dump_certificate(FILETYPE_TEXT, x509)
665 assert b'X509v3 Subject Key Identifier:' in text
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400666
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400667 def test_missing_subject(self):
668 """
Alex Chanc6077062016-11-18 13:53:39 +0000669 If an extension requires a subject and the `subject` parameter
Alex Gaynor31287502015-09-05 16:11:27 -0400670 is given no value, something happens.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400671 """
Alex Chanc6077062016-11-18 13:53:39 +0000672 with pytest.raises(Error):
673 X509Extension(b'subjectKeyIdentifier', False, b'hash')
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400674
Alex Chanc6077062016-11-18 13:53:39 +0000675 @pytest.mark.parametrize('bad_obj', [
676 True,
677 object(),
678 "hello",
679 [],
680 ])
681 def test_invalid_subject(self, bad_obj):
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400682 """
Alex Chanc6077062016-11-18 13:53:39 +0000683 If the `subject` parameter is given a value which is not an
684 `X509` instance, `TypeError` is raised.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400685 """
Alex Chanc6077062016-11-18 13:53:39 +0000686 with pytest.raises(TypeError):
687 X509Extension(
688 'basicConstraints', False, 'CA:TRUE', subject=bad_obj)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400689
Alex Chanc6077062016-11-18 13:53:39 +0000690 def test_unused_issuer(self, x509_data):
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400691 """
Alex Chanc6077062016-11-18 13:53:39 +0000692 The `issuer` parameter to `X509Extension` may be provided for an
693 extension which does not use it and is ignored in this case.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400694 """
Alex Chanc6077062016-11-18 13:53:39 +0000695 pkey, x509 = x509_data
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400696 ext1 = X509Extension(
Alex Chanc6077062016-11-18 13:53:39 +0000697 b'basicConstraints', False, b'CA:TRUE', issuer=x509)
698 x509.add_extensions([ext1])
699 x509.sign(pkey, 'sha1')
700 text = dump_certificate(FILETYPE_TEXT, x509)
701 assert b'X509v3 Basic Constraints:' in text
702 assert b'CA:TRUE' in text
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400703
Alex Chanc6077062016-11-18 13:53:39 +0000704 def test_issuer(self, x509_data):
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400705 """
Alex Chanc6077062016-11-18 13:53:39 +0000706 If an extension requires an issuer, the `issuer` parameter to
707 `X509Extension` provides its value.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400708 """
Alex Chanc6077062016-11-18 13:53:39 +0000709 pkey, x509 = x509_data
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400710 ext2 = X509Extension(
Alex Gaynore7f51982016-09-11 11:48:14 -0400711 b'authorityKeyIdentifier', False, b'issuer:always',
Alex Chanc6077062016-11-18 13:53:39 +0000712 issuer=x509)
713 x509.add_extensions([ext2])
714 x509.sign(pkey, 'sha1')
715 text = dump_certificate(FILETYPE_TEXT, x509)
716 assert b'X509v3 Authority Key Identifier:' in text
717 assert b'DirName:/CN=Yoda root CA' in text
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400718
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400719 def test_missing_issuer(self):
720 """
Alex Chanc6077062016-11-18 13:53:39 +0000721 If an extension requires an issue and the `issuer` parameter is
722 given no value, something happens.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400723 """
Alex Chanc6077062016-11-18 13:53:39 +0000724 with pytest.raises(Error):
725 X509Extension(
726 b'authorityKeyIdentifier',
727 False, b'keyid:always,issuer:always')
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400728
Alex Chanc6077062016-11-18 13:53:39 +0000729 @pytest.mark.parametrize('bad_obj', [
730 True,
731 object(),
732 "hello",
733 [],
734 ])
735 def test_invalid_issuer(self, bad_obj):
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400736 """
Alex Chanc6077062016-11-18 13:53:39 +0000737 If the `issuer` parameter is given a value which is not an
738 `X509` instance, `TypeError` is raised.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400739 """
Alex Chanc6077062016-11-18 13:53:39 +0000740 with pytest.raises(TypeError):
741 X509Extension(
742 'basicConstraints', False, 'keyid:always,issuer:always',
743 issuer=bad_obj)
Rick Dean47262da2009-07-08 16:17:17 -0500744
745
Paul Kehrer72d968b2016-07-29 15:31:04 +0800746class TestPKey(object):
747 """
748 py.test-based tests for :class:`OpenSSL.crypto.PKey`.
749
750 If possible, add new tests here.
751 """
752
753 def test_convert_from_cryptography_private_key(self):
754 """
755 PKey.from_cryptography_key creates a proper private PKey.
756 """
757 key = serialization.load_pem_private_key(
758 intermediate_key_pem, None, backend
759 )
760 pkey = PKey.from_cryptography_key(key)
761
762 assert isinstance(pkey, PKey)
763 assert pkey.bits() == key.key_size
764 assert pkey._only_public is False
765 assert pkey._initialized is True
766
767 def test_convert_from_cryptography_public_key(self):
768 """
769 PKey.from_cryptography_key creates a proper public PKey.
770 """
771 key = serialization.load_pem_public_key(cleartextPublicKeyPEM, backend)
772 pkey = PKey.from_cryptography_key(key)
773
774 assert isinstance(pkey, PKey)
775 assert pkey.bits() == key.key_size
776 assert pkey._only_public is True
777 assert pkey._initialized is True
778
779 def test_convert_from_cryptography_unsupported_type(self):
780 """
781 PKey.from_cryptography_key raises TypeError with an unsupported type.
782 """
783 key = serialization.load_pem_private_key(
784 ec_private_key_pem, None, backend
785 )
786 with pytest.raises(TypeError):
787 PKey.from_cryptography_key(key)
788
789 def test_convert_public_pkey_to_cryptography_key(self):
790 """
791 PKey.to_cryptography_key creates a proper cryptography public key.
792 """
793 pkey = load_publickey(FILETYPE_PEM, cleartextPublicKeyPEM)
794 key = pkey.to_cryptography_key()
795
796 assert isinstance(key, rsa.RSAPublicKey)
797 assert pkey.bits() == key.key_size
798
799 def test_convert_private_pkey_to_cryptography_key(self):
800 """
801 PKey.to_cryptography_key creates a proper cryptography private key.
802 """
803 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
804 key = pkey.to_cryptography_key()
805
806 assert isinstance(key, rsa.RSAPrivateKey)
807 assert pkey.bits() == key.key_size
808
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400809 def test_type(self):
810 """
Alex Chan9e2a9932017-01-25 14:29:19 +0000811 `PKey` and `PKeyType` refer to the same type object and can be used to
812 create instances of that type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400813 """
Alex Chan9e2a9932017-01-25 14:29:19 +0000814 assert PKey is PKeyType
815 assert is_consistent_type(PKey, 'PKey')
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400816
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500817 def test_construction(self):
818 """
Alex Chan9e2a9932017-01-25 14:29:19 +0000819 `PKey` takes no arguments and returns a new `PKey` instance.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500820 """
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500821 key = PKey()
Alex Chan9e2a9932017-01-25 14:29:19 +0000822 assert isinstance(key, PKey)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500823
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500824 def test_pregeneration(self):
825 """
Alex Chan9e2a9932017-01-25 14:29:19 +0000826 `PKey.bits` and `PKey.type` return `0` before the key is generated.
827 `PKey.check` raises `TypeError` before the key is generated.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500828 """
829 key = PKey()
Alex Chan9e2a9932017-01-25 14:29:19 +0000830 assert key.type() == 0
831 assert key.bits() == 0
832 with pytest.raises(TypeError):
833 key.check()
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500834
Alex Chan9e2a9932017-01-25 14:29:19 +0000835 def test_failed_generation(self):
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500836 """
Alex Chan9e2a9932017-01-25 14:29:19 +0000837 `PKey.generate_key` takes two arguments, the first giving the key type
838 as one of `TYPE_RSA` or `TYPE_DSA` and the second giving the number of
839 bits to generate. If an invalid type is specified or generation fails,
840 `Error` is raised. If an invalid number of bits is specified,
841 `ValueError` or `Error` is raised.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500842 """
843 key = PKey()
Alex Chan9e2a9932017-01-25 14:29:19 +0000844 with pytest.raises(TypeError):
845 key.generate_key("foo", "bar")
846 with pytest.raises(Error):
847 key.generate_key(-1, 0)
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500848
Alex Chan9e2a9932017-01-25 14:29:19 +0000849 with pytest.raises(ValueError):
850 key.generate_key(TYPE_RSA, -1)
851 with pytest.raises(ValueError):
852 key.generate_key(TYPE_RSA, 0)
Jean-Paul Calderoned71fe982008-03-06 00:31:50 -0500853
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400854 with pytest.raises(TypeError):
855 key.generate_key(TYPE_RSA, object())
856
Jean-Paul Calderoned71fe982008-03-06 00:31:50 -0500857 # XXX RSA generation for small values of bits is fairly buggy in a wide
858 # range of OpenSSL versions. I need to figure out what the safe lower
859 # bound for a reasonable number of OpenSSL versions is and explicitly
860 # check for that in the wrapper. The failure behavior is typically an
861 # infinite loop inside OpenSSL.
862
Alex Chan9e2a9932017-01-25 14:29:19 +0000863 # with pytest.raises(Error):
864 # key.generate_key(TYPE_RSA, 2)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500865
866 # XXX DSA generation seems happy with any number of bits. The DSS
867 # says bits must be between 512 and 1024 inclusive. OpenSSL's DSA
868 # generator doesn't seem to care about the upper limit at all. For
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500869 # the lower limit, it uses 512 if anything smaller is specified.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500870 # So, it doesn't seem possible to make generate_key fail for
871 # TYPE_DSA with a bits argument which is at least an int.
872
Alex Chan9e2a9932017-01-25 14:29:19 +0000873 # with pytest.raises(Error):
874 # key.generate_key(TYPE_DSA, -7)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500875
Alex Chan9e2a9932017-01-25 14:29:19 +0000876 def test_rsa_generation(self):
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500877 """
Alex Chan9e2a9932017-01-25 14:29:19 +0000878 `PKey.generate_key` generates an RSA key when passed `TYPE_RSA` as a
879 type and a reasonable number of bits.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500880 """
881 bits = 128
882 key = PKey()
883 key.generate_key(TYPE_RSA, bits)
Alex Chan9e2a9932017-01-25 14:29:19 +0000884 assert key.type() == TYPE_RSA
885 assert key.bits() == bits
886 assert key.check()
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500887
Alex Chan9e2a9932017-01-25 14:29:19 +0000888 def test_dsa_generation(self):
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500889 """
Alex Chan9e2a9932017-01-25 14:29:19 +0000890 `PKey.generate_key` generates a DSA key when passed `TYPE_DSA` as a
891 type and a reasonable number of bits.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500892 """
893 # 512 is a magic number. The DSS (Digital Signature Standard)
894 # allows a minimum of 512 bits for DSA. DSA_generate_parameters
895 # will silently promote any value below 512 to 512.
896 bits = 512
897 key = PKey()
898 key.generate_key(TYPE_DSA, bits)
Alex Chan9e2a9932017-01-25 14:29:19 +0000899 assert key.type() == TYPE_DSA
900 assert key.bits() == bits
901 with pytest.raises(TypeError):
902 key.check()
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500903
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500904 def test_regeneration(self):
905 """
Alex Chan9e2a9932017-01-25 14:29:19 +0000906 `PKey.generate_key` can be called multiple times on the same key to
907 generate new keys.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500908 """
909 key = PKey()
910 for type, bits in [(TYPE_RSA, 512), (TYPE_DSA, 576)]:
Alex Gaynor7f636492015-09-04 13:26:52 -0400911 key.generate_key(type, bits)
Alex Chan9e2a9932017-01-25 14:29:19 +0000912 assert key.type() == type
913 assert key.bits() == bits
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500914
Alex Chan9e2a9932017-01-25 14:29:19 +0000915 def test_inconsistent_key(self):
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400916 """
Alex Chan9e2a9932017-01-25 14:29:19 +0000917 `PKey.check` returns `Error` if the key is not consistent.
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400918 """
919 key = load_privatekey(FILETYPE_PEM, inconsistentPrivateKeyPEM)
Alex Chan9e2a9932017-01-25 14:29:19 +0000920 with pytest.raises(Error):
921 key.check()
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400922
Jean-Paul Calderone02d01972011-10-31 10:39:29 -0400923 def test_check_public_key(self):
924 """
Alex Chan9e2a9932017-01-25 14:29:19 +0000925 `PKey.check` raises `TypeError` if only the public part of the key
926 is available.
Jean-Paul Calderone02d01972011-10-31 10:39:29 -0400927 """
928 # A trick to get a public-only key
929 key = PKey()
930 key.generate_key(TYPE_RSA, 512)
931 cert = X509()
932 cert.set_pubkey(key)
933 pub = cert.get_pubkey()
Alex Chan9e2a9932017-01-25 14:29:19 +0000934 with pytest.raises(TypeError):
935 pub.check()
Jean-Paul Calderone02d01972011-10-31 10:39:29 -0400936
937
Alex Chan9e2a9932017-01-25 14:29:19 +0000938def x509_name(**attrs):
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500939 """
Alex Chan9e2a9932017-01-25 14:29:19 +0000940 Return a new X509Name with the given attributes.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500941 """
Alex Chan9e2a9932017-01-25 14:29:19 +0000942 # XXX There's no other way to get a new X509Name yet.
943 name = X509().get_subject()
944 attrs = list(attrs.items())
Alex Gaynoraceb3e22015-09-05 12:00:22 -0400945
Alex Chan9e2a9932017-01-25 14:29:19 +0000946 # Make the order stable - order matters!
947 def key(attr):
948 return attr[1]
949 attrs.sort(key=key)
950 for k, v in attrs:
951 setattr(name, k, v)
952 return name
Alex Gaynor85b49702015-09-05 16:30:59 -0400953
Alex Chan9e2a9932017-01-25 14:29:19 +0000954
955class TestX509Name(object):
956 """
957 Unit tests for `OpenSSL.crypto.X509Name`.
958 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500959
Rick Deane15b1472009-07-09 15:53:42 -0500960 def test_type(self):
961 """
Alex Chan9e2a9932017-01-25 14:29:19 +0000962 The type of X509Name objects is `X509NameType`.
Rick Deane15b1472009-07-09 15:53:42 -0500963 """
Alex Chan9e2a9932017-01-25 14:29:19 +0000964 assert X509Name is X509NameType
965 assert X509NameType.__name__ == 'X509Name'
966 assert isinstance(X509NameType, type)
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400967
Alex Chan9e2a9932017-01-25 14:29:19 +0000968 name = x509_name()
969 assert isinstance(name, X509NameType)
Rick Deane15b1472009-07-09 15:53:42 -0500970
Alex Chan9e2a9932017-01-25 14:29:19 +0000971 def test_only_string_attributes(self):
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400972 """
Alex Chan9e2a9932017-01-25 14:29:19 +0000973 Attempting to set a non-`str` attribute name on an `X509Name` instance
974 causes `TypeError` to be raised.
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400975 """
Alex Chan9e2a9932017-01-25 14:29:19 +0000976 name = x509_name()
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400977 # Beyond these cases, you may also think that unicode should be
Alex Gaynor31287502015-09-05 16:11:27 -0400978 # rejected. Sorry, you're wrong. unicode is automatically converted
979 # to str outside of the control of X509Name, so there's no way to
980 # reject it.
Jean-Paul Calderoneff363be2013-03-03 10:21:23 -0800981
Alex Gaynor31287502015-09-05 16:11:27 -0400982 # Also, this used to test str subclasses, but that test is less
983 # relevant now that the implementation is in Python instead of C. Also
984 # PyPy automatically converts str subclasses to str when they are
985 # passed to setattr, so we can't test it on PyPy. Apparently CPython
986 # does this sometimes as well.
Alex Chan9e2a9932017-01-25 14:29:19 +0000987 with pytest.raises(TypeError):
988 setattr(name, None, "hello")
989 with pytest.raises(TypeError):
990 setattr(name, 30, "hello")
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400991
Alex Chan9e2a9932017-01-25 14:29:19 +0000992 def test_set_invalid_attribute(self):
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400993 """
Alex Chan9e2a9932017-01-25 14:29:19 +0000994 Attempting to set any attribute name on an `X509Name` instance for
995 which no corresponding NID is defined causes `AttributeError` to be
996 raised.
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400997 """
Alex Chan9e2a9932017-01-25 14:29:19 +0000998 name = x509_name()
999 with pytest.raises(AttributeError):
1000 setattr(name, "no such thing", None)
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -04001001
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -05001002 def test_attributes(self):
1003 """
Alex Chan9e2a9932017-01-25 14:29:19 +00001004 `X509Name` instances have attributes for each standard (?)
1005 X509Name field.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -05001006 """
Alex Chan9e2a9932017-01-25 14:29:19 +00001007 name = x509_name()
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -05001008 name.commonName = "foo"
Alex Gaynor37726112016-07-04 09:51:32 -04001009 assert name.commonName == "foo"
1010 assert name.CN == "foo"
1011
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -05001012 name.CN = "baz"
Alex Gaynor37726112016-07-04 09:51:32 -04001013 assert name.commonName == "baz"
1014 assert name.CN == "baz"
1015
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -05001016 name.commonName = "bar"
Alex Gaynor37726112016-07-04 09:51:32 -04001017 assert name.commonName == "bar"
1018 assert name.CN == "bar"
1019
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -05001020 name.CN = "quux"
Alex Gaynor37726112016-07-04 09:51:32 -04001021 assert name.commonName == "quux"
1022 assert name.CN == "quux"
1023
1024 assert name.OU is None
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -05001025
Alex Gaynor7778e792016-07-03 23:38:48 -04001026 with pytest.raises(AttributeError):
1027 name.foobar
1028
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -05001029 def test_copy(self):
1030 """
Alex Chan9e2a9932017-01-25 14:29:19 +00001031 `X509Name` creates a new `X509Name` instance with all the same
1032 attributes as an existing `X509Name` instance when called with one.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -05001033 """
Alex Chan9e2a9932017-01-25 14:29:19 +00001034 name = x509_name(commonName="foo", emailAddress="bar@example.com")
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -05001035
1036 copy = X509Name(name)
Alex Chan9e2a9932017-01-25 14:29:19 +00001037 assert copy.commonName == "foo"
1038 assert copy.emailAddress == "bar@example.com"
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -05001039
1040 # Mutate the copy and ensure the original is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -05001041 copy.commonName = "baz"
Alex Chan9e2a9932017-01-25 14:29:19 +00001042 assert name.commonName == "foo"
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -05001043
1044 # Mutate the original and ensure the copy is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -05001045 name.emailAddress = "quux@example.com"
Alex Chan9e2a9932017-01-25 14:29:19 +00001046 assert copy.emailAddress == "bar@example.com"
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -05001047
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -05001048 def test_repr(self):
1049 """
Alex Chan9e2a9932017-01-25 14:29:19 +00001050 `repr` passed an `X509Name` instance should return a string containing
1051 a description of the type and the NIDs which have been set on it.
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -05001052 """
Alex Chan9e2a9932017-01-25 14:29:19 +00001053 name = x509_name(commonName="foo", emailAddress="bar")
1054 assert repr(name) == "<X509Name object '/emailAddress=bar/CN=foo'>"
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -05001055
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -05001056 def test_comparison(self):
1057 """
Alex Chan9e2a9932017-01-25 14:29:19 +00001058 `X509Name` instances should compare based on their NIDs.
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -05001059 """
Alex Chan9e2a9932017-01-25 14:29:19 +00001060 def _equality(a, b, assert_true, assert_false):
1061 assert_true(a == b)
1062 assert_false(a != b)
1063 assert_true(b == a)
1064 assert_false(b != a)
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -05001065
Alex Chan9e2a9932017-01-25 14:29:19 +00001066 def assert_true(x):
1067 assert x
1068
1069 def assert_false(x):
1070 assert not x
1071
1072 def assert_equal(a, b):
1073 _equality(a, b, assert_true, assert_false)
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -05001074
1075 # Instances compare equal to themselves.
Alex Chan9e2a9932017-01-25 14:29:19 +00001076 name = x509_name()
1077 assert_equal(name, name)
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -05001078
1079 # Empty instances should compare equal to each other.
Alex Chan9e2a9932017-01-25 14:29:19 +00001080 assert_equal(x509_name(), x509_name())
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -05001081
1082 # Instances with equal NIDs should compare equal to each other.
Alex Chan9e2a9932017-01-25 14:29:19 +00001083 assert_equal(x509_name(commonName="foo"),
1084 x509_name(commonName="foo"))
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -05001085
1086 # Instance with equal NIDs set using different aliases should compare
1087 # equal to each other.
Alex Chan9e2a9932017-01-25 14:29:19 +00001088 assert_equal(x509_name(commonName="foo"),
1089 x509_name(CN="foo"))
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -05001090
1091 # Instances with more than one NID with the same values should compare
1092 # equal to each other.
Alex Chan9e2a9932017-01-25 14:29:19 +00001093 assert_equal(x509_name(CN="foo", organizationalUnitName="bar"),
1094 x509_name(commonName="foo", OU="bar"))
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -05001095
Alex Chan9e2a9932017-01-25 14:29:19 +00001096 def assert_not_equal(a, b):
1097 _equality(a, b, assert_false, assert_true)
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -05001098
1099 # Instances with different values for the same NID should not compare
1100 # equal to each other.
Alex Chan9e2a9932017-01-25 14:29:19 +00001101 assert_not_equal(x509_name(CN="foo"),
1102 x509_name(CN="bar"))
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -05001103
1104 # Instances with different NIDs should not compare equal to each other.
Alex Chan9e2a9932017-01-25 14:29:19 +00001105 assert_not_equal(x509_name(CN="foo"),
1106 x509_name(OU="foo"))
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -05001107
Alex Chan9e2a9932017-01-25 14:29:19 +00001108 assert_not_equal(x509_name(), object())
Alex Gaynor7778e792016-07-03 23:38:48 -04001109
Alex Chan9e2a9932017-01-25 14:29:19 +00001110 def _inequality(a, b, assert_true, assert_false):
1111 assert_true(a < b)
1112 assert_true(a <= b)
1113 assert_true(b > a)
1114 assert_true(b >= a)
1115 assert_false(a > b)
1116 assert_false(a >= b)
1117 assert_false(b < a)
1118 assert_false(b <= a)
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -05001119
Alex Chan9e2a9932017-01-25 14:29:19 +00001120 def assert_less_than(a, b):
1121 _inequality(a, b, assert_true, assert_false)
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -05001122
1123 # An X509Name with a NID with a value which sorts less than the value
1124 # of the same NID on another X509Name compares less than the other
1125 # X509Name.
Alex Chan9e2a9932017-01-25 14:29:19 +00001126 assert_less_than(x509_name(CN="abc"),
1127 x509_name(CN="def"))
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -05001128
Alex Chan9e2a9932017-01-25 14:29:19 +00001129 def assert_greater_than(a, b):
1130 _inequality(a, b, assert_false, assert_true)
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -05001131
1132 # An X509Name with a NID with a value which sorts greater than the
1133 # value of the same NID on another X509Name compares greater than the
1134 # other X509Name.
Alex Chan9e2a9932017-01-25 14:29:19 +00001135 assert_greater_than(x509_name(CN="def"),
1136 x509_name(CN="abc"))
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001137
Jean-Paul Calderone110cd092008-03-24 17:27:42 -04001138 def test_hash(self):
1139 """
Alex Chan9e2a9932017-01-25 14:29:19 +00001140 `X509Name.hash` returns an integer hash based on the value of the name.
Jean-Paul Calderone110cd092008-03-24 17:27:42 -04001141 """
Alex Chan9e2a9932017-01-25 14:29:19 +00001142 a = x509_name(CN="foo")
1143 b = x509_name(CN="foo")
1144 assert a.hash() == b.hash()
Jean-Paul Calderone110cd092008-03-24 17:27:42 -04001145 a.CN = "bar"
Alex Chan9e2a9932017-01-25 14:29:19 +00001146 assert a.hash() != b.hash()
Jean-Paul Calderone110cd092008-03-24 17:27:42 -04001147
Jean-Paul Calderonee957a002008-03-25 15:16:51 -04001148 def test_der(self):
1149 """
Alex Chan9e2a9932017-01-25 14:29:19 +00001150 `X509Name.der` returns the DER encoded form of the name.
Jean-Paul Calderonee957a002008-03-25 15:16:51 -04001151 """
Alex Chan9e2a9932017-01-25 14:29:19 +00001152 a = x509_name(CN="foo", C="US")
1153 assert (a.der() ==
1154 b'0\x1b1\x0b0\t\x06\x03U\x04\x06\x13\x02US'
1155 b'1\x0c0\n\x06\x03U\x04\x03\x0c\x03foo')
Jean-Paul Calderonee957a002008-03-25 15:16:51 -04001156
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -04001157 def test_get_components(self):
1158 """
Alex Chan9e2a9932017-01-25 14:29:19 +00001159 `X509Name.get_components` returns a `list` of two-tuples of `str`
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -04001160 giving the NIDs and associated values which make up the name.
1161 """
Alex Chan9e2a9932017-01-25 14:29:19 +00001162 a = x509_name()
1163 assert a.get_components() == []
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -04001164 a.CN = "foo"
Alex Chan9e2a9932017-01-25 14:29:19 +00001165 assert a.get_components() == [(b"CN", b"foo")]
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -04001166 a.organizationalUnitName = "bar"
Alex Chan9e2a9932017-01-25 14:29:19 +00001167 assert a.get_components() == [(b"CN", b"foo"), (b"OU", b"bar")]
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -04001168
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001169 def test_load_nul_byte_attribute(self):
1170 """
Alex Chan9e2a9932017-01-25 14:29:19 +00001171 An `X509Name` from an `X509` instance loaded from a file can have a
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001172 NUL byte in the value of one of its attributes.
1173 """
1174 cert = load_certificate(FILETYPE_PEM, nulbyteSubjectAltNamePEM)
1175 subject = cert.get_subject()
Alex Chan9e2a9932017-01-25 14:29:19 +00001176 assert "null.python.org\x00example.org" == subject.commonName
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001177
Alex Chan9e2a9932017-01-25 14:29:19 +00001178 def test_set_attribute_failure(self):
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -05001179 """
1180 If the value of an attribute cannot be set for some reason then
Alex Chan9e2a9932017-01-25 14:29:19 +00001181 `Error` is raised.
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -05001182 """
Alex Chan9e2a9932017-01-25 14:29:19 +00001183 name = x509_name()
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -05001184 # This value is too long
Alex Chan9e2a9932017-01-25 14:29:19 +00001185 with pytest.raises(Error):
1186 setattr(name, "O", b"x" * 512)
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -05001187
1188
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001189class _PKeyInteractionTestsMixin:
1190 """
1191 Tests which involve another thing and a PKey.
1192 """
Alex Gaynoraceb3e22015-09-05 12:00:22 -04001193
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001194 def signable(self):
1195 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001196 Return something with a :py:meth:`set_pubkey`, :py:meth:`set_pubkey`,
1197 and :py:meth:`sign` method.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001198 """
1199 raise NotImplementedError()
1200
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001201 def test_signWithUngenerated(self):
1202 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001203 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when pass a
1204 :py:class:`PKey` with no parts.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001205 """
1206 request = self.signable()
1207 key = PKey()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001208 self.assertRaises(ValueError, request.sign, key, GOOD_DIGEST)
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001209
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001210 def test_signWithPublicKey(self):
1211 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001212 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when pass a
1213 :py:class:`PKey` with no private part as the signing key.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001214 """
1215 request = self.signable()
1216 key = PKey()
1217 key.generate_key(TYPE_RSA, 512)
1218 request.set_pubkey(key)
1219 pub = request.get_pubkey()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001220 self.assertRaises(ValueError, request.sign, pub, GOOD_DIGEST)
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001221
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -04001222 def test_signWithUnknownDigest(self):
1223 """
Alex Gaynor31287502015-09-05 16:11:27 -04001224 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when passed a
1225 digest name which is not known.
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -04001226 """
1227 request = self.signable()
1228 key = PKey()
1229 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001230 self.assertRaises(ValueError, request.sign, key, BAD_DIGEST)
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -04001231
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04001232 def test_sign(self):
1233 """
Alex Gaynor31287502015-09-05 16:11:27 -04001234 :py:meth:`X509Req.sign` succeeds when passed a private key object and a
1235 valid digest function. :py:meth:`X509Req.verify` can be used to check
1236 the signature.
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04001237 """
1238 request = self.signable()
1239 key = PKey()
1240 key.generate_key(TYPE_RSA, 512)
1241 request.set_pubkey(key)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001242 request.sign(key, GOOD_DIGEST)
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04001243 # If the type has a verify method, cover that too.
1244 if getattr(request, 'verify', None) is not None:
1245 pub = request.get_pubkey()
1246 self.assertTrue(request.verify(pub))
1247 # Make another key that won't verify.
1248 key = PKey()
1249 key.generate_key(TYPE_RSA, 512)
1250 self.assertRaises(Error, request.verify, key)
1251
1252
Jean-Paul Calderone18808652009-07-05 12:54:05 -04001253class X509ReqTests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001254 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001255 Tests for :py:class:`OpenSSL.crypto.X509Req`.
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001256 """
Alex Gaynoraceb3e22015-09-05 12:00:22 -04001257
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001258 def signable(self):
1259 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001260 Create and return a new :py:class:`X509Req`.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001261 """
1262 return X509Req()
1263
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001264 def test_type(self):
1265 """
Alex Gaynor31287502015-09-05 16:11:27 -04001266 :py:obj:`X509Req` and :py:obj:`X509ReqType` refer to the same type
1267 object and can be used to create instances of that type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001268 """
1269 self.assertIdentical(X509Req, X509ReqType)
1270 self.assertConsistentType(X509Req, 'X509Req')
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001271
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001272 def test_construction(self):
1273 """
Alex Gaynor31287502015-09-05 16:11:27 -04001274 :py:obj:`X509Req` takes no arguments and returns an
1275 :py:obj:`X509ReqType` instance.
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001276 """
1277 request = X509Req()
Alex Gaynor31287502015-09-05 16:11:27 -04001278 assert isinstance(request, X509ReqType)
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001279
Jean-Paul Calderone8dd19b82008-12-28 20:41:16 -05001280 def test_version(self):
1281 """
Alex Gaynor31287502015-09-05 16:11:27 -04001282 :py:obj:`X509ReqType.set_version` sets the X.509 version of the
1283 certificate request. :py:obj:`X509ReqType.get_version` returns the
1284 X.509 version of the certificate request. The initial value of the
1285 version is 0.
Jean-Paul Calderone8dd19b82008-12-28 20:41:16 -05001286 """
1287 request = X509Req()
1288 self.assertEqual(request.get_version(), 0)
1289 request.set_version(1)
1290 self.assertEqual(request.get_version(), 1)
1291 request.set_version(3)
1292 self.assertEqual(request.get_version(), 3)
1293
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001294 def test_version_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001295 """
Alex Gaynor31287502015-09-05 16:11:27 -04001296 :py:obj:`X509ReqType.set_version` raises :py:obj:`TypeError` if called
1297 with the wrong number of arguments or with a non-:py:obj:`int`
1298 argument. :py:obj:`X509ReqType.get_version` raises :py:obj:`TypeError`
1299 if called with any arguments.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001300 """
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001301 request = X509Req()
1302 self.assertRaises(TypeError, request.set_version)
1303 self.assertRaises(TypeError, request.set_version, "foo")
1304 self.assertRaises(TypeError, request.set_version, 1, 2)
1305 self.assertRaises(TypeError, request.get_version, None)
1306
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001307 def test_get_subject(self):
1308 """
Alex Gaynor31287502015-09-05 16:11:27 -04001309 :py:obj:`X509ReqType.get_subject` returns an :py:obj:`X509Name` for the
1310 subject of the request and which is valid even after the request object
1311 is otherwise dead.
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001312 """
1313 request = X509Req()
1314 subject = request.get_subject()
Alex Gaynor31287502015-09-05 16:11:27 -04001315 assert isinstance(subject, X509NameType)
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001316 subject.commonName = "foo"
1317 self.assertEqual(request.get_subject().commonName, "foo")
1318 del request
1319 subject.commonName = "bar"
1320 self.assertEqual(subject.commonName, "bar")
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001321
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001322 def test_get_subject_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001323 """
Alex Gaynor31287502015-09-05 16:11:27 -04001324 :py:obj:`X509ReqType.get_subject` raises :py:obj:`TypeError` if called
1325 with any arguments.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001326 """
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001327 request = X509Req()
1328 self.assertRaises(TypeError, request.get_subject, None)
1329
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001330 def test_add_extensions(self):
1331 """
Alex Gaynor31287502015-09-05 16:11:27 -04001332 :py:obj:`X509Req.add_extensions` accepts a :py:obj:`list` of
1333 :py:obj:`X509Extension` instances and adds them to the X509 request.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001334 """
1335 request = X509Req()
1336 request.add_extensions([
Alex Gaynore7f51982016-09-11 11:48:14 -04001337 X509Extension(b'basicConstraints', True, b'CA:false')])
Stephen Holsappleca545b72014-01-28 21:43:25 -08001338 exts = request.get_extensions()
Stephen Holsapple7fbdf642014-03-01 20:05:47 -08001339 self.assertEqual(len(exts), 1)
Alex Gaynore7f51982016-09-11 11:48:14 -04001340 self.assertEqual(exts[0].get_short_name(), b'basicConstraints')
Stephen Holsapple7fbdf642014-03-01 20:05:47 -08001341 self.assertEqual(exts[0].get_critical(), 1)
Alex Gaynore7f51982016-09-11 11:48:14 -04001342 self.assertEqual(exts[0].get_data(), b'0\x00')
Stephen Holsapple7fbdf642014-03-01 20:05:47 -08001343
Stephen Holsapple7fbdf642014-03-01 20:05:47 -08001344 def test_get_extensions(self):
1345 """
1346 :py:obj:`X509Req.get_extensions` returns a :py:obj:`list` of
1347 extensions added to this X509 request.
1348 """
1349 request = X509Req()
1350 exts = request.get_extensions()
1351 self.assertEqual(exts, [])
1352 request.add_extensions([
Alex Gaynore7f51982016-09-11 11:48:14 -04001353 X509Extension(b'basicConstraints', True, b'CA:true'),
1354 X509Extension(b'keyUsage', False, b'digitalSignature')])
Stephen Holsapple7fbdf642014-03-01 20:05:47 -08001355 exts = request.get_extensions()
1356 self.assertEqual(len(exts), 2)
Alex Gaynore7f51982016-09-11 11:48:14 -04001357 self.assertEqual(exts[0].get_short_name(), b'basicConstraints')
Stephen Holsapple7fbdf642014-03-01 20:05:47 -08001358 self.assertEqual(exts[0].get_critical(), 1)
Alex Gaynore7f51982016-09-11 11:48:14 -04001359 self.assertEqual(exts[0].get_data(), b'0\x03\x01\x01\xff')
1360 self.assertEqual(exts[1].get_short_name(), b'keyUsage')
Stephen Holsapple7fbdf642014-03-01 20:05:47 -08001361 self.assertEqual(exts[1].get_critical(), 0)
Alex Gaynore7f51982016-09-11 11:48:14 -04001362 self.assertEqual(exts[1].get_data(), b'\x03\x02\x07\x80')
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001363
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001364 def test_add_extensions_wrong_args(self):
1365 """
Alex Gaynor31287502015-09-05 16:11:27 -04001366 :py:obj:`X509Req.add_extensions` raises :py:obj:`TypeError` if called
1367 with the wrong number of arguments or with a non-:py:obj:`list`. Or it
1368 raises :py:obj:`ValueError` if called with a :py:obj:`list` containing
1369 objects other than :py:obj:`X509Extension` instances.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001370 """
1371 request = X509Req()
1372 self.assertRaises(TypeError, request.add_extensions)
1373 self.assertRaises(TypeError, request.add_extensions, object())
1374 self.assertRaises(ValueError, request.add_extensions, [object()])
1375 self.assertRaises(TypeError, request.add_extensions, [], None)
1376
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001377 def test_verify_wrong_args(self):
1378 """
1379 :py:obj:`X509Req.verify` raises :py:obj:`TypeError` if called with zero
1380 arguments or more than one argument or if passed anything other than a
1381 :py:obj:`PKey` instance as its single argument.
1382 """
1383 request = X509Req()
1384 self.assertRaises(TypeError, request.verify)
1385 self.assertRaises(TypeError, request.verify, object())
1386 self.assertRaises(TypeError, request.verify, PKey(), object())
1387
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001388 def test_verify_uninitialized_key(self):
1389 """
Alex Gaynor31287502015-09-05 16:11:27 -04001390 :py:obj:`X509Req.verify` raises :py:obj:`OpenSSL.crypto.Error` if
1391 called with a :py:obj:`OpenSSL.crypto.PKey` which contains no key data.
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001392 """
1393 request = X509Req()
1394 pkey = PKey()
1395 self.assertRaises(Error, request.verify, pkey)
1396
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001397 def test_verify_wrong_key(self):
1398 """
Alex Gaynor31287502015-09-05 16:11:27 -04001399 :py:obj:`X509Req.verify` raises :py:obj:`OpenSSL.crypto.Error` if
1400 called with a :py:obj:`OpenSSL.crypto.PKey` which does not represent
1401 the public part of the key which signed the request.
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001402 """
1403 request = X509Req()
1404 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001405 request.sign(pkey, GOOD_DIGEST)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001406 another_pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
1407 self.assertRaises(Error, request.verify, another_pkey)
1408
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001409 def test_verify_success(self):
1410 """
1411 :py:obj:`X509Req.verify` returns :py:obj:`True` if called with a
Alex Gaynor31287502015-09-05 16:11:27 -04001412 :py:obj:`OpenSSL.crypto.PKey` which represents the public part of the
1413 key which signed the request.
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001414 """
1415 request = X509Req()
1416 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001417 request.sign(pkey, GOOD_DIGEST)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001418 self.assertEqual(True, request.verify(pkey))
1419
1420
Jean-Paul Calderone18808652009-07-05 12:54:05 -04001421class X509Tests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001422 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001423 Tests for :py:obj:`OpenSSL.crypto.X509`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001424 """
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001425 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
Jean-Paul Calderone8114b452008-03-25 15:27:59 -04001426
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001427 extpem = """
1428-----BEGIN CERTIFICATE-----
1429MIIC3jCCAkegAwIBAgIJAJHFjlcCgnQzMA0GCSqGSIb3DQEBBQUAMEcxCzAJBgNV
1430BAYTAlNFMRUwEwYDVQQIEwxXZXN0ZXJib3R0b20xEjAQBgNVBAoTCUNhdGFsb2dp
1431eDENMAsGA1UEAxMEUm9vdDAeFw0wODA0MjIxNDQ1MzhaFw0wOTA0MjIxNDQ1Mzha
1432MFQxCzAJBgNVBAYTAlNFMQswCQYDVQQIEwJXQjEUMBIGA1UEChMLT3Blbk1ldGFk
1433aXIxIjAgBgNVBAMTGW5vZGUxLm9tMi5vcGVubWV0YWRpci5vcmcwgZ8wDQYJKoZI
1434hvcNAQEBBQADgY0AMIGJAoGBAPIcQMrwbk2nESF/0JKibj9i1x95XYAOwP+LarwT
1435Op4EQbdlI9SY+uqYqlERhF19w7CS+S6oyqx0DRZSk4Y9dZ9j9/xgm2u/f136YS1u
1436zgYFPvfUs6PqYLPSM8Bw+SjJ+7+2+TN+Tkiof9WP1cMjodQwOmdsiRbR0/J7+b1B
1437hec1AgMBAAGjgcQwgcEwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNT
1438TCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFIdHsBcMVVMbAO7j6NCj
143903HgLnHaMB8GA1UdIwQYMBaAFL2h9Bf9Mre4vTdOiHTGAt7BRY/8MEYGA1UdEQQ/
1440MD2CDSouZXhhbXBsZS5vcmeCESoub20yLmV4bWFwbGUuY29thwSC7wgKgRNvbTJA
1441b3Blbm1ldGFkaXIub3JnMA0GCSqGSIb3DQEBBQUAA4GBALd7WdXkp2KvZ7/PuWZA
1442MPlIxyjS+Ly11+BNE0xGQRp9Wz+2lABtpgNqssvU156+HkKd02rGheb2tj7MX9hG
1443uZzbwDAZzJPjzDQDD7d3cWsrVcfIdqVU7epHqIadnOF+X0ghJ39pAm6VVadnSXCt
1444WpOdIpB8KksUTCzV591Nr1wd
1445-----END CERTIFICATE-----
1446 """
Alex Gaynoraceb3e22015-09-05 12:00:22 -04001447
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001448 def signable(self):
1449 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001450 Create and return a new :py:obj:`X509`.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001451 """
1452 return X509()
1453
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001454 def test_type(self):
1455 """
Alex Gaynor31287502015-09-05 16:11:27 -04001456 :py:obj:`X509` and :py:obj:`X509Type` refer to the same type object and
1457 can be used to create instances of that type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001458 """
1459 self.assertIdentical(X509, X509Type)
1460 self.assertConsistentType(X509, 'X509')
1461
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001462 def test_construction(self):
1463 """
Alex Gaynor31287502015-09-05 16:11:27 -04001464 :py:obj:`X509` takes no arguments and returns an instance of
1465 :py:obj:`X509Type`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001466 """
1467 certificate = X509()
1468 self.assertTrue(
1469 isinstance(certificate, X509Type),
1470 "%r is of type %r, should be %r" % (certificate,
1471 type(certificate),
1472 X509Type))
Rick Deane15b1472009-07-09 15:53:42 -05001473 self.assertEqual(type(X509Type).__name__, 'type')
1474 self.assertEqual(type(certificate).__name__, 'X509')
1475 self.assertEqual(type(certificate), X509Type)
Rick Dean04113e72009-07-16 12:06:35 -05001476 self.assertEqual(type(certificate), X509)
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001477
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001478 def test_get_version_wrong_args(self):
1479 """
Alex Gaynor31287502015-09-05 16:11:27 -04001480 :py:obj:`X509.get_version` raises :py:obj:`TypeError` if invoked with
1481 any arguments.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001482 """
1483 cert = X509()
1484 self.assertRaises(TypeError, cert.get_version, None)
1485
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001486 def test_set_version_wrong_args(self):
1487 """
Alex Gaynor31287502015-09-05 16:11:27 -04001488 :py:obj:`X509.set_version` raises :py:obj:`TypeError` if invoked with
1489 the wrong number of arguments or an argument not of type :py:obj:`int`.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001490 """
1491 cert = X509()
1492 self.assertRaises(TypeError, cert.set_version)
1493 self.assertRaises(TypeError, cert.set_version, None)
1494 self.assertRaises(TypeError, cert.set_version, 1, None)
1495
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001496 def test_version(self):
1497 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001498 :py:obj:`X509.set_version` sets the certificate version number.
1499 :py:obj:`X509.get_version` retrieves it.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001500 """
1501 cert = X509()
1502 cert.set_version(1234)
1503 self.assertEquals(cert.get_version(), 1234)
1504
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001505 def test_get_serial_number_wrong_args(self):
1506 """
Alex Gaynor31287502015-09-05 16:11:27 -04001507 :py:obj:`X509.get_serial_number` raises :py:obj:`TypeError` if invoked
1508 with any arguments.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001509 """
1510 cert = X509()
1511 self.assertRaises(TypeError, cert.get_serial_number, None)
1512
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001513 def test_serial_number(self):
1514 """
Alex Gaynor31287502015-09-05 16:11:27 -04001515 The serial number of an :py:obj:`X509Type` can be retrieved and
1516 modified with :py:obj:`X509Type.get_serial_number` and
1517 :py:obj:`X509Type.set_serial_number`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001518 """
1519 certificate = X509()
1520 self.assertRaises(TypeError, certificate.set_serial_number)
1521 self.assertRaises(TypeError, certificate.set_serial_number, 1, 2)
1522 self.assertRaises(TypeError, certificate.set_serial_number, "1")
1523 self.assertRaises(TypeError, certificate.set_serial_number, 5.5)
1524 self.assertEqual(certificate.get_serial_number(), 0)
1525 certificate.set_serial_number(1)
1526 self.assertEqual(certificate.get_serial_number(), 1)
1527 certificate.set_serial_number(2 ** 32 + 1)
1528 self.assertEqual(certificate.get_serial_number(), 2 ** 32 + 1)
1529 certificate.set_serial_number(2 ** 64 + 1)
1530 self.assertEqual(certificate.get_serial_number(), 2 ** 64 + 1)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001531 certificate.set_serial_number(2 ** 128 + 1)
1532 self.assertEqual(certificate.get_serial_number(), 2 ** 128 + 1)
1533
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001534 def _setBoundTest(self, which):
1535 """
Alex Gaynor31287502015-09-05 16:11:27 -04001536 :py:obj:`X509Type.set_notBefore` takes a string in the format of an
1537 ASN1 GENERALIZEDTIME and sets the beginning of the certificate's
1538 validity period to it.
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001539 """
1540 certificate = X509()
1541 set = getattr(certificate, 'set_not' + which)
1542 get = getattr(certificate, 'get_not' + which)
1543
Jean-Paul Calderonee0615b52008-03-09 21:44:46 -04001544 # Starts with no value.
1545 self.assertEqual(get(), None)
1546
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001547 # GMT (Or is it UTC?) -exarkun
Alex Gaynore7f51982016-09-11 11:48:14 -04001548 when = b"20040203040506Z"
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001549 set(when)
1550 self.assertEqual(get(), when)
1551
1552 # A plus two hours and thirty minutes offset
Alex Gaynore7f51982016-09-11 11:48:14 -04001553 when = b"20040203040506+0530"
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001554 set(when)
1555 self.assertEqual(get(), when)
1556
1557 # A minus one hour fifteen minutes offset
Alex Gaynore7f51982016-09-11 11:48:14 -04001558 when = b"20040203040506-0115"
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001559 set(when)
1560 self.assertEqual(get(), when)
1561
1562 # An invalid string results in a ValueError
Alex Gaynore7f51982016-09-11 11:48:14 -04001563 self.assertRaises(ValueError, set, b"foo bar")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001564
Jean-Paul Calderone31ca2002010-01-30 15:14:43 -05001565 # The wrong number of arguments results in a TypeError.
1566 self.assertRaises(TypeError, set)
Alex Gaynor85b49702015-09-05 16:30:59 -04001567 with pytest.raises(TypeError):
1568 set(b"20040203040506Z", b"20040203040506Z")
Alex Gaynore7f51982016-09-11 11:48:14 -04001569 self.assertRaises(TypeError, get, b"foo bar")
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001570
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001571 # XXX ASN1_TIME (not GENERALIZEDTIME)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001572
1573 def test_set_notBefore(self):
1574 """
Alex Gaynor31287502015-09-05 16:11:27 -04001575 :py:obj:`X509Type.set_notBefore` takes a string in the format of an
1576 ASN1 GENERALIZEDTIME and sets the beginning of the certificate's
1577 validity period to it.
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001578 """
1579 self._setBoundTest("Before")
1580
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001581 def test_set_notAfter(self):
1582 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001583 :py:obj:`X509Type.set_notAfter` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001584 GENERALIZEDTIME and sets the end of the certificate's validity period
1585 to it.
1586 """
1587 self._setBoundTest("After")
Jean-Paul Calderone76576d52008-03-24 16:04:46 -04001588
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001589 def test_get_notBefore(self):
1590 """
Alex Gaynor31287502015-09-05 16:11:27 -04001591 :py:obj:`X509Type.get_notBefore` returns a string in the format of an
1592 ASN1 GENERALIZEDTIME even for certificates which store it as UTCTIME
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001593 internally.
1594 """
Jean-Paul Calderone8114b452008-03-25 15:27:59 -04001595 cert = load_certificate(FILETYPE_PEM, self.pemData)
Alex Gaynore7f51982016-09-11 11:48:14 -04001596 self.assertEqual(cert.get_notBefore(), b"20090325123658Z")
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001597
Rick Dean38a05c82009-07-18 01:41:30 -05001598 def test_get_notAfter(self):
1599 """
Alex Gaynor31287502015-09-05 16:11:27 -04001600 :py:obj:`X509Type.get_notAfter` returns a string in the format of an
1601 ASN1 GENERALIZEDTIME even for certificates which store it as UTCTIME
Rick Dean38a05c82009-07-18 01:41:30 -05001602 internally.
1603 """
1604 cert = load_certificate(FILETYPE_PEM, self.pemData)
Alex Gaynore7f51982016-09-11 11:48:14 -04001605 self.assertEqual(cert.get_notAfter(), b"20170611123658Z")
Rick Dean38a05c82009-07-18 01:41:30 -05001606
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001607 def test_gmtime_adj_notBefore_wrong_args(self):
1608 """
Alex Gaynor31287502015-09-05 16:11:27 -04001609 :py:obj:`X509Type.gmtime_adj_notBefore` raises :py:obj:`TypeError` if
1610 called with the wrong number of arguments or a non-:py:obj:`int`
1611 argument.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001612 """
1613 cert = X509()
1614 self.assertRaises(TypeError, cert.gmtime_adj_notBefore)
1615 self.assertRaises(TypeError, cert.gmtime_adj_notBefore, None)
1616 self.assertRaises(TypeError, cert.gmtime_adj_notBefore, 123, None)
1617
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001618 def test_gmtime_adj_notBefore(self):
1619 """
Alex Gaynor31287502015-09-05 16:11:27 -04001620 :py:obj:`X509Type.gmtime_adj_notBefore` changes the not-before
1621 timestamp to be the current time plus the number of seconds passed in.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001622 """
1623 cert = load_certificate(FILETYPE_PEM, self.pemData)
Alex Gaynor85b49702015-09-05 16:30:59 -04001624 not_before_min = (
1625 datetime.utcnow().replace(microsecond=0) + timedelta(seconds=100)
1626 )
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001627 cert.gmtime_adj_notBefore(100)
Alex Gaynor85b49702015-09-05 16:30:59 -04001628 not_before = datetime.strptime(
1629 cert.get_notBefore().decode(), "%Y%m%d%H%M%SZ"
1630 )
Maximilian Hilsbed25c92015-07-25 12:58:07 +02001631 not_before_max = datetime.utcnow() + timedelta(seconds=100)
1632 self.assertTrue(not_before_min <= not_before <= not_before_max)
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001633
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001634 def test_gmtime_adj_notAfter_wrong_args(self):
1635 """
Alex Gaynor31287502015-09-05 16:11:27 -04001636 :py:obj:`X509Type.gmtime_adj_notAfter` raises :py:obj:`TypeError` if
1637 called with the wrong number of arguments or a non-:py:obj:`int`
1638 argument.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001639 """
1640 cert = X509()
1641 self.assertRaises(TypeError, cert.gmtime_adj_notAfter)
1642 self.assertRaises(TypeError, cert.gmtime_adj_notAfter, None)
1643 self.assertRaises(TypeError, cert.gmtime_adj_notAfter, 123, None)
1644
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001645 def test_gmtime_adj_notAfter(self):
1646 """
Alex Gaynor31287502015-09-05 16:11:27 -04001647 :py:obj:`X509Type.gmtime_adj_notAfter` changes the not-after timestamp
1648 to be the current time plus the number of seconds passed in.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001649 """
1650 cert = load_certificate(FILETYPE_PEM, self.pemData)
Alex Gaynor85b49702015-09-05 16:30:59 -04001651 not_after_min = (
1652 datetime.utcnow().replace(microsecond=0) + timedelta(seconds=100)
1653 )
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001654 cert.gmtime_adj_notAfter(100)
Alex Gaynor85b49702015-09-05 16:30:59 -04001655 not_after = datetime.strptime(
1656 cert.get_notAfter().decode(), "%Y%m%d%H%M%SZ"
1657 )
Maximilian Hilsbed25c92015-07-25 12:58:07 +02001658 not_after_max = datetime.utcnow() + timedelta(seconds=100)
1659 self.assertTrue(not_after_min <= not_after <= not_after_max)
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001660
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001661 def test_has_expired_wrong_args(self):
1662 """
Alex Gaynor31287502015-09-05 16:11:27 -04001663 :py:obj:`X509Type.has_expired` raises :py:obj:`TypeError` if called
1664 with any arguments.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001665 """
1666 cert = X509()
1667 self.assertRaises(TypeError, cert.has_expired, None)
1668
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001669 def test_has_expired(self):
1670 """
Alex Gaynor31287502015-09-05 16:11:27 -04001671 :py:obj:`X509Type.has_expired` returns :py:obj:`True` if the
1672 certificate's not-after time is in the past.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001673 """
1674 cert = X509()
1675 cert.gmtime_adj_notAfter(-1)
1676 self.assertTrue(cert.has_expired())
1677
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001678 def test_has_not_expired(self):
1679 """
Alex Gaynor31287502015-09-05 16:11:27 -04001680 :py:obj:`X509Type.has_expired` returns :py:obj:`False` if the
1681 certificate's not-after time is in the future.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001682 """
1683 cert = X509()
1684 cert.gmtime_adj_notAfter(2)
1685 self.assertFalse(cert.has_expired())
1686
Jeff Tangfc18f7b2015-04-15 17:42:33 -04001687 def test_root_has_not_expired(self):
1688 """
Alex Gaynor31287502015-09-05 16:11:27 -04001689 :py:obj:`X509Type.has_expired` returns :py:obj:`False` if the
1690 certificate's not-after time is in the future.
Jeff Tangfc18f7b2015-04-15 17:42:33 -04001691 """
1692 cert = load_certificate(FILETYPE_PEM, root_cert_pem)
1693 self.assertFalse(cert.has_expired())
1694
Rick Dean38a05c82009-07-18 01:41:30 -05001695 def test_digest(self):
1696 """
Alex Gaynor31287502015-09-05 16:11:27 -04001697 :py:obj:`X509.digest` returns a string giving ":"-separated hex-encoded
1698 words of the digest of the certificate.
Rick Dean38a05c82009-07-18 01:41:30 -05001699 """
Jeff Tangfc18f7b2015-04-15 17:42:33 -04001700 cert = load_certificate(FILETYPE_PEM, root_cert_pem)
Rick Dean38a05c82009-07-18 01:41:30 -05001701 self.assertEqual(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001702 # This is MD5 instead of GOOD_DIGEST because the digest algorithm
1703 # actually matters to the assertion (ie, another arbitrary, good
1704 # digest will not product the same digest).
Jeff Tangfc18f7b2015-04-15 17:42:33 -04001705 # Digest verified with the command:
1706 # openssl x509 -in root_cert.pem -noout -fingerprint -md5
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001707 cert.digest("MD5"),
Alex Gaynore7f51982016-09-11 11:48:14 -04001708 b"19:B3:05:26:2B:F8:F2:FF:0B:8F:21:07:A8:28:B8:75")
Rick Dean38a05c82009-07-18 01:41:30 -05001709
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001710 def _extcert(self, pkey, extensions):
1711 cert = X509()
1712 cert.set_pubkey(pkey)
1713 cert.get_subject().commonName = "Unit Tests"
1714 cert.get_issuer().commonName = "Unit Tests"
Alex Gaynore7f51982016-09-11 11:48:14 -04001715 when = datetime.now().strftime("%Y%m%d%H%M%SZ").encode("ascii")
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001716 cert.set_notBefore(when)
1717 cert.set_notAfter(when)
1718
1719 cert.add_extensions(extensions)
Jeff Tangfc18f7b2015-04-15 17:42:33 -04001720 cert.sign(pkey, 'sha1')
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001721 return load_certificate(
1722 FILETYPE_PEM, dump_certificate(FILETYPE_PEM, cert))
1723
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001724 def test_extension_count(self):
1725 """
Alex Gaynor31287502015-09-05 16:11:27 -04001726 :py:obj:`X509.get_extension_count` returns the number of extensions
1727 that are present in the certificate.
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001728 """
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001729 pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
Alex Gaynore7f51982016-09-11 11:48:14 -04001730 ca = X509Extension(b'basicConstraints', True, b'CA:FALSE')
1731 key = X509Extension(b'keyUsage', True, b'digitalSignature')
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001732 subjectAltName = X509Extension(
Alex Gaynore7f51982016-09-11 11:48:14 -04001733 b'subjectAltName', True, b'DNS:example.com')
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001734
1735 # Try a certificate with no extensions at all.
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001736 c = self._extcert(pkey, [])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001737 self.assertEqual(c.get_extension_count(), 0)
1738
1739 # And a certificate with one
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001740 c = self._extcert(pkey, [ca])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001741 self.assertEqual(c.get_extension_count(), 1)
1742
1743 # And a certificate with several
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001744 c = self._extcert(pkey, [ca, key, subjectAltName])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001745 self.assertEqual(c.get_extension_count(), 3)
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001746
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001747 def test_get_extension(self):
1748 """
Alex Gaynor31287502015-09-05 16:11:27 -04001749 :py:obj:`X509.get_extension` takes an integer and returns an
1750 :py:obj:`X509Extension` corresponding to the extension at that index.
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001751 """
1752 pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
Alex Gaynore7f51982016-09-11 11:48:14 -04001753 ca = X509Extension(b'basicConstraints', True, b'CA:FALSE')
1754 key = X509Extension(b'keyUsage', True, b'digitalSignature')
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001755 subjectAltName = X509Extension(
Alex Gaynore7f51982016-09-11 11:48:14 -04001756 b'subjectAltName', False, b'DNS:example.com')
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001757
1758 cert = self._extcert(pkey, [ca, key, subjectAltName])
1759
1760 ext = cert.get_extension(0)
1761 self.assertTrue(isinstance(ext, X509Extension))
1762 self.assertTrue(ext.get_critical())
Alex Gaynore7f51982016-09-11 11:48:14 -04001763 self.assertEqual(ext.get_short_name(), b'basicConstraints')
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001764
1765 ext = cert.get_extension(1)
1766 self.assertTrue(isinstance(ext, X509Extension))
1767 self.assertTrue(ext.get_critical())
Alex Gaynore7f51982016-09-11 11:48:14 -04001768 self.assertEqual(ext.get_short_name(), b'keyUsage')
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001769
1770 ext = cert.get_extension(2)
1771 self.assertTrue(isinstance(ext, X509Extension))
1772 self.assertFalse(ext.get_critical())
Alex Gaynore7f51982016-09-11 11:48:14 -04001773 self.assertEqual(ext.get_short_name(), b'subjectAltName')
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001774
1775 self.assertRaises(IndexError, cert.get_extension, -1)
1776 self.assertRaises(IndexError, cert.get_extension, 4)
1777 self.assertRaises(TypeError, cert.get_extension, "hello")
1778
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001779 def test_nullbyte_subjectAltName(self):
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001780 """
Jean-Paul Calderone9af07b02013-08-23 16:07:31 -04001781 The fields of a `subjectAltName` extension on an X509 may contain NUL
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001782 bytes and this value is reflected in the string representation of the
1783 extension object.
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001784 """
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001785 cert = load_certificate(FILETYPE_PEM, nulbyteSubjectAltNamePEM)
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001786
1787 ext = cert.get_extension(3)
Alex Gaynore7f51982016-09-11 11:48:14 -04001788 self.assertEqual(ext.get_short_name(), b'subjectAltName')
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001789 self.assertEqual(
Alex Gaynore7f51982016-09-11 11:48:14 -04001790 b"DNS:altnull.python.org\x00example.com, "
1791 b"email:null@python.org\x00user@example.org, "
1792 b"URI:http://null.python.org\x00http://example.org, "
1793 b"IP Address:192.0.2.1, IP Address:2001:DB8:0:0:0:0:0:1\n",
1794 str(ext).encode("ascii"))
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001795
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001796 def test_invalid_digest_algorithm(self):
1797 """
Alex Gaynor31287502015-09-05 16:11:27 -04001798 :py:obj:`X509.digest` raises :py:obj:`ValueError` if called with an
1799 unrecognized hash algorithm.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001800 """
1801 cert = X509()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001802 self.assertRaises(ValueError, cert.digest, BAD_DIGEST)
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001803
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001804 def test_get_subject_wrong_args(self):
1805 """
Alex Gaynor31287502015-09-05 16:11:27 -04001806 :py:obj:`X509.get_subject` raises :py:obj:`TypeError` if called with
1807 any arguments.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001808 """
1809 cert = X509()
1810 self.assertRaises(TypeError, cert.get_subject, None)
1811
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001812 def test_get_subject(self):
1813 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001814 :py:obj:`X509.get_subject` returns an :py:obj:`X509Name` instance.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001815 """
1816 cert = load_certificate(FILETYPE_PEM, self.pemData)
1817 subj = cert.get_subject()
1818 self.assertTrue(isinstance(subj, X509Name))
1819 self.assertEquals(
1820 subj.get_components(),
Alex Gaynore7f51982016-09-11 11:48:14 -04001821 [(b'C', b'US'), (b'ST', b'IL'), (b'L', b'Chicago'),
1822 (b'O', b'Testing'), (b'CN', b'Testing Root CA')])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001823
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001824 def test_set_subject_wrong_args(self):
1825 """
Alex Gaynor31287502015-09-05 16:11:27 -04001826 :py:obj:`X509.set_subject` raises a :py:obj:`TypeError` if called with
1827 the wrong number of arguments or an argument not of type
1828 :py:obj:`X509Name`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001829 """
1830 cert = X509()
1831 self.assertRaises(TypeError, cert.set_subject)
1832 self.assertRaises(TypeError, cert.set_subject, None)
Alex Gaynor85b49702015-09-05 16:30:59 -04001833 with pytest.raises(TypeError):
1834 cert.set_subject(cert.get_subject(), None)
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001835
1836 def test_set_subject(self):
1837 """
Alex Gaynor31287502015-09-05 16:11:27 -04001838 :py:obj:`X509.set_subject` changes the subject of the certificate to
1839 the one passed in.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001840 """
1841 cert = X509()
1842 name = cert.get_subject()
1843 name.C = 'AU'
1844 name.O = 'Unit Tests'
1845 cert.set_subject(name)
1846 self.assertEquals(
1847 cert.get_subject().get_components(),
Alex Gaynore7f51982016-09-11 11:48:14 -04001848 [(b'C', b'AU'), (b'O', b'Unit Tests')])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001849
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001850 def test_get_issuer_wrong_args(self):
1851 """
Alex Gaynor31287502015-09-05 16:11:27 -04001852 :py:obj:`X509.get_issuer` raises :py:obj:`TypeError` if called with any
1853 arguments.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001854 """
1855 cert = X509()
1856 self.assertRaises(TypeError, cert.get_issuer, None)
1857
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001858 def test_get_issuer(self):
1859 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001860 :py:obj:`X509.get_issuer` returns an :py:obj:`X509Name` instance.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001861 """
1862 cert = load_certificate(FILETYPE_PEM, self.pemData)
1863 subj = cert.get_issuer()
1864 self.assertTrue(isinstance(subj, X509Name))
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001865 comp = subj.get_components()
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001866 self.assertEquals(
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001867 comp,
Alex Gaynore7f51982016-09-11 11:48:14 -04001868 [(b'C', b'US'), (b'ST', b'IL'), (b'L', b'Chicago'),
1869 (b'O', b'Testing'), (b'CN', b'Testing Root CA')])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001870
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001871 def test_set_issuer_wrong_args(self):
1872 """
Alex Gaynor31287502015-09-05 16:11:27 -04001873 :py:obj:`X509.set_issuer` raises a :py:obj:`TypeError` if called with
1874 the wrong number of arguments or an argument not of type
1875 :py:obj:`X509Name`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001876 """
1877 cert = X509()
1878 self.assertRaises(TypeError, cert.set_issuer)
1879 self.assertRaises(TypeError, cert.set_issuer, None)
1880 self.assertRaises(TypeError, cert.set_issuer, cert.get_issuer(), None)
1881
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001882 def test_set_issuer(self):
1883 """
Alex Gaynor31287502015-09-05 16:11:27 -04001884 :py:obj:`X509.set_issuer` changes the issuer of the certificate to the
1885 one passed in.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001886 """
1887 cert = X509()
1888 name = cert.get_issuer()
1889 name.C = 'AU'
1890 name.O = 'Unit Tests'
1891 cert.set_issuer(name)
1892 self.assertEquals(
1893 cert.get_issuer().get_components(),
Alex Gaynore7f51982016-09-11 11:48:14 -04001894 [(b'C', b'AU'), (b'O', b'Unit Tests')])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001895
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001896 def test_get_pubkey_uninitialized(self):
1897 """
Alex Gaynor31287502015-09-05 16:11:27 -04001898 When called on a certificate with no public key,
1899 :py:obj:`X509.get_pubkey` raises :py:obj:`OpenSSL.crypto.Error`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001900 """
1901 cert = X509()
1902 self.assertRaises(Error, cert.get_pubkey)
1903
Alex Gaynor7778e792016-07-03 23:38:48 -04001904 def test_set_pubkey_wrong_type(self):
1905 """
1906 :obj:`X509.set_pubkey` raises :obj:`TypeError` when given an object of
1907 the wrong type.
1908 """
1909 cert = X509()
1910 with pytest.raises(TypeError):
1911 cert.set_pubkey(object())
1912
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001913 def test_subject_name_hash_wrong_args(self):
1914 """
Alex Gaynor31287502015-09-05 16:11:27 -04001915 :py:obj:`X509.subject_name_hash` raises :py:obj:`TypeError` if called
1916 with any arguments.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001917 """
1918 cert = X509()
1919 self.assertRaises(TypeError, cert.subject_name_hash, None)
1920
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001921 def test_subject_name_hash(self):
1922 """
Alex Gaynor31287502015-09-05 16:11:27 -04001923 :py:obj:`X509.subject_name_hash` returns the hash of the certificate's
1924 subject name.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001925 """
1926 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -04001927 self.assertIn(
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001928 cert.subject_name_hash(),
Alex Gaynoraceb3e22015-09-05 12:00:22 -04001929 [3350047874, # OpenSSL 0.9.8, MD5
1930 3278919224, # OpenSSL 1.0.0, SHA1
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -04001931 ])
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001932
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001933 def test_get_signature_algorithm(self):
1934 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001935 :py:obj:`X509Type.get_signature_algorithm` returns a string which means
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001936 the algorithm used to sign the certificate.
1937 """
1938 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001939 self.assertEqual(
Alex Gaynore7f51982016-09-11 11:48:14 -04001940 b"sha1WithRSAEncryption", cert.get_signature_algorithm())
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001941
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001942 def test_get_undefined_signature_algorithm(self):
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001943 """
Alex Gaynor31287502015-09-05 16:11:27 -04001944 :py:obj:`X509Type.get_signature_algorithm` raises :py:obj:`ValueError`
1945 if the signature algorithm is undefined or unknown.
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001946 """
1947 # This certificate has been modified to indicate a bogus OID in the
1948 # signature algorithm field so that OpenSSL does not recognize it.
Alex Gaynore7f51982016-09-11 11:48:14 -04001949 certPEM = b"""\
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001950-----BEGIN CERTIFICATE-----
1951MIIC/zCCAmigAwIBAgIBATAGBgJ8BQUAMHsxCzAJBgNVBAYTAlNHMREwDwYDVQQK
1952EwhNMkNyeXB0bzEUMBIGA1UECxMLTTJDcnlwdG8gQ0ExJDAiBgNVBAMTG00yQ3J5
1953cHRvIENlcnRpZmljYXRlIE1hc3RlcjEdMBsGCSqGSIb3DQEJARYObmdwc0Bwb3N0
1954MS5jb20wHhcNMDAwOTEwMDk1MTMwWhcNMDIwOTEwMDk1MTMwWjBTMQswCQYDVQQG
1955EwJTRzERMA8GA1UEChMITTJDcnlwdG8xEjAQBgNVBAMTCWxvY2FsaG9zdDEdMBsG
1956CSqGSIb3DQEJARYObmdwc0Bwb3N0MS5jb20wXDANBgkqhkiG9w0BAQEFAANLADBI
1957AkEArL57d26W9fNXvOhNlZzlPOACmvwOZ5AdNgLzJ1/MfsQQJ7hHVeHmTAjM664V
1958+fXvwUGJLziCeBo1ysWLRnl8CQIDAQABo4IBBDCCAQAwCQYDVR0TBAIwADAsBglg
1959hkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0O
1960BBYEFM+EgpK+eyZiwFU1aOPSbczbPSpVMIGlBgNVHSMEgZ0wgZqAFPuHI2nrnDqT
1961FeXFvylRT/7tKDgBoX+kfTB7MQswCQYDVQQGEwJTRzERMA8GA1UEChMITTJDcnlw
1962dG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtNMkNyeXB0byBDZXJ0
1963aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tggEA
1964MA0GCSqGSIb3DQEBBAUAA4GBADv8KpPo+gfJxN2ERK1Y1l17sz/ZhzoGgm5XCdbx
1965jEY7xKfpQngV599k1xhl11IMqizDwu0855agrckg2MCTmOI9DZzDD77tAYb+Dk0O
1966PEVk0Mk/V0aIsDE9bolfCi/i/QWZ3N8s5nTWMNyBBBmoSliWCm4jkkRZRD0ejgTN
1967tgI5
1968-----END CERTIFICATE-----
Alex Gaynore7f51982016-09-11 11:48:14 -04001969"""
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001970 cert = load_certificate(FILETYPE_PEM, certPEM)
1971 self.assertRaises(ValueError, cert.get_signature_algorithm)
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001972
Alex Gaynor37726112016-07-04 09:51:32 -04001973 def test_sign_bad_pubkey_type(self):
1974 """
1975 :obj:`X509.sign` raises :obj:`TypeError` when called with the wrong
1976 type.
1977 """
1978 cert = X509()
1979 with pytest.raises(TypeError):
1980 cert.sign(object(), b"sha256")
1981
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001982
Alex Chan9e2a9932017-01-25 14:29:19 +00001983class TestX509Store(object):
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001984 """
Alex Chan9e2a9932017-01-25 14:29:19 +00001985 Test for `OpenSSL.crypto.X509Store`.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001986 """
Alex Gaynoraceb3e22015-09-05 12:00:22 -04001987
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001988 def test_type(self):
1989 """
Alex Chan9e2a9932017-01-25 14:29:19 +00001990 `X509Store` is a type object.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001991 """
Alex Chan9e2a9932017-01-25 14:29:19 +00001992 assert X509Store is X509StoreType
1993 assert is_consistent_type(X509Store, 'X509Store')
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001994
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001995 def test_add_cert(self):
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001996 """
Alex Chan9e2a9932017-01-25 14:29:19 +00001997 `X509Store.add_cert` adds a `X509` instance to the certificate store.
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001998 """
1999 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002000 store = X509Store()
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08002001 store.add_cert(cert)
2002
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08002003 def test_add_cert_rejects_duplicate(self):
2004 """
Alex Chan9e2a9932017-01-25 14:29:19 +00002005 `X509Store.add_cert` raises `OpenSSL.crypto.Error` if an attempt is
2006 made to add the same certificate to the store more than once.
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08002007 """
2008 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
2009 store = X509Store()
2010 store.add_cert(cert)
Alex Chan9e2a9932017-01-25 14:29:19 +00002011 with pytest.raises(Error):
2012 store.add_cert(cert)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002013
2014
Rick Dean623ee362009-07-17 12:22:16 -05002015class PKCS12Tests(TestCase):
2016 """
Alex Gaynor31287502015-09-05 16:11:27 -04002017 Test for :py:obj:`OpenSSL.crypto.PKCS12` and
2018 :py:obj:`OpenSSL.crypto.load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05002019 """
2020 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
2021
Jean-Paul Calderonec3a41f72009-07-25 12:36:02 -04002022 def test_type(self):
2023 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002024 :py:obj:`PKCS12Type` is a type object.
Jean-Paul Calderonec3a41f72009-07-25 12:36:02 -04002025 """
2026 self.assertIdentical(PKCS12, PKCS12Type)
2027 self.assertConsistentType(PKCS12, 'PKCS12')
2028
Rick Deanf94096c2009-07-18 14:23:06 -05002029 def test_empty_construction(self):
Rick Dean38a05c82009-07-18 01:41:30 -05002030 """
Alex Gaynor31287502015-09-05 16:11:27 -04002031 :py:obj:`PKCS12` returns a new instance of :py:obj:`PKCS12` with no
2032 certificate, private key, CA certificates, or friendly name.
Rick Dean38a05c82009-07-18 01:41:30 -05002033 """
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002034 p12 = PKCS12()
Rick Dean623ee362009-07-17 12:22:16 -05002035 self.assertEqual(None, p12.get_certificate())
2036 self.assertEqual(None, p12.get_privatekey())
2037 self.assertEqual(None, p12.get_ca_certificates())
Rick Dean42d69e12009-07-20 11:36:08 -05002038 self.assertEqual(None, p12.get_friendlyname())
Rick Dean623ee362009-07-17 12:22:16 -05002039
2040 def test_type_errors(self):
Rick Dean38a05c82009-07-18 01:41:30 -05002041 """
Alex Gaynor31287502015-09-05 16:11:27 -04002042 The :py:obj:`PKCS12` setter functions (:py:obj:`set_certificate`,
2043 :py:obj:`set_privatekey`, :py:obj:`set_ca_certificates`, and
2044 :py:obj:`set_friendlyname`) raise :py:obj:`TypeError` when passed
2045 objects of types other than those expected.
Rick Dean38a05c82009-07-18 01:41:30 -05002046 """
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002047 p12 = PKCS12()
Rick Dean623ee362009-07-17 12:22:16 -05002048 self.assertRaises(TypeError, p12.set_certificate, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05002049 self.assertRaises(TypeError, p12.set_certificate, PKey())
2050 self.assertRaises(TypeError, p12.set_certificate, X509)
Rick Dean623ee362009-07-17 12:22:16 -05002051 self.assertRaises(TypeError, p12.set_privatekey, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05002052 self.assertRaises(TypeError, p12.set_privatekey, 'legbone')
2053 self.assertRaises(TypeError, p12.set_privatekey, X509())
Rick Dean623ee362009-07-17 12:22:16 -05002054 self.assertRaises(TypeError, p12.set_ca_certificates, 3)
2055 self.assertRaises(TypeError, p12.set_ca_certificates, X509())
2056 self.assertRaises(TypeError, p12.set_ca_certificates, (3, 4))
Alex Gaynor7f636492015-09-04 13:26:52 -04002057 self.assertRaises(TypeError, p12.set_ca_certificates, (PKey(),))
Rick Dean42d69e12009-07-20 11:36:08 -05002058 self.assertRaises(TypeError, p12.set_friendlyname, 6)
2059 self.assertRaises(TypeError, p12.set_friendlyname, ('foo', 'bar'))
Rick Dean623ee362009-07-17 12:22:16 -05002060
2061 def test_key_only(self):
2062 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002063 A :py:obj:`PKCS12` with only a private key can be exported using
2064 :py:obj:`PKCS12.export` and loaded again using :py:obj:`load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05002065 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002066 passwd = b"blah"
Rick Dean623ee362009-07-17 12:22:16 -05002067 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002068 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002069 p12.set_privatekey(pkey)
Rick Dean623ee362009-07-17 12:22:16 -05002070 self.assertEqual(None, p12.get_certificate())
2071 self.assertEqual(pkey, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05002072 try:
2073 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
2074 except Error:
2075 # Some versions of OpenSSL will throw an exception
2076 # for this nearly useless PKCS12 we tried to generate:
2077 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
2078 return
Rick Dean623ee362009-07-17 12:22:16 -05002079 p12 = load_pkcs12(dumped_p12, passwd)
2080 self.assertEqual(None, p12.get_ca_certificates())
2081 self.assertEqual(None, p12.get_certificate())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002082
2083 # OpenSSL fails to bring the key back to us. So sad. Perhaps in the
2084 # future this will be improved.
2085 self.assertTrue(isinstance(p12.get_privatekey(), (PKey, type(None))))
Rick Dean623ee362009-07-17 12:22:16 -05002086
2087 def test_cert_only(self):
2088 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002089 A :py:obj:`PKCS12` with only a certificate can be exported using
2090 :py:obj:`PKCS12.export` and loaded again using :py:obj:`load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05002091 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002092 passwd = b"blah"
Rick Dean623ee362009-07-17 12:22:16 -05002093 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002094 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002095 p12.set_certificate(cert)
Rick Dean623ee362009-07-17 12:22:16 -05002096 self.assertEqual(cert, p12.get_certificate())
2097 self.assertEqual(None, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05002098 try:
2099 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
2100 except Error:
2101 # Some versions of OpenSSL will throw an exception
2102 # for this nearly useless PKCS12 we tried to generate:
2103 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
2104 return
Rick Dean623ee362009-07-17 12:22:16 -05002105 p12 = load_pkcs12(dumped_p12, passwd)
2106 self.assertEqual(None, p12.get_privatekey())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002107
2108 # OpenSSL fails to bring the cert back to us. Groany mcgroan.
2109 self.assertTrue(isinstance(p12.get_certificate(), (X509, type(None))))
2110
2111 # Oh ho. It puts the certificate into the ca certificates list, in
2112 # fact. Totally bogus, I would think. Nevertheless, let's exploit
2113 # that to check to see if it reconstructed the certificate we expected
2114 # it to. At some point, hopefully this will change so that
2115 # p12.get_certificate() is actually what returns the loaded
2116 # certificate.
2117 self.assertEqual(
2118 cleartextCertificatePEM,
2119 dump_certificate(FILETYPE_PEM, p12.get_ca_certificates()[0]))
Rick Dean623ee362009-07-17 12:22:16 -05002120
Alex Gaynor31287502015-09-05 16:11:27 -04002121 def gen_pkcs12(self, cert_pem=None, key_pem=None, ca_pem=None,
2122 friendly_name=None):
Rick Dean623ee362009-07-17 12:22:16 -05002123 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002124 Generate a PKCS12 object with components from PEM. Verify that the set
2125 functions return None.
Rick Dean623ee362009-07-17 12:22:16 -05002126 """
Rick Deanf94096c2009-07-18 14:23:06 -05002127 p12 = PKCS12()
2128 if cert_pem:
2129 ret = p12.set_certificate(load_certificate(FILETYPE_PEM, cert_pem))
2130 self.assertEqual(ret, None)
2131 if key_pem:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002132 ret = p12.set_privatekey(load_privatekey(FILETYPE_PEM, key_pem))
Rick Deanf94096c2009-07-18 14:23:06 -05002133 self.assertEqual(ret, None)
2134 if ca_pem:
Alex Gaynor85b49702015-09-05 16:30:59 -04002135 ret = p12.set_ca_certificates(
2136 (load_certificate(FILETYPE_PEM, ca_pem),)
2137 )
Rick Deanf94096c2009-07-18 14:23:06 -05002138 self.assertEqual(ret, None)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002139 if friendly_name:
2140 ret = p12.set_friendlyname(friendly_name)
Rick Dean42d69e12009-07-20 11:36:08 -05002141 self.assertEqual(ret, None)
Rick Deanf94096c2009-07-18 14:23:06 -05002142 return p12
2143
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002144 def check_recovery(self, p12_str, key=None, cert=None, ca=None, passwd=b"",
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002145 extra=()):
Rick Deanf94096c2009-07-18 14:23:06 -05002146 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002147 Use openssl program to confirm three components are recoverable from a
2148 PKCS12 string.
Rick Deanf94096c2009-07-18 14:23:06 -05002149 """
2150 if key:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002151 recovered_key = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002152 p12_str, b"pkcs12", b"-nocerts", b"-nodes", b"-passin",
2153 b"pass:" + passwd, *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05002154 self.assertEqual(recovered_key[-len(key):], key)
2155 if cert:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002156 recovered_cert = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002157 p12_str, b"pkcs12", b"-clcerts", b"-nodes", b"-passin",
2158 b"pass:" + passwd, b"-nokeys", *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05002159 self.assertEqual(recovered_cert[-len(cert):], cert)
2160 if ca:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002161 recovered_cert = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002162 p12_str, b"pkcs12", b"-cacerts", b"-nodes", b"-passin",
2163 b"pass:" + passwd, b"-nokeys", *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05002164 self.assertEqual(recovered_cert[-len(ca):], ca)
2165
Stephen Holsapple38482622014-04-05 20:29:34 -07002166 def verify_pkcs12_container(self, p12):
2167 """
2168 Verify that the PKCS#12 container contains the correct client
2169 certificate and private key.
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002170
2171 :param p12: The PKCS12 instance to verify.
2172 :type p12: :py:class:`PKCS12`
Stephen Holsapple38482622014-04-05 20:29:34 -07002173 """
2174 cert_pem = dump_certificate(FILETYPE_PEM, p12.get_certificate())
2175 key_pem = dump_privatekey(FILETYPE_PEM, p12.get_privatekey())
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002176 self.assertEqual(
2177 (client_cert_pem, client_key_pem, None),
2178 (cert_pem, key_pem, p12.get_ca_certificates()))
Stephen Holsapple38482622014-04-05 20:29:34 -07002179
Rick Deanf94096c2009-07-18 14:23:06 -05002180 def test_load_pkcs12(self):
2181 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002182 A PKCS12 string generated using the openssl command line can be loaded
Jonathan Ballet648875f2011-07-16 14:14:58 +09002183 with :py:obj:`load_pkcs12` and its components extracted and examined.
Rick Deanf94096c2009-07-18 14:23:06 -05002184 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002185 passwd = b"whatever"
Rick Dean623ee362009-07-17 12:22:16 -05002186 pem = client_key_pem + client_cert_pem
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002187 p12_str = _runopenssl(
Alex Gaynor85b49702015-09-05 16:30:59 -04002188 pem,
2189 b"pkcs12",
2190 b"-export",
2191 b"-clcerts",
2192 b"-passout",
2193 b"pass:" + passwd
2194 )
Stephen Holsapple38482622014-04-05 20:29:34 -07002195 p12 = load_pkcs12(p12_str, passphrase=passwd)
2196 self.verify_pkcs12_container(p12)
2197
Abraham Martinc5484ba2015-03-25 15:33:05 +00002198 def test_load_pkcs12_text_passphrase(self):
2199 """
2200 A PKCS12 string generated using the openssl command line can be loaded
2201 with :py:obj:`load_pkcs12` and its components extracted and examined.
2202 Using text as passphrase instead of bytes. DeprecationWarning expected.
2203 """
2204 pem = client_key_pem + client_cert_pem
2205 passwd = b"whatever"
2206 p12_str = _runopenssl(pem, b"pkcs12", b"-export", b"-clcerts",
2207 b"-passout", b"pass:" + passwd)
2208 with catch_warnings(record=True) as w:
2209 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002210 p12 = load_pkcs12(p12_str, passphrase=b"whatever".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002211
2212 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002213 "{0} for passphrase is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002214 WARNING_TYPE_EXPECTED
2215 ),
2216 str(w[-1].message)
2217 )
2218 self.assertIs(w[-1].category, DeprecationWarning)
2219
Abraham Martinc5484ba2015-03-25 15:33:05 +00002220 self.verify_pkcs12_container(p12)
2221
Stephen Holsapple38482622014-04-05 20:29:34 -07002222 def test_load_pkcs12_no_passphrase(self):
2223 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002224 A PKCS12 string generated using openssl command line can be loaded with
2225 :py:obj:`load_pkcs12` without a passphrase and its components extracted
2226 and examined.
Stephen Holsapple38482622014-04-05 20:29:34 -07002227 """
2228 pem = client_key_pem + client_cert_pem
2229 p12_str = _runopenssl(
2230 pem, b"pkcs12", b"-export", b"-clcerts", b"-passout", b"pass:")
2231 p12 = load_pkcs12(p12_str)
2232 self.verify_pkcs12_container(p12)
2233
Stephen Holsapple38482622014-04-05 20:29:34 -07002234 def _dump_and_load(self, dump_passphrase, load_passphrase):
2235 """
2236 A helper method to dump and load a PKCS12 object.
2237 """
2238 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem)
2239 dumped_p12 = p12.export(passphrase=dump_passphrase, iter=2, maciter=3)
2240 return load_pkcs12(dumped_p12, passphrase=load_passphrase)
2241
Stephen Holsapple38482622014-04-05 20:29:34 -07002242 def test_load_pkcs12_null_passphrase_load_empty(self):
2243 """
2244 A PKCS12 string can be dumped with a null passphrase, loaded with an
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002245 empty passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002246 extracted and examined.
2247 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002248 self.verify_pkcs12_container(
2249 self._dump_and_load(dump_passphrase=None, load_passphrase=b''))
Stephen Holsapple38482622014-04-05 20:29:34 -07002250
Stephen Holsapple38482622014-04-05 20:29:34 -07002251 def test_load_pkcs12_null_passphrase_load_null(self):
2252 """
2253 A PKCS12 string can be dumped with a null passphrase, loaded with a
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002254 null passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002255 extracted and examined.
2256 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002257 self.verify_pkcs12_container(
2258 self._dump_and_load(dump_passphrase=None, load_passphrase=None))
Stephen Holsapple38482622014-04-05 20:29:34 -07002259
Stephen Holsapple38482622014-04-05 20:29:34 -07002260 def test_load_pkcs12_empty_passphrase_load_empty(self):
2261 """
2262 A PKCS12 string can be dumped with an empty passphrase, loaded with an
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002263 empty passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002264 extracted and examined.
2265 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002266 self.verify_pkcs12_container(
2267 self._dump_and_load(dump_passphrase=b'', load_passphrase=b''))
Stephen Holsapple38482622014-04-05 20:29:34 -07002268
Stephen Holsapple38482622014-04-05 20:29:34 -07002269 def test_load_pkcs12_empty_passphrase_load_null(self):
2270 """
2271 A PKCS12 string can be dumped with an empty passphrase, loaded with a
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002272 null passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002273 extracted and examined.
2274 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002275 self.verify_pkcs12_container(
2276 self._dump_and_load(dump_passphrase=b'', load_passphrase=None))
Rick Deanf94096c2009-07-18 14:23:06 -05002277
Rick Deanee568302009-07-24 09:56:29 -05002278 def test_load_pkcs12_garbage(self):
2279 """
Alex Gaynor85b49702015-09-05 16:30:59 -04002280 :py:obj:`load_pkcs12` raises :py:obj:`OpenSSL.crypto.Error` when passed
2281 a string which is not a PKCS12 dump.
Rick Deanee568302009-07-24 09:56:29 -05002282 """
2283 passwd = 'whatever'
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002284 e = self.assertRaises(Error, load_pkcs12, b'fruit loops', passwd)
Alex Gaynor7f636492015-09-04 13:26:52 -04002285 self.assertEqual(e.args[0][0][0], 'asn1 encoding routines')
2286 self.assertEqual(len(e.args[0][0]), 3)
Rick Deanee568302009-07-24 09:56:29 -05002287
Rick Deanf94096c2009-07-18 14:23:06 -05002288 def test_replace(self):
2289 """
Alex Gaynor31287502015-09-05 16:11:27 -04002290 :py:obj:`PKCS12.set_certificate` replaces the certificate in a PKCS12
2291 cluster. :py:obj:`PKCS12.set_privatekey` replaces the private key.
Jonathan Ballet648875f2011-07-16 14:14:58 +09002292 :py:obj:`PKCS12.set_ca_certificates` replaces the CA certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05002293 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002294 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
2295 p12.set_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2296 p12.set_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002297 root_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05002298 client_cert = load_certificate(FILETYPE_PEM, client_cert_pem)
Alex Gaynoraceb3e22015-09-05 12:00:22 -04002299 p12.set_ca_certificates([root_cert]) # not a tuple
Rick Dean623ee362009-07-17 12:22:16 -05002300 self.assertEqual(1, len(p12.get_ca_certificates()))
2301 self.assertEqual(root_cert, p12.get_ca_certificates()[0])
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002302 p12.set_ca_certificates([client_cert, root_cert])
Rick Deanf94096c2009-07-18 14:23:06 -05002303 self.assertEqual(2, len(p12.get_ca_certificates()))
2304 self.assertEqual(client_cert, p12.get_ca_certificates()[0])
2305 self.assertEqual(root_cert, p12.get_ca_certificates()[1])
2306
Rick Deanf94096c2009-07-18 14:23:06 -05002307 def test_friendly_name(self):
2308 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002309 The *friendlyName* of a PKCS12 can be set and retrieved via
Alex Gaynor85b49702015-09-05 16:30:59 -04002310 :py:obj:`PKCS12.get_friendlyname` and
2311 :py:obj:`PKCS12_set_friendlyname`, and a :py:obj:`PKCS12` with a
2312 friendly name set can be dumped with :py:obj:`PKCS12.export`.
Rick Deanf94096c2009-07-18 14:23:06 -05002313 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002314 passwd = b'Dogmeat[]{}!@#$%^&*()~`?/.,<>-_+=";:'
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002315 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Alex Gaynore7f51982016-09-11 11:48:14 -04002316 for friendly_name in [b'Serverlicious', None, b'###']:
Rick Dean42d69e12009-07-20 11:36:08 -05002317 p12.set_friendlyname(friendly_name)
2318 self.assertEqual(p12.get_friendlyname(), friendly_name)
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002319 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
Rick Dean42d69e12009-07-20 11:36:08 -05002320 reloaded_p12 = load_pkcs12(dumped_p12, passwd)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002321 self.assertEqual(
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -04002322 p12.get_friendlyname(), reloaded_p12.get_friendlyname())
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002323 # We would use the openssl program to confirm the friendly
2324 # name, but it is not possible. The pkcs12 command
2325 # does not store the friendly name in the cert's
Rick Dean42d69e12009-07-20 11:36:08 -05002326 # alias, which we could then extract.
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002327 self.check_recovery(
2328 dumped_p12, key=server_key_pem, cert=server_cert_pem,
2329 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05002330
Rick Deanf94096c2009-07-18 14:23:06 -05002331 def test_various_empty_passphrases(self):
2332 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002333 Test that missing, None, and '' passphrases are identical for PKCS12
2334 export.
Rick Deanf94096c2009-07-18 14:23:06 -05002335 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002336 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002337 passwd = b""
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002338 dumped_p12_empty = p12.export(iter=2, maciter=0, passphrase=passwd)
2339 dumped_p12_none = p12.export(iter=3, maciter=2, passphrase=None)
2340 dumped_p12_nopw = p12.export(iter=9, maciter=4)
2341 for dumped_p12 in [dumped_p12_empty, dumped_p12_none, dumped_p12_nopw]:
2342 self.check_recovery(
2343 dumped_p12, key=client_key_pem, cert=client_cert_pem,
2344 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05002345
Rick Deanf94096c2009-07-18 14:23:06 -05002346 def test_removing_ca_cert(self):
2347 """
Alex Gaynor31287502015-09-05 16:11:27 -04002348 Passing :py:obj:`None` to :py:obj:`PKCS12.set_ca_certificates` removes
2349 all CA certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05002350 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002351 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
2352 p12.set_ca_certificates(None)
Rick Dean623ee362009-07-17 12:22:16 -05002353 self.assertEqual(None, p12.get_ca_certificates())
Rick Deanf94096c2009-07-18 14:23:06 -05002354
Rick Deanf94096c2009-07-18 14:23:06 -05002355 def test_export_without_mac(self):
2356 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002357 Exporting a PKCS12 with a :py:obj:`maciter` of ``-1`` excludes the MAC
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002358 entirely.
Rick Deanf94096c2009-07-18 14:23:06 -05002359 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002360 passwd = b"Lake Michigan"
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002361 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Dean623ee362009-07-17 12:22:16 -05002362 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002363 self.check_recovery(
2364 dumped_p12, key=server_key_pem, cert=server_cert_pem,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002365 passwd=passwd, extra=(b"-nomacver",))
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002366
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002367 def test_load_without_mac(self):
2368 """
2369 Loading a PKCS12 without a MAC does something other than crash.
2370 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002371 passwd = b"Lake Michigan"
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002372 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
2373 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Rick Dean321a0512009-08-13 17:21:29 -05002374 try:
2375 recovered_p12 = load_pkcs12(dumped_p12, passwd)
2376 # The person who generated this PCKS12 should be flogged,
2377 # or better yet we should have a means to determine
2378 # whether a PCKS12 had a MAC that was verified.
2379 # Anyway, libopenssl chooses to allow it, so the
2380 # pyopenssl binding does as well.
2381 self.assertTrue(isinstance(recovered_p12, PKCS12))
2382 except Error:
2383 # Failing here with an exception is preferred as some openssl
2384 # versions do.
2385 pass
Rick Dean623ee362009-07-17 12:22:16 -05002386
Rick Dean25bcc1f2009-07-20 11:53:13 -05002387 def test_zero_len_list_for_ca(self):
2388 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002389 A PKCS12 with an empty CA certificates list can be exported.
Rick Dean25bcc1f2009-07-20 11:53:13 -05002390 """
Alex Gaynor6575bd12015-09-05 16:44:36 -04002391 passwd = b'Hobie 18'
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002392 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem)
Alex Gaynor85b49702015-09-05 16:30:59 -04002393 p12.set_ca_certificates([])
2394 self.assertEqual((), p12.get_ca_certificates())
2395 dumped_p12 = p12.export(passphrase=passwd, iter=3)
2396 self.check_recovery(
2397 dumped_p12, key=server_key_pem, cert=server_cert_pem,
2398 passwd=passwd)
Rick Dean25bcc1f2009-07-20 11:53:13 -05002399
Rick Deanf94096c2009-07-18 14:23:06 -05002400 def test_export_without_args(self):
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002401 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002402 All the arguments to :py:obj:`PKCS12.export` are optional.
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002403 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002404 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05002405 dumped_p12 = p12.export() # no args
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002406 self.check_recovery(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002407 dumped_p12, key=server_key_pem, cert=server_cert_pem, passwd=b"")
Rick Deanf94096c2009-07-18 14:23:06 -05002408
Abraham Martinc5484ba2015-03-25 15:33:05 +00002409 def test_export_without_bytes(self):
2410 """
2411 Test :py:obj:`PKCS12.export` with text not bytes as passphrase
2412 """
2413 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
2414
2415 with catch_warnings(record=True) as w:
2416 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002417 dumped_p12 = p12.export(passphrase=b"randomtext".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002418 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002419 "{0} for passphrase is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002420 WARNING_TYPE_EXPECTED
2421 ),
2422 str(w[-1].message)
2423 )
2424 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinc5484ba2015-03-25 15:33:05 +00002425 self.check_recovery(
Alex Gaynor791212d2015-09-05 15:46:08 -04002426 dumped_p12,
2427 key=server_key_pem,
2428 cert=server_cert_pem,
2429 passwd=b"randomtext"
2430 )
Abraham Martinc5484ba2015-03-25 15:33:05 +00002431
Rick Deanf94096c2009-07-18 14:23:06 -05002432 def test_key_cert_mismatch(self):
2433 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002434 :py:obj:`PKCS12.export` raises an exception when a key and certificate
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002435 mismatch.
Rick Deanf94096c2009-07-18 14:23:06 -05002436 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002437 p12 = self.gen_pkcs12(server_cert_pem, client_key_pem, root_cert_pem)
2438 self.assertRaises(Error, p12.export)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002439
2440
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002441# These quoting functions taken directly from Twisted's twisted.python.win32.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002442_cmdLineQuoteRe = re.compile(br'(\\*)"')
2443_cmdLineQuoteRe2 = re.compile(br'(\\+)\Z')
Alex Gaynoraceb3e22015-09-05 12:00:22 -04002444
2445
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002446def cmdLineQuote(s):
2447 """
2448 Internal method for quoting a single command-line argument.
2449
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002450 See http://www.perlmonks.org/?node_id=764004
2451
Jonathan Ballet648875f2011-07-16 14:14:58 +09002452 :type: :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002453 :param s: A single unquoted string to quote for something that is expecting
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002454 cmd.exe-style quoting
2455
Jonathan Ballet648875f2011-07-16 14:14:58 +09002456 :rtype: :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002457 :return: A cmd.exe-style quoted string
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002458 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002459 s = _cmdLineQuoteRe2.sub(br"\1\1", _cmdLineQuoteRe.sub(br'\1\1\\"', s))
2460 return b'"' + s + b'"'
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002461
2462
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002463def quoteArguments(arguments):
2464 """
2465 Quote an iterable of command-line arguments for passing to CreateProcess or
Alex Gaynor791212d2015-09-05 15:46:08 -04002466 a similar API. This allows the list passed to
2467 :py:obj:`reactor.spawnProcess` to match the child process's
2468 :py:obj:`sys.argv` properly.
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002469
Jonathan Ballet648875f2011-07-16 14:14:58 +09002470 :type arguments: :py:obj:`iterable` of :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002471 :param arguments: An iterable of unquoted arguments to quote
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002472
Jonathan Ballet648875f2011-07-16 14:14:58 +09002473 :rtype: :py:obj:`str`
Alex Gaynor791212d2015-09-05 15:46:08 -04002474 :return: A space-delimited string containing quoted versions of
2475 :py:obj:`arguments`
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002476 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002477 return b' '.join(map(cmdLineQuote, arguments))
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002478
2479
Rick Dean4c9ad612009-07-17 15:05:22 -05002480def _runopenssl(pem, *args):
2481 """
2482 Run the command line openssl tool with the given arguments and write
Rick Dean55d1ce62009-08-13 17:40:24 -05002483 the given PEM to its stdin. Not safe for quotes.
Rick Dean4c9ad612009-07-17 15:05:22 -05002484 """
Jean-Paul Calderone038de952009-08-21 12:16:06 -04002485 if os.name == 'posix':
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002486 command = b"openssl " + b" ".join([
Alex Gaynor85b49702015-09-05 16:30:59 -04002487 (b"'" + arg.replace(b"'", b"'\\''") + b"'")
2488 for arg in args
2489 ])
Rick Dean55d1ce62009-08-13 17:40:24 -05002490 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002491 command = b"openssl " + quoteArguments(args)
2492 proc = Popen(native(command), shell=True, stdin=PIPE, stdout=PIPE)
Jean-Paul Calderone62ca8da2010-08-11 19:58:08 -04002493 proc.stdin.write(pem)
2494 proc.stdin.close()
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002495 output = proc.stdout.read()
2496 proc.stdout.close()
2497 proc.wait()
2498 return output
Rick Dean4c9ad612009-07-17 15:05:22 -05002499
2500
Hynek Schlawack40d448f2016-06-03 16:15:14 -07002501class TestLoadPublicKey(object):
Paul Kehrer32fc4e62016-06-03 15:21:44 -07002502 """
Hynek Schlawack40d448f2016-06-03 16:15:14 -07002503 Tests for :func:`load_publickey`.
Paul Kehrer32fc4e62016-06-03 15:21:44 -07002504 """
Hynek Schlawack40d448f2016-06-03 16:15:14 -07002505 def test_loading_works(self):
Paul Kehrer32fc4e62016-06-03 15:21:44 -07002506 """
Hynek Schlawack40d448f2016-06-03 16:15:14 -07002507 load_publickey loads public keys and sets correct attributes.
Paul Kehrer32fc4e62016-06-03 15:21:44 -07002508 """
2509 key = load_publickey(FILETYPE_PEM, cleartextPublicKeyPEM)
Hynek Schlawack40d448f2016-06-03 16:15:14 -07002510
2511 assert True is key._only_public
2512 assert 2048 == key.bits()
2513 assert TYPE_RSA == key.type()
2514
2515 def test_invalid_type(self):
2516 """
2517 load_publickey doesn't support FILETYPE_TEXT.
2518 """
2519 with pytest.raises(ValueError):
2520 load_publickey(FILETYPE_TEXT, cleartextPublicKeyPEM)
2521
2522 def test_invalid_key_format(self):
2523 """
2524 load_publickey explodes on incorrect keys.
2525 """
2526 with pytest.raises(Error):
2527 load_publickey(FILETYPE_ASN1, cleartextPublicKeyPEM)
2528
2529 def test_tolerates_unicode_strings(self):
2530 """
2531 load_publickey works with text strings, not just bytes.
2532 """
2533 serialized = cleartextPublicKeyPEM.decode('ascii')
2534 key = load_publickey(FILETYPE_PEM, serialized)
2535 dumped_pem = dump_publickey(FILETYPE_PEM, key)
2536
2537 assert dumped_pem == cleartextPublicKeyPEM
Paul Kehrer32fc4e62016-06-03 15:21:44 -07002538
2539
Jean-Paul Calderone18808652009-07-05 12:54:05 -04002540class FunctionTests(TestCase):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002541 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002542 Tests for free-functions in the :py:obj:`OpenSSL.crypto` module.
Hynek Schlawack40d448f2016-06-03 16:15:14 -07002543
2544 Add new tests to `TestFunctions` above.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002545 """
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002546
2547 def test_load_privatekey_invalid_format(self):
2548 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002549 :py:obj:`load_privatekey` raises :py:obj:`ValueError` if passed an
2550 unknown filetype.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002551 """
2552 self.assertRaises(ValueError, load_privatekey, 100, root_key_pem)
2553
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002554 def test_load_privatekey_invalid_passphrase_type(self):
2555 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002556 :py:obj:`load_privatekey` raises :py:obj:`TypeError` if passed a
2557 passphrase that is neither a :py:obj:`str` nor a callable.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002558 """
2559 self.assertRaises(
2560 TypeError,
2561 load_privatekey,
2562 FILETYPE_PEM, encryptedPrivateKeyPEMPassphrase, object())
2563
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002564 def test_load_privatekey_wrong_args(self):
2565 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002566 :py:obj:`load_privatekey` raises :py:obj:`TypeError` if called with the
2567 wrong number of arguments.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002568 """
2569 self.assertRaises(TypeError, load_privatekey)
2570
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002571 def test_load_privatekey_wrongPassphrase(self):
2572 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002573 :py:obj:`load_privatekey` raises :py:obj:`OpenSSL.crypto.Error` when it
2574 is passed an encrypted PEM and an incorrect passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002575 """
Greg Bowser36eb2de2017-01-24 11:38:55 -05002576 exc = self.assertRaises(
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002577 Error,
Alex Gaynore7f51982016-09-11 11:48:14 -04002578 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, b"quack")
Greg Bowser36eb2de2017-01-24 11:38:55 -05002579 self.assertNotEqual(exc.args[0], [])
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002580
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002581 def test_load_privatekey_passphraseWrongType(self):
2582 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002583 :py:obj:`load_privatekey` raises :py:obj:`ValueError` when it is passed
2584 a passphrase with a private key encoded in a format, that doesn't
2585 support encryption.
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002586 """
2587 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2588 blob = dump_privatekey(FILETYPE_ASN1, key)
2589 self.assertRaises(ValueError,
Alex Gaynor791212d2015-09-05 15:46:08 -04002590 load_privatekey, FILETYPE_ASN1, blob, "secret")
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002591
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002592 def test_load_privatekey_passphrase(self):
2593 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002594 :py:obj:`load_privatekey` can create a :py:obj:`PKey` object from an
2595 encrypted PEM string if given the passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002596 """
2597 key = load_privatekey(
2598 FILETYPE_PEM, encryptedPrivateKeyPEM,
2599 encryptedPrivateKeyPEMPassphrase)
2600 self.assertTrue(isinstance(key, PKeyType))
2601
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002602 def test_load_privatekey_passphrase_exception(self):
2603 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002604 If the passphrase callback raises an exception, that exception is
2605 raised by :py:obj:`load_privatekey`.
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002606 """
2607 def cb(ignored):
2608 raise ArithmeticError
2609
Alex Gaynor791212d2015-09-05 15:46:08 -04002610 with pytest.raises(ArithmeticError):
2611 load_privatekey(FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002612
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002613 def test_load_privatekey_wrongPassphraseCallback(self):
2614 """
Jean-Paul Calderoned440a082011-09-14 11:02:05 -04002615 :py:obj:`load_privatekey` raises :py:obj:`OpenSSL.crypto.Error` when it
2616 is passed an encrypted PEM and a passphrase callback which returns an
2617 incorrect passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002618 """
2619 called = []
Alex Gaynoraceb3e22015-09-05 12:00:22 -04002620
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002621 def cb(*a):
2622 called.append(None)
Alex Gaynore7f51982016-09-11 11:48:14 -04002623 return b"quack"
Greg Bowser36eb2de2017-01-24 11:38:55 -05002624 exc = self.assertRaises(
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002625 Error,
2626 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2627 self.assertTrue(called)
Greg Bowser36eb2de2017-01-24 11:38:55 -05002628 self.assertNotEqual(exc.args[0], [])
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002629
2630 def test_load_privatekey_passphraseCallback(self):
2631 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002632 :py:obj:`load_privatekey` can create a :py:obj:`PKey` object from an
2633 encrypted PEM string if given a passphrase callback which returns the
2634 correct password.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002635 """
2636 called = []
Alex Gaynoraceb3e22015-09-05 12:00:22 -04002637
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002638 def cb(writing):
2639 called.append(writing)
2640 return encryptedPrivateKeyPEMPassphrase
2641 key = load_privatekey(FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2642 self.assertTrue(isinstance(key, PKeyType))
2643 self.assertEqual(called, [False])
2644
Jean-Paul Calderone105cb952011-09-14 10:16:46 -04002645 def test_load_privatekey_passphrase_wrong_return_type(self):
2646 """
2647 :py:obj:`load_privatekey` raises :py:obj:`ValueError` if the passphrase
2648 callback returns something other than a byte string.
2649 """
2650 self.assertRaises(
2651 ValueError,
2652 load_privatekey,
2653 FILETYPE_PEM, encryptedPrivateKeyPEM, lambda *args: 3)
2654
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002655 def test_dump_privatekey_wrong_args(self):
2656 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002657 :py:obj:`dump_privatekey` raises :py:obj:`TypeError` if called with the
2658 wrong number of arguments.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002659 """
2660 self.assertRaises(TypeError, dump_privatekey)
Jean-Paul Calderone1eeccd82011-09-14 10:18:52 -04002661 # If cipher name is given, password is required.
2662 self.assertRaises(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002663 TypeError, dump_privatekey, FILETYPE_PEM, PKey(), GOOD_CIPHER)
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002664
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002665 def test_dump_privatekey_unknown_cipher(self):
2666 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002667 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` if called with an
2668 unrecognized cipher name.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002669 """
2670 key = PKey()
2671 key.generate_key(TYPE_RSA, 512)
2672 self.assertRaises(
2673 ValueError, dump_privatekey,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002674 FILETYPE_PEM, key, BAD_CIPHER, "passphrase")
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002675
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002676 def test_dump_privatekey_invalid_passphrase_type(self):
2677 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002678 :py:obj:`dump_privatekey` raises :py:obj:`TypeError` if called with a
2679 passphrase which is neither a :py:obj:`str` nor a callable.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002680 """
2681 key = PKey()
2682 key.generate_key(TYPE_RSA, 512)
2683 self.assertRaises(
2684 TypeError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002685 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, object())
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002686
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002687 def test_dump_privatekey_invalid_filetype(self):
2688 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002689 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` if called with an
2690 unrecognized filetype.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002691 """
2692 key = PKey()
2693 key.generate_key(TYPE_RSA, 512)
2694 self.assertRaises(ValueError, dump_privatekey, 100, key)
2695
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002696 def test_load_privatekey_passphraseCallbackLength(self):
2697 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002698 :py:obj:`crypto.load_privatekey` should raise an error when the
2699 passphrase provided by the callback is too long, not silently truncate
2700 it.
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002701 """
2702 def cb(ignored):
2703 return "a" * 1025
2704
Alex Gaynor791212d2015-09-05 15:46:08 -04002705 with pytest.raises(ValueError):
2706 load_privatekey(FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002707
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002708 def test_dump_privatekey_passphrase(self):
2709 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002710 :py:obj:`dump_privatekey` writes an encrypted PEM when given a
2711 passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002712 """
Alex Gaynore7f51982016-09-11 11:48:14 -04002713 passphrase = b"foo"
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002714 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002715 pem = dump_privatekey(FILETYPE_PEM, key, GOOD_CIPHER, passphrase)
2716 self.assertTrue(isinstance(pem, binary_type))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002717 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
2718 self.assertTrue(isinstance(loadedKey, PKeyType))
2719 self.assertEqual(loadedKey.type(), key.type())
2720 self.assertEqual(loadedKey.bits(), key.bits())
2721
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002722 def test_dump_privatekey_passphraseWrongType(self):
2723 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002724 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` when it is passed
2725 a passphrase with a private key encoded in a format, that doesn't
2726 support encryption.
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002727 """
2728 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Alex Gaynor791212d2015-09-05 15:46:08 -04002729 with pytest.raises(ValueError):
2730 dump_privatekey(FILETYPE_ASN1, key, GOOD_CIPHER, "secret")
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002731
Rick Dean5b7b6372009-04-01 11:34:06 -05002732 def test_dump_certificate(self):
2733 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002734 :py:obj:`dump_certificate` writes PEM, DER, and text.
Rick Dean5b7b6372009-04-01 11:34:06 -05002735 """
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002736 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
Rick Dean5b7b6372009-04-01 11:34:06 -05002737 cert = load_certificate(FILETYPE_PEM, pemData)
2738 dumped_pem = dump_certificate(FILETYPE_PEM, cert)
2739 self.assertEqual(dumped_pem, cleartextCertificatePEM)
2740 dumped_der = dump_certificate(FILETYPE_ASN1, cert)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002741 good_der = _runopenssl(dumped_pem, b"x509", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002742 self.assertEqual(dumped_der, good_der)
2743 cert2 = load_certificate(FILETYPE_ASN1, dumped_der)
2744 dumped_pem2 = dump_certificate(FILETYPE_PEM, cert2)
2745 self.assertEqual(dumped_pem2, cleartextCertificatePEM)
2746 dumped_text = dump_certificate(FILETYPE_TEXT, cert)
Alex Gaynor316aa2c2016-09-10 14:42:53 -04002747 good_text = _runopenssl(
2748 dumped_pem, b"x509", b"-noout", b"-text", b"-nameopt", b"")
Rick Dean5b7b6372009-04-01 11:34:06 -05002749 self.assertEqual(dumped_text, good_text)
2750
Alex Gaynor37726112016-07-04 09:51:32 -04002751 def test_dump_certificate_bad_type(self):
2752 """
2753 :obj:`dump_certificate` raises a :obj:`ValueError` if it's called with
2754 a bad type.
2755 """
2756 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
2757 with pytest.raises(ValueError):
2758 dump_certificate(object(), cert)
2759
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002760 def test_dump_privatekey_pem(self):
Rick Dean5b7b6372009-04-01 11:34:06 -05002761 """
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002762 :py:obj:`dump_privatekey` writes a PEM
Rick Dean5b7b6372009-04-01 11:34:06 -05002763 """
2764 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -04002765 self.assertTrue(key.check())
Rick Dean5b7b6372009-04-01 11:34:06 -05002766 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2767 self.assertEqual(dumped_pem, cleartextPrivateKeyPEM)
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002768
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002769 def test_dump_privatekey_asn1(self):
2770 """
2771 :py:obj:`dump_privatekey` writes a DER
2772 """
2773 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2774 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2775
Rick Dean5b7b6372009-04-01 11:34:06 -05002776 dumped_der = dump_privatekey(FILETYPE_ASN1, key)
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002777 # XXX This OpenSSL call writes "writing RSA key" to standard out. Sad.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002778 good_der = _runopenssl(dumped_pem, b"rsa", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002779 self.assertEqual(dumped_der, good_der)
2780 key2 = load_privatekey(FILETYPE_ASN1, dumped_der)
2781 dumped_pem2 = dump_privatekey(FILETYPE_PEM, key2)
2782 self.assertEqual(dumped_pem2, cleartextPrivateKeyPEM)
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002783
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002784 def test_dump_privatekey_text(self):
2785 """
2786 :py:obj:`dump_privatekey` writes a text
2787 """
2788 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2789 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2790
Rick Dean5b7b6372009-04-01 11:34:06 -05002791 dumped_text = dump_privatekey(FILETYPE_TEXT, key)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002792 good_text = _runopenssl(dumped_pem, b"rsa", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002793 self.assertEqual(dumped_text, good_text)
2794
Cory Benfield6492f7c2015-10-27 16:57:58 +09002795 def test_dump_publickey_pem(self):
2796 """
Cory Benfield11c10192015-10-27 17:23:03 +09002797 dump_publickey writes a PEM.
Cory Benfield6492f7c2015-10-27 16:57:58 +09002798 """
2799 key = load_publickey(FILETYPE_PEM, cleartextPublicKeyPEM)
2800 dumped_pem = dump_publickey(FILETYPE_PEM, key)
Cory Benfieldd86f1d82015-10-27 17:25:17 +09002801 assert dumped_pem == cleartextPublicKeyPEM
Cory Benfield6492f7c2015-10-27 16:57:58 +09002802
2803 def test_dump_publickey_asn1(self):
2804 """
Cory Benfield11c10192015-10-27 17:23:03 +09002805 dump_publickey writes a DER.
Cory Benfield6492f7c2015-10-27 16:57:58 +09002806 """
2807 key = load_publickey(FILETYPE_PEM, cleartextPublicKeyPEM)
2808 dumped_der = dump_publickey(FILETYPE_ASN1, key)
2809 key2 = load_publickey(FILETYPE_ASN1, dumped_der)
2810 dumped_pem2 = dump_publickey(FILETYPE_PEM, key2)
Cory Benfieldd86f1d82015-10-27 17:25:17 +09002811 assert dumped_pem2 == cleartextPublicKeyPEM
Cory Benfield6492f7c2015-10-27 16:57:58 +09002812
Cory Benfielde02c7d82015-10-27 17:34:49 +09002813 def test_dump_publickey_invalid_type(self):
2814 """
2815 dump_publickey doesn't support FILETYPE_TEXT.
2816 """
2817 key = load_publickey(FILETYPE_PEM, cleartextPublicKeyPEM)
2818
2819 with pytest.raises(ValueError):
2820 dump_publickey(FILETYPE_TEXT, key)
2821
Rick Dean5b7b6372009-04-01 11:34:06 -05002822 def test_dump_certificate_request(self):
2823 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002824 :py:obj:`dump_certificate_request` writes a PEM, DER, and text.
Rick Dean5b7b6372009-04-01 11:34:06 -05002825 """
Alex Gaynor31287502015-09-05 16:11:27 -04002826 req = load_certificate_request(
2827 FILETYPE_PEM, cleartextCertificateRequestPEM)
Rick Dean5b7b6372009-04-01 11:34:06 -05002828 dumped_pem = dump_certificate_request(FILETYPE_PEM, req)
2829 self.assertEqual(dumped_pem, cleartextCertificateRequestPEM)
2830 dumped_der = dump_certificate_request(FILETYPE_ASN1, req)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002831 good_der = _runopenssl(dumped_pem, b"req", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002832 self.assertEqual(dumped_der, good_der)
2833 req2 = load_certificate_request(FILETYPE_ASN1, dumped_der)
2834 dumped_pem2 = dump_certificate_request(FILETYPE_PEM, req2)
2835 self.assertEqual(dumped_pem2, cleartextCertificateRequestPEM)
2836 dumped_text = dump_certificate_request(FILETYPE_TEXT, req)
Alex Gaynor316aa2c2016-09-10 14:42:53 -04002837 good_text = _runopenssl(
2838 dumped_pem, b"req", b"-noout", b"-text", b"-nameopt", b"")
Rick Dean5b7b6372009-04-01 11:34:06 -05002839 self.assertEqual(dumped_text, good_text)
Jean-Paul Calderoneaf43cdf2010-08-03 18:40:52 -04002840 self.assertRaises(ValueError, dump_certificate_request, 100, req)
Rick Dean5b7b6372009-04-01 11:34:06 -05002841
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002842 def test_dump_privatekey_passphraseCallback(self):
2843 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002844 :py:obj:`dump_privatekey` writes an encrypted PEM when given a callback
2845 which returns the correct passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002846 """
Alex Gaynore7f51982016-09-11 11:48:14 -04002847 passphrase = b"foo"
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002848 called = []
Alex Gaynoraceb3e22015-09-05 12:00:22 -04002849
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002850 def cb(writing):
2851 called.append(writing)
2852 return passphrase
2853 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002854 pem = dump_privatekey(FILETYPE_PEM, key, GOOD_CIPHER, cb)
2855 self.assertTrue(isinstance(pem, binary_type))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002856 self.assertEqual(called, [True])
2857 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
2858 self.assertTrue(isinstance(loadedKey, PKeyType))
2859 self.assertEqual(loadedKey.type(), key.type())
2860 self.assertEqual(loadedKey.bits(), key.bits())
Rick Dean5b7b6372009-04-01 11:34:06 -05002861
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002862 def test_dump_privatekey_passphrase_exception(self):
2863 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002864 :py:obj:`dump_privatekey` should not overwrite the exception raised
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002865 by the passphrase callback.
2866 """
2867 def cb(ignored):
2868 raise ArithmeticError
2869
2870 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Alex Gaynor85b49702015-09-05 16:30:59 -04002871 with pytest.raises(ArithmeticError):
2872 dump_privatekey(FILETYPE_PEM, key, GOOD_CIPHER, cb)
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002873
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002874 def test_dump_privatekey_passphraseCallbackLength(self):
2875 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002876 :py:obj:`crypto.dump_privatekey` should raise an error when the
2877 passphrase provided by the callback is too long, not silently truncate
2878 it.
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002879 """
2880 def cb(ignored):
2881 return "a" * 1025
2882
2883 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Alex Gaynor85b49702015-09-05 16:30:59 -04002884 with pytest.raises(ValueError):
2885 dump_privatekey(FILETYPE_PEM, key, GOOD_CIPHER, cb)
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002886
Alex Gaynor4b9c96a2014-08-14 09:51:48 -07002887 def test_load_pkcs7_data_pem(self):
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002888 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002889 :py:obj:`load_pkcs7_data` accepts a PKCS#7 string and returns an
2890 instance of :py:obj:`PKCS7Type`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002891 """
2892 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2893 self.assertTrue(isinstance(pkcs7, PKCS7Type))
2894
Alex Gaynor4b9c96a2014-08-14 09:51:48 -07002895 def test_load_pkcs7_data_asn1(self):
Alex Gaynor9875a912014-08-14 13:35:05 -07002896 """
2897 :py:obj:`load_pkcs7_data` accepts a bytes containing ASN1 data
2898 representing PKCS#7 and returns an instance of :py:obj`PKCS7Type`.
2899 """
Alex Gaynor4b9c96a2014-08-14 09:51:48 -07002900 pkcs7 = load_pkcs7_data(FILETYPE_ASN1, pkcs7DataASN1)
2901 self.assertTrue(isinstance(pkcs7, PKCS7Type))
2902
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002903 def test_load_pkcs7_data_invalid(self):
2904 """
2905 If the data passed to :py:obj:`load_pkcs7_data` is invalid,
2906 :py:obj:`Error` is raised.
2907 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002908 self.assertRaises(Error, load_pkcs7_data, FILETYPE_PEM, b"foo")
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002909
Alex Gaynor09a386e2016-07-03 09:32:44 -04002910 def test_load_pkcs7_type_invalid(self):
2911 """
2912 If the type passed to :obj:`load_pkcs7_data`, :obj:`ValueError` is
2913 raised.
2914 """
2915 with pytest.raises(ValueError):
2916 load_pkcs7_data(object(), b"foo")
2917
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002918
Alex Chan9e2a9932017-01-25 14:29:19 +00002919class TestLoadCertificate(object):
Jean-Paul Calderone4a68b402013-12-29 16:54:58 -05002920 """
Alex Chan9e2a9932017-01-25 14:29:19 +00002921 Tests for `load_certificate_request`.
Jean-Paul Calderone4a68b402013-12-29 16:54:58 -05002922 """
Alex Gaynoraceb3e22015-09-05 12:00:22 -04002923
Alex Chan9e2a9932017-01-25 14:29:19 +00002924 def test_bad_file_type(self):
Jean-Paul Calderone4a68b402013-12-29 16:54:58 -05002925 """
Alex Chan9e2a9932017-01-25 14:29:19 +00002926 If the file type passed to `load_certificate_request` is neither
2927 `FILETYPE_PEM` nor `FILETYPE_ASN1` then `ValueError` is raised.
Jean-Paul Calderone4a68b402013-12-29 16:54:58 -05002928 """
Alex Gaynor7778e792016-07-03 23:38:48 -04002929 with pytest.raises(ValueError):
2930 load_certificate_request(object(), b"")
2931 with pytest.raises(ValueError):
2932 load_certificate(object(), b"")
Jean-Paul Calderone4a68b402013-12-29 16:54:58 -05002933
Alex Gaynor37726112016-07-04 09:51:32 -04002934 def test_bad_certificate(self):
2935 """
Alex Chan9e2a9932017-01-25 14:29:19 +00002936 If the bytes passed to `load_certificate` are not a valid certificate,
2937 an exception is raised.
Alex Gaynor37726112016-07-04 09:51:32 -04002938 """
2939 with pytest.raises(Error):
2940 load_certificate(FILETYPE_ASN1, b"lol")
2941
Jean-Paul Calderone4a68b402013-12-29 16:54:58 -05002942
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002943class PKCS7Tests(TestCase):
2944 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002945 Tests for :py:obj:`PKCS7Type`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002946 """
Alex Gaynoraceb3e22015-09-05 12:00:22 -04002947
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002948 def test_type(self):
2949 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002950 :py:obj:`PKCS7Type` is a type object.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002951 """
2952 self.assertTrue(isinstance(PKCS7Type, type))
2953 self.assertEqual(PKCS7Type.__name__, 'PKCS7')
2954
2955 # XXX This doesn't currently work.
2956 # self.assertIdentical(PKCS7, PKCS7Type)
2957
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002958 # XXX Opposite results for all these following methods
2959
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002960 def test_type_is_signed_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002961 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002962 :py:obj:`PKCS7Type.type_is_signed` raises :py:obj:`TypeError` if called
2963 with any arguments.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002964 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002965 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2966 self.assertRaises(TypeError, pkcs7.type_is_signed, None)
2967
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002968 def test_type_is_signed(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002969 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002970 :py:obj:`PKCS7Type.type_is_signed` returns :py:obj:`True` if the PKCS7
2971 object is of the type *signed*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002972 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002973 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2974 self.assertTrue(pkcs7.type_is_signed())
2975
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002976 def test_type_is_enveloped_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002977 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002978 :py:obj:`PKCS7Type.type_is_enveloped` raises :py:obj:`TypeError` if
2979 called with any arguments.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002980 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002981 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2982 self.assertRaises(TypeError, pkcs7.type_is_enveloped, None)
2983
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002984 def test_type_is_enveloped(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002985 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002986 :py:obj:`PKCS7Type.type_is_enveloped` returns :py:obj:`False` if the
2987 PKCS7 object is not of the type *enveloped*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002988 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002989 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2990 self.assertFalse(pkcs7.type_is_enveloped())
2991
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002992 def test_type_is_signedAndEnveloped_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002993 """
Alex Gaynor791212d2015-09-05 15:46:08 -04002994 :py:obj:`PKCS7Type.type_is_signedAndEnveloped` raises
2995 :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002996 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002997 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2998 self.assertRaises(TypeError, pkcs7.type_is_signedAndEnveloped, None)
2999
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04003000 def test_type_is_signedAndEnveloped(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04003001 """
Alex Gaynor791212d2015-09-05 15:46:08 -04003002 :py:obj:`PKCS7Type.type_is_signedAndEnveloped` returns :py:obj:`False`
3003 if the PKCS7 object is not of the type *signed and enveloped*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04003004 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04003005 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
3006 self.assertFalse(pkcs7.type_is_signedAndEnveloped())
3007
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04003008 def test_type_is_data(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04003009 """
Alex Gaynor791212d2015-09-05 15:46:08 -04003010 :py:obj:`PKCS7Type.type_is_data` returns :py:obj:`False` if the PKCS7
3011 object is not of the type data.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04003012 """
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04003013 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
3014 self.assertFalse(pkcs7.type_is_data())
3015
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04003016 def test_type_is_data_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04003017 """
Alex Gaynor791212d2015-09-05 15:46:08 -04003018 :py:obj:`PKCS7Type.type_is_data` raises :py:obj:`TypeError` if called
3019 with any arguments.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04003020 """
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04003021 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
3022 self.assertRaises(TypeError, pkcs7.type_is_data, None)
3023
Jean-Paul Calderone97b28ca2010-07-30 10:56:07 -04003024 def test_get_type_name_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04003025 """
Alex Gaynor791212d2015-09-05 15:46:08 -04003026 :py:obj:`PKCS7Type.get_type_name` raises :py:obj:`TypeError` if called
3027 with any arguments.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04003028 """
Jean-Paul Calderone97b28ca2010-07-30 10:56:07 -04003029 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
3030 self.assertRaises(TypeError, pkcs7.get_type_name, None)
3031
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04003032 def test_get_type_name(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04003033 """
Alex Gaynor791212d2015-09-05 15:46:08 -04003034 :py:obj:`PKCS7Type.get_type_name` returns a :py:obj:`str` giving the
3035 type name.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04003036 """
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04003037 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
Alex Gaynore7f51982016-09-11 11:48:14 -04003038 self.assertEquals(pkcs7.get_type_name(), b'pkcs7-signedData')
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04003039
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04003040 def test_attribute(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04003041 """
Alex Gaynor791212d2015-09-05 15:46:08 -04003042 If an attribute other than one of the methods tested here is accessed
3043 on an instance of :py:obj:`PKCS7Type`, :py:obj:`AttributeError` is
3044 raised.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04003045 """
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04003046 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
3047 self.assertRaises(AttributeError, getattr, pkcs7, "foo")
3048
3049
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04003050class NetscapeSPKITests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04003051 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003052 Tests for :py:obj:`OpenSSL.crypto.NetscapeSPKI`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04003053 """
Alex Gaynoraceb3e22015-09-05 12:00:22 -04003054
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04003055 def signable(self):
3056 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003057 Return a new :py:obj:`NetscapeSPKI` for use with signing tests.
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04003058 """
3059 return NetscapeSPKI()
3060
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003061 def test_type(self):
3062 """
Alex Gaynor791212d2015-09-05 15:46:08 -04003063 :py:obj:`NetscapeSPKI` and :py:obj:`NetscapeSPKIType` refer to the same
3064 type object and can be used to create instances of that type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003065 """
3066 self.assertIdentical(NetscapeSPKI, NetscapeSPKIType)
3067 self.assertConsistentType(NetscapeSPKI, 'NetscapeSPKI')
3068
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04003069 def test_construction(self):
3070 """
Alex Gaynor791212d2015-09-05 15:46:08 -04003071 :py:obj:`NetscapeSPKI` returns an instance of
3072 :py:obj:`NetscapeSPKIType`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04003073 """
3074 nspki = NetscapeSPKI()
3075 self.assertTrue(isinstance(nspki, NetscapeSPKIType))
3076
Jean-Paul Calderone969efaa2010-08-03 18:19:19 -04003077 def test_invalid_attribute(self):
3078 """
Alex Gaynor791212d2015-09-05 15:46:08 -04003079 Accessing a non-existent attribute of a :py:obj:`NetscapeSPKI` instance
3080 causes an :py:obj:`AttributeError` to be raised.
Jean-Paul Calderone969efaa2010-08-03 18:19:19 -04003081 """
3082 nspki = NetscapeSPKI()
3083 self.assertRaises(AttributeError, lambda: nspki.foo)
3084
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04003085 def test_b64_encode(self):
3086 """
Alex Gaynor791212d2015-09-05 15:46:08 -04003087 :py:obj:`NetscapeSPKI.b64_encode` encodes the certificate to a base64
3088 blob.
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04003089 """
3090 nspki = NetscapeSPKI()
3091 blob = nspki.b64_encode()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003092 self.assertTrue(isinstance(blob, binary_type))
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04003093
3094
Paul Kehrer2c605ba2016-03-11 11:17:26 -04003095class TestRevoked(object):
3096 """
Alex Chandeec9342016-12-19 22:00:38 +00003097 Tests for `OpenSSL.crypto.Revoked`.
Paul Kehrer2c605ba2016-03-11 11:17:26 -04003098 """
3099 def test_ignores_unsupported_revoked_cert_extension_get_reason(self):
3100 """
3101 The get_reason method on the Revoked class checks to see if the
3102 extension is NID_crl_reason and should skip it otherwise. This test
3103 loads a CRL with extensions it should ignore.
3104 """
3105 crl = load_crl(FILETYPE_PEM, crlDataUnsupportedExtension)
3106 revoked = crl.get_revoked()
3107 reason = revoked[1].get_reason()
3108 assert reason == b'Unspecified'
3109
3110 def test_ignores_unsupported_revoked_cert_extension_set_new_reason(self):
3111 crl = load_crl(FILETYPE_PEM, crlDataUnsupportedExtension)
3112 revoked = crl.get_revoked()
3113 revoked[1].set_reason(None)
3114 reason = revoked[1].get_reason()
3115 assert reason is None
3116
Rick Dean536ba022009-07-24 23:57:27 -05003117 def test_construction(self):
3118 """
Alex Chandeec9342016-12-19 22:00:38 +00003119 Confirm we can create `OpenSSL.crypto.Revoked`. Check that it is
3120 empty.
Rick Dean536ba022009-07-24 23:57:27 -05003121 """
3122 revoked = Revoked()
Alex Chandeec9342016-12-19 22:00:38 +00003123 assert isinstance(revoked, Revoked)
3124 assert type(revoked) == Revoked
3125 assert revoked.get_serial() == b'00'
3126 assert revoked.get_rev_date() is None
3127 assert revoked.get_reason() is None
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05003128
Rick Dean536ba022009-07-24 23:57:27 -05003129 def test_serial(self):
3130 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05003131 Confirm we can set and get serial numbers from
Alex Chandeec9342016-12-19 22:00:38 +00003132 `OpenSSL.crypto.Revoked`. Confirm errors are handled with grace.
Rick Dean536ba022009-07-24 23:57:27 -05003133 """
3134 revoked = Revoked()
Alex Gaynore7f51982016-09-11 11:48:14 -04003135 ret = revoked.set_serial(b'10b')
Alex Chandeec9342016-12-19 22:00:38 +00003136 assert ret is None
Rick Dean536ba022009-07-24 23:57:27 -05003137 ser = revoked.get_serial()
Alex Chandeec9342016-12-19 22:00:38 +00003138 assert ser == b'010B'
Rick Dean536ba022009-07-24 23:57:27 -05003139
Alex Gaynore7f51982016-09-11 11:48:14 -04003140 revoked.set_serial(b'31ppp') # a type error would be nice
Rick Dean536ba022009-07-24 23:57:27 -05003141 ser = revoked.get_serial()
Alex Chandeec9342016-12-19 22:00:38 +00003142 assert ser == b'31'
Rick Dean536ba022009-07-24 23:57:27 -05003143
Alex Chandeec9342016-12-19 22:00:38 +00003144 with pytest.raises(ValueError):
3145 revoked.set_serial(b'pqrst')
3146 with pytest.raises(TypeError):
3147 revoked.set_serial(100)
Rick Dean536ba022009-07-24 23:57:27 -05003148
Rick Dean536ba022009-07-24 23:57:27 -05003149 def test_date(self):
3150 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05003151 Confirm we can set and get revocation dates from
Alex Chandeec9342016-12-19 22:00:38 +00003152 `OpenSSL.crypto.Revoked`. Confirm errors are handled with grace.
Rick Dean536ba022009-07-24 23:57:27 -05003153 """
3154 revoked = Revoked()
3155 date = revoked.get_rev_date()
Alex Chandeec9342016-12-19 22:00:38 +00003156 assert date is None
Rick Dean536ba022009-07-24 23:57:27 -05003157
Alex Gaynore7f51982016-09-11 11:48:14 -04003158 now = datetime.now().strftime("%Y%m%d%H%M%SZ").encode("ascii")
Rick Dean536ba022009-07-24 23:57:27 -05003159 ret = revoked.set_rev_date(now)
Alex Chandeec9342016-12-19 22:00:38 +00003160 assert ret is None
Rick Dean536ba022009-07-24 23:57:27 -05003161 date = revoked.get_rev_date()
Alex Chandeec9342016-12-19 22:00:38 +00003162 assert date == now
Rick Dean536ba022009-07-24 23:57:27 -05003163
Rick Dean6385faf2009-07-26 00:07:47 -05003164 def test_reason(self):
3165 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05003166 Confirm we can set and get revocation reasons from
Alex Chandeec9342016-12-19 22:00:38 +00003167 `OpenSSL.crypto.Revoked`. The "get" need to work as "set".
3168 Likewise, each reason of all_reasons() must work.
Rick Dean6385faf2009-07-26 00:07:47 -05003169 """
3170 revoked = Revoked()
3171 for r in revoked.all_reasons():
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04003172 for x in range(2):
Rick Dean6385faf2009-07-26 00:07:47 -05003173 ret = revoked.set_reason(r)
Alex Chandeec9342016-12-19 22:00:38 +00003174 assert ret is None
Rick Dean6385faf2009-07-26 00:07:47 -05003175 reason = revoked.get_reason()
Alex Chandeec9342016-12-19 22:00:38 +00003176 assert (
3177 reason.lower().replace(b' ', b'') ==
Alex Gaynore7f51982016-09-11 11:48:14 -04003178 r.lower().replace(b' ', b''))
Alex Gaynoraceb3e22015-09-05 12:00:22 -04003179 r = reason # again with the resp of get
Rick Dean6385faf2009-07-26 00:07:47 -05003180
3181 revoked.set_reason(None)
Alex Chandeec9342016-12-19 22:00:38 +00003182 assert revoked.get_reason() is None
Rick Dean6385faf2009-07-26 00:07:47 -05003183
Alex Chandeec9342016-12-19 22:00:38 +00003184 def test_set_reason_invalid_reason(self):
Rick Dean6385faf2009-07-26 00:07:47 -05003185 """
Alex Chandeec9342016-12-19 22:00:38 +00003186 Calling `OpenSSL.crypto.Revoked.set_reason` with an argument which
3187 isn't a valid reason results in `ValueError` being raised.
Rick Dean6385faf2009-07-26 00:07:47 -05003188 """
3189 revoked = Revoked()
Alex Chandeec9342016-12-19 22:00:38 +00003190 with pytest.raises(ValueError):
3191 revoked.set_reason(b'blue')
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05003192
3193
Alex Chan7be83a52017-01-24 15:19:29 +00003194class TestCRL(object):
Rick Dean536ba022009-07-24 23:57:27 -05003195 """
Alex Chan7be83a52017-01-24 15:19:29 +00003196 Tests for `OpenSSL.crypto.CRL`.
Rick Dean536ba022009-07-24 23:57:27 -05003197 """
3198 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
3199 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
3200
Dan Sully44e767a2016-06-04 18:05:27 -07003201 root_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3202 root_key = load_privatekey(FILETYPE_PEM, root_key_pem)
3203 intermediate_cert = load_certificate(FILETYPE_PEM, intermediate_cert_pem)
3204 intermediate_key = load_privatekey(FILETYPE_PEM, intermediate_key_pem)
3205 intermediate_server_cert = load_certificate(
3206 FILETYPE_PEM, intermediate_server_cert_pem)
3207 intermediate_server_key = load_privatekey(
3208 FILETYPE_PEM, intermediate_server_key_pem)
3209
Rick Dean536ba022009-07-24 23:57:27 -05003210 def test_construction(self):
3211 """
Alex Chan7be83a52017-01-24 15:19:29 +00003212 Confirm we can create `OpenSSL.crypto.CRL`. Check
Rick Dean536ba022009-07-24 23:57:27 -05003213 that it is empty
3214 """
3215 crl = CRL()
Alex Chan7be83a52017-01-24 15:19:29 +00003216 assert isinstance(crl, CRL)
3217 assert crl.get_revoked() is None
Jean-Paul Calderone2efd03e2010-01-30 13:59:55 -05003218
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003219 def _get_crl(self):
Rick Dean536ba022009-07-24 23:57:27 -05003220 """
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003221 Get a new ``CRL`` with a revocation.
Rick Dean536ba022009-07-24 23:57:27 -05003222 """
3223 crl = CRL()
3224 revoked = Revoked()
Alex Gaynore7f51982016-09-11 11:48:14 -04003225 now = datetime.now().strftime("%Y%m%d%H%M%SZ").encode("ascii")
Rick Dean536ba022009-07-24 23:57:27 -05003226 revoked.set_rev_date(now)
Alex Gaynore7f51982016-09-11 11:48:14 -04003227 revoked.set_serial(b'3ab')
3228 revoked.set_reason(b'sUpErSeDEd')
Rick Dean536ba022009-07-24 23:57:27 -05003229 crl.add_revoked(revoked)
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003230 return crl
Rick Dean536ba022009-07-24 23:57:27 -05003231
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003232 def test_export_pem(self):
3233 """
3234 If not passed a format, ``CRL.export`` returns a "PEM" format string
3235 representing a serial number, a revoked reason, and certificate issuer
3236 information.
3237 """
3238 crl = self._get_crl()
Rick Dean536ba022009-07-24 23:57:27 -05003239 # PEM format
3240 dumped_crl = crl.export(self.cert, self.pkey, days=20)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003241 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003242
3243 # These magic values are based on the way the CRL above was constructed
3244 # and with what certificate it was exported.
Alex Gaynore7f51982016-09-11 11:48:14 -04003245 text.index(b'Serial Number: 03AB')
3246 text.index(b'Superseded')
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003247 text.index(
Alex Gaynore7f51982016-09-11 11:48:14 -04003248 b'Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA'
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003249 )
3250
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003251 def test_export_der(self):
3252 """
3253 If passed ``FILETYPE_ASN1`` for the format, ``CRL.export`` returns a
3254 "DER" format string representing a serial number, a revoked reason, and
3255 certificate issuer information.
3256 """
3257 crl = self._get_crl()
Rick Dean536ba022009-07-24 23:57:27 -05003258
3259 # DER format
3260 dumped_crl = crl.export(self.cert, self.pkey, FILETYPE_ASN1)
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003261 text = _runopenssl(
3262 dumped_crl, b"crl", b"-noout", b"-text", b"-inform", b"DER"
3263 )
Alex Gaynore7f51982016-09-11 11:48:14 -04003264 text.index(b'Serial Number: 03AB')
3265 text.index(b'Superseded')
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003266 text.index(
Alex Gaynore7f51982016-09-11 11:48:14 -04003267 b'Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA'
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003268 )
3269
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003270 def test_export_text(self):
3271 """
3272 If passed ``FILETYPE_TEXT`` for the format, ``CRL.export`` returns a
3273 text format string like the one produced by the openssl command line
3274 tool.
3275 """
3276 crl = self._get_crl()
3277
3278 dumped_crl = crl.export(self.cert, self.pkey, FILETYPE_ASN1)
3279 text = _runopenssl(
3280 dumped_crl, b"crl", b"-noout", b"-text", b"-inform", b"DER"
3281 )
Rick Dean536ba022009-07-24 23:57:27 -05003282
3283 # text format
3284 dumped_text = crl.export(self.cert, self.pkey, type=FILETYPE_TEXT)
Alex Chan7be83a52017-01-24 15:19:29 +00003285 assert text == dumped_text
Rick Dean536ba022009-07-24 23:57:27 -05003286
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003287 def test_export_custom_digest(self):
3288 """
3289 If passed the name of a digest function, ``CRL.export`` uses a
3290 signature algorithm based on that digest function.
3291 """
3292 crl = self._get_crl()
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04003293 dumped_crl = crl.export(self.cert, self.pkey, digest=b"sha1")
Bulat Gaifullin1966c972014-09-22 09:47:20 +04003294 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
Alex Gaynore7f51982016-09-11 11:48:14 -04003295 text.index(b'Signature Algorithm: sha1')
Bulat Gaifullin1966c972014-09-22 09:47:20 +04003296
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04003297 def test_export_md5_digest(self):
3298 """
3299 If passed md5 as the digest function, ``CRL.export`` uses md5 and does
3300 not emit a deprecation warning.
3301 """
3302 crl = self._get_crl()
Alex Chan7be83a52017-01-24 15:19:29 +00003303 with pytest.warns(None) as catcher:
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04003304 simplefilter("always")
Alex Chan7be83a52017-01-24 15:19:29 +00003305 assert 0 == len(catcher)
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04003306 dumped_crl = crl.export(self.cert, self.pkey, digest=b"md5")
3307 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
Alex Gaynore7f51982016-09-11 11:48:14 -04003308 text.index(b'Signature Algorithm: md5')
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04003309
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003310 def test_export_default_digest(self):
3311 """
3312 If not passed the name of a digest function, ``CRL.export`` uses a
3313 signature algorithm based on MD5 and emits a deprecation warning.
3314 """
3315 crl = self._get_crl()
Alex Chan7be83a52017-01-24 15:19:29 +00003316 with pytest.warns(None) as catcher:
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003317 simplefilter("always")
3318 dumped_crl = crl.export(self.cert, self.pkey)
Alex Chan7be83a52017-01-24 15:19:29 +00003319 assert (
3320 "The default message digest (md5) is deprecated. "
3321 "Pass the name of a message digest explicitly." ==
3322 str(catcher[0].message)
3323 )
Bulat Gaifullin1966c972014-09-22 09:47:20 +04003324 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
Alex Gaynore7f51982016-09-11 11:48:14 -04003325 text.index(b'Signature Algorithm: md5')
Bulat Gaifullin1966c972014-09-22 09:47:20 +04003326
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -04003327 def test_export_invalid(self):
3328 """
Alex Chan7be83a52017-01-24 15:19:29 +00003329 If `CRL.export` is used with an uninitialized `X509` instance,
3330 `OpenSSL.crypto.Error` is raised.
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -04003331 """
3332 crl = CRL()
Alex Chan7be83a52017-01-24 15:19:29 +00003333 with pytest.raises(Error):
3334 crl.export(X509(), PKey())
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -04003335
Jean-Paul Calderone56515342010-01-30 13:49:38 -05003336 def test_add_revoked_keyword(self):
3337 """
Alex Chan7be83a52017-01-24 15:19:29 +00003338 `OpenSSL.CRL.add_revoked` accepts its single argument as the
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003339 ``revoked`` keyword argument.
Jean-Paul Calderone56515342010-01-30 13:49:38 -05003340 """
3341 crl = CRL()
3342 revoked = Revoked()
Paul Kehrerb11bffc2016-03-10 18:30:29 -04003343 revoked.set_serial(b"01")
Paul Kehrer2fe23b02016-03-09 22:02:15 -04003344 revoked.set_rev_date(b"20160310020145Z")
Jean-Paul Calderone56515342010-01-30 13:49:38 -05003345 crl.add_revoked(revoked=revoked)
Alex Chan7be83a52017-01-24 15:19:29 +00003346 assert isinstance(crl.get_revoked()[0], Revoked)
Jean-Paul Calderone56515342010-01-30 13:49:38 -05003347
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05003348 def test_export_wrong_args(self):
3349 """
Alex Chan7be83a52017-01-24 15:19:29 +00003350 Calling `OpenSSL.CRL.export` with arguments other than the certificate,
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05003351 private key, integer file type, and integer number of days it
Alex Chan7be83a52017-01-24 15:19:29 +00003352 expects, results in a `TypeError` being raised.
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05003353 """
3354 crl = CRL()
Alex Gaynor85b49702015-09-05 16:30:59 -04003355 with pytest.raises(TypeError):
3356 crl.export(None, self.pkey, FILETYPE_PEM, 10)
3357 with pytest.raises(TypeError):
3358 crl.export(self.cert, None, FILETYPE_PEM, 10)
3359 with pytest.raises(TypeError):
3360 crl.export(self.cert, self.pkey, None, 10)
Alex Chan7be83a52017-01-24 15:19:29 +00003361 with pytest.raises(TypeError):
3362 crl.export(self.cert, FILETYPE_PEM, None)
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05003363
Jean-Paul Calderoneea198422010-01-30 13:58:23 -05003364 def test_export_unknown_filetype(self):
3365 """
Alex Chan7be83a52017-01-24 15:19:29 +00003366 Calling `OpenSSL.CRL.export` with a file type other than
3367 `FILETYPE_PEM`, `FILETYPE_ASN1`, or
3368 `FILETYPE_TEXT` results in a `ValueError` being raised.
Jean-Paul Calderoneea198422010-01-30 13:58:23 -05003369 """
3370 crl = CRL()
Alex Gaynor85b49702015-09-05 16:30:59 -04003371 with pytest.raises(ValueError):
3372 crl.export(self.cert, self.pkey, 100, 10)
Jean-Paul Calderoneea198422010-01-30 13:58:23 -05003373
Bulat Gaifullin925f7862014-09-22 10:10:44 +04003374 def test_export_unknown_digest(self):
Bulat Gaifullin5f9eea42014-09-23 19:35:15 +04003375 """
Alex Chan7be83a52017-01-24 15:19:29 +00003376 Calling `OpenSSL.CRL.export` with an unsupported digest results
3377 in a `ValueError` being raised.
Bulat Gaifullin5f9eea42014-09-23 19:35:15 +04003378 """
Bulat Gaifullin925f7862014-09-22 10:10:44 +04003379 crl = CRL()
Alex Chan7be83a52017-01-24 15:19:29 +00003380 with pytest.raises(ValueError):
3381 crl.export(
3382 self.cert, self.pkey, FILETYPE_PEM, 10, b"strange-digest")
Bulat Gaifullin925f7862014-09-22 10:10:44 +04003383
Rick Dean536ba022009-07-24 23:57:27 -05003384 def test_get_revoked(self):
3385 """
Alex Chan7be83a52017-01-24 15:19:29 +00003386 Use python to create a simple CRL with two revocations. Get back the
3387 `Revoked` using `OpenSSL.CRL.get_revoked` and verify them.
Rick Dean536ba022009-07-24 23:57:27 -05003388 """
3389 crl = CRL()
3390
3391 revoked = Revoked()
Alex Gaynore7f51982016-09-11 11:48:14 -04003392 now = datetime.now().strftime("%Y%m%d%H%M%SZ").encode("ascii")
Rick Dean536ba022009-07-24 23:57:27 -05003393 revoked.set_rev_date(now)
Alex Gaynore7f51982016-09-11 11:48:14 -04003394 revoked.set_serial(b'3ab')
Rick Dean536ba022009-07-24 23:57:27 -05003395 crl.add_revoked(revoked)
Alex Gaynore7f51982016-09-11 11:48:14 -04003396 revoked.set_serial(b'100')
3397 revoked.set_reason(b'sUpErSeDEd')
Rick Dean536ba022009-07-24 23:57:27 -05003398 crl.add_revoked(revoked)
3399
3400 revs = crl.get_revoked()
Alex Chan7be83a52017-01-24 15:19:29 +00003401 assert len(revs) == 2
3402 assert type(revs[0]) == Revoked
3403 assert type(revs[1]) == Revoked
3404 assert revs[0].get_serial() == b'03AB'
3405 assert revs[1].get_serial() == b'0100'
3406 assert revs[0].get_rev_date() == now
3407 assert revs[1].get_rev_date() == now
Jean-Paul Calderoneecef6fa2010-01-30 13:47:18 -05003408
Rick Dean536ba022009-07-24 23:57:27 -05003409 def test_load_crl(self):
3410 """
Alex Chan7be83a52017-01-24 15:19:29 +00003411 Load a known CRL and inspect its revocations. Both EM and DER formats
3412 are loaded.
Rick Dean536ba022009-07-24 23:57:27 -05003413 """
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003414 crl = load_crl(FILETYPE_PEM, crlData)
Rick Dean536ba022009-07-24 23:57:27 -05003415 revs = crl.get_revoked()
Alex Chan7be83a52017-01-24 15:19:29 +00003416 assert len(revs) == 2
3417 assert revs[0].get_serial() == b'03AB'
3418 assert revs[0].get_reason() is None
3419 assert revs[1].get_serial() == b'0100'
3420 assert revs[1].get_reason() == b'Superseded'
Rick Dean536ba022009-07-24 23:57:27 -05003421
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003422 der = _runopenssl(crlData, b"crl", b"-outform", b"DER")
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05003423 crl = load_crl(FILETYPE_ASN1, der)
Rick Dean536ba022009-07-24 23:57:27 -05003424 revs = crl.get_revoked()
Alex Chan7be83a52017-01-24 15:19:29 +00003425 assert len(revs) == 2
3426 assert revs[0].get_serial() == b'03AB'
3427 assert revs[0].get_reason() is None
3428 assert revs[1].get_serial() == b'0100'
3429 assert revs[1].get_reason() == b'Superseded'
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003430
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003431 def test_load_crl_bad_filetype(self):
3432 """
Alex Chan7be83a52017-01-24 15:19:29 +00003433 Calling `OpenSSL.crypto.load_crl` with an unknown file type raises a
3434 `ValueError`.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003435 """
Alex Chan7be83a52017-01-24 15:19:29 +00003436 with pytest.raises(ValueError):
3437 load_crl(100, crlData)
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003438
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003439 def test_load_crl_bad_data(self):
3440 """
Alex Chan7be83a52017-01-24 15:19:29 +00003441 Calling `OpenSSL.crypto.load_crl` with file data which can't be loaded
3442 raises a `OpenSSL.crypto.Error`.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003443 """
Alex Chan7be83a52017-01-24 15:19:29 +00003444 with pytest.raises(Error):
3445 load_crl(FILETYPE_PEM, b"hello, world")
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003446
Dan Sully44e767a2016-06-04 18:05:27 -07003447 def test_get_issuer(self):
3448 """
Alex Chan7be83a52017-01-24 15:19:29 +00003449 Load a known CRL and assert its issuer's common name is what we expect
3450 from the encoded crlData string.
Dan Sully44e767a2016-06-04 18:05:27 -07003451 """
3452 crl = load_crl(FILETYPE_PEM, crlData)
Alex Chan7be83a52017-01-24 15:19:29 +00003453 assert isinstance(crl.get_issuer(), X509Name)
3454 assert crl.get_issuer().CN == 'Testing Root CA'
Dan Sully44e767a2016-06-04 18:05:27 -07003455
Dominic Chenf05b2122015-10-13 16:32:35 +00003456 def test_dump_crl(self):
3457 """
3458 The dumped CRL matches the original input.
3459 """
3460 crl = load_crl(FILETYPE_PEM, crlData)
3461 buf = dump_crl(FILETYPE_PEM, crl)
3462 assert buf == crlData
3463
Dan Sully44e767a2016-06-04 18:05:27 -07003464 def _make_test_crl(self, issuer_cert, issuer_key, certs=()):
3465 """
3466 Create a CRL.
3467
3468 :param list[X509] certs: A list of certificates to revoke.
3469 :rtype: CRL
3470 """
3471 crl = CRL()
3472 for cert in certs:
3473 revoked = Revoked()
3474 # FIXME: This string splicing is an unfortunate implementation
3475 # detail that has been reported in
3476 # https://github.com/pyca/pyopenssl/issues/258
3477 serial = hex(cert.get_serial_number())[2:].encode('utf-8')
3478 revoked.set_serial(serial)
3479 revoked.set_reason(b'unspecified')
3480 revoked.set_rev_date(b'20140601000000Z')
3481 crl.add_revoked(revoked)
3482 crl.set_version(1)
3483 crl.set_lastUpdate(b'20140601000000Z')
3484 crl.set_nextUpdate(b'20180601000000Z')
3485 crl.sign(issuer_cert, issuer_key, digest=b'sha512')
3486 return crl
3487
3488 def test_verify_with_revoked(self):
3489 """
Alex Chan7be83a52017-01-24 15:19:29 +00003490 `verify_certificate` raises error when an intermediate certificate is
3491 revoked.
Dan Sully44e767a2016-06-04 18:05:27 -07003492 """
3493 store = X509Store()
3494 store.add_cert(self.root_cert)
3495 store.add_cert(self.intermediate_cert)
3496 root_crl = self._make_test_crl(
3497 self.root_cert, self.root_key, certs=[self.intermediate_cert])
3498 intermediate_crl = self._make_test_crl(
3499 self.intermediate_cert, self.intermediate_key, certs=[])
3500 store.add_crl(root_crl)
3501 store.add_crl(intermediate_crl)
3502 store.set_flags(
3503 X509StoreFlags.CRL_CHECK | X509StoreFlags.CRL_CHECK_ALL)
3504 store_ctx = X509StoreContext(store, self.intermediate_server_cert)
Alex Chan7be83a52017-01-24 15:19:29 +00003505 with pytest.raises(X509StoreContextError) as err:
3506 store_ctx.verify_certificate()
3507 assert err.value.args[0][2] == 'certificate revoked'
Dan Sully44e767a2016-06-04 18:05:27 -07003508
3509 def test_verify_with_missing_crl(self):
3510 """
Alex Chan7be83a52017-01-24 15:19:29 +00003511 `verify_certificate` raises error when an intermediate certificate's
3512 CRL is missing.
Dan Sully44e767a2016-06-04 18:05:27 -07003513 """
3514 store = X509Store()
3515 store.add_cert(self.root_cert)
3516 store.add_cert(self.intermediate_cert)
3517 root_crl = self._make_test_crl(
3518 self.root_cert, self.root_key, certs=[self.intermediate_cert])
3519 store.add_crl(root_crl)
3520 store.set_flags(
3521 X509StoreFlags.CRL_CHECK | X509StoreFlags.CRL_CHECK_ALL)
3522 store_ctx = X509StoreContext(store, self.intermediate_server_cert)
Alex Chan7be83a52017-01-24 15:19:29 +00003523 with pytest.raises(X509StoreContextError) as err:
3524 store_ctx.verify_certificate()
3525 assert err.value.args[0][2] == 'unable to get certificate CRL'
3526 assert err.value.certificate.get_subject().CN == 'intermediate-service'
Dan Sully44e767a2016-06-04 18:05:27 -07003527
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04003528
Alex Chan7be83a52017-01-24 15:19:29 +00003529class TestX509StoreContext(object):
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003530 """
Alex Chan7be83a52017-01-24 15:19:29 +00003531 Tests for `OpenSSL.crypto.X509StoreContext`.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003532 """
3533 root_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3534 intermediate_cert = load_certificate(FILETYPE_PEM, intermediate_cert_pem)
Alex Gaynor31287502015-09-05 16:11:27 -04003535 intermediate_server_cert = load_certificate(
3536 FILETYPE_PEM, intermediate_server_cert_pem)
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003537
3538 def test_valid(self):
3539 """
Alex Chan7be83a52017-01-24 15:19:29 +00003540 `verify_certificate` returns ``None`` when called with a certificate
3541 and valid chain.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003542 """
3543 store = X509Store()
3544 store.add_cert(self.root_cert)
3545 store.add_cert(self.intermediate_cert)
3546 store_ctx = X509StoreContext(store, self.intermediate_server_cert)
Alex Chan7be83a52017-01-24 15:19:29 +00003547 assert store_ctx.verify_certificate() is None
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003548
3549 def test_reuse(self):
3550 """
Alex Chan7be83a52017-01-24 15:19:29 +00003551 `verify_certificate` can be called multiple times with the same
Jean-Paul Calderone06e01b92015-01-18 15:43:13 -05003552 ``X509StoreContext`` instance to produce the same result.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003553 """
3554 store = X509Store()
3555 store.add_cert(self.root_cert)
3556 store.add_cert(self.intermediate_cert)
3557 store_ctx = X509StoreContext(store, self.intermediate_server_cert)
Alex Chan7be83a52017-01-24 15:19:29 +00003558 assert store_ctx.verify_certificate() is None
3559 assert store_ctx.verify_certificate() is None
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003560
3561 def test_trusted_self_signed(self):
3562 """
Alex Chan7be83a52017-01-24 15:19:29 +00003563 `verify_certificate` returns ``None`` when called with a self-signed
3564 certificate and itself in the chain.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003565 """
3566 store = X509Store()
3567 store.add_cert(self.root_cert)
3568 store_ctx = X509StoreContext(store, self.root_cert)
Alex Chan7be83a52017-01-24 15:19:29 +00003569 assert store_ctx.verify_certificate() is None
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003570
3571 def test_untrusted_self_signed(self):
3572 """
Alex Chan7be83a52017-01-24 15:19:29 +00003573 `verify_certificate` raises error when a self-signed certificate is
3574 verified without itself in the chain.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003575 """
3576 store = X509Store()
3577 store_ctx = X509StoreContext(store, self.root_cert)
Alex Gaynor85b49702015-09-05 16:30:59 -04003578 with pytest.raises(X509StoreContextError) as exc:
3579 store_ctx.verify_certificate()
3580
3581 assert exc.value.args[0][2] == 'self signed certificate'
3582 assert exc.value.certificate.get_subject().CN == 'Testing Root CA'
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003583
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003584 def test_invalid_chain_no_root(self):
3585 """
Alex Chan7be83a52017-01-24 15:19:29 +00003586 `verify_certificate` raises error when a root certificate is missing
3587 from the chain.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003588 """
3589 store = X509Store()
3590 store.add_cert(self.intermediate_cert)
3591 store_ctx = X509StoreContext(store, self.intermediate_server_cert)
Alex Gaynor85b49702015-09-05 16:30:59 -04003592
3593 with pytest.raises(X509StoreContextError) as exc:
3594 store_ctx.verify_certificate()
3595
3596 assert exc.value.args[0][2] == 'unable to get issuer certificate'
3597 assert exc.value.certificate.get_subject().CN == 'intermediate'
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003598
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003599 def test_invalid_chain_no_intermediate(self):
3600 """
Alex Chan7be83a52017-01-24 15:19:29 +00003601 `verify_certificate` raises error when an intermediate certificate is
3602 missing from the chain.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003603 """
3604 store = X509Store()
3605 store.add_cert(self.root_cert)
3606 store_ctx = X509StoreContext(store, self.intermediate_server_cert)
Jean-Paul Calderone517816e2015-01-18 15:39:26 -05003607
Alex Gaynor85b49702015-09-05 16:30:59 -04003608 with pytest.raises(X509StoreContextError) as exc:
3609 store_ctx.verify_certificate()
3610
3611 assert exc.value.args[0][2] == 'unable to get local issuer certificate'
3612 assert exc.value.certificate.get_subject().CN == 'intermediate-service'
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07003613
Stephen Holsapple46a09252015-02-12 14:45:43 -08003614 def test_modification_pre_verify(self):
3615 """
Alex Chan7be83a52017-01-24 15:19:29 +00003616 `verify_certificate` can use a store context modified after
Stephen Holsapple46a09252015-02-12 14:45:43 -08003617 instantiation.
3618 """
3619 store_bad = X509Store()
3620 store_bad.add_cert(self.intermediate_cert)
3621 store_good = X509Store()
3622 store_good.add_cert(self.root_cert)
3623 store_good.add_cert(self.intermediate_cert)
3624 store_ctx = X509StoreContext(store_bad, self.intermediate_server_cert)
Alex Gaynor85b49702015-09-05 16:30:59 -04003625
3626 with pytest.raises(X509StoreContextError) as exc:
3627 store_ctx.verify_certificate()
3628
3629 assert exc.value.args[0][2] == 'unable to get issuer certificate'
3630 assert exc.value.certificate.get_subject().CN == 'intermediate'
3631
Stephen Holsapple46a09252015-02-12 14:45:43 -08003632 store_ctx.set_store(store_good)
Alex Chan7be83a52017-01-24 15:19:29 +00003633 assert store_ctx.verify_certificate() is None
Stephen Holsapple46a09252015-02-12 14:45:43 -08003634
Thomas Sileoe15e60a2016-11-22 18:13:30 +01003635 def test_verify_with_time(self):
3636 """
3637 `verify_certificate` raises error when the verification time is
3638 set at notAfter.
3639 """
3640 store = X509Store()
3641 store.add_cert(self.root_cert)
3642 store.add_cert(self.intermediate_cert)
3643
3644 expire_time = self.intermediate_server_cert.get_notAfter()
3645 expire_datetime = datetime.strptime(
3646 expire_time.decode('utf-8'), '%Y%m%d%H%M%SZ'
3647 )
3648 store.set_time(expire_datetime)
3649
3650 store_ctx = X509StoreContext(store, self.intermediate_server_cert)
3651 with pytest.raises(X509StoreContextError) as exc:
3652 store_ctx.verify_certificate()
3653
3654 assert exc.value.args[0][2] == 'certificate has expired'
3655
Stephen Holsapple46a09252015-02-12 14:45:43 -08003656
Alex Chan7be83a52017-01-24 15:19:29 +00003657class TestSignVerify(object):
James Yonan7c2e5d32010-02-27 05:45:50 -07003658 """
Alex Chan7be83a52017-01-24 15:19:29 +00003659 Tests for `OpenSSL.crypto.sign` and `OpenSSL.crypto.verify`.
James Yonan7c2e5d32010-02-27 05:45:50 -07003660 """
Alex Gaynoraceb3e22015-09-05 12:00:22 -04003661
James Yonan7c2e5d32010-02-27 05:45:50 -07003662 def test_sign_verify(self):
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04003663 """
Alex Chan7be83a52017-01-24 15:19:29 +00003664 `sign` generates a cryptographic signature which `verify` can check.
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04003665 """
Alex Gaynore7f51982016-09-11 11:48:14 -04003666 content = (
3667 b"It was a bright cold day in April, and the clocks were striking "
3668 b"thirteen. Winston Smith, his chin nuzzled into his breast in an "
3669 b"effort to escape the vile wind, slipped quickly through the "
3670 b"glass doors of Victory Mansions, though not quickly enough to "
3671 b"prevent a swirl of gritty dust from entering along with him.")
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04003672
3673 # sign the content with this private key
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04003674 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04003675 # verify the content with this cert
3676 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3677 # certificate unrelated to priv_key, used to trigger an error
3678 bad_cert = load_certificate(FILETYPE_PEM, server_cert_pem)
James Yonan7c2e5d32010-02-27 05:45:50 -07003679
Jean-Paul Calderoned08feb02010-10-12 21:53:24 -04003680 for digest in ['md5', 'sha1']:
James Yonan7c2e5d32010-02-27 05:45:50 -07003681 sig = sign(priv_key, content, digest)
3682
Alex Gaynoraceb3e22015-09-05 12:00:22 -04003683 # Verify the signature of content, will throw an exception if
3684 # error.
James Yonan7c2e5d32010-02-27 05:45:50 -07003685 verify(good_cert, sig, content, digest)
3686
3687 # This should fail because the certificate doesn't match the
3688 # private key that was used to sign the content.
Alex Chan7be83a52017-01-24 15:19:29 +00003689 with pytest.raises(Error):
3690 verify(bad_cert, sig, content, digest)
James Yonan7c2e5d32010-02-27 05:45:50 -07003691
3692 # This should fail because we've "tainted" the content after
3693 # signing it.
Alex Chan7be83a52017-01-24 15:19:29 +00003694 with pytest.raises(Error):
3695 verify(good_cert, sig, content + b"tainted", digest)
James Yonan7c2e5d32010-02-27 05:45:50 -07003696
3697 # test that unknown digest types fail
Alex Chan7be83a52017-01-24 15:19:29 +00003698 with pytest.raises(ValueError):
3699 sign(priv_key, content, "strange-digest")
3700 with pytest.raises(ValueError):
3701 verify(good_cert, sig, content, "strange-digest")
James Yonan7c2e5d32010-02-27 05:45:50 -07003702
Abraham Martinc5484ba2015-03-25 15:33:05 +00003703 def test_sign_verify_with_text(self):
3704 """
Alex Chan7be83a52017-01-24 15:19:29 +00003705 `sign` generates a cryptographic signature which
3706 `verify` can check. Deprecation warnings raised because using
Alex Gaynor791212d2015-09-05 15:46:08 -04003707 text instead of bytes as content
Abraham Martinc5484ba2015-03-25 15:33:05 +00003708 """
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003709 content = (
Jean-Paul Calderone362c1f52015-03-29 08:01:39 -04003710 b"It was a bright cold day in April, and the clocks were striking "
3711 b"thirteen. Winston Smith, his chin nuzzled into his breast in an "
3712 b"effort to escape the vile wind, slipped quickly through the "
3713 b"glass doors of Victory Mansions, though not quickly enough to "
3714 b"prevent a swirl of gritty dust from entering along with him."
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003715 ).decode("ascii")
Abraham Martinc5484ba2015-03-25 15:33:05 +00003716
3717 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
3718 cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3719 for digest in ['md5', 'sha1']:
Alex Chan7be83a52017-01-24 15:19:29 +00003720 with pytest.warns(DeprecationWarning) as w:
Abraham Martinc5484ba2015-03-25 15:33:05 +00003721 simplefilter("always")
3722 sig = sign(priv_key, content, digest)
Alex Chan7be83a52017-01-24 15:19:29 +00003723 assert (
3724 "{0} for data is no longer accepted, use bytes".format(
3725 WARNING_TYPE_EXPECTED
3726 ) == str(w[-1].message))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003727
Alex Chan7be83a52017-01-24 15:19:29 +00003728 with pytest.warns(DeprecationWarning) as w:
Abraham Martinc5484ba2015-03-25 15:33:05 +00003729 simplefilter("always")
3730 verify(cert, sig, content, digest)
Alex Chan7be83a52017-01-24 15:19:29 +00003731 assert (
3732 "{0} for data is no longer accepted, use bytes".format(
3733 WARNING_TYPE_EXPECTED
3734 ) == str(w[-1].message))
Abraham Martinc5484ba2015-03-25 15:33:05 +00003735
Jean-Paul Calderone9828f662010-12-08 22:57:26 -05003736 def test_sign_nulls(self):
3737 """
Alex Chan7be83a52017-01-24 15:19:29 +00003738 `sign` produces a signature for a string with embedded nulls.
Jean-Paul Calderone9828f662010-12-08 22:57:26 -05003739 """
Alex Gaynore7f51982016-09-11 11:48:14 -04003740 content = b"Watch out! \0 Did you see it?"
Jean-Paul Calderone9828f662010-12-08 22:57:26 -05003741 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
3742 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3743 sig = sign(priv_key, content, "sha1")
3744 verify(good_cert, sig, content, "sha1")
3745
Colleen Murphye09399b2016-03-01 17:40:49 -08003746 def test_sign_with_large_key(self):
3747 """
Alex Chan7be83a52017-01-24 15:19:29 +00003748 `sign` produces a signature for a string when using a long key.
Colleen Murphye09399b2016-03-01 17:40:49 -08003749 """
Alex Gaynore7f51982016-09-11 11:48:14 -04003750 content = (
3751 b"It was a bright cold day in April, and the clocks were striking "
3752 b"thirteen. Winston Smith, his chin nuzzled into his breast in an "
3753 b"effort to escape the vile wind, slipped quickly through the "
3754 b"glass doors of Victory Mansions, though not quickly enough to "
3755 b"prevent a swirl of gritty dust from entering along with him.")
Colleen Murphye09399b2016-03-01 17:40:49 -08003756
3757 priv_key = load_privatekey(FILETYPE_PEM, large_key_pem)
3758 sign(priv_key, content, "sha1")
3759
Jean-Paul Calderone9828f662010-12-08 22:57:26 -05003760
Alex Chan63ef9bc2016-12-19 12:02:06 +00003761class TestEllipticCurve(object):
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003762 """
Alex Chan63ef9bc2016-12-19 12:02:06 +00003763 Tests for `_EllipticCurve`, `get_elliptic_curve`, and
3764 `get_elliptic_curves`.
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003765 """
Alex Gaynoraceb3e22015-09-05 12:00:22 -04003766
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003767 def test_set(self):
3768 """
Alex Chan63ef9bc2016-12-19 12:02:06 +00003769 `get_elliptic_curves` returns a `set`.
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003770 """
Alex Chan63ef9bc2016-12-19 12:02:06 +00003771 assert isinstance(get_elliptic_curves(), set)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003772
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003773 def test_a_curve(self):
3774 """
Alex Chan63ef9bc2016-12-19 12:02:06 +00003775 `get_elliptic_curve` can be used to retrieve a particular supported
3776 curve.
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003777 """
3778 curves = get_elliptic_curves()
Alex Chan63ef9bc2016-12-19 12:02:06 +00003779 curve = next(iter(curves))
3780 assert curve.name == get_elliptic_curve(curve.name).name
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003781
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003782 def test_not_a_curve(self):
3783 """
Alex Chan63ef9bc2016-12-19 12:02:06 +00003784 `get_elliptic_curve` raises `ValueError` if called with a name which
3785 does not identify a supported curve.
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003786 """
Alex Chan63ef9bc2016-12-19 12:02:06 +00003787 with pytest.raises(ValueError):
3788 get_elliptic_curve(u"this curve was just invented")
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003789
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003790 def test_repr(self):
3791 """
3792 The string representation of a curve object includes simply states the
3793 object is a curve and what its name is.
3794 """
3795 curves = get_elliptic_curves()
Alex Chan63ef9bc2016-12-19 12:02:06 +00003796 curve = next(iter(curves))
3797 assert "<Curve %r>" % (curve.name,) == repr(curve)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003798
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003799 def test_to_EC_KEY(self):
3800 """
3801 The curve object can export a version of itself as an EC_KEY* via the
Alex Chan63ef9bc2016-12-19 12:02:06 +00003802 private `_EllipticCurve._to_EC_KEY`.
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003803 """
3804 curves = get_elliptic_curves()
Alex Chan63ef9bc2016-12-19 12:02:06 +00003805 curve = next(iter(curves))
3806 # It's not easy to assert anything about this object. However, see
3807 # leakcheck/crypto.py for a test that demonstrates it at least does
3808 # not leak memory.
3809 curve._to_EC_KEY()
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003810
3811
Jean-Paul Calderone1be77082014-04-30 18:17:41 -04003812class EllipticCurveFactory(object):
3813 """
3814 A helper to get the names of two curves.
3815 """
Alex Gaynoraceb3e22015-09-05 12:00:22 -04003816
Jean-Paul Calderone1be77082014-04-30 18:17:41 -04003817 def __init__(self):
3818 curves = iter(get_elliptic_curves())
Alex Chan63ef9bc2016-12-19 12:02:06 +00003819 self.curve_name = next(curves).name
3820 self.another_curve_name = next(curves).name
Jean-Paul Calderone1be77082014-04-30 18:17:41 -04003821
3822
Alex Chan63ef9bc2016-12-19 12:02:06 +00003823class TestEllipticCurveEquality(EqualityTestsMixin):
Jean-Paul Calderone1be77082014-04-30 18:17:41 -04003824 """
Alex Chan63ef9bc2016-12-19 12:02:06 +00003825 Tests `_EllipticCurve`\ 's implementation of ``==`` and ``!=``.
Jean-Paul Calderone1be77082014-04-30 18:17:41 -04003826 """
3827 curve_factory = EllipticCurveFactory()
3828
3829 if curve_factory.curve_name is None:
3830 skip = "There are no curves available there can be no curve objects."
3831
Jean-Paul Calderone1be77082014-04-30 18:17:41 -04003832 def anInstance(self):
3833 """
3834 Get the curve object for an arbitrary curve supported by the system.
3835 """
3836 return get_elliptic_curve(self.curve_factory.curve_name)
3837
Jean-Paul Calderone1be77082014-04-30 18:17:41 -04003838 def anotherInstance(self):
3839 """
3840 Get the curve object for an arbitrary curve supported by the system -
3841 but not the one returned by C{anInstance}.
3842 """
3843 return get_elliptic_curve(self.curve_factory.another_curve_name)
3844
3845
Alex Chan63ef9bc2016-12-19 12:02:06 +00003846class TestEllipticCurveHash(object):
Jean-Paul Calderone22c31242014-05-01 07:49:47 -04003847 """
Alex Chan63ef9bc2016-12-19 12:02:06 +00003848 Tests for `_EllipticCurve`'s implementation of hashing (thus use as
3849 an item in a `dict` or `set`).
Jean-Paul Calderone22c31242014-05-01 07:49:47 -04003850 """
3851 curve_factory = EllipticCurveFactory()
3852
3853 if curve_factory.curve_name is None:
3854 skip = "There are no curves available there can be no curve objects."
3855
Jean-Paul Calderone22c31242014-05-01 07:49:47 -04003856 def test_contains(self):
3857 """
Alex Chan63ef9bc2016-12-19 12:02:06 +00003858 The ``in`` operator reports that a `set` containing a curve does
3859 contain that curve.
Jean-Paul Calderone22c31242014-05-01 07:49:47 -04003860 """
3861 curve = get_elliptic_curve(self.curve_factory.curve_name)
3862 curves = set([curve])
Alex Chan63ef9bc2016-12-19 12:02:06 +00003863 assert curve in curves
Jean-Paul Calderone22c31242014-05-01 07:49:47 -04003864
Jean-Paul Calderone22c31242014-05-01 07:49:47 -04003865 def test_does_not_contain(self):
3866 """
Alex Chan63ef9bc2016-12-19 12:02:06 +00003867 The ``in`` operator reports that a `set` not containing a curve
3868 does not contain that curve.
Jean-Paul Calderone22c31242014-05-01 07:49:47 -04003869 """
3870 curve = get_elliptic_curve(self.curve_factory.curve_name)
Alex Gaynor85b49702015-09-05 16:30:59 -04003871 curves = set([
3872 get_elliptic_curve(self.curve_factory.another_curve_name)
3873 ])
Alex Chan63ef9bc2016-12-19 12:02:06 +00003874 assert curve not in curves