blob: b2ad004a205e59fdf126a8d4484b44d51196dadd [file] [log] [blame]
Jean-Paul Calderone8671c852011-03-02 19:26:20 -05001# Copyright (c) Jean-Paul Calderone
2# See LICENSE file for details.
Jean-Paul Calderone8b63d452008-03-21 18:31:12 -04003
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -05004"""
Jonathan Ballet648875f2011-07-16 14:14:58 +09005Unit tests for :py:mod:`OpenSSL.crypto`.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -05006"""
7
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04008from unittest import main
Jean-Paul Calderone60432792015-04-13 12:26:07 -04009from warnings import catch_warnings, simplefilter
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -040010
Alex Gaynor4b9c96a2014-08-14 09:51:48 -070011import base64
12import os
13import re
Jean-Paul Calderone62ca8da2010-08-11 19:58:08 -040014from subprocess import PIPE, Popen
Rick Dean47262da2009-07-08 16:17:17 -050015from datetime import datetime, timedelta
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -050016
Jean-Paul Calderoneeb86f3a2014-04-19 09:45:57 -040017from six import u, b, binary_type
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050018
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -050019from OpenSSL.crypto import TYPE_RSA, TYPE_DSA, Error, PKey, PKeyType
Jean-Paul Calderone78381d22008-03-06 23:35:22 -050020from OpenSSL.crypto import X509, X509Type, X509Name, X509NameType
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080021from OpenSSL.crypto import X509Store, X509StoreType, X509Req, X509ReqType
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -050022from OpenSSL.crypto import X509Extension, X509ExtensionType
Rick Dean5b7b6372009-04-01 11:34:06 -050023from OpenSSL.crypto import load_certificate, load_privatekey
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -040024from OpenSSL.crypto import FILETYPE_PEM, FILETYPE_ASN1, FILETYPE_TEXT
Jean-Paul Calderone71919862009-04-01 13:01:19 -040025from OpenSSL.crypto import dump_certificate, load_certificate_request
26from OpenSSL.crypto import dump_certificate_request, dump_privatekey
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -040027from OpenSSL.crypto import PKCS7Type, load_pkcs7_data
Jean-Paul Calderone9178ee62010-01-25 17:55:30 -050028from OpenSSL.crypto import PKCS12, PKCS12Type, load_pkcs12
Rick Dean536ba022009-07-24 23:57:27 -050029from OpenSSL.crypto import CRL, Revoked, load_crl
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -040030from OpenSSL.crypto import NetscapeSPKI, NetscapeSPKIType
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040031from OpenSSL.crypto import (
32 sign, verify, get_elliptic_curve, get_elliptic_curves)
Jean-Paul Calderone1be77082014-04-30 18:17:41 -040033from OpenSSL.test.util import EqualityTestsMixin, TestCase
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040034from OpenSSL._util import native, lib
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040035
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -040036def normalize_certificate_pem(pem):
37 return dump_certificate(FILETYPE_PEM, load_certificate(FILETYPE_PEM, pem))
38
39
40def normalize_privatekey_pem(pem):
41 return dump_privatekey(FILETYPE_PEM, load_privatekey(FILETYPE_PEM, pem))
42
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040043
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050044GOOD_CIPHER = "blowfish"
45BAD_CIPHER = "zippers"
46
47GOOD_DIGEST = "MD5"
48BAD_DIGEST = "monkeys"
49
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040050root_cert_pem = b("""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -050051MIIC7TCCAlagAwIBAgIIPQzE4MbeufQwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE
52BhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdU
53ZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwIhgPMjAwOTAzMjUxMjM2
54NThaGA8yMDE3MDYxMTEyMzY1OFowWDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklM
55MRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9U
56ZXN0aW5nIFJvb3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPmaQumL
57urpE527uSEHdL1pqcDRmWzu+98Y6YHzT/J7KWEamyMCNZ6fRW1JCR782UQ8a07fy
582xXsKy4WdKaxyG8CcatwmXvpvRQ44dSANMihHELpANTdyVp6DCysED6wkQFurHlF
591dshEaJw8b/ypDhmbVIo6Ci1xvCJqivbLFnbAgMBAAGjgbswgbgwHQYDVR0OBBYE
60FINVdy1eIfFJDAkk51QJEo3IfgSuMIGIBgNVHSMEgYAwfoAUg1V3LV4h8UkMCSTn
61VAkSjch+BK6hXKRaMFgxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UE
62BxMHQ2hpY2FnbzEQMA4GA1UEChMHVGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBS
63b290IENBggg9DMTgxt659DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB
64AGGCDazMJGoWNBpc03u6+smc95dEead2KlZXBATOdFT1VesY3+nUOqZhEhTGlDMi
65hkgaZnzoIq/Uamidegk4hirsCT/R+6vsKAAxNTcBjUeZjlykCJWy5ojShGftXIKY
66w/njVbKMXrvc83qmTdGl3TAM0fxQIpqgcglFLveEBgzn
67-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040068""")
Rick Dean94e46fd2009-07-18 14:51:24 -050069
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040070root_key_pem = b("""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -050071MIICXQIBAAKBgQD5mkLpi7q6ROdu7khB3S9aanA0Zls7vvfGOmB80/yeylhGpsjA
72jWen0VtSQke/NlEPGtO38tsV7CsuFnSmschvAnGrcJl76b0UOOHUgDTIoRxC6QDU
733claegwsrBA+sJEBbqx5RdXbIRGicPG/8qQ4Zm1SKOgotcbwiaor2yxZ2wIDAQAB
74AoGBAPCgMpmLxzwDaUmcFbTJUvlLW1hoxNNYSu2jIZm1k/hRAcE60JYwvBkgz3UB
75yMEh0AtLxYe0bFk6EHah11tMUPgscbCq73snJ++8koUw+csk22G65hOs51bVb7Aa
766JBe67oLzdtvgCUFAA2qfrKzWRZzAdhUirQUZgySZk+Xq1pBAkEA/kZG0A6roTSM
77BVnx7LnPfsycKUsTumorpXiylZJjTi9XtmzxhrYN6wgZlDOOwOLgSQhszGpxVoMD
78u3gByT1b2QJBAPtL3mSKdvwRu/+40zaZLwvSJRxaj0mcE4BJOS6Oqs/hS1xRlrNk
79PpQ7WJ4yM6ZOLnXzm2mKyxm50Mv64109FtMCQQDOqS2KkjHaLowTGVxwC0DijMfr
80I9Lf8sSQk32J5VWCySWf5gGTfEnpmUa41gKTMJIbqZZLucNuDcOtzUaeWZlZAkA8
81ttXigLnCqR486JDPTi9ZscoZkZ+w7y6e/hH8t6d5Vjt48JVyfjPIaJY+km58LcN3
826AWSeGAdtRFHVzR7oHjVAkB4hutvxiOeiIVQNBhM6RSI9aBPMI21DoX2JRoxvNW2
83cbvAhow217X9V0dVerEOKxnNYspXRrh36h7k4mQA+sDq
84-----END RSA PRIVATE KEY-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040085""")
Rick Dean94e46fd2009-07-18 14:51:24 -050086
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040087server_cert_pem = b("""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -050088MIICKDCCAZGgAwIBAgIJAJn/HpR21r/8MA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
89BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
90VGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBSb290IENBMCIYDzIwMDkwMzI1MTIz
91NzUzWhgPMjAxNzA2MTExMjM3NTNaMBgxFjAUBgNVBAMTDWxvdmVseSBzZXJ2ZXIw
92gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAL6m+G653V0tpBC/OKl22VxOi2Cv
93lK4TYu9LHSDP9uDVTe7V5D5Tl6qzFoRRx5pfmnkqT5B+W9byp2NU3FC5hLm5zSAr
94b45meUhjEJ/ifkZgbNUjHdBIGP9MAQUHZa5WKdkGIJvGAvs8UzUqlr4TBWQIB24+
95lJ+Ukk/CRgasrYwdAgMBAAGjNjA0MB0GA1UdDgQWBBS4kC7Ij0W1TZXZqXQFAM2e
96gKEG2DATBgNVHSUEDDAKBggrBgEFBQcDATANBgkqhkiG9w0BAQUFAAOBgQBh30Li
97dJ+NlxIOx5343WqIBka3UbsOb2kxWrbkVCrvRapCMLCASO4FqiKWM+L0VDBprqIp
982mgpFQ6FHpoIENGvJhdEKpptQ5i7KaGhnDNTfdy3x1+h852G99f1iyj0RmbuFcM8
99uzujnS8YXWvM7DM1Ilozk4MzPug8jzFp5uhKCQ==
100-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400101""")
Rick Dean94e46fd2009-07-18 14:51:24 -0500102
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -0400103server_key_pem = normalize_privatekey_pem(b("""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500104MIICWwIBAAKBgQC+pvhuud1dLaQQvzipdtlcTotgr5SuE2LvSx0gz/bg1U3u1eQ+
105U5eqsxaEUceaX5p5Kk+QflvW8qdjVNxQuYS5uc0gK2+OZnlIYxCf4n5GYGzVIx3Q
106SBj/TAEFB2WuVinZBiCbxgL7PFM1Kpa+EwVkCAduPpSflJJPwkYGrK2MHQIDAQAB
107AoGAbwuZ0AR6JveahBaczjfnSpiFHf+mve2UxoQdpyr6ROJ4zg/PLW5K/KXrC48G
108j6f3tXMrfKHcpEoZrQWUfYBRCUsGD5DCazEhD8zlxEHahIsqpwA0WWssJA2VOLEN
109j6DuV2pCFbw67rfTBkTSo32ahfXxEKev5KswZk0JIzH3ooECQQDgzS9AI89h0gs8
110Dt+1m11Rzqo3vZML7ZIyGApUzVan+a7hbc33nbGRkAXjHaUBJO31it/H6dTO+uwX
111msWwNG5ZAkEA2RyFKs5xR5USTFaKLWCgpH/ydV96KPOpBND7TKQx62snDenFNNbn
112FwwOhpahld+vqhYk+pfuWWUpQciE+Bu7ZQJASjfT4sQv4qbbKK/scePicnDdx9th
1134e1EeB9xwb+tXXXUo/6Bor/AcUNwfiQ6Zt9PZOK9sR3lMZSsP7rMi7kzuQJABie6
1141sXXjFH7nNJvRG4S39cIxq8YRYTy68II/dlB2QzGpKxV/POCxbJ/zu0CU79tuYK7
115NaeNCFfH3aeTrX0LyQJAMBWjWmeKM2G2sCExheeQK0ROnaBC8itCECD4Jsve4nqf
116r50+LF74iLXFwqysVCebPKMOpDWp/qQ1BbJQIPs7/A==
117-----END RSA PRIVATE KEY-----
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -0400118"""))
Rick Dean94e46fd2009-07-18 14:51:24 -0500119
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400120client_cert_pem = b("""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500121MIICJjCCAY+gAwIBAgIJAKxpFI5lODkjMA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
122BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
123VGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBSb290IENBMCIYDzIwMDkwMzI1MTIz
124ODA1WhgPMjAxNzA2MTExMjM4MDVaMBYxFDASBgNVBAMTC3VnbHkgY2xpZW50MIGf
125MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDAZh/SRtNm5ntMT4qb6YzEpTroMlq2
126rn+GrRHRiZ+xkCw/CGNhbtPir7/QxaUj26BSmQrHw1bGKEbPsWiW7bdXSespl+xK
127iku4G/KvnnmWdeJHqsiXeUZtqurMELcPQAw9xPHEuhqqUJvvEoMTsnCEqGM+7Dtb
128oCRajYyHfluARQIDAQABozYwNDAdBgNVHQ4EFgQUNQB+qkaOaEVecf1J3TTUtAff
1290fAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQEFBQADgYEAyv/Jh7gM
130Q3OHvmsFEEvRI+hsW8y66zK4K5de239Y44iZrFYkt7Q5nBPMEWDj4F2hLYWL/qtI
1319Zdr0U4UDCU9SmmGYh4o7R4TZ5pGFvBYvjhHbkSFYFQXZxKUi+WUxplP6I0wr2KJ
132PSTJCjJOn3xo2NTKRgV1gaoTf2EhL+RG8TQ=
133-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400134""")
Rick Dean94e46fd2009-07-18 14:51:24 -0500135
Jean-Paul Calderone22cbe502011-05-04 17:01:43 -0400136client_key_pem = normalize_privatekey_pem(b("""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500137MIICXgIBAAKBgQDAZh/SRtNm5ntMT4qb6YzEpTroMlq2rn+GrRHRiZ+xkCw/CGNh
138btPir7/QxaUj26BSmQrHw1bGKEbPsWiW7bdXSespl+xKiku4G/KvnnmWdeJHqsiX
139eUZtqurMELcPQAw9xPHEuhqqUJvvEoMTsnCEqGM+7DtboCRajYyHfluARQIDAQAB
140AoGATkZ+NceY5Glqyl4mD06SdcKfV65814vg2EL7V9t8+/mi9rYL8KztSXGlQWPX
141zuHgtRoMl78yQ4ZJYOBVo+nsx8KZNRCEBlE19bamSbQLCeQMenWnpeYyQUZ908gF
142h6L9qsFVJepgA9RDgAjyDoS5CaWCdCCPCH2lDkdcqC54SVUCQQDseuduc4wi8h4t
143V8AahUn9fn9gYfhoNuM0gdguTA0nPLVWz4hy1yJiWYQe0H7NLNNTmCKiLQaJpAbb
144TC6vE8C7AkEA0Ee8CMJUc20BnGEmxwgWcVuqFWaKCo8jTH1X38FlATUsyR3krjW2
145dL3yDD9NwHxsYP7nTKp/U8MV7U9IBn4y/wJBAJl7H0/BcLeRmuJk7IqJ7b635iYB
146D/9beFUw3MUXmQXZUfyYz39xf6CDZsu1GEdEC5haykeln3Of4M9d/4Kj+FcCQQCY
147si6xwT7GzMDkk/ko684AV3KPc/h6G0yGtFIrMg7J3uExpR/VdH2KgwMkZXisSMvw
148JJEQjOMCVsEJlRk54WWjAkEAzoZNH6UhDdBK5F38rVt/y4SEHgbSfJHIAmPS32Kq
149f6GGcfNpip0Uk7q7udTKuX7Q/buZi/C4YW7u3VKAquv9NA==
150-----END RSA PRIVATE KEY-----
Jean-Paul Calderone22cbe502011-05-04 17:01:43 -0400151"""))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400152
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400153cleartextCertificatePEM = b("""-----BEGIN CERTIFICATE-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400154MIIC7TCCAlagAwIBAgIIPQzE4MbeufQwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE
155BhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdU
156ZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwIhgPMjAwOTAzMjUxMjM2
157NThaGA8yMDE3MDYxMTEyMzY1OFowWDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklM
158MRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9U
159ZXN0aW5nIFJvb3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPmaQumL
160urpE527uSEHdL1pqcDRmWzu+98Y6YHzT/J7KWEamyMCNZ6fRW1JCR782UQ8a07fy
1612xXsKy4WdKaxyG8CcatwmXvpvRQ44dSANMihHELpANTdyVp6DCysED6wkQFurHlF
1621dshEaJw8b/ypDhmbVIo6Ci1xvCJqivbLFnbAgMBAAGjgbswgbgwHQYDVR0OBBYE
163FINVdy1eIfFJDAkk51QJEo3IfgSuMIGIBgNVHSMEgYAwfoAUg1V3LV4h8UkMCSTn
164VAkSjch+BK6hXKRaMFgxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UE
165BxMHQ2hpY2FnbzEQMA4GA1UEChMHVGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBS
166b290IENBggg9DMTgxt659DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB
167AGGCDazMJGoWNBpc03u6+smc95dEead2KlZXBATOdFT1VesY3+nUOqZhEhTGlDMi
168hkgaZnzoIq/Uamidegk4hirsCT/R+6vsKAAxNTcBjUeZjlykCJWy5ojShGftXIKY
169w/njVbKMXrvc83qmTdGl3TAM0fxQIpqgcglFLveEBgzn
170-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400171""")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400172
Jean-Paul Calderoned50d2042011-05-04 17:00:49 -0400173cleartextPrivateKeyPEM = normalize_privatekey_pem(b("""\
174-----BEGIN RSA PRIVATE KEY-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400175MIICXQIBAAKBgQD5mkLpi7q6ROdu7khB3S9aanA0Zls7vvfGOmB80/yeylhGpsjA
176jWen0VtSQke/NlEPGtO38tsV7CsuFnSmschvAnGrcJl76b0UOOHUgDTIoRxC6QDU
1773claegwsrBA+sJEBbqx5RdXbIRGicPG/8qQ4Zm1SKOgotcbwiaor2yxZ2wIDAQAB
178AoGBAPCgMpmLxzwDaUmcFbTJUvlLW1hoxNNYSu2jIZm1k/hRAcE60JYwvBkgz3UB
179yMEh0AtLxYe0bFk6EHah11tMUPgscbCq73snJ++8koUw+csk22G65hOs51bVb7Aa
1806JBe67oLzdtvgCUFAA2qfrKzWRZzAdhUirQUZgySZk+Xq1pBAkEA/kZG0A6roTSM
181BVnx7LnPfsycKUsTumorpXiylZJjTi9XtmzxhrYN6wgZlDOOwOLgSQhszGpxVoMD
182u3gByT1b2QJBAPtL3mSKdvwRu/+40zaZLwvSJRxaj0mcE4BJOS6Oqs/hS1xRlrNk
183PpQ7WJ4yM6ZOLnXzm2mKyxm50Mv64109FtMCQQDOqS2KkjHaLowTGVxwC0DijMfr
184I9Lf8sSQk32J5VWCySWf5gGTfEnpmUa41gKTMJIbqZZLucNuDcOtzUaeWZlZAkA8
185ttXigLnCqR486JDPTi9ZscoZkZ+w7y6e/hH8t6d5Vjt48JVyfjPIaJY+km58LcN3
1866AWSeGAdtRFHVzR7oHjVAkB4hutvxiOeiIVQNBhM6RSI9aBPMI21DoX2JRoxvNW2
187cbvAhow217X9V0dVerEOKxnNYspXRrh36h7k4mQA+sDq
188-----END RSA PRIVATE KEY-----
Jean-Paul Calderoned50d2042011-05-04 17:00:49 -0400189"""))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400190
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400191cleartextCertificateRequestPEM = b("""-----BEGIN CERTIFICATE REQUEST-----
192MIIBnjCCAQcCAQAwXjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQH
193EwdDaGljYWdvMRcwFQYDVQQKEw5NeSBDb21wYW55IEx0ZDEXMBUGA1UEAxMORnJl
194ZGVyaWNrIERlYW4wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANp6Y17WzKSw
195BsUWkXdqg6tnXy8H8hA1msCMWpc+/2KJ4mbv5NyD6UD+/SqagQqulPbF/DFea9nA
196E0zhmHJELcM8gUTIlXv/cgDWnmK4xj8YkjVUiCdqKRAKeuzLG1pGmwwF5lGeJpXN
197xQn5ecR0UYSOWj6TTGXB9VyUMQzCClcBAgMBAAGgADANBgkqhkiG9w0BAQUFAAOB
198gQAAJGuF/R/GGbeC7FbFW+aJgr9ee0Xbl6nlhu7pTe67k+iiKT2dsl2ti68MVTnu
199Vrb3HUNqOkiwsJf6kCtq5oPn3QVYzTa76Dt2y3Rtzv6boRSlmlfrgS92GNma8JfR
200oICQk3nAudi6zl1Dix3BCv1pUp5KMtGn3MeDEi6QFGy2rA==
201-----END CERTIFICATE REQUEST-----
202""")
Rick Dean5b7b6372009-04-01 11:34:06 -0500203
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400204encryptedPrivateKeyPEM = b("""-----BEGIN RSA PRIVATE KEY-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400205Proc-Type: 4,ENCRYPTED
206DEK-Info: DES-EDE3-CBC,9573604A18579E9E
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400207
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400208SHOho56WxDkT0ht10UTeKc0F5u8cqIa01kzFAmETw0MAs8ezYtK15NPdCXUm3X/2
209a17G7LSF5bkxOgZ7vpXyMzun/owrj7CzvLxyncyEFZWvtvzaAhPhvTJtTIB3kf8B
2108+qRcpTGK7NgXEgYBW5bj1y4qZkD4zCL9o9NQzsKI3Ie8i0239jsDOWR38AxjXBH
211mGwAQ4Z6ZN5dnmM4fhMIWsmFf19sNyAML4gHenQCHhmXbjXeVq47aC2ProInJbrm
212+00TcisbAQ40V9aehVbcDKtS4ZbMVDwncAjpXpcncC54G76N6j7F7wL7L/FuXa3A
213fvSVy9n2VfF/pJ3kYSflLHH2G/DFxjF7dl0GxhKPxJjp3IJi9VtuvmN9R2jZWLQF
214tfC8dXgy/P9CfFQhlinqBTEwgH0oZ/d4k4NVFDSdEMaSdmBAjlHpc+Vfdty3HVnV
215rKXj//wslsFNm9kIwJGIgKUa/n2jsOiydrsk1mgH7SmNCb3YHgZhbbnq0qLat/HC
216gHDt3FHpNQ31QzzL3yrenFB2L9osIsnRsDTPFNi4RX4SpDgNroxOQmyzCCV6H+d4
217o1mcnNiZSdxLZxVKccq0AfRpHqpPAFnJcQHP6xyT9MZp6fBa0XkxDnt9kNU8H3Qw
2187SJWZ69VXjBUzMlQViLuaWMgTnL+ZVyFZf9hTF7U/ef4HMLMAVNdiaGG+G+AjCV/
219MbzjS007Oe4qqBnCWaFPSnJX6uLApeTbqAxAeyCql56ULW5x6vDMNC3dwjvS/CEh
22011n8RkgFIQA0AhuKSIg3CbuartRsJnWOLwgLTzsrKYL4yRog1RJrtw==
221-----END RSA PRIVATE KEY-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400222""")
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400223
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400224encryptedPrivateKeyPEMPassphrase = b("foobar")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400225
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400226# Some PKCS#7 stuff. Generated with the openssl command line:
227#
228# openssl crl2pkcs7 -inform pem -outform pem -certfile s.pem -nocrl
229#
230# with a certificate and key (but the key should be irrelevant) in s.pem
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400231pkcs7Data = b("""\
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400232-----BEGIN PKCS7-----
233MIIDNwYJKoZIhvcNAQcCoIIDKDCCAyQCAQExADALBgkqhkiG9w0BBwGgggMKMIID
234BjCCAm+gAwIBAgIBATANBgkqhkiG9w0BAQQFADB7MQswCQYDVQQGEwJTRzERMA8G
235A1UEChMITTJDcnlwdG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtN
236MkNyeXB0byBDZXJ0aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNA
237cG9zdDEuY29tMB4XDTAwMDkxMDA5NTEzMFoXDTAyMDkxMDA5NTEzMFowUzELMAkG
238A1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwlsb2NhbGhvc3Qx
239HTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tMFwwDQYJKoZIhvcNAQEBBQAD
240SwAwSAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh5kwI
241zOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEAAaOCAQQwggEAMAkGA1UdEwQCMAAw
242LAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0G
243A1UdDgQWBBTPhIKSvnsmYsBVNWjj0m3M2z0qVTCBpQYDVR0jBIGdMIGagBT7hyNp
24465w6kxXlxb8pUU/+7Sg4AaF/pH0wezELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0y
245Q3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlwdG8g
246Q2VydGlmaWNhdGUgTWFzdGVyMR0wGwYJKoZIhvcNAQkBFg5uZ3BzQHBvc3QxLmNv
247bYIBADANBgkqhkiG9w0BAQQFAAOBgQA7/CqT6PoHycTdhEStWNZde7M/2Yc6BoJu
248VwnW8YxGO8Sn6UJ4FeffZNcYZddSDKosw8LtPOeWoK3JINjAk5jiPQ2cww++7QGG
249/g5NDjxFZNDJP1dGiLAxPW6JXwov4v0FmdzfLOZ01jDcgQQZqEpYlgpuI5JEWUQ9
250Ho4EzbYCOaEAMQA=
251-----END PKCS7-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400252""")
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400253
Alex Gaynor8fa1dd62014-08-14 09:57:51 -0700254pkcs7DataASN1 = base64.b64decode(b"""
Alex Gaynor4b9c96a2014-08-14 09:51:48 -0700255MIIDNwYJKoZIhvcNAQcCoIIDKDCCAyQCAQExADALBgkqhkiG9w0BBwGgggMKMIID
256BjCCAm+gAwIBAgIBATANBgkqhkiG9w0BAQQFADB7MQswCQYDVQQGEwJTRzERMA8G
257A1UEChMITTJDcnlwdG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtN
258MkNyeXB0byBDZXJ0aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNA
259cG9zdDEuY29tMB4XDTAwMDkxMDA5NTEzMFoXDTAyMDkxMDA5NTEzMFowUzELMAkG
260A1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwlsb2NhbGhvc3Qx
261HTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tMFwwDQYJKoZIhvcNAQEBBQAD
262SwAwSAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh5kwI
263zOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEAAaOCAQQwggEAMAkGA1UdEwQCMAAw
264LAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0G
265A1UdDgQWBBTPhIKSvnsmYsBVNWjj0m3M2z0qVTCBpQYDVR0jBIGdMIGagBT7hyNp
26665w6kxXlxb8pUU/+7Sg4AaF/pH0wezELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0y
267Q3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlwdG8g
268Q2VydGlmaWNhdGUgTWFzdGVyMR0wGwYJKoZIhvcNAQkBFg5uZ3BzQHBvc3QxLmNv
269bYIBADANBgkqhkiG9w0BAQQFAAOBgQA7/CqT6PoHycTdhEStWNZde7M/2Yc6BoJu
270VwnW8YxGO8Sn6UJ4FeffZNcYZddSDKosw8LtPOeWoK3JINjAk5jiPQ2cww++7QGG
271/g5NDjxFZNDJP1dGiLAxPW6JXwov4v0FmdzfLOZ01jDcgQQZqEpYlgpuI5JEWUQ9
272Ho4EzbYCOaEAMQA=
Alex Gaynor8fa1dd62014-08-14 09:57:51 -0700273""")
Alex Gaynor4b9c96a2014-08-14 09:51:48 -0700274
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400275crlData = b("""\
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -0500276-----BEGIN X509 CRL-----
277MIIBWzCBxTANBgkqhkiG9w0BAQQFADBYMQswCQYDVQQGEwJVUzELMAkGA1UECBMC
278SUwxEDAOBgNVBAcTB0NoaWNhZ28xEDAOBgNVBAoTB1Rlc3RpbmcxGDAWBgNVBAMT
279D1Rlc3RpbmcgUm9vdCBDQRcNMDkwNzI2MDQzNDU2WhcNMTIwOTI3MDI0MTUyWjA8
280MBUCAgOrGA8yMDA5MDcyNTIzMzQ1NlowIwICAQAYDzIwMDkwNzI1MjMzNDU2WjAM
281MAoGA1UdFQQDCgEEMA0GCSqGSIb3DQEBBAUAA4GBAEBt7xTs2htdD3d4ErrcGAw1
2824dKcVnIWTutoI7xxen26Wwvh8VCsT7i/UeP+rBl9rC/kfjWjzQk3/zleaarGTpBT
2830yp4HXRFFoRhhSE/hP+eteaPXRgrsNRLHe9ZDd69wmh7J1wMDb0m81RG7kqcbsid
284vrzEeLDRiiPl92dyyWmu
285-----END X509 CRL-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400286""")
Jean-Paul Calderonee890db32010-08-22 16:55:15 -0400287
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400288
289# A broken RSA private key which can be used to test the error path through
290# PKey.check.
291inconsistentPrivateKeyPEM = b("""-----BEGIN RSA PRIVATE KEY-----
292MIIBPAIBAAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh
2935kwIzOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEaAQJBAIqm/bz4NA1H++Vx5Ewx
294OcKp3w19QSaZAwlGRtsUxrP7436QjnREM3Bm8ygU11BjkPVmtrKm6AayQfCHqJoT
295zIECIQDW0BoMoL0HOYM/mrTLhaykYAVqgIeJsPjvkEhTFXWBuQIhAM3deFAvWNu4
296nklUQ37XsCT2c9tmNt1LAT+slG2JOTTRAiAuXDtC/m3NYVwyHfFm+zKHRzHkClk2
297HjubeEgjpj32AQIhAJqMGTaZVOwevTXvvHwNeH+vRWsAYU/gbx+OQB+7VOcBAiEA
298oolb6NMg/R3enNPvS1O4UU1H8wpaF77L4yiSWlE0p4w=
299-----END RSA PRIVATE KEY-----
300""")
301
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -0400302# certificate with NULL bytes in subjectAltName and common name
303
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400304nulbyteSubjectAltNamePEM = b("""-----BEGIN CERTIFICATE-----
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -0400305MIIE2DCCA8CgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBxTELMAkGA1UEBhMCVVMx
306DzANBgNVBAgMBk9yZWdvbjESMBAGA1UEBwwJQmVhdmVydG9uMSMwIQYDVQQKDBpQ
307eXRob24gU29mdHdhcmUgRm91bmRhdGlvbjEgMB4GA1UECwwXUHl0aG9uIENvcmUg
308RGV2ZWxvcG1lbnQxJDAiBgNVBAMMG251bGwucHl0aG9uLm9yZwBleGFtcGxlLm9y
309ZzEkMCIGCSqGSIb3DQEJARYVcHl0aG9uLWRldkBweXRob24ub3JnMB4XDTEzMDgw
310NzEzMTE1MloXDTEzMDgwNzEzMTI1MlowgcUxCzAJBgNVBAYTAlVTMQ8wDQYDVQQI
311DAZPcmVnb24xEjAQBgNVBAcMCUJlYXZlcnRvbjEjMCEGA1UECgwaUHl0aG9uIFNv
312ZnR3YXJlIEZvdW5kYXRpb24xIDAeBgNVBAsMF1B5dGhvbiBDb3JlIERldmVsb3Bt
313ZW50MSQwIgYDVQQDDBtudWxsLnB5dGhvbi5vcmcAZXhhbXBsZS5vcmcxJDAiBgkq
314hkiG9w0BCQEWFXB5dGhvbi1kZXZAcHl0aG9uLm9yZzCCASIwDQYJKoZIhvcNAQEB
315BQADggEPADCCAQoCggEBALXq7cn7Rn1vO3aA3TrzA5QLp6bb7B3f/yN0CJ2XFj+j
316pHs+Gw6WWSUDpybiiKnPec33BFawq3kyblnBMjBU61ioy5HwQqVkJ8vUVjGIUq3P
317vX/wBmQfzCe4o4uM89gpHyUL9UYGG8oCRa17dgqcv7u5rg0Wq2B1rgY+nHwx3JIv
318KRrgSwyRkGzpN8WQ1yrXlxWjgI9de0mPVDDUlywcWze1q2kwaEPTM3hLAmD1PESA
319oY/n8A/RXoeeRs9i/Pm/DGUS8ZPINXk/yOzsR/XvvkTVroIeLZqfmFpnZeF0cHzL
32008LODkVJJ9zjLdT7SA4vnne4FEbAxDbKAq5qkYzaL4UCAwEAAaOB0DCBzTAMBgNV
321HRMBAf8EAjAAMB0GA1UdDgQWBBSIWlXAUv9hzVKjNQ/qWpwkOCL3XDALBgNVHQ8E
322BAMCBeAwgZAGA1UdEQSBiDCBhYIeYWx0bnVsbC5weXRob24ub3JnAGV4YW1wbGUu
323Y29tgSBudWxsQHB5dGhvbi5vcmcAdXNlckBleGFtcGxlLm9yZ4YpaHR0cDovL251
324bGwucHl0aG9uLm9yZwBodHRwOi8vZXhhbXBsZS5vcmeHBMAAAgGHECABDbgAAAAA
325AAAAAAAAAAEwDQYJKoZIhvcNAQEFBQADggEBAKxPRe99SaghcI6IWT7UNkJw9aO9
326i9eo0Fj2MUqxpKbdb9noRDy2CnHWf7EIYZ1gznXPdwzSN4YCjV5d+Q9xtBaowT0j
327HPERs1ZuytCNNJTmhyqZ8q6uzMLoht4IqH/FBfpvgaeC5tBTnTT0rD5A/olXeimk
328kX4LxlEx5RAvpGB2zZVRGr6LobD9rVK91xuHYNIxxxfEGE8tCCWjp0+3ksri9SXx
329VHWBnbM9YaL32u3hxm8sYB/Yb8WSBavJCWJJqRStVRHM1koZlJmXNx2BX4vPo6iW
330RFEIPQsFZRLrtnCAiEhyT8bC2s/Njlu6ly9gtJZWSV46Q3ZjBL4q9sHKqZQ=
331-----END CERTIFICATE-----""")
332
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400333
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400334class X509ExtTests(TestCase):
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400335 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900336 Tests for :py:class:`OpenSSL.crypto.X509Extension`.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400337 """
338
339 def setUp(self):
340 """
341 Create a new private key and start a certificate request (for a test
342 method to finish in one way or another).
343 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -0800344 super(X509ExtTests, self).setUp()
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400345 # Basic setup stuff to generate a certificate
346 self.pkey = PKey()
347 self.pkey.generate_key(TYPE_RSA, 384)
348 self.req = X509Req()
349 self.req.set_pubkey(self.pkey)
350 # Authority good you have.
351 self.req.get_subject().commonName = "Yoda root CA"
352 self.x509 = X509()
353 self.subject = self.x509.get_subject()
354 self.subject.commonName = self.req.get_subject().commonName
355 self.x509.set_issuer(self.subject)
356 self.x509.set_pubkey(self.pkey)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400357 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
358 expire = b((datetime.now() + timedelta(days=100)).strftime("%Y%m%d%H%M%SZ"))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400359 self.x509.set_notBefore(now)
360 self.x509.set_notAfter(expire)
361
362
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -0800363 def tearDown(self):
364 """
365 Forget all of the pyOpenSSL objects so they can be garbage collected,
366 their memory released, and not interfere with the leak detection code.
367 """
368 self.pkey = self.req = self.x509 = self.subject = None
369 super(X509ExtTests, self).tearDown()
370
371
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400372 def test_str(self):
373 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900374 The string representation of :py:class:`X509Extension` instances as returned by
375 :py:data:`str` includes stuff.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400376 """
377 # This isn't necessarily the best string representation. Perhaps it
378 # will be changed/improved in the future.
379 self.assertEquals(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400380 str(X509Extension(b('basicConstraints'), True, b('CA:false'))),
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400381 'CA:FALSE')
382
383
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400384 def test_type(self):
385 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900386 :py:class:`X509Extension` and :py:class:`X509ExtensionType` refer to the same type object
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400387 and can be used to create instances of that type.
388 """
389 self.assertIdentical(X509Extension, X509ExtensionType)
390 self.assertConsistentType(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400391 X509Extension,
392 'X509Extension', b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400393
394
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500395 def test_construction(self):
396 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900397 :py:class:`X509Extension` accepts an extension type name, a critical flag,
398 and an extension value and returns an :py:class:`X509ExtensionType` instance.
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500399 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400400 basic = X509Extension(b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500401 self.assertTrue(
402 isinstance(basic, X509ExtensionType),
403 "%r is of type %r, should be %r" % (
404 basic, type(basic), X509ExtensionType))
405
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400406 comment = X509Extension(
407 b('nsComment'), False, b('pyOpenSSL unit test'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500408 self.assertTrue(
409 isinstance(comment, X509ExtensionType),
410 "%r is of type %r, should be %r" % (
411 comment, type(comment), X509ExtensionType))
412
413
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500414 def test_invalid_extension(self):
415 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900416 :py:class:`X509Extension` raises something if it is passed a bad extension
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500417 name or value.
418 """
419 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400420 Error, X509Extension, b('thisIsMadeUp'), False, b('hi'))
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500421 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400422 Error, X509Extension, b('basicConstraints'), False, b('blah blah'))
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500423
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500424 # Exercise a weird one (an extension which uses the r2i method). This
425 # exercises the codepath that requires a non-NULL ctx to be passed to
426 # X509V3_EXT_nconf. It can't work now because we provide no
427 # configuration database. It might be made to work in the future.
428 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400429 Error, X509Extension, b('proxyCertInfo'), True,
430 b('language:id-ppl-anyLanguage,pathlen:1,policy:text:AB'))
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500431
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500432
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500433 def test_get_critical(self):
434 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900435 :py:meth:`X509ExtensionType.get_critical` returns the value of the
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500436 extension's critical flag.
437 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400438 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500439 self.assertTrue(ext.get_critical())
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400440 ext = X509Extension(b('basicConstraints'), False, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500441 self.assertFalse(ext.get_critical())
442
Jean-Paul Calderone7535dab2008-03-06 18:53:11 -0500443
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500444 def test_get_short_name(self):
445 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900446 :py:meth:`X509ExtensionType.get_short_name` returns a string giving the short
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500447 type name of the extension.
448 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400449 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
450 self.assertEqual(ext.get_short_name(), b('basicConstraints'))
451 ext = X509Extension(b('nsComment'), True, b('foo bar'))
452 self.assertEqual(ext.get_short_name(), b('nsComment'))
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500453
454
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400455 def test_get_data(self):
456 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900457 :py:meth:`X509Extension.get_data` returns a string giving the data of the
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400458 extension.
459 """
460 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
461 # Expect to get back the DER encoded form of CA:true.
462 self.assertEqual(ext.get_data(), b('0\x03\x01\x01\xff'))
463
464
465 def test_get_data_wrong_args(self):
466 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900467 :py:meth:`X509Extension.get_data` raises :py:exc:`TypeError` if passed any arguments.
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400468 """
469 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
470 self.assertRaises(TypeError, ext.get_data, None)
471 self.assertRaises(TypeError, ext.get_data, "foo")
472 self.assertRaises(TypeError, ext.get_data, 7)
473
474
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400475 def test_unused_subject(self):
Rick Dean47262da2009-07-08 16:17:17 -0500476 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900477 The :py:data:`subject` parameter to :py:class:`X509Extension` may be provided for an
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400478 extension which does not use it and is ignored in this case.
Rick Dean47262da2009-07-08 16:17:17 -0500479 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400480 ext1 = X509Extension(
481 b('basicConstraints'), False, b('CA:TRUE'), subject=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400482 self.x509.add_extensions([ext1])
483 self.x509.sign(self.pkey, 'sha1')
484 # This is a little lame. Can we think of a better way?
485 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400486 self.assertTrue(b('X509v3 Basic Constraints:') in text)
487 self.assertTrue(b('CA:TRUE') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400488
489
490 def test_subject(self):
491 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900492 If an extension requires a subject, the :py:data:`subject` parameter to
493 :py:class:`X509Extension` provides its value.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400494 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400495 ext3 = X509Extension(
496 b('subjectKeyIdentifier'), False, b('hash'), subject=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400497 self.x509.add_extensions([ext3])
498 self.x509.sign(self.pkey, 'sha1')
499 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400500 self.assertTrue(b('X509v3 Subject Key Identifier:') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400501
502
503 def test_missing_subject(self):
504 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900505 If an extension requires a subject and the :py:data:`subject` parameter is
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400506 given no value, something happens.
507 """
508 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400509 Error, X509Extension, b('subjectKeyIdentifier'), False, b('hash'))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400510
511
512 def test_invalid_subject(self):
513 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900514 If the :py:data:`subject` parameter is given a value which is not an
515 :py:class:`X509` instance, :py:exc:`TypeError` is raised.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400516 """
517 for badObj in [True, object(), "hello", [], self]:
518 self.assertRaises(
519 TypeError,
520 X509Extension,
521 'basicConstraints', False, 'CA:TRUE', subject=badObj)
522
523
524 def test_unused_issuer(self):
525 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900526 The :py:data:`issuer` parameter to :py:class:`X509Extension` may be provided for an
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400527 extension which does not use it and is ignored in this case.
528 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400529 ext1 = X509Extension(
530 b('basicConstraints'), False, b('CA:TRUE'), issuer=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400531 self.x509.add_extensions([ext1])
532 self.x509.sign(self.pkey, 'sha1')
533 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400534 self.assertTrue(b('X509v3 Basic Constraints:') in text)
535 self.assertTrue(b('CA:TRUE') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400536
537
538 def test_issuer(self):
539 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900540 If an extension requires a issuer, the :py:data:`issuer` parameter to
541 :py:class:`X509Extension` provides its value.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400542 """
543 ext2 = X509Extension(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400544 b('authorityKeyIdentifier'), False, b('issuer:always'),
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400545 issuer=self.x509)
546 self.x509.add_extensions([ext2])
547 self.x509.sign(self.pkey, 'sha1')
548 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400549 self.assertTrue(b('X509v3 Authority Key Identifier:') in text)
550 self.assertTrue(b('DirName:/CN=Yoda root CA') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400551
552
553 def test_missing_issuer(self):
554 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900555 If an extension requires an issue and the :py:data:`issuer` parameter is given
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400556 no value, something happens.
557 """
558 self.assertRaises(
559 Error,
560 X509Extension,
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400561 b('authorityKeyIdentifier'), False,
562 b('keyid:always,issuer:always'))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400563
564
565 def test_invalid_issuer(self):
566 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900567 If the :py:data:`issuer` parameter is given a value which is not an
568 :py:class:`X509` instance, :py:exc:`TypeError` is raised.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400569 """
570 for badObj in [True, object(), "hello", [], self]:
571 self.assertRaises(
572 TypeError,
573 X509Extension,
574 'authorityKeyIdentifier', False, 'keyid:always,issuer:always',
575 issuer=badObj)
Rick Dean47262da2009-07-08 16:17:17 -0500576
577
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500578
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400579class PKeyTests(TestCase):
Jean-Paul Calderoneac930e12008-03-06 18:50:51 -0500580 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900581 Unit tests for :py:class:`OpenSSL.crypto.PKey`.
Jean-Paul Calderoneac930e12008-03-06 18:50:51 -0500582 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400583 def test_type(self):
584 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900585 :py:class:`PKey` and :py:class:`PKeyType` refer to the same type object
586 and can be used to create instances of that type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400587 """
588 self.assertIdentical(PKey, PKeyType)
589 self.assertConsistentType(PKey, 'PKey')
590
591
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500592 def test_construction(self):
593 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900594 :py:class:`PKey` takes no arguments and returns a new :py:class:`PKey` instance.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500595 """
596 self.assertRaises(TypeError, PKey, None)
597 key = PKey()
598 self.assertTrue(
599 isinstance(key, PKeyType),
600 "%r is of type %r, should be %r" % (key, type(key), PKeyType))
601
602
603 def test_pregeneration(self):
604 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900605 :py:attr:`PKeyType.bits` and :py:attr:`PKeyType.type` return :py:data:`0` before the key is
606 generated. :py:attr:`PKeyType.check` raises :py:exc:`TypeError` before the key is
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500607 generated.
608 """
609 key = PKey()
610 self.assertEqual(key.type(), 0)
611 self.assertEqual(key.bits(), 0)
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400612 self.assertRaises(TypeError, key.check)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500613
614
615 def test_failedGeneration(self):
616 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900617 :py:meth:`PKeyType.generate_key` takes two arguments, the first giving the key
618 type as one of :py:data:`TYPE_RSA` or :py:data:`TYPE_DSA` and the second giving the
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500619 number of bits to generate. If an invalid type is specified or
Jonathan Ballet648875f2011-07-16 14:14:58 +0900620 generation fails, :py:exc:`Error` is raised. If an invalid number of bits is
621 specified, :py:exc:`ValueError` or :py:exc:`Error` is raised.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500622 """
623 key = PKey()
624 self.assertRaises(TypeError, key.generate_key)
625 self.assertRaises(TypeError, key.generate_key, 1, 2, 3)
626 self.assertRaises(TypeError, key.generate_key, "foo", "bar")
627 self.assertRaises(Error, key.generate_key, -1, 0)
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500628
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500629 self.assertRaises(ValueError, key.generate_key, TYPE_RSA, -1)
630 self.assertRaises(ValueError, key.generate_key, TYPE_RSA, 0)
Jean-Paul Calderoned71fe982008-03-06 00:31:50 -0500631
632 # XXX RSA generation for small values of bits is fairly buggy in a wide
633 # range of OpenSSL versions. I need to figure out what the safe lower
634 # bound for a reasonable number of OpenSSL versions is and explicitly
635 # check for that in the wrapper. The failure behavior is typically an
636 # infinite loop inside OpenSSL.
637
638 # self.assertRaises(Error, key.generate_key, TYPE_RSA, 2)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500639
640 # XXX DSA generation seems happy with any number of bits. The DSS
641 # says bits must be between 512 and 1024 inclusive. OpenSSL's DSA
642 # generator doesn't seem to care about the upper limit at all. For
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500643 # the lower limit, it uses 512 if anything smaller is specified.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500644 # So, it doesn't seem possible to make generate_key fail for
645 # TYPE_DSA with a bits argument which is at least an int.
646
647 # self.assertRaises(Error, key.generate_key, TYPE_DSA, -7)
648
649
650 def test_rsaGeneration(self):
651 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900652 :py:meth:`PKeyType.generate_key` generates an RSA key when passed
653 :py:data:`TYPE_RSA` as a type and a reasonable number of bits.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500654 """
655 bits = 128
656 key = PKey()
657 key.generate_key(TYPE_RSA, bits)
658 self.assertEqual(key.type(), TYPE_RSA)
659 self.assertEqual(key.bits(), bits)
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -0400660 self.assertTrue(key.check())
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500661
662
663 def test_dsaGeneration(self):
664 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900665 :py:meth:`PKeyType.generate_key` generates a DSA key when passed
666 :py:data:`TYPE_DSA` as a type and a reasonable number of bits.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500667 """
668 # 512 is a magic number. The DSS (Digital Signature Standard)
669 # allows a minimum of 512 bits for DSA. DSA_generate_parameters
670 # will silently promote any value below 512 to 512.
671 bits = 512
672 key = PKey()
673 key.generate_key(TYPE_DSA, bits)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800674 # self.assertEqual(key.type(), TYPE_DSA)
675 # self.assertEqual(key.bits(), bits)
676 # self.assertRaises(TypeError, key.check)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500677
678
679 def test_regeneration(self):
680 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900681 :py:meth:`PKeyType.generate_key` can be called multiple times on the same
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500682 key to generate new keys.
683 """
684 key = PKey()
685 for type, bits in [(TYPE_RSA, 512), (TYPE_DSA, 576)]:
686 key.generate_key(type, bits)
687 self.assertEqual(key.type(), type)
688 self.assertEqual(key.bits(), bits)
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500689
690
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400691 def test_inconsistentKey(self):
692 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900693 :py:`PKeyType.check` returns :py:exc:`Error` if the key is not consistent.
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400694 """
695 key = load_privatekey(FILETYPE_PEM, inconsistentPrivateKeyPEM)
Jean-Paul Calderoned338e4e2009-05-13 15:45:07 -0400696 self.assertRaises(Error, key.check)
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400697
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500698
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400699 def test_check_wrong_args(self):
700 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900701 :py:meth:`PKeyType.check` raises :py:exc:`TypeError` if called with any arguments.
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400702 """
703 self.assertRaises(TypeError, PKey().check, None)
704 self.assertRaises(TypeError, PKey().check, object())
705 self.assertRaises(TypeError, PKey().check, 1)
706
707
Jean-Paul Calderone02d01972011-10-31 10:39:29 -0400708 def test_check_public_key(self):
709 """
710 :py:meth:`PKeyType.check` raises :py:exc:`TypeError` if only the public
711 part of the key is available.
712 """
713 # A trick to get a public-only key
714 key = PKey()
715 key.generate_key(TYPE_RSA, 512)
716 cert = X509()
717 cert.set_pubkey(key)
718 pub = cert.get_pubkey()
719 self.assertRaises(TypeError, pub.check)
720
721
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400722
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400723class X509NameTests(TestCase):
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500724 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900725 Unit tests for :py:class:`OpenSSL.crypto.X509Name`.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500726 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500727 def _x509name(self, **attrs):
728 # XXX There's no other way to get a new X509Name yet.
729 name = X509().get_subject()
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400730 attrs = list(attrs.items())
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500731 # Make the order stable - order matters!
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400732 def key(attr):
733 return attr[1]
734 attrs.sort(key=key)
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500735 for k, v in attrs:
736 setattr(name, k, v)
737 return name
738
739
Rick Deane15b1472009-07-09 15:53:42 -0500740 def test_type(self):
741 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900742 The type of X509Name objects is :py:class:`X509NameType`.
Rick Deane15b1472009-07-09 15:53:42 -0500743 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400744 self.assertIdentical(X509Name, X509NameType)
745 self.assertEqual(X509NameType.__name__, 'X509Name')
746 self.assertTrue(isinstance(X509NameType, type))
747
Rick Deane15b1472009-07-09 15:53:42 -0500748 name = self._x509name()
749 self.assertTrue(
750 isinstance(name, X509NameType),
751 "%r is of type %r, should be %r" % (
752 name, type(name), X509NameType))
Rick Deane15b1472009-07-09 15:53:42 -0500753
754
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400755 def test_onlyStringAttributes(self):
756 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900757 Attempting to set a non-:py:data:`str` attribute name on an :py:class:`X509NameType`
758 instance causes :py:exc:`TypeError` to be raised.
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400759 """
760 name = self._x509name()
761 # Beyond these cases, you may also think that unicode should be
762 # rejected. Sorry, you're wrong. unicode is automatically converted to
763 # str outside of the control of X509Name, so there's no way to reject
764 # it.
Jean-Paul Calderoneff363be2013-03-03 10:21:23 -0800765
766 # Also, this used to test str subclasses, but that test is less relevant
767 # now that the implementation is in Python instead of C. Also PyPy
768 # automatically converts str subclasses to str when they are passed to
769 # setattr, so we can't test it on PyPy. Apparently CPython does this
770 # sometimes as well.
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400771 self.assertRaises(TypeError, setattr, name, None, "hello")
772 self.assertRaises(TypeError, setattr, name, 30, "hello")
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400773
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -0500774
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400775 def test_setInvalidAttribute(self):
776 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900777 Attempting to set any attribute name on an :py:class:`X509NameType` instance for
778 which no corresponding NID is defined causes :py:exc:`AttributeError` to be
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400779 raised.
780 """
781 name = self._x509name()
782 self.assertRaises(AttributeError, setattr, name, "no such thing", None)
783
784
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500785 def test_attributes(self):
786 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900787 :py:class:`X509NameType` instances have attributes for each standard (?)
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500788 X509Name field.
789 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500790 name = self._x509name()
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500791 name.commonName = "foo"
792 self.assertEqual(name.commonName, "foo")
793 self.assertEqual(name.CN, "foo")
794 name.CN = "baz"
795 self.assertEqual(name.commonName, "baz")
796 self.assertEqual(name.CN, "baz")
797 name.commonName = "bar"
798 self.assertEqual(name.commonName, "bar")
799 self.assertEqual(name.CN, "bar")
800 name.CN = "quux"
801 self.assertEqual(name.commonName, "quux")
802 self.assertEqual(name.CN, "quux")
803
804
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500805 def test_copy(self):
806 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900807 :py:class:`X509Name` creates a new :py:class:`X509NameType` instance with all the same
808 attributes as an existing :py:class:`X509NameType` instance when called with
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500809 one.
810 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500811 name = self._x509name(commonName="foo", emailAddress="bar@example.com")
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500812
813 copy = X509Name(name)
814 self.assertEqual(copy.commonName, "foo")
815 self.assertEqual(copy.emailAddress, "bar@example.com")
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500816
817 # Mutate the copy and ensure the original is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500818 copy.commonName = "baz"
819 self.assertEqual(name.commonName, "foo")
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500820
821 # Mutate the original and ensure the copy is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500822 name.emailAddress = "quux@example.com"
823 self.assertEqual(copy.emailAddress, "bar@example.com")
824
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500825
826 def test_repr(self):
827 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900828 :py:func:`repr` passed an :py:class:`X509NameType` instance should return a string
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500829 containing a description of the type and the NIDs which have been set
830 on it.
831 """
832 name = self._x509name(commonName="foo", emailAddress="bar")
833 self.assertEqual(
834 repr(name),
835 "<X509Name object '/emailAddress=bar/CN=foo'>")
836
837
838 def test_comparison(self):
839 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900840 :py:class:`X509NameType` instances should compare based on their NIDs.
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500841 """
842 def _equality(a, b, assertTrue, assertFalse):
843 assertTrue(a == b, "(%r == %r) --> False" % (a, b))
844 assertFalse(a != b)
845 assertTrue(b == a)
846 assertFalse(b != a)
847
848 def assertEqual(a, b):
849 _equality(a, b, self.assertTrue, self.assertFalse)
850
851 # Instances compare equal to themselves.
852 name = self._x509name()
853 assertEqual(name, name)
854
855 # Empty instances should compare equal to each other.
856 assertEqual(self._x509name(), self._x509name())
857
858 # Instances with equal NIDs should compare equal to each other.
859 assertEqual(self._x509name(commonName="foo"),
860 self._x509name(commonName="foo"))
861
862 # Instance with equal NIDs set using different aliases should compare
863 # equal to each other.
864 assertEqual(self._x509name(commonName="foo"),
865 self._x509name(CN="foo"))
866
867 # Instances with more than one NID with the same values should compare
868 # equal to each other.
869 assertEqual(self._x509name(CN="foo", organizationalUnitName="bar"),
870 self._x509name(commonName="foo", OU="bar"))
871
872 def assertNotEqual(a, b):
873 _equality(a, b, self.assertFalse, self.assertTrue)
874
875 # Instances with different values for the same NID should not compare
876 # equal to each other.
877 assertNotEqual(self._x509name(CN="foo"),
878 self._x509name(CN="bar"))
879
880 # Instances with different NIDs should not compare equal to each other.
881 assertNotEqual(self._x509name(CN="foo"),
882 self._x509name(OU="foo"))
883
884 def _inequality(a, b, assertTrue, assertFalse):
885 assertTrue(a < b)
886 assertTrue(a <= b)
887 assertTrue(b > a)
888 assertTrue(b >= a)
889 assertFalse(a > b)
890 assertFalse(a >= b)
891 assertFalse(b < a)
892 assertFalse(b <= a)
893
894 def assertLessThan(a, b):
895 _inequality(a, b, self.assertTrue, self.assertFalse)
896
897 # An X509Name with a NID with a value which sorts less than the value
898 # of the same NID on another X509Name compares less than the other
899 # X509Name.
900 assertLessThan(self._x509name(CN="abc"),
901 self._x509name(CN="def"))
902
903 def assertGreaterThan(a, b):
904 _inequality(a, b, self.assertFalse, self.assertTrue)
905
906 # An X509Name with a NID with a value which sorts greater than the
907 # value of the same NID on another X509Name compares greater than the
908 # other X509Name.
909 assertGreaterThan(self._x509name(CN="def"),
910 self._x509name(CN="abc"))
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -0500911
912
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400913 def test_hash(self):
914 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900915 :py:meth:`X509Name.hash` returns an integer hash based on the value of the
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400916 name.
917 """
918 a = self._x509name(CN="foo")
919 b = self._x509name(CN="foo")
920 self.assertEqual(a.hash(), b.hash())
921 a.CN = "bar"
922 self.assertNotEqual(a.hash(), b.hash())
923
924
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400925 def test_der(self):
926 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900927 :py:meth:`X509Name.der` returns the DER encoded form of the name.
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400928 """
929 a = self._x509name(CN="foo", C="US")
930 self.assertEqual(
931 a.der(),
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -0400932 b('0\x1b1\x0b0\t\x06\x03U\x04\x06\x13\x02US'
933 '1\x0c0\n\x06\x03U\x04\x03\x13\x03foo'))
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400934
935
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400936 def test_get_components(self):
937 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900938 :py:meth:`X509Name.get_components` returns a :py:data:`list` of
939 two-tuples of :py:data:`str`
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400940 giving the NIDs and associated values which make up the name.
941 """
942 a = self._x509name()
943 self.assertEqual(a.get_components(), [])
944 a.CN = "foo"
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -0400945 self.assertEqual(a.get_components(), [(b("CN"), b("foo"))])
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400946 a.organizationalUnitName = "bar"
947 self.assertEqual(
948 a.get_components(),
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -0400949 [(b("CN"), b("foo")), (b("OU"), b("bar"))])
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400950
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400951
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400952 def test_load_nul_byte_attribute(self):
953 """
Jean-Paul Calderone9af07b02013-08-23 16:07:31 -0400954 An :py:class:`OpenSSL.crypto.X509Name` from an
955 :py:class:`OpenSSL.crypto.X509` instance loaded from a file can have a
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400956 NUL byte in the value of one of its attributes.
957 """
958 cert = load_certificate(FILETYPE_PEM, nulbyteSubjectAltNamePEM)
959 subject = cert.get_subject()
960 self.assertEqual(
Jean-Paul Calderone06754fc2013-08-23 15:47:47 -0400961 "null.python.org\x00example.org", subject.commonName)
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400962
963
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -0500964 def test_setAttributeFailure(self):
965 """
966 If the value of an attribute cannot be set for some reason then
967 :py:class:`OpenSSL.crypto.Error` is raised.
968 """
969 name = self._x509name()
970 # This value is too long
971 self.assertRaises(Error, setattr, name, "O", b"x" * 512)
972
973
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400974
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400975class _PKeyInteractionTestsMixin:
976 """
977 Tests which involve another thing and a PKey.
978 """
979 def signable(self):
980 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900981 Return something with a :py:meth:`set_pubkey`, :py:meth:`set_pubkey`,
982 and :py:meth:`sign` method.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400983 """
984 raise NotImplementedError()
985
986
987 def test_signWithUngenerated(self):
988 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900989 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when pass a
990 :py:class:`PKey` with no parts.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400991 """
992 request = self.signable()
993 key = PKey()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500994 self.assertRaises(ValueError, request.sign, key, GOOD_DIGEST)
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400995
996
997 def test_signWithPublicKey(self):
998 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900999 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when pass a
1000 :py:class:`PKey` with no private part as the signing key.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001001 """
1002 request = self.signable()
1003 key = PKey()
1004 key.generate_key(TYPE_RSA, 512)
1005 request.set_pubkey(key)
1006 pub = request.get_pubkey()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001007 self.assertRaises(ValueError, request.sign, pub, GOOD_DIGEST)
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001008
1009
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -04001010 def test_signWithUnknownDigest(self):
1011 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001012 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when passed a digest name which is
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -04001013 not known.
1014 """
1015 request = self.signable()
1016 key = PKey()
1017 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001018 self.assertRaises(ValueError, request.sign, key, BAD_DIGEST)
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -04001019
1020
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04001021 def test_sign(self):
1022 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001023 :py:meth:`X509Req.sign` succeeds when passed a private key object and a valid
1024 digest function. :py:meth:`X509Req.verify` can be used to check the signature.
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04001025 """
1026 request = self.signable()
1027 key = PKey()
1028 key.generate_key(TYPE_RSA, 512)
1029 request.set_pubkey(key)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001030 request.sign(key, GOOD_DIGEST)
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04001031 # If the type has a verify method, cover that too.
1032 if getattr(request, 'verify', None) is not None:
1033 pub = request.get_pubkey()
1034 self.assertTrue(request.verify(pub))
1035 # Make another key that won't verify.
1036 key = PKey()
1037 key.generate_key(TYPE_RSA, 512)
1038 self.assertRaises(Error, request.verify, key)
1039
1040
1041
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001042
Jean-Paul Calderone18808652009-07-05 12:54:05 -04001043class X509ReqTests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001044 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001045 Tests for :py:class:`OpenSSL.crypto.X509Req`.
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001046 """
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001047 def signable(self):
1048 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001049 Create and return a new :py:class:`X509Req`.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001050 """
1051 return X509Req()
1052
1053
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001054 def test_type(self):
1055 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001056 :py:obj:`X509Req` and :py:obj:`X509ReqType` refer to the same type object and can be
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001057 used to create instances of that type.
1058 """
1059 self.assertIdentical(X509Req, X509ReqType)
1060 self.assertConsistentType(X509Req, 'X509Req')
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001061
1062
1063 def test_construction(self):
1064 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001065 :py:obj:`X509Req` takes no arguments and returns an :py:obj:`X509ReqType` instance.
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001066 """
1067 request = X509Req()
1068 self.assertTrue(
1069 isinstance(request, X509ReqType),
1070 "%r is of type %r, should be %r" % (request, type(request), X509ReqType))
1071
1072
Jean-Paul Calderone8dd19b82008-12-28 20:41:16 -05001073 def test_version(self):
1074 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001075 :py:obj:`X509ReqType.set_version` sets the X.509 version of the certificate
1076 request. :py:obj:`X509ReqType.get_version` returns the X.509 version of
Jean-Paul Calderone8dd19b82008-12-28 20:41:16 -05001077 the certificate request. The initial value of the version is 0.
1078 """
1079 request = X509Req()
1080 self.assertEqual(request.get_version(), 0)
1081 request.set_version(1)
1082 self.assertEqual(request.get_version(), 1)
1083 request.set_version(3)
1084 self.assertEqual(request.get_version(), 3)
1085
1086
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001087 def test_version_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001088 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001089 :py:obj:`X509ReqType.set_version` raises :py:obj:`TypeError` if called with the wrong
1090 number of arguments or with a non-:py:obj:`int` argument.
1091 :py:obj:`X509ReqType.get_version` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001092 arguments.
1093 """
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001094 request = X509Req()
1095 self.assertRaises(TypeError, request.set_version)
1096 self.assertRaises(TypeError, request.set_version, "foo")
1097 self.assertRaises(TypeError, request.set_version, 1, 2)
1098 self.assertRaises(TypeError, request.get_version, None)
1099
1100
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001101 def test_get_subject(self):
1102 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001103 :py:obj:`X509ReqType.get_subject` returns an :py:obj:`X509Name` for the subject of
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001104 the request and which is valid even after the request object is
1105 otherwise dead.
1106 """
1107 request = X509Req()
1108 subject = request.get_subject()
1109 self.assertTrue(
1110 isinstance(subject, X509NameType),
1111 "%r is of type %r, should be %r" % (subject, type(subject), X509NameType))
1112 subject.commonName = "foo"
1113 self.assertEqual(request.get_subject().commonName, "foo")
1114 del request
1115 subject.commonName = "bar"
1116 self.assertEqual(subject.commonName, "bar")
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001117
1118
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001119 def test_get_subject_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001120 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001121 :py:obj:`X509ReqType.get_subject` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001122 arguments.
1123 """
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001124 request = X509Req()
1125 self.assertRaises(TypeError, request.get_subject, None)
1126
1127
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001128 def test_add_extensions(self):
1129 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001130 :py:obj:`X509Req.add_extensions` accepts a :py:obj:`list` of :py:obj:`X509Extension`
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001131 instances and adds them to the X509 request.
1132 """
1133 request = X509Req()
1134 request.add_extensions([
Jean-Paul Calderonee16f9f32010-08-22 19:20:37 -04001135 X509Extension(b('basicConstraints'), True, b('CA:false'))])
Stephen Holsappleca545b72014-01-28 21:43:25 -08001136 exts = request.get_extensions()
Stephen Holsapple7fbdf642014-03-01 20:05:47 -08001137 self.assertEqual(len(exts), 1)
1138 self.assertEqual(exts[0].get_short_name(), b('basicConstraints'))
1139 self.assertEqual(exts[0].get_critical(), 1)
1140 self.assertEqual(exts[0].get_data(), b('0\x00'))
1141
1142
1143 def test_get_extensions(self):
1144 """
1145 :py:obj:`X509Req.get_extensions` returns a :py:obj:`list` of
1146 extensions added to this X509 request.
1147 """
1148 request = X509Req()
1149 exts = request.get_extensions()
1150 self.assertEqual(exts, [])
1151 request.add_extensions([
1152 X509Extension(b('basicConstraints'), True, b('CA:true')),
1153 X509Extension(b('keyUsage'), False, b('digitalSignature'))])
1154 exts = request.get_extensions()
1155 self.assertEqual(len(exts), 2)
1156 self.assertEqual(exts[0].get_short_name(), b('basicConstraints'))
1157 self.assertEqual(exts[0].get_critical(), 1)
1158 self.assertEqual(exts[0].get_data(), b('0\x03\x01\x01\xff'))
1159 self.assertEqual(exts[1].get_short_name(), b('keyUsage'))
1160 self.assertEqual(exts[1].get_critical(), 0)
1161 self.assertEqual(exts[1].get_data(), b('\x03\x02\x07\x80'))
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001162
1163
1164 def test_add_extensions_wrong_args(self):
1165 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001166 :py:obj:`X509Req.add_extensions` raises :py:obj:`TypeError` if called with the wrong
1167 number of arguments or with a non-:py:obj:`list`. Or it raises :py:obj:`ValueError`
1168 if called with a :py:obj:`list` containing objects other than :py:obj:`X509Extension`
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001169 instances.
1170 """
1171 request = X509Req()
1172 self.assertRaises(TypeError, request.add_extensions)
1173 self.assertRaises(TypeError, request.add_extensions, object())
1174 self.assertRaises(ValueError, request.add_extensions, [object()])
1175 self.assertRaises(TypeError, request.add_extensions, [], None)
1176
1177
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001178 def test_verify_wrong_args(self):
1179 """
1180 :py:obj:`X509Req.verify` raises :py:obj:`TypeError` if called with zero
1181 arguments or more than one argument or if passed anything other than a
1182 :py:obj:`PKey` instance as its single argument.
1183 """
1184 request = X509Req()
1185 self.assertRaises(TypeError, request.verify)
1186 self.assertRaises(TypeError, request.verify, object())
1187 self.assertRaises(TypeError, request.verify, PKey(), object())
1188
1189
1190 def test_verify_uninitialized_key(self):
1191 """
1192 :py:obj:`X509Req.verify` raises :py:obj:`OpenSSL.crypto.Error` if called
1193 with a :py:obj:`OpenSSL.crypto.PKey` which contains no key data.
1194 """
1195 request = X509Req()
1196 pkey = PKey()
1197 self.assertRaises(Error, request.verify, pkey)
1198
1199
1200 def test_verify_wrong_key(self):
1201 """
1202 :py:obj:`X509Req.verify` raises :py:obj:`OpenSSL.crypto.Error` if called
1203 with a :py:obj:`OpenSSL.crypto.PKey` which does not represent the public
1204 part of the key which signed the request.
1205 """
1206 request = X509Req()
1207 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001208 request.sign(pkey, GOOD_DIGEST)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001209 another_pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
1210 self.assertRaises(Error, request.verify, another_pkey)
1211
1212
1213 def test_verify_success(self):
1214 """
1215 :py:obj:`X509Req.verify` returns :py:obj:`True` if called with a
1216 :py:obj:`OpenSSL.crypto.PKey` which represents the public part ofthe key
1217 which signed the request.
1218 """
1219 request = X509Req()
1220 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001221 request.sign(pkey, GOOD_DIGEST)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001222 self.assertEqual(True, request.verify(pkey))
1223
1224
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001225
Jean-Paul Calderone18808652009-07-05 12:54:05 -04001226class X509Tests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001227 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001228 Tests for :py:obj:`OpenSSL.crypto.X509`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001229 """
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001230 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
Jean-Paul Calderone8114b452008-03-25 15:27:59 -04001231
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001232 extpem = """
1233-----BEGIN CERTIFICATE-----
1234MIIC3jCCAkegAwIBAgIJAJHFjlcCgnQzMA0GCSqGSIb3DQEBBQUAMEcxCzAJBgNV
1235BAYTAlNFMRUwEwYDVQQIEwxXZXN0ZXJib3R0b20xEjAQBgNVBAoTCUNhdGFsb2dp
1236eDENMAsGA1UEAxMEUm9vdDAeFw0wODA0MjIxNDQ1MzhaFw0wOTA0MjIxNDQ1Mzha
1237MFQxCzAJBgNVBAYTAlNFMQswCQYDVQQIEwJXQjEUMBIGA1UEChMLT3Blbk1ldGFk
1238aXIxIjAgBgNVBAMTGW5vZGUxLm9tMi5vcGVubWV0YWRpci5vcmcwgZ8wDQYJKoZI
1239hvcNAQEBBQADgY0AMIGJAoGBAPIcQMrwbk2nESF/0JKibj9i1x95XYAOwP+LarwT
1240Op4EQbdlI9SY+uqYqlERhF19w7CS+S6oyqx0DRZSk4Y9dZ9j9/xgm2u/f136YS1u
1241zgYFPvfUs6PqYLPSM8Bw+SjJ+7+2+TN+Tkiof9WP1cMjodQwOmdsiRbR0/J7+b1B
1242hec1AgMBAAGjgcQwgcEwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNT
1243TCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFIdHsBcMVVMbAO7j6NCj
124403HgLnHaMB8GA1UdIwQYMBaAFL2h9Bf9Mre4vTdOiHTGAt7BRY/8MEYGA1UdEQQ/
1245MD2CDSouZXhhbXBsZS5vcmeCESoub20yLmV4bWFwbGUuY29thwSC7wgKgRNvbTJA
1246b3Blbm1ldGFkaXIub3JnMA0GCSqGSIb3DQEBBQUAA4GBALd7WdXkp2KvZ7/PuWZA
1247MPlIxyjS+Ly11+BNE0xGQRp9Wz+2lABtpgNqssvU156+HkKd02rGheb2tj7MX9hG
1248uZzbwDAZzJPjzDQDD7d3cWsrVcfIdqVU7epHqIadnOF+X0ghJ39pAm6VVadnSXCt
1249WpOdIpB8KksUTCzV591Nr1wd
1250-----END CERTIFICATE-----
1251 """
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001252 def signable(self):
1253 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001254 Create and return a new :py:obj:`X509`.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001255 """
1256 return X509()
1257
1258
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001259 def test_type(self):
1260 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001261 :py:obj:`X509` and :py:obj:`X509Type` refer to the same type object and can be used
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001262 to create instances of that type.
1263 """
1264 self.assertIdentical(X509, X509Type)
1265 self.assertConsistentType(X509, 'X509')
1266
1267
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001268 def test_construction(self):
1269 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001270 :py:obj:`X509` takes no arguments and returns an instance of :py:obj:`X509Type`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001271 """
1272 certificate = X509()
1273 self.assertTrue(
1274 isinstance(certificate, X509Type),
1275 "%r is of type %r, should be %r" % (certificate,
1276 type(certificate),
1277 X509Type))
Rick Deane15b1472009-07-09 15:53:42 -05001278 self.assertEqual(type(X509Type).__name__, 'type')
1279 self.assertEqual(type(certificate).__name__, 'X509')
1280 self.assertEqual(type(certificate), X509Type)
Rick Dean04113e72009-07-16 12:06:35 -05001281 self.assertEqual(type(certificate), X509)
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001282
1283
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001284 def test_get_version_wrong_args(self):
1285 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001286 :py:obj:`X509.get_version` raises :py:obj:`TypeError` if invoked with any arguments.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001287 """
1288 cert = X509()
1289 self.assertRaises(TypeError, cert.get_version, None)
1290
1291
1292 def test_set_version_wrong_args(self):
1293 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001294 :py:obj:`X509.set_version` raises :py:obj:`TypeError` if invoked with the wrong number
1295 of arguments or an argument not of type :py:obj:`int`.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001296 """
1297 cert = X509()
1298 self.assertRaises(TypeError, cert.set_version)
1299 self.assertRaises(TypeError, cert.set_version, None)
1300 self.assertRaises(TypeError, cert.set_version, 1, None)
1301
1302
1303 def test_version(self):
1304 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001305 :py:obj:`X509.set_version` sets the certificate version number.
1306 :py:obj:`X509.get_version` retrieves it.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001307 """
1308 cert = X509()
1309 cert.set_version(1234)
1310 self.assertEquals(cert.get_version(), 1234)
1311
1312
1313 def test_get_serial_number_wrong_args(self):
1314 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001315 :py:obj:`X509.get_serial_number` raises :py:obj:`TypeError` if invoked with any
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001316 arguments.
1317 """
1318 cert = X509()
1319 self.assertRaises(TypeError, cert.get_serial_number, None)
1320
1321
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001322 def test_serial_number(self):
1323 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001324 The serial number of an :py:obj:`X509Type` can be retrieved and modified with
1325 :py:obj:`X509Type.get_serial_number` and :py:obj:`X509Type.set_serial_number`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001326 """
1327 certificate = X509()
1328 self.assertRaises(TypeError, certificate.set_serial_number)
1329 self.assertRaises(TypeError, certificate.set_serial_number, 1, 2)
1330 self.assertRaises(TypeError, certificate.set_serial_number, "1")
1331 self.assertRaises(TypeError, certificate.set_serial_number, 5.5)
1332 self.assertEqual(certificate.get_serial_number(), 0)
1333 certificate.set_serial_number(1)
1334 self.assertEqual(certificate.get_serial_number(), 1)
1335 certificate.set_serial_number(2 ** 32 + 1)
1336 self.assertEqual(certificate.get_serial_number(), 2 ** 32 + 1)
1337 certificate.set_serial_number(2 ** 64 + 1)
1338 self.assertEqual(certificate.get_serial_number(), 2 ** 64 + 1)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001339 certificate.set_serial_number(2 ** 128 + 1)
1340 self.assertEqual(certificate.get_serial_number(), 2 ** 128 + 1)
1341
1342
1343 def _setBoundTest(self, which):
1344 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001345 :py:obj:`X509Type.set_notBefore` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001346 GENERALIZEDTIME and sets the beginning of the certificate's validity
1347 period to it.
1348 """
1349 certificate = X509()
1350 set = getattr(certificate, 'set_not' + which)
1351 get = getattr(certificate, 'get_not' + which)
1352
Jean-Paul Calderonee0615b52008-03-09 21:44:46 -04001353 # Starts with no value.
1354 self.assertEqual(get(), None)
1355
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001356 # GMT (Or is it UTC?) -exarkun
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001357 when = b("20040203040506Z")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001358 set(when)
1359 self.assertEqual(get(), when)
1360
1361 # A plus two hours and thirty minutes offset
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001362 when = b("20040203040506+0530")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001363 set(when)
1364 self.assertEqual(get(), when)
1365
1366 # A minus one hour fifteen minutes offset
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001367 when = b("20040203040506-0115")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001368 set(when)
1369 self.assertEqual(get(), when)
1370
1371 # An invalid string results in a ValueError
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001372 self.assertRaises(ValueError, set, b("foo bar"))
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001373
Jean-Paul Calderone31ca2002010-01-30 15:14:43 -05001374 # The wrong number of arguments results in a TypeError.
1375 self.assertRaises(TypeError, set)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001376 self.assertRaises(TypeError, set, b("20040203040506Z"), b("20040203040506Z"))
1377 self.assertRaises(TypeError, get, b("foo bar"))
1378
Jean-Paul Calderone31ca2002010-01-30 15:14:43 -05001379
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001380 # XXX ASN1_TIME (not GENERALIZEDTIME)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001381
1382 def test_set_notBefore(self):
1383 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001384 :py:obj:`X509Type.set_notBefore` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001385 GENERALIZEDTIME and sets the beginning of the certificate's validity
1386 period to it.
1387 """
1388 self._setBoundTest("Before")
1389
1390
1391 def test_set_notAfter(self):
1392 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001393 :py:obj:`X509Type.set_notAfter` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001394 GENERALIZEDTIME and sets the end of the certificate's validity period
1395 to it.
1396 """
1397 self._setBoundTest("After")
Jean-Paul Calderone76576d52008-03-24 16:04:46 -04001398
1399
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001400 def test_get_notBefore(self):
1401 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001402 :py:obj:`X509Type.get_notBefore` returns a string in the format of an ASN1
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001403 GENERALIZEDTIME even for certificates which store it as UTCTIME
1404 internally.
1405 """
Jean-Paul Calderone8114b452008-03-25 15:27:59 -04001406 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001407 self.assertEqual(cert.get_notBefore(), b("20090325123658Z"))
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001408
Rick Dean38a05c82009-07-18 01:41:30 -05001409
1410 def test_get_notAfter(self):
1411 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001412 :py:obj:`X509Type.get_notAfter` returns a string in the format of an ASN1
Rick Dean38a05c82009-07-18 01:41:30 -05001413 GENERALIZEDTIME even for certificates which store it as UTCTIME
1414 internally.
1415 """
1416 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001417 self.assertEqual(cert.get_notAfter(), b("20170611123658Z"))
Rick Dean38a05c82009-07-18 01:41:30 -05001418
1419
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001420 def test_gmtime_adj_notBefore_wrong_args(self):
1421 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001422 :py:obj:`X509Type.gmtime_adj_notBefore` raises :py:obj:`TypeError` if called with the
1423 wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001424 """
1425 cert = X509()
1426 self.assertRaises(TypeError, cert.gmtime_adj_notBefore)
1427 self.assertRaises(TypeError, cert.gmtime_adj_notBefore, None)
1428 self.assertRaises(TypeError, cert.gmtime_adj_notBefore, 123, None)
1429
1430
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001431 def test_gmtime_adj_notBefore(self):
1432 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001433 :py:obj:`X509Type.gmtime_adj_notBefore` changes the not-before timestamp to be
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001434 the current time plus the number of seconds passed in.
1435 """
1436 cert = load_certificate(FILETYPE_PEM, self.pemData)
1437 now = datetime.utcnow() + timedelta(seconds=100)
1438 cert.gmtime_adj_notBefore(100)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001439 self.assertEqual(cert.get_notBefore(), b(now.strftime("%Y%m%d%H%M%SZ")))
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001440
1441
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001442 def test_gmtime_adj_notAfter_wrong_args(self):
1443 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001444 :py:obj:`X509Type.gmtime_adj_notAfter` raises :py:obj:`TypeError` if called with the
1445 wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001446 """
1447 cert = X509()
1448 self.assertRaises(TypeError, cert.gmtime_adj_notAfter)
1449 self.assertRaises(TypeError, cert.gmtime_adj_notAfter, None)
1450 self.assertRaises(TypeError, cert.gmtime_adj_notAfter, 123, None)
1451
1452
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001453 def test_gmtime_adj_notAfter(self):
1454 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001455 :py:obj:`X509Type.gmtime_adj_notAfter` changes the not-after timestamp to be
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001456 the current time plus the number of seconds passed in.
1457 """
1458 cert = load_certificate(FILETYPE_PEM, self.pemData)
1459 now = datetime.utcnow() + timedelta(seconds=100)
1460 cert.gmtime_adj_notAfter(100)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001461 self.assertEqual(cert.get_notAfter(), b(now.strftime("%Y%m%d%H%M%SZ")))
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001462
1463
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001464 def test_has_expired_wrong_args(self):
1465 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001466 :py:obj:`X509Type.has_expired` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001467 arguments.
1468 """
1469 cert = X509()
1470 self.assertRaises(TypeError, cert.has_expired, None)
1471
1472
1473 def test_has_expired(self):
1474 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001475 :py:obj:`X509Type.has_expired` returns :py:obj:`True` if the certificate's not-after
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001476 time is in the past.
1477 """
1478 cert = X509()
1479 cert.gmtime_adj_notAfter(-1)
1480 self.assertTrue(cert.has_expired())
1481
1482
1483 def test_has_not_expired(self):
1484 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001485 :py:obj:`X509Type.has_expired` returns :py:obj:`False` if the certificate's not-after
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001486 time is in the future.
1487 """
1488 cert = X509()
1489 cert.gmtime_adj_notAfter(2)
1490 self.assertFalse(cert.has_expired())
1491
1492
Rick Dean38a05c82009-07-18 01:41:30 -05001493 def test_digest(self):
1494 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001495 :py:obj:`X509.digest` returns a string giving ":"-separated hex-encoded words
Rick Dean38a05c82009-07-18 01:41:30 -05001496 of the digest of the certificate.
1497 """
1498 cert = X509()
1499 self.assertEqual(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001500 # This is MD5 instead of GOOD_DIGEST because the digest algorithm
1501 # actually matters to the assertion (ie, another arbitrary, good
1502 # digest will not product the same digest).
1503 cert.digest("MD5"),
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001504 b("A8:EB:07:F8:53:25:0A:F2:56:05:C5:A5:C4:C4:C7:15"))
Rick Dean38a05c82009-07-18 01:41:30 -05001505
1506
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001507 def _extcert(self, pkey, extensions):
1508 cert = X509()
1509 cert.set_pubkey(pkey)
1510 cert.get_subject().commonName = "Unit Tests"
1511 cert.get_issuer().commonName = "Unit Tests"
1512 when = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
1513 cert.set_notBefore(when)
1514 cert.set_notAfter(when)
1515
1516 cert.add_extensions(extensions)
1517 return load_certificate(
1518 FILETYPE_PEM, dump_certificate(FILETYPE_PEM, cert))
1519
1520
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001521 def test_extension_count(self):
1522 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001523 :py:obj:`X509.get_extension_count` returns the number of extensions that are
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001524 present in the certificate.
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001525 """
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001526 pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001527 ca = X509Extension(b('basicConstraints'), True, b('CA:FALSE'))
1528 key = X509Extension(b('keyUsage'), True, b('digitalSignature'))
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001529 subjectAltName = X509Extension(
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001530 b('subjectAltName'), True, b('DNS:example.com'))
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001531
1532 # Try a certificate with no extensions at all.
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001533 c = self._extcert(pkey, [])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001534 self.assertEqual(c.get_extension_count(), 0)
1535
1536 # And a certificate with one
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001537 c = self._extcert(pkey, [ca])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001538 self.assertEqual(c.get_extension_count(), 1)
1539
1540 # And a certificate with several
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001541 c = self._extcert(pkey, [ca, key, subjectAltName])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001542 self.assertEqual(c.get_extension_count(), 3)
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001543
1544
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001545 def test_get_extension(self):
1546 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001547 :py:obj:`X509.get_extension` takes an integer and returns an :py:obj:`X509Extension`
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001548 corresponding to the extension at that index.
1549 """
1550 pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001551 ca = X509Extension(b('basicConstraints'), True, b('CA:FALSE'))
1552 key = X509Extension(b('keyUsage'), True, b('digitalSignature'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001553 subjectAltName = X509Extension(
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001554 b('subjectAltName'), False, b('DNS:example.com'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001555
1556 cert = self._extcert(pkey, [ca, key, subjectAltName])
1557
1558 ext = cert.get_extension(0)
1559 self.assertTrue(isinstance(ext, X509Extension))
1560 self.assertTrue(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001561 self.assertEqual(ext.get_short_name(), b('basicConstraints'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001562
1563 ext = cert.get_extension(1)
1564 self.assertTrue(isinstance(ext, X509Extension))
1565 self.assertTrue(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001566 self.assertEqual(ext.get_short_name(), b('keyUsage'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001567
1568 ext = cert.get_extension(2)
1569 self.assertTrue(isinstance(ext, X509Extension))
1570 self.assertFalse(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001571 self.assertEqual(ext.get_short_name(), b('subjectAltName'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001572
1573 self.assertRaises(IndexError, cert.get_extension, -1)
1574 self.assertRaises(IndexError, cert.get_extension, 4)
1575 self.assertRaises(TypeError, cert.get_extension, "hello")
1576
1577
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001578 def test_nullbyte_subjectAltName(self):
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001579 """
Jean-Paul Calderone9af07b02013-08-23 16:07:31 -04001580 The fields of a `subjectAltName` extension on an X509 may contain NUL
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001581 bytes and this value is reflected in the string representation of the
1582 extension object.
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001583 """
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001584 cert = load_certificate(FILETYPE_PEM, nulbyteSubjectAltNamePEM)
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001585
1586 ext = cert.get_extension(3)
1587 self.assertEqual(ext.get_short_name(), b('subjectAltName'))
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001588 self.assertEqual(
1589 b("DNS:altnull.python.org\x00example.com, "
1590 "email:null@python.org\x00user@example.org, "
1591 "URI:http://null.python.org\x00http://example.org, "
1592 "IP Address:192.0.2.1, IP Address:2001:DB8:0:0:0:0:0:1\n"),
1593 b(str(ext)))
1594
Rick Dean38a05c82009-07-18 01:41:30 -05001595
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001596 def test_invalid_digest_algorithm(self):
1597 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001598 :py:obj:`X509.digest` raises :py:obj:`ValueError` if called with an unrecognized hash
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001599 algorithm.
1600 """
1601 cert = X509()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001602 self.assertRaises(ValueError, cert.digest, BAD_DIGEST)
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001603
1604
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001605 def test_get_subject_wrong_args(self):
1606 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001607 :py:obj:`X509.get_subject` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001608 """
1609 cert = X509()
1610 self.assertRaises(TypeError, cert.get_subject, None)
1611
1612
1613 def test_get_subject(self):
1614 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001615 :py:obj:`X509.get_subject` returns an :py:obj:`X509Name` instance.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001616 """
1617 cert = load_certificate(FILETYPE_PEM, self.pemData)
1618 subj = cert.get_subject()
1619 self.assertTrue(isinstance(subj, X509Name))
1620 self.assertEquals(
1621 subj.get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001622 [(b('C'), b('US')), (b('ST'), b('IL')), (b('L'), b('Chicago')),
1623 (b('O'), b('Testing')), (b('CN'), b('Testing Root CA'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001624
1625
1626 def test_set_subject_wrong_args(self):
1627 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001628 :py:obj:`X509.set_subject` raises a :py:obj:`TypeError` if called with the wrong
1629 number of arguments or an argument not of type :py:obj:`X509Name`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001630 """
1631 cert = X509()
1632 self.assertRaises(TypeError, cert.set_subject)
1633 self.assertRaises(TypeError, cert.set_subject, None)
1634 self.assertRaises(TypeError, cert.set_subject, cert.get_subject(), None)
1635
1636
1637 def test_set_subject(self):
1638 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001639 :py:obj:`X509.set_subject` changes the subject of the certificate to the one
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001640 passed in.
1641 """
1642 cert = X509()
1643 name = cert.get_subject()
1644 name.C = 'AU'
1645 name.O = 'Unit Tests'
1646 cert.set_subject(name)
1647 self.assertEquals(
1648 cert.get_subject().get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001649 [(b('C'), b('AU')), (b('O'), b('Unit Tests'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001650
1651
1652 def test_get_issuer_wrong_args(self):
1653 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001654 :py:obj:`X509.get_issuer` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001655 """
1656 cert = X509()
1657 self.assertRaises(TypeError, cert.get_issuer, None)
1658
1659
1660 def test_get_issuer(self):
1661 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001662 :py:obj:`X509.get_issuer` returns an :py:obj:`X509Name` instance.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001663 """
1664 cert = load_certificate(FILETYPE_PEM, self.pemData)
1665 subj = cert.get_issuer()
1666 self.assertTrue(isinstance(subj, X509Name))
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001667 comp = subj.get_components()
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001668 self.assertEquals(
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001669 comp,
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001670 [(b('C'), b('US')), (b('ST'), b('IL')), (b('L'), b('Chicago')),
1671 (b('O'), b('Testing')), (b('CN'), b('Testing Root CA'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001672
1673
1674 def test_set_issuer_wrong_args(self):
1675 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001676 :py:obj:`X509.set_issuer` raises a :py:obj:`TypeError` if called with the wrong
1677 number of arguments or an argument not of type :py:obj:`X509Name`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001678 """
1679 cert = X509()
1680 self.assertRaises(TypeError, cert.set_issuer)
1681 self.assertRaises(TypeError, cert.set_issuer, None)
1682 self.assertRaises(TypeError, cert.set_issuer, cert.get_issuer(), None)
1683
1684
1685 def test_set_issuer(self):
1686 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001687 :py:obj:`X509.set_issuer` changes the issuer of the certificate to the one
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001688 passed in.
1689 """
1690 cert = X509()
1691 name = cert.get_issuer()
1692 name.C = 'AU'
1693 name.O = 'Unit Tests'
1694 cert.set_issuer(name)
1695 self.assertEquals(
1696 cert.get_issuer().get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001697 [(b('C'), b('AU')), (b('O'), b('Unit Tests'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001698
1699
1700 def test_get_pubkey_uninitialized(self):
1701 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001702 When called on a certificate with no public key, :py:obj:`X509.get_pubkey`
1703 raises :py:obj:`OpenSSL.crypto.Error`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001704 """
1705 cert = X509()
1706 self.assertRaises(Error, cert.get_pubkey)
1707
1708
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001709 def test_subject_name_hash_wrong_args(self):
1710 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001711 :py:obj:`X509.subject_name_hash` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001712 arguments.
1713 """
1714 cert = X509()
1715 self.assertRaises(TypeError, cert.subject_name_hash, None)
1716
1717
1718 def test_subject_name_hash(self):
1719 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001720 :py:obj:`X509.subject_name_hash` returns the hash of the certificate's subject
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001721 name.
1722 """
1723 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -04001724 self.assertIn(
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001725 cert.subject_name_hash(),
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -04001726 [3350047874, # OpenSSL 0.9.8, MD5
1727 3278919224, # OpenSSL 1.0.0, SHA1
1728 ])
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001729
1730
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001731 def test_get_signature_algorithm(self):
1732 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001733 :py:obj:`X509Type.get_signature_algorithm` returns a string which means
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001734 the algorithm used to sign the certificate.
1735 """
1736 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001737 self.assertEqual(
1738 b("sha1WithRSAEncryption"), cert.get_signature_algorithm())
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001739
1740
1741 def test_get_undefined_signature_algorithm(self):
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001742 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001743 :py:obj:`X509Type.get_signature_algorithm` raises :py:obj:`ValueError` if the
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001744 signature algorithm is undefined or unknown.
1745 """
1746 # This certificate has been modified to indicate a bogus OID in the
1747 # signature algorithm field so that OpenSSL does not recognize it.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001748 certPEM = b("""\
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001749-----BEGIN CERTIFICATE-----
1750MIIC/zCCAmigAwIBAgIBATAGBgJ8BQUAMHsxCzAJBgNVBAYTAlNHMREwDwYDVQQK
1751EwhNMkNyeXB0bzEUMBIGA1UECxMLTTJDcnlwdG8gQ0ExJDAiBgNVBAMTG00yQ3J5
1752cHRvIENlcnRpZmljYXRlIE1hc3RlcjEdMBsGCSqGSIb3DQEJARYObmdwc0Bwb3N0
1753MS5jb20wHhcNMDAwOTEwMDk1MTMwWhcNMDIwOTEwMDk1MTMwWjBTMQswCQYDVQQG
1754EwJTRzERMA8GA1UEChMITTJDcnlwdG8xEjAQBgNVBAMTCWxvY2FsaG9zdDEdMBsG
1755CSqGSIb3DQEJARYObmdwc0Bwb3N0MS5jb20wXDANBgkqhkiG9w0BAQEFAANLADBI
1756AkEArL57d26W9fNXvOhNlZzlPOACmvwOZ5AdNgLzJ1/MfsQQJ7hHVeHmTAjM664V
1757+fXvwUGJLziCeBo1ysWLRnl8CQIDAQABo4IBBDCCAQAwCQYDVR0TBAIwADAsBglg
1758hkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0O
1759BBYEFM+EgpK+eyZiwFU1aOPSbczbPSpVMIGlBgNVHSMEgZ0wgZqAFPuHI2nrnDqT
1760FeXFvylRT/7tKDgBoX+kfTB7MQswCQYDVQQGEwJTRzERMA8GA1UEChMITTJDcnlw
1761dG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtNMkNyeXB0byBDZXJ0
1762aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tggEA
1763MA0GCSqGSIb3DQEBBAUAA4GBADv8KpPo+gfJxN2ERK1Y1l17sz/ZhzoGgm5XCdbx
1764jEY7xKfpQngV599k1xhl11IMqizDwu0855agrckg2MCTmOI9DZzDD77tAYb+Dk0O
1765PEVk0Mk/V0aIsDE9bolfCi/i/QWZ3N8s5nTWMNyBBBmoSliWCm4jkkRZRD0ejgTN
1766tgI5
1767-----END CERTIFICATE-----
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001768""")
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001769 cert = load_certificate(FILETYPE_PEM, certPEM)
1770 self.assertRaises(ValueError, cert.get_signature_algorithm)
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001771
1772
Rick Dean38a05c82009-07-18 01:41:30 -05001773
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001774class X509StoreTests(TestCase):
1775 """
1776 Test for :py:obj:`OpenSSL.crypto.X509Store`.
1777 """
1778 def test_type(self):
1779 """
1780 :py:obj:`X509StoreType` is a type object.
1781 """
1782 self.assertIdentical(X509Store, X509StoreType)
1783 self.assertConsistentType(X509Store, 'X509Store')
1784
1785
1786 def test_add_cert_wrong_args(self):
1787 store = X509Store()
1788 self.assertRaises(TypeError, store.add_cert)
1789 self.assertRaises(TypeError, store.add_cert, object())
1790 self.assertRaises(TypeError, store.add_cert, X509(), object())
1791
1792
1793 def test_add_cert(self):
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001794 """
1795 :py:obj:`X509Store.add_cert` adds a :py:obj:`X509` instance to the
1796 certificate store.
1797 """
1798 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001799 store = X509Store()
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001800 store.add_cert(cert)
1801
1802
1803 def test_add_cert_rejects_duplicate(self):
1804 """
1805 :py:obj:`X509Store.add_cert` raises :py:obj:`OpenSSL.crypto.Error` if an
1806 attempt is made to add the same certificate to the store more than once.
1807 """
1808 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
1809 store = X509Store()
1810 store.add_cert(cert)
1811 self.assertRaises(Error, store.add_cert, cert)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001812
1813
1814
Rick Dean623ee362009-07-17 12:22:16 -05001815class PKCS12Tests(TestCase):
1816 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001817 Test for :py:obj:`OpenSSL.crypto.PKCS12` and :py:obj:`OpenSSL.crypto.load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001818 """
1819 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
1820
Jean-Paul Calderonec3a41f72009-07-25 12:36:02 -04001821 def test_type(self):
1822 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001823 :py:obj:`PKCS12Type` is a type object.
Jean-Paul Calderonec3a41f72009-07-25 12:36:02 -04001824 """
1825 self.assertIdentical(PKCS12, PKCS12Type)
1826 self.assertConsistentType(PKCS12, 'PKCS12')
1827
1828
Rick Deanf94096c2009-07-18 14:23:06 -05001829 def test_empty_construction(self):
Rick Dean38a05c82009-07-18 01:41:30 -05001830 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001831 :py:obj:`PKCS12` returns a new instance of :py:obj:`PKCS12` with no certificate,
Jean-Paul Calderonedc857b52009-07-25 12:25:07 -04001832 private key, CA certificates, or friendly name.
Rick Dean38a05c82009-07-18 01:41:30 -05001833 """
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001834 p12 = PKCS12()
Rick Dean623ee362009-07-17 12:22:16 -05001835 self.assertEqual(None, p12.get_certificate())
1836 self.assertEqual(None, p12.get_privatekey())
1837 self.assertEqual(None, p12.get_ca_certificates())
Rick Dean42d69e12009-07-20 11:36:08 -05001838 self.assertEqual(None, p12.get_friendlyname())
Rick Dean623ee362009-07-17 12:22:16 -05001839
Rick Dean38a05c82009-07-18 01:41:30 -05001840
Rick Dean623ee362009-07-17 12:22:16 -05001841 def test_type_errors(self):
Rick Dean38a05c82009-07-18 01:41:30 -05001842 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001843 The :py:obj:`PKCS12` setter functions (:py:obj:`set_certificate`, :py:obj:`set_privatekey`,
1844 :py:obj:`set_ca_certificates`, and :py:obj:`set_friendlyname`) raise :py:obj:`TypeError`
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001845 when passed objects of types other than those expected.
Rick Dean38a05c82009-07-18 01:41:30 -05001846 """
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001847 p12 = PKCS12()
Rick Dean623ee362009-07-17 12:22:16 -05001848 self.assertRaises(TypeError, p12.set_certificate, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05001849 self.assertRaises(TypeError, p12.set_certificate, PKey())
1850 self.assertRaises(TypeError, p12.set_certificate, X509)
Rick Dean623ee362009-07-17 12:22:16 -05001851 self.assertRaises(TypeError, p12.set_privatekey, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05001852 self.assertRaises(TypeError, p12.set_privatekey, 'legbone')
1853 self.assertRaises(TypeError, p12.set_privatekey, X509())
Rick Dean623ee362009-07-17 12:22:16 -05001854 self.assertRaises(TypeError, p12.set_ca_certificates, 3)
1855 self.assertRaises(TypeError, p12.set_ca_certificates, X509())
1856 self.assertRaises(TypeError, p12.set_ca_certificates, (3, 4))
Rick Deanf94096c2009-07-18 14:23:06 -05001857 self.assertRaises(TypeError, p12.set_ca_certificates, ( PKey(), ))
Rick Dean42d69e12009-07-20 11:36:08 -05001858 self.assertRaises(TypeError, p12.set_friendlyname, 6)
1859 self.assertRaises(TypeError, p12.set_friendlyname, ('foo', 'bar'))
Rick Dean623ee362009-07-17 12:22:16 -05001860
Rick Dean38a05c82009-07-18 01:41:30 -05001861
Rick Dean623ee362009-07-17 12:22:16 -05001862 def test_key_only(self):
1863 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001864 A :py:obj:`PKCS12` with only a private key can be exported using
1865 :py:obj:`PKCS12.export` and loaded again using :py:obj:`load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001866 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001867 passwd = b"blah"
Rick Dean623ee362009-07-17 12:22:16 -05001868 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001869 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001870 p12.set_privatekey(pkey)
Rick Dean623ee362009-07-17 12:22:16 -05001871 self.assertEqual(None, p12.get_certificate())
1872 self.assertEqual(pkey, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05001873 try:
1874 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
1875 except Error:
1876 # Some versions of OpenSSL will throw an exception
1877 # for this nearly useless PKCS12 we tried to generate:
1878 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
1879 return
Rick Dean623ee362009-07-17 12:22:16 -05001880 p12 = load_pkcs12(dumped_p12, passwd)
1881 self.assertEqual(None, p12.get_ca_certificates())
1882 self.assertEqual(None, p12.get_certificate())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001883
1884 # OpenSSL fails to bring the key back to us. So sad. Perhaps in the
1885 # future this will be improved.
1886 self.assertTrue(isinstance(p12.get_privatekey(), (PKey, type(None))))
Rick Dean623ee362009-07-17 12:22:16 -05001887
Rick Dean38a05c82009-07-18 01:41:30 -05001888
Rick Dean623ee362009-07-17 12:22:16 -05001889 def test_cert_only(self):
1890 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001891 A :py:obj:`PKCS12` with only a certificate can be exported using
1892 :py:obj:`PKCS12.export` and loaded again using :py:obj:`load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001893 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001894 passwd = b"blah"
Rick Dean623ee362009-07-17 12:22:16 -05001895 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001896 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001897 p12.set_certificate(cert)
Rick Dean623ee362009-07-17 12:22:16 -05001898 self.assertEqual(cert, p12.get_certificate())
1899 self.assertEqual(None, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05001900 try:
1901 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
1902 except Error:
1903 # Some versions of OpenSSL will throw an exception
1904 # for this nearly useless PKCS12 we tried to generate:
1905 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
1906 return
Rick Dean623ee362009-07-17 12:22:16 -05001907 p12 = load_pkcs12(dumped_p12, passwd)
1908 self.assertEqual(None, p12.get_privatekey())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001909
1910 # OpenSSL fails to bring the cert back to us. Groany mcgroan.
1911 self.assertTrue(isinstance(p12.get_certificate(), (X509, type(None))))
1912
1913 # Oh ho. It puts the certificate into the ca certificates list, in
1914 # fact. Totally bogus, I would think. Nevertheless, let's exploit
1915 # that to check to see if it reconstructed the certificate we expected
1916 # it to. At some point, hopefully this will change so that
1917 # p12.get_certificate() is actually what returns the loaded
1918 # certificate.
1919 self.assertEqual(
1920 cleartextCertificatePEM,
1921 dump_certificate(FILETYPE_PEM, p12.get_ca_certificates()[0]))
Rick Dean623ee362009-07-17 12:22:16 -05001922
1923
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001924 def gen_pkcs12(self, cert_pem=None, key_pem=None, ca_pem=None, friendly_name=None):
Rick Dean623ee362009-07-17 12:22:16 -05001925 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001926 Generate a PKCS12 object with components from PEM. Verify that the set
1927 functions return None.
Rick Dean623ee362009-07-17 12:22:16 -05001928 """
Rick Deanf94096c2009-07-18 14:23:06 -05001929 p12 = PKCS12()
1930 if cert_pem:
1931 ret = p12.set_certificate(load_certificate(FILETYPE_PEM, cert_pem))
1932 self.assertEqual(ret, None)
1933 if key_pem:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001934 ret = p12.set_privatekey(load_privatekey(FILETYPE_PEM, key_pem))
Rick Deanf94096c2009-07-18 14:23:06 -05001935 self.assertEqual(ret, None)
1936 if ca_pem:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001937 ret = p12.set_ca_certificates((load_certificate(FILETYPE_PEM, ca_pem),))
Rick Deanf94096c2009-07-18 14:23:06 -05001938 self.assertEqual(ret, None)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001939 if friendly_name:
1940 ret = p12.set_friendlyname(friendly_name)
Rick Dean42d69e12009-07-20 11:36:08 -05001941 self.assertEqual(ret, None)
Rick Deanf94096c2009-07-18 14:23:06 -05001942 return p12
1943
1944
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001945 def check_recovery(self, p12_str, key=None, cert=None, ca=None, passwd=b"",
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001946 extra=()):
Rick Deanf94096c2009-07-18 14:23:06 -05001947 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001948 Use openssl program to confirm three components are recoverable from a
1949 PKCS12 string.
Rick Deanf94096c2009-07-18 14:23:06 -05001950 """
1951 if key:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001952 recovered_key = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001953 p12_str, b"pkcs12", b"-nocerts", b"-nodes", b"-passin",
1954 b"pass:" + passwd, *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001955 self.assertEqual(recovered_key[-len(key):], key)
1956 if cert:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001957 recovered_cert = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001958 p12_str, b"pkcs12", b"-clcerts", b"-nodes", b"-passin",
1959 b"pass:" + passwd, b"-nokeys", *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001960 self.assertEqual(recovered_cert[-len(cert):], cert)
1961 if ca:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001962 recovered_cert = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001963 p12_str, b"pkcs12", b"-cacerts", b"-nodes", b"-passin",
1964 b"pass:" + passwd, b"-nokeys", *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001965 self.assertEqual(recovered_cert[-len(ca):], ca)
1966
1967
Stephen Holsapple38482622014-04-05 20:29:34 -07001968 def verify_pkcs12_container(self, p12):
1969 """
1970 Verify that the PKCS#12 container contains the correct client
1971 certificate and private key.
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04001972
1973 :param p12: The PKCS12 instance to verify.
1974 :type p12: :py:class:`PKCS12`
Stephen Holsapple38482622014-04-05 20:29:34 -07001975 """
1976 cert_pem = dump_certificate(FILETYPE_PEM, p12.get_certificate())
1977 key_pem = dump_privatekey(FILETYPE_PEM, p12.get_privatekey())
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04001978 self.assertEqual(
1979 (client_cert_pem, client_key_pem, None),
1980 (cert_pem, key_pem, p12.get_ca_certificates()))
Stephen Holsapple38482622014-04-05 20:29:34 -07001981
1982
Rick Deanf94096c2009-07-18 14:23:06 -05001983 def test_load_pkcs12(self):
1984 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001985 A PKCS12 string generated using the openssl command line can be loaded
Jonathan Ballet648875f2011-07-16 14:14:58 +09001986 with :py:obj:`load_pkcs12` and its components extracted and examined.
Rick Deanf94096c2009-07-18 14:23:06 -05001987 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001988 passwd = b"whatever"
Rick Dean623ee362009-07-17 12:22:16 -05001989 pem = client_key_pem + client_cert_pem
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001990 p12_str = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001991 pem, b"pkcs12", b"-export", b"-clcerts", b"-passout", b"pass:" + passwd)
Stephen Holsapple38482622014-04-05 20:29:34 -07001992 p12 = load_pkcs12(p12_str, passphrase=passwd)
1993 self.verify_pkcs12_container(p12)
1994
1995
1996 def test_load_pkcs12_no_passphrase(self):
1997 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04001998 A PKCS12 string generated using openssl command line can be loaded with
1999 :py:obj:`load_pkcs12` without a passphrase and its components extracted
2000 and examined.
Stephen Holsapple38482622014-04-05 20:29:34 -07002001 """
2002 pem = client_key_pem + client_cert_pem
2003 p12_str = _runopenssl(
2004 pem, b"pkcs12", b"-export", b"-clcerts", b"-passout", b"pass:")
2005 p12 = load_pkcs12(p12_str)
2006 self.verify_pkcs12_container(p12)
2007
2008
2009 def _dump_and_load(self, dump_passphrase, load_passphrase):
2010 """
2011 A helper method to dump and load a PKCS12 object.
2012 """
2013 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem)
2014 dumped_p12 = p12.export(passphrase=dump_passphrase, iter=2, maciter=3)
2015 return load_pkcs12(dumped_p12, passphrase=load_passphrase)
2016
2017
2018 def test_load_pkcs12_null_passphrase_load_empty(self):
2019 """
2020 A PKCS12 string can be dumped with a null passphrase, loaded with an
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002021 empty passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002022 extracted and examined.
2023 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002024 self.verify_pkcs12_container(
2025 self._dump_and_load(dump_passphrase=None, load_passphrase=b''))
Stephen Holsapple38482622014-04-05 20:29:34 -07002026
2027
2028 def test_load_pkcs12_null_passphrase_load_null(self):
2029 """
2030 A PKCS12 string can be dumped with a null passphrase, loaded with a
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002031 null passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002032 extracted and examined.
2033 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002034 self.verify_pkcs12_container(
2035 self._dump_and_load(dump_passphrase=None, load_passphrase=None))
Stephen Holsapple38482622014-04-05 20:29:34 -07002036
2037
2038 def test_load_pkcs12_empty_passphrase_load_empty(self):
2039 """
2040 A PKCS12 string can be dumped with an empty passphrase, loaded with an
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002041 empty passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002042 extracted and examined.
2043 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002044 self.verify_pkcs12_container(
2045 self._dump_and_load(dump_passphrase=b'', load_passphrase=b''))
Stephen Holsapple38482622014-04-05 20:29:34 -07002046
2047
2048 def test_load_pkcs12_empty_passphrase_load_null(self):
2049 """
2050 A PKCS12 string can be dumped with an empty passphrase, loaded with a
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002051 null passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002052 extracted and examined.
2053 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002054 self.verify_pkcs12_container(
2055 self._dump_and_load(dump_passphrase=b'', load_passphrase=None))
Rick Deanf94096c2009-07-18 14:23:06 -05002056
Rick Deanee568302009-07-24 09:56:29 -05002057
2058 def test_load_pkcs12_garbage(self):
2059 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002060 :py:obj:`load_pkcs12` raises :py:obj:`OpenSSL.crypto.Error` when passed a string
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002061 which is not a PKCS12 dump.
Rick Deanee568302009-07-24 09:56:29 -05002062 """
2063 passwd = 'whatever'
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002064 e = self.assertRaises(Error, load_pkcs12, b'fruit loops', passwd)
Jean-Paul Calderonede075462014-01-18 10:34:12 -05002065 self.assertEqual( e.args[0][0][0], 'asn1 encoding routines')
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -04002066 self.assertEqual( len(e.args[0][0]), 3)
Rick Deanee568302009-07-24 09:56:29 -05002067
2068
Rick Deanf94096c2009-07-18 14:23:06 -05002069 def test_replace(self):
2070 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002071 :py:obj:`PKCS12.set_certificate` replaces the certificate in a PKCS12 cluster.
2072 :py:obj:`PKCS12.set_privatekey` replaces the private key.
2073 :py:obj:`PKCS12.set_ca_certificates` replaces the CA certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05002074 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002075 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
2076 p12.set_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2077 p12.set_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002078 root_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05002079 client_cert = load_certificate(FILETYPE_PEM, client_cert_pem)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002080 p12.set_ca_certificates([root_cert]) # not a tuple
Rick Dean623ee362009-07-17 12:22:16 -05002081 self.assertEqual(1, len(p12.get_ca_certificates()))
2082 self.assertEqual(root_cert, p12.get_ca_certificates()[0])
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002083 p12.set_ca_certificates([client_cert, root_cert])
Rick Deanf94096c2009-07-18 14:23:06 -05002084 self.assertEqual(2, len(p12.get_ca_certificates()))
2085 self.assertEqual(client_cert, p12.get_ca_certificates()[0])
2086 self.assertEqual(root_cert, p12.get_ca_certificates()[1])
2087
2088
2089 def test_friendly_name(self):
2090 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002091 The *friendlyName* of a PKCS12 can be set and retrieved via
Jonathan Ballet648875f2011-07-16 14:14:58 +09002092 :py:obj:`PKCS12.get_friendlyname` and :py:obj:`PKCS12_set_friendlyname`, and a
2093 :py:obj:`PKCS12` with a friendly name set can be dumped with :py:obj:`PKCS12.export`.
Rick Deanf94096c2009-07-18 14:23:06 -05002094 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002095 passwd = b'Dogmeat[]{}!@#$%^&*()~`?/.,<>-_+=";:'
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002096 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -04002097 for friendly_name in [b('Serverlicious'), None, b('###')]:
Rick Dean42d69e12009-07-20 11:36:08 -05002098 p12.set_friendlyname(friendly_name)
2099 self.assertEqual(p12.get_friendlyname(), friendly_name)
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002100 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
Rick Dean42d69e12009-07-20 11:36:08 -05002101 reloaded_p12 = load_pkcs12(dumped_p12, passwd)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002102 self.assertEqual(
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -04002103 p12.get_friendlyname(), reloaded_p12.get_friendlyname())
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002104 # We would use the openssl program to confirm the friendly
2105 # name, but it is not possible. The pkcs12 command
2106 # does not store the friendly name in the cert's
Rick Dean42d69e12009-07-20 11:36:08 -05002107 # alias, which we could then extract.
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002108 self.check_recovery(
2109 dumped_p12, key=server_key_pem, cert=server_cert_pem,
2110 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05002111
2112
2113 def test_various_empty_passphrases(self):
2114 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002115 Test that missing, None, and '' passphrases are identical for PKCS12
2116 export.
Rick Deanf94096c2009-07-18 14:23:06 -05002117 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002118 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002119 passwd = b""
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002120 dumped_p12_empty = p12.export(iter=2, maciter=0, passphrase=passwd)
2121 dumped_p12_none = p12.export(iter=3, maciter=2, passphrase=None)
2122 dumped_p12_nopw = p12.export(iter=9, maciter=4)
2123 for dumped_p12 in [dumped_p12_empty, dumped_p12_none, dumped_p12_nopw]:
2124 self.check_recovery(
2125 dumped_p12, key=client_key_pem, cert=client_cert_pem,
2126 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05002127
2128
2129 def test_removing_ca_cert(self):
2130 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002131 Passing :py:obj:`None` to :py:obj:`PKCS12.set_ca_certificates` removes all CA
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002132 certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05002133 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002134 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
2135 p12.set_ca_certificates(None)
Rick Dean623ee362009-07-17 12:22:16 -05002136 self.assertEqual(None, p12.get_ca_certificates())
Rick Deanf94096c2009-07-18 14:23:06 -05002137
2138
2139 def test_export_without_mac(self):
2140 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002141 Exporting a PKCS12 with a :py:obj:`maciter` of ``-1`` excludes the MAC
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002142 entirely.
Rick Deanf94096c2009-07-18 14:23:06 -05002143 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002144 passwd = b"Lake Michigan"
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002145 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Dean623ee362009-07-17 12:22:16 -05002146 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002147 self.check_recovery(
2148 dumped_p12, key=server_key_pem, cert=server_cert_pem,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002149 passwd=passwd, extra=(b"-nomacver",))
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002150
2151
2152 def test_load_without_mac(self):
2153 """
2154 Loading a PKCS12 without a MAC does something other than crash.
2155 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002156 passwd = b"Lake Michigan"
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002157 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
2158 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Rick Dean321a0512009-08-13 17:21:29 -05002159 try:
2160 recovered_p12 = load_pkcs12(dumped_p12, passwd)
2161 # The person who generated this PCKS12 should be flogged,
2162 # or better yet we should have a means to determine
2163 # whether a PCKS12 had a MAC that was verified.
2164 # Anyway, libopenssl chooses to allow it, so the
2165 # pyopenssl binding does as well.
2166 self.assertTrue(isinstance(recovered_p12, PKCS12))
2167 except Error:
2168 # Failing here with an exception is preferred as some openssl
2169 # versions do.
2170 pass
Rick Dean623ee362009-07-17 12:22:16 -05002171
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002172
Rick Dean25bcc1f2009-07-20 11:53:13 -05002173 def test_zero_len_list_for_ca(self):
2174 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002175 A PKCS12 with an empty CA certificates list can be exported.
Rick Dean25bcc1f2009-07-20 11:53:13 -05002176 """
2177 passwd = 'Hobie 18'
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002178 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002179 # p12.set_ca_certificates([])
2180 # self.assertEqual((), p12.get_ca_certificates())
2181 # dumped_p12 = p12.export(passphrase=passwd, iter=3)
2182 # self.check_recovery(
2183 # dumped_p12, key=server_key_pem, cert=server_cert_pem,
2184 # passwd=passwd)
Rick Dean25bcc1f2009-07-20 11:53:13 -05002185
2186
Rick Deanf94096c2009-07-18 14:23:06 -05002187 def test_export_without_args(self):
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002188 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002189 All the arguments to :py:obj:`PKCS12.export` are optional.
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002190 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002191 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05002192 dumped_p12 = p12.export() # no args
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002193 self.check_recovery(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002194 dumped_p12, key=server_key_pem, cert=server_cert_pem, passwd=b"")
Rick Deanf94096c2009-07-18 14:23:06 -05002195
2196
2197 def test_key_cert_mismatch(self):
2198 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002199 :py:obj:`PKCS12.export` raises an exception when a key and certificate
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002200 mismatch.
Rick Deanf94096c2009-07-18 14:23:06 -05002201 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002202 p12 = self.gen_pkcs12(server_cert_pem, client_key_pem, root_cert_pem)
2203 self.assertRaises(Error, p12.export)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002204
2205
2206
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002207# These quoting functions taken directly from Twisted's twisted.python.win32.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002208_cmdLineQuoteRe = re.compile(br'(\\*)"')
2209_cmdLineQuoteRe2 = re.compile(br'(\\+)\Z')
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002210def cmdLineQuote(s):
2211 """
2212 Internal method for quoting a single command-line argument.
2213
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002214 See http://www.perlmonks.org/?node_id=764004
2215
Jonathan Ballet648875f2011-07-16 14:14:58 +09002216 :type: :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002217 :param s: A single unquoted string to quote for something that is expecting
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002218 cmd.exe-style quoting
2219
Jonathan Ballet648875f2011-07-16 14:14:58 +09002220 :rtype: :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002221 :return: A cmd.exe-style quoted string
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002222 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002223 s = _cmdLineQuoteRe2.sub(br"\1\1", _cmdLineQuoteRe.sub(br'\1\1\\"', s))
2224 return b'"' + s + b'"'
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002225
2226
2227
2228def quoteArguments(arguments):
2229 """
2230 Quote an iterable of command-line arguments for passing to CreateProcess or
Jonathan Ballet648875f2011-07-16 14:14:58 +09002231 a similar API. This allows the list passed to :py:obj:`reactor.spawnProcess` to
2232 match the child process's :py:obj:`sys.argv` properly.
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002233
Jonathan Ballet648875f2011-07-16 14:14:58 +09002234 :type arguments: :py:obj:`iterable` of :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002235 :param arguments: An iterable of unquoted arguments to quote
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002236
Jonathan Ballet648875f2011-07-16 14:14:58 +09002237 :rtype: :py:obj:`str`
2238 :return: A space-delimited string containing quoted versions of :py:obj:`arguments`
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002239 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002240 return b' '.join(map(cmdLineQuote, arguments))
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002241
2242
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002243
Rick Dean4c9ad612009-07-17 15:05:22 -05002244def _runopenssl(pem, *args):
2245 """
2246 Run the command line openssl tool with the given arguments and write
Rick Dean55d1ce62009-08-13 17:40:24 -05002247 the given PEM to its stdin. Not safe for quotes.
Rick Dean4c9ad612009-07-17 15:05:22 -05002248 """
Jean-Paul Calderone038de952009-08-21 12:16:06 -04002249 if os.name == 'posix':
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002250 command = b"openssl " + b" ".join([
2251 (b"'" + arg.replace(b"'", b"'\\''") + b"'")
2252 for arg in args])
Rick Dean55d1ce62009-08-13 17:40:24 -05002253 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002254 command = b"openssl " + quoteArguments(args)
2255 proc = Popen(native(command), shell=True, stdin=PIPE, stdout=PIPE)
Jean-Paul Calderone62ca8da2010-08-11 19:58:08 -04002256 proc.stdin.write(pem)
2257 proc.stdin.close()
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002258 output = proc.stdout.read()
2259 proc.stdout.close()
2260 proc.wait()
2261 return output
Rick Dean4c9ad612009-07-17 15:05:22 -05002262
2263
2264
Jean-Paul Calderone18808652009-07-05 12:54:05 -04002265class FunctionTests(TestCase):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002266 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002267 Tests for free-functions in the :py:obj:`OpenSSL.crypto` module.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002268 """
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002269
2270 def test_load_privatekey_invalid_format(self):
2271 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002272 :py:obj:`load_privatekey` raises :py:obj:`ValueError` if passed an unknown filetype.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002273 """
2274 self.assertRaises(ValueError, load_privatekey, 100, root_key_pem)
2275
2276
2277 def test_load_privatekey_invalid_passphrase_type(self):
2278 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002279 :py:obj:`load_privatekey` raises :py:obj:`TypeError` if passed a passphrase that is
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002280 neither a :py:obj:`str` nor a callable.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002281 """
2282 self.assertRaises(
2283 TypeError,
2284 load_privatekey,
2285 FILETYPE_PEM, encryptedPrivateKeyPEMPassphrase, object())
2286
2287
2288 def test_load_privatekey_wrong_args(self):
2289 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002290 :py:obj:`load_privatekey` raises :py:obj:`TypeError` if called with the wrong number
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002291 of arguments.
2292 """
2293 self.assertRaises(TypeError, load_privatekey)
2294
2295
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002296 def test_load_privatekey_wrongPassphrase(self):
2297 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002298 :py:obj:`load_privatekey` raises :py:obj:`OpenSSL.crypto.Error` when it is passed an
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002299 encrypted PEM and an incorrect passphrase.
2300 """
2301 self.assertRaises(
2302 Error,
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002303 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, b("quack"))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002304
2305
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002306 def test_load_privatekey_passphraseWrongType(self):
2307 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002308 :py:obj:`load_privatekey` raises :py:obj:`ValueError` when it is passed a passphrase
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002309 with a private key encoded in a format, that doesn't support
2310 encryption.
2311 """
2312 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2313 blob = dump_privatekey(FILETYPE_ASN1, key)
2314 self.assertRaises(ValueError,
2315 load_privatekey, FILETYPE_ASN1, blob, "secret")
2316
2317
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002318 def test_load_privatekey_passphrase(self):
2319 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002320 :py:obj:`load_privatekey` can create a :py:obj:`PKey` object from an encrypted PEM
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002321 string if given the passphrase.
2322 """
2323 key = load_privatekey(
2324 FILETYPE_PEM, encryptedPrivateKeyPEM,
2325 encryptedPrivateKeyPEMPassphrase)
2326 self.assertTrue(isinstance(key, PKeyType))
2327
2328
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002329 def test_load_privatekey_passphrase_exception(self):
2330 """
2331 If the passphrase callback raises an exception, that exception is raised
2332 by :py:obj:`load_privatekey`.
2333 """
2334 def cb(ignored):
2335 raise ArithmeticError
2336
2337 self.assertRaises(ArithmeticError,
2338 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2339
2340
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002341 def test_load_privatekey_wrongPassphraseCallback(self):
2342 """
Jean-Paul Calderoned440a082011-09-14 11:02:05 -04002343 :py:obj:`load_privatekey` raises :py:obj:`OpenSSL.crypto.Error` when it
2344 is passed an encrypted PEM and a passphrase callback which returns an
2345 incorrect passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002346 """
2347 called = []
2348 def cb(*a):
2349 called.append(None)
Jean-Paul Calderoned440a082011-09-14 11:02:05 -04002350 return b("quack")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002351 self.assertRaises(
2352 Error,
2353 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2354 self.assertTrue(called)
2355
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002356
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002357 def test_load_privatekey_passphraseCallback(self):
2358 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002359 :py:obj:`load_privatekey` can create a :py:obj:`PKey` object from an encrypted PEM
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002360 string if given a passphrase callback which returns the correct
2361 password.
2362 """
2363 called = []
2364 def cb(writing):
2365 called.append(writing)
2366 return encryptedPrivateKeyPEMPassphrase
2367 key = load_privatekey(FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2368 self.assertTrue(isinstance(key, PKeyType))
2369 self.assertEqual(called, [False])
2370
2371
Jean-Paul Calderone105cb952011-09-14 10:16:46 -04002372 def test_load_privatekey_passphrase_wrong_return_type(self):
2373 """
2374 :py:obj:`load_privatekey` raises :py:obj:`ValueError` if the passphrase
2375 callback returns something other than a byte string.
2376 """
2377 self.assertRaises(
2378 ValueError,
2379 load_privatekey,
2380 FILETYPE_PEM, encryptedPrivateKeyPEM, lambda *args: 3)
2381
2382
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002383 def test_dump_privatekey_wrong_args(self):
2384 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002385 :py:obj:`dump_privatekey` raises :py:obj:`TypeError` if called with the wrong number
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002386 of arguments.
2387 """
2388 self.assertRaises(TypeError, dump_privatekey)
Jean-Paul Calderone1eeccd82011-09-14 10:18:52 -04002389 # If cipher name is given, password is required.
2390 self.assertRaises(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002391 TypeError, dump_privatekey, FILETYPE_PEM, PKey(), GOOD_CIPHER)
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002392
2393
2394 def test_dump_privatekey_unknown_cipher(self):
2395 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002396 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` if called with an unrecognized
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002397 cipher name.
2398 """
2399 key = PKey()
2400 key.generate_key(TYPE_RSA, 512)
2401 self.assertRaises(
2402 ValueError, dump_privatekey,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002403 FILETYPE_PEM, key, BAD_CIPHER, "passphrase")
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002404
2405
2406 def test_dump_privatekey_invalid_passphrase_type(self):
2407 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002408 :py:obj:`dump_privatekey` raises :py:obj:`TypeError` if called with a passphrase which
2409 is neither a :py:obj:`str` nor a callable.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002410 """
2411 key = PKey()
2412 key.generate_key(TYPE_RSA, 512)
2413 self.assertRaises(
2414 TypeError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002415 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, object())
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002416
2417
2418 def test_dump_privatekey_invalid_filetype(self):
2419 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002420 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` if called with an unrecognized
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002421 filetype.
2422 """
2423 key = PKey()
2424 key.generate_key(TYPE_RSA, 512)
2425 self.assertRaises(ValueError, dump_privatekey, 100, key)
2426
2427
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002428 def test_load_privatekey_passphraseCallbackLength(self):
2429 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002430 :py:obj:`crypto.load_privatekey` should raise an error when the passphrase
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002431 provided by the callback is too long, not silently truncate it.
2432 """
2433 def cb(ignored):
2434 return "a" * 1025
2435
2436 self.assertRaises(ValueError,
2437 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2438
2439
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002440 def test_dump_privatekey_passphrase(self):
2441 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002442 :py:obj:`dump_privatekey` writes an encrypted PEM when given a passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002443 """
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002444 passphrase = b("foo")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002445 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002446 pem = dump_privatekey(FILETYPE_PEM, key, GOOD_CIPHER, passphrase)
2447 self.assertTrue(isinstance(pem, binary_type))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002448 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
2449 self.assertTrue(isinstance(loadedKey, PKeyType))
2450 self.assertEqual(loadedKey.type(), key.type())
2451 self.assertEqual(loadedKey.bits(), key.bits())
2452
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002453
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002454 def test_dump_privatekey_passphraseWrongType(self):
2455 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002456 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` when it is passed a passphrase
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002457 with a private key encoded in a format, that doesn't support
2458 encryption.
2459 """
2460 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2461 self.assertRaises(ValueError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002462 dump_privatekey, FILETYPE_ASN1, key, GOOD_CIPHER, "secret")
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002463
2464
Rick Dean5b7b6372009-04-01 11:34:06 -05002465 def test_dump_certificate(self):
2466 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002467 :py:obj:`dump_certificate` writes PEM, DER, and text.
Rick Dean5b7b6372009-04-01 11:34:06 -05002468 """
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002469 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
Rick Dean5b7b6372009-04-01 11:34:06 -05002470 cert = load_certificate(FILETYPE_PEM, pemData)
2471 dumped_pem = dump_certificate(FILETYPE_PEM, cert)
2472 self.assertEqual(dumped_pem, cleartextCertificatePEM)
2473 dumped_der = dump_certificate(FILETYPE_ASN1, cert)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002474 good_der = _runopenssl(dumped_pem, b"x509", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002475 self.assertEqual(dumped_der, good_der)
2476 cert2 = load_certificate(FILETYPE_ASN1, dumped_der)
2477 dumped_pem2 = dump_certificate(FILETYPE_PEM, cert2)
2478 self.assertEqual(dumped_pem2, cleartextCertificatePEM)
2479 dumped_text = dump_certificate(FILETYPE_TEXT, cert)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002480 good_text = _runopenssl(dumped_pem, b"x509", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002481 self.assertEqual(dumped_text, good_text)
2482
2483
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002484 def test_dump_privatekey_pem(self):
Rick Dean5b7b6372009-04-01 11:34:06 -05002485 """
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002486 :py:obj:`dump_privatekey` writes a PEM
Rick Dean5b7b6372009-04-01 11:34:06 -05002487 """
2488 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -04002489 self.assertTrue(key.check())
Rick Dean5b7b6372009-04-01 11:34:06 -05002490 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2491 self.assertEqual(dumped_pem, cleartextPrivateKeyPEM)
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002492
2493
2494 def test_dump_privatekey_asn1(self):
2495 """
2496 :py:obj:`dump_privatekey` writes a DER
2497 """
2498 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2499 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2500
Rick Dean5b7b6372009-04-01 11:34:06 -05002501 dumped_der = dump_privatekey(FILETYPE_ASN1, key)
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002502 # XXX This OpenSSL call writes "writing RSA key" to standard out. Sad.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002503 good_der = _runopenssl(dumped_pem, b"rsa", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002504 self.assertEqual(dumped_der, good_der)
2505 key2 = load_privatekey(FILETYPE_ASN1, dumped_der)
2506 dumped_pem2 = dump_privatekey(FILETYPE_PEM, key2)
2507 self.assertEqual(dumped_pem2, cleartextPrivateKeyPEM)
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002508
2509
2510 def test_dump_privatekey_text(self):
2511 """
2512 :py:obj:`dump_privatekey` writes a text
2513 """
2514 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2515 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2516
Rick Dean5b7b6372009-04-01 11:34:06 -05002517 dumped_text = dump_privatekey(FILETYPE_TEXT, key)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002518 good_text = _runopenssl(dumped_pem, b"rsa", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002519 self.assertEqual(dumped_text, good_text)
2520
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002521
Rick Dean5b7b6372009-04-01 11:34:06 -05002522 def test_dump_certificate_request(self):
2523 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002524 :py:obj:`dump_certificate_request` writes a PEM, DER, and text.
Rick Dean5b7b6372009-04-01 11:34:06 -05002525 """
2526 req = load_certificate_request(FILETYPE_PEM, cleartextCertificateRequestPEM)
2527 dumped_pem = dump_certificate_request(FILETYPE_PEM, req)
2528 self.assertEqual(dumped_pem, cleartextCertificateRequestPEM)
2529 dumped_der = dump_certificate_request(FILETYPE_ASN1, req)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002530 good_der = _runopenssl(dumped_pem, b"req", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002531 self.assertEqual(dumped_der, good_der)
2532 req2 = load_certificate_request(FILETYPE_ASN1, dumped_der)
2533 dumped_pem2 = dump_certificate_request(FILETYPE_PEM, req2)
2534 self.assertEqual(dumped_pem2, cleartextCertificateRequestPEM)
2535 dumped_text = dump_certificate_request(FILETYPE_TEXT, req)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002536 good_text = _runopenssl(dumped_pem, b"req", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002537 self.assertEqual(dumped_text, good_text)
Jean-Paul Calderoneaf43cdf2010-08-03 18:40:52 -04002538 self.assertRaises(ValueError, dump_certificate_request, 100, req)
Rick Dean5b7b6372009-04-01 11:34:06 -05002539
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002540
2541 def test_dump_privatekey_passphraseCallback(self):
2542 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002543 :py:obj:`dump_privatekey` writes an encrypted PEM when given a callback which
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002544 returns the correct passphrase.
2545 """
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002546 passphrase = b("foo")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002547 called = []
2548 def cb(writing):
2549 called.append(writing)
2550 return passphrase
2551 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002552 pem = dump_privatekey(FILETYPE_PEM, key, GOOD_CIPHER, cb)
2553 self.assertTrue(isinstance(pem, binary_type))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002554 self.assertEqual(called, [True])
2555 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
2556 self.assertTrue(isinstance(loadedKey, PKeyType))
2557 self.assertEqual(loadedKey.type(), key.type())
2558 self.assertEqual(loadedKey.bits(), key.bits())
Rick Dean5b7b6372009-04-01 11:34:06 -05002559
2560
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002561 def test_dump_privatekey_passphrase_exception(self):
2562 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002563 :py:obj:`dump_privatekey` should not overwrite the exception raised
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002564 by the passphrase callback.
2565 """
2566 def cb(ignored):
2567 raise ArithmeticError
2568
2569 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2570 self.assertRaises(ArithmeticError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002571 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, cb)
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002572
2573
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002574 def test_dump_privatekey_passphraseCallbackLength(self):
2575 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002576 :py:obj:`crypto.dump_privatekey` should raise an error when the passphrase
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002577 provided by the callback is too long, not silently truncate it.
2578 """
2579 def cb(ignored):
2580 return "a" * 1025
2581
2582 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2583 self.assertRaises(ValueError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002584 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, cb)
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002585
2586
Alex Gaynor4b9c96a2014-08-14 09:51:48 -07002587 def test_load_pkcs7_data_pem(self):
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002588 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002589 :py:obj:`load_pkcs7_data` accepts a PKCS#7 string and returns an instance of
2590 :py:obj:`PKCS7Type`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002591 """
2592 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2593 self.assertTrue(isinstance(pkcs7, PKCS7Type))
2594
2595
Alex Gaynor4b9c96a2014-08-14 09:51:48 -07002596 def test_load_pkcs7_data_asn1(self):
Alex Gaynor9875a912014-08-14 13:35:05 -07002597 """
2598 :py:obj:`load_pkcs7_data` accepts a bytes containing ASN1 data
2599 representing PKCS#7 and returns an instance of :py:obj`PKCS7Type`.
2600 """
Alex Gaynor4b9c96a2014-08-14 09:51:48 -07002601 pkcs7 = load_pkcs7_data(FILETYPE_ASN1, pkcs7DataASN1)
2602 self.assertTrue(isinstance(pkcs7, PKCS7Type))
2603
2604
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002605 def test_load_pkcs7_data_invalid(self):
2606 """
2607 If the data passed to :py:obj:`load_pkcs7_data` is invalid,
2608 :py:obj:`Error` is raised.
2609 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002610 self.assertRaises(Error, load_pkcs7_data, FILETYPE_PEM, b"foo")
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002611
2612
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002613
Jean-Paul Calderone4a68b402013-12-29 16:54:58 -05002614class LoadCertificateTests(TestCase):
2615 """
2616 Tests for :py:obj:`load_certificate_request`.
2617 """
2618 def test_badFileType(self):
2619 """
2620 If the file type passed to :py:obj:`load_certificate_request` is
2621 neither :py:obj:`FILETYPE_PEM` nor :py:obj:`FILETYPE_ASN1` then
2622 :py:class:`ValueError` is raised.
2623 """
2624 self.assertRaises(ValueError, load_certificate_request, object(), b"")
2625
2626
2627
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002628class PKCS7Tests(TestCase):
2629 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002630 Tests for :py:obj:`PKCS7Type`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002631 """
2632 def test_type(self):
2633 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002634 :py:obj:`PKCS7Type` is a type object.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002635 """
2636 self.assertTrue(isinstance(PKCS7Type, type))
2637 self.assertEqual(PKCS7Type.__name__, 'PKCS7')
2638
2639 # XXX This doesn't currently work.
2640 # self.assertIdentical(PKCS7, PKCS7Type)
2641
2642
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002643 # XXX Opposite results for all these following methods
2644
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002645 def test_type_is_signed_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002646 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002647 :py:obj:`PKCS7Type.type_is_signed` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002648 arguments.
2649 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002650 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2651 self.assertRaises(TypeError, pkcs7.type_is_signed, None)
2652
2653
2654 def test_type_is_signed(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002655 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002656 :py:obj:`PKCS7Type.type_is_signed` returns :py:obj:`True` if the PKCS7 object is of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002657 the type *signed*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002658 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002659 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2660 self.assertTrue(pkcs7.type_is_signed())
2661
2662
2663 def test_type_is_enveloped_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002664 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002665 :py:obj:`PKCS7Type.type_is_enveloped` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002666 arguments.
2667 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002668 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2669 self.assertRaises(TypeError, pkcs7.type_is_enveloped, None)
2670
2671
2672 def test_type_is_enveloped(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002673 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002674 :py:obj:`PKCS7Type.type_is_enveloped` returns :py:obj:`False` if the PKCS7 object is
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002675 not of the type *enveloped*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002676 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002677 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2678 self.assertFalse(pkcs7.type_is_enveloped())
2679
2680
2681 def test_type_is_signedAndEnveloped_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002682 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002683 :py:obj:`PKCS7Type.type_is_signedAndEnveloped` raises :py:obj:`TypeError` if called
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002684 with any arguments.
2685 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002686 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2687 self.assertRaises(TypeError, pkcs7.type_is_signedAndEnveloped, None)
2688
2689
2690 def test_type_is_signedAndEnveloped(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002691 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002692 :py:obj:`PKCS7Type.type_is_signedAndEnveloped` returns :py:obj:`False` if the PKCS7
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002693 object is not of the type *signed and enveloped*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002694 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002695 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2696 self.assertFalse(pkcs7.type_is_signedAndEnveloped())
2697
2698
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002699 def test_type_is_data(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002700 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002701 :py:obj:`PKCS7Type.type_is_data` returns :py:obj:`False` if the PKCS7 object is not of
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002702 the type data.
2703 """
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002704 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2705 self.assertFalse(pkcs7.type_is_data())
2706
2707
2708 def test_type_is_data_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002709 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002710 :py:obj:`PKCS7Type.type_is_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002711 arguments.
2712 """
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002713 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2714 self.assertRaises(TypeError, pkcs7.type_is_data, None)
2715
2716
Jean-Paul Calderone97b28ca2010-07-30 10:56:07 -04002717 def test_get_type_name_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002718 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002719 :py:obj:`PKCS7Type.get_type_name` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002720 arguments.
2721 """
Jean-Paul Calderone97b28ca2010-07-30 10:56:07 -04002722 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2723 self.assertRaises(TypeError, pkcs7.get_type_name, None)
2724
2725
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002726 def test_get_type_name(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002727 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002728 :py:obj:`PKCS7Type.get_type_name` returns a :py:obj:`str` giving the type name.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002729 """
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002730 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
Jean-Paul Calderone07640f12010-08-22 17:14:43 -04002731 self.assertEquals(pkcs7.get_type_name(), b('pkcs7-signedData'))
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002732
2733
2734 def test_attribute(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002735 """
2736 If an attribute other than one of the methods tested here is accessed on
Jonathan Ballet648875f2011-07-16 14:14:58 +09002737 an instance of :py:obj:`PKCS7Type`, :py:obj:`AttributeError` is raised.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002738 """
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002739 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2740 self.assertRaises(AttributeError, getattr, pkcs7, "foo")
2741
2742
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002743
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002744class NetscapeSPKITests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002745 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002746 Tests for :py:obj:`OpenSSL.crypto.NetscapeSPKI`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002747 """
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002748 def signable(self):
2749 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002750 Return a new :py:obj:`NetscapeSPKI` for use with signing tests.
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002751 """
2752 return NetscapeSPKI()
2753
2754
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002755 def test_type(self):
2756 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002757 :py:obj:`NetscapeSPKI` and :py:obj:`NetscapeSPKIType` refer to the same type object
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002758 and can be used to create instances of that type.
2759 """
2760 self.assertIdentical(NetscapeSPKI, NetscapeSPKIType)
2761 self.assertConsistentType(NetscapeSPKI, 'NetscapeSPKI')
2762
2763
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002764 def test_construction(self):
2765 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002766 :py:obj:`NetscapeSPKI` returns an instance of :py:obj:`NetscapeSPKIType`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002767 """
2768 nspki = NetscapeSPKI()
2769 self.assertTrue(isinstance(nspki, NetscapeSPKIType))
2770
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002771
Jean-Paul Calderone969efaa2010-08-03 18:19:19 -04002772 def test_invalid_attribute(self):
2773 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002774 Accessing a non-existent attribute of a :py:obj:`NetscapeSPKI` instance causes
2775 an :py:obj:`AttributeError` to be raised.
Jean-Paul Calderone969efaa2010-08-03 18:19:19 -04002776 """
2777 nspki = NetscapeSPKI()
2778 self.assertRaises(AttributeError, lambda: nspki.foo)
2779
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002780
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002781 def test_b64_encode(self):
2782 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002783 :py:obj:`NetscapeSPKI.b64_encode` encodes the certificate to a base64 blob.
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002784 """
2785 nspki = NetscapeSPKI()
2786 blob = nspki.b64_encode()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002787 self.assertTrue(isinstance(blob, binary_type))
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002788
2789
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002790
Rick Dean536ba022009-07-24 23:57:27 -05002791class RevokedTests(TestCase):
2792 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002793 Tests for :py:obj:`OpenSSL.crypto.Revoked`
Rick Dean536ba022009-07-24 23:57:27 -05002794 """
2795 def test_construction(self):
2796 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002797 Confirm we can create :py:obj:`OpenSSL.crypto.Revoked`. Check
Rick Dean536ba022009-07-24 23:57:27 -05002798 that it is empty.
2799 """
2800 revoked = Revoked()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002801 self.assertTrue(isinstance(revoked, Revoked))
2802 self.assertEquals(type(revoked), Revoked)
2803 self.assertEquals(revoked.get_serial(), b('00'))
2804 self.assertEquals(revoked.get_rev_date(), None)
2805 self.assertEquals(revoked.get_reason(), None)
Rick Dean536ba022009-07-24 23:57:27 -05002806
2807
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002808 def test_construction_wrong_args(self):
2809 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002810 Calling :py:obj:`OpenSSL.crypto.Revoked` with any arguments results
2811 in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002812 """
2813 self.assertRaises(TypeError, Revoked, None)
2814 self.assertRaises(TypeError, Revoked, 1)
2815 self.assertRaises(TypeError, Revoked, "foo")
2816
2817
Rick Dean536ba022009-07-24 23:57:27 -05002818 def test_serial(self):
2819 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002820 Confirm we can set and get serial numbers from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002821 :py:obj:`OpenSSL.crypto.Revoked`. Confirm errors are handled
Rick Dean536ba022009-07-24 23:57:27 -05002822 with grace.
2823 """
2824 revoked = Revoked()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002825 ret = revoked.set_serial(b('10b'))
2826 self.assertEquals(ret, None)
Rick Dean536ba022009-07-24 23:57:27 -05002827 ser = revoked.get_serial()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002828 self.assertEquals(ser, b('010B'))
Rick Dean536ba022009-07-24 23:57:27 -05002829
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002830 revoked.set_serial(b('31ppp')) # a type error would be nice
Rick Dean536ba022009-07-24 23:57:27 -05002831 ser = revoked.get_serial()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002832 self.assertEquals(ser, b('31'))
Rick Dean536ba022009-07-24 23:57:27 -05002833
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002834 self.assertRaises(ValueError, revoked.set_serial, b('pqrst'))
Rick Dean536ba022009-07-24 23:57:27 -05002835 self.assertRaises(TypeError, revoked.set_serial, 100)
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002836 self.assertRaises(TypeError, revoked.get_serial, 1)
2837 self.assertRaises(TypeError, revoked.get_serial, None)
2838 self.assertRaises(TypeError, revoked.get_serial, "")
Rick Dean536ba022009-07-24 23:57:27 -05002839
2840
2841 def test_date(self):
2842 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002843 Confirm we can set and get revocation dates from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002844 :py:obj:`OpenSSL.crypto.Revoked`. Confirm errors are handled
Rick Dean536ba022009-07-24 23:57:27 -05002845 with grace.
2846 """
2847 revoked = Revoked()
2848 date = revoked.get_rev_date()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002849 self.assertEquals(date, None)
Rick Dean536ba022009-07-24 23:57:27 -05002850
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002851 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05002852 ret = revoked.set_rev_date(now)
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002853 self.assertEqual(ret, None)
Rick Dean536ba022009-07-24 23:57:27 -05002854 date = revoked.get_rev_date()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002855 self.assertEqual(date, now)
Rick Dean536ba022009-07-24 23:57:27 -05002856
2857
Rick Dean6385faf2009-07-26 00:07:47 -05002858 def test_reason(self):
2859 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002860 Confirm we can set and get revocation reasons from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002861 :py:obj:`OpenSSL.crypto.Revoked`. The "get" need to work
Rick Dean6385faf2009-07-26 00:07:47 -05002862 as "set". Likewise, each reason of all_reasons() must work.
2863 """
2864 revoked = Revoked()
2865 for r in revoked.all_reasons():
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002866 for x in range(2):
Rick Dean6385faf2009-07-26 00:07:47 -05002867 ret = revoked.set_reason(r)
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002868 self.assertEquals(ret, None)
Rick Dean6385faf2009-07-26 00:07:47 -05002869 reason = revoked.get_reason()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002870 self.assertEquals(
2871 reason.lower().replace(b(' '), b('')),
2872 r.lower().replace(b(' '), b('')))
Rick Dean6385faf2009-07-26 00:07:47 -05002873 r = reason # again with the resp of get
2874
2875 revoked.set_reason(None)
2876 self.assertEqual(revoked.get_reason(), None)
2877
2878
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002879 def test_set_reason_wrong_arguments(self):
Rick Dean6385faf2009-07-26 00:07:47 -05002880 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002881 Calling :py:obj:`OpenSSL.crypto.Revoked.set_reason` with other than
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002882 one argument, or an argument which isn't a valid reason,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002883 results in :py:obj:`TypeError` or :py:obj:`ValueError` being raised.
Rick Dean6385faf2009-07-26 00:07:47 -05002884 """
2885 revoked = Revoked()
2886 self.assertRaises(TypeError, revoked.set_reason, 100)
Jean-Paul Calderone281b62b2010-08-28 14:22:29 -04002887 self.assertRaises(ValueError, revoked.set_reason, b('blue'))
Rick Dean6385faf2009-07-26 00:07:47 -05002888
Rick Dean536ba022009-07-24 23:57:27 -05002889
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002890 def test_get_reason_wrong_arguments(self):
2891 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002892 Calling :py:obj:`OpenSSL.crypto.Revoked.get_reason` with any
2893 arguments results in :py:obj:`TypeError` being raised.
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002894 """
2895 revoked = Revoked()
2896 self.assertRaises(TypeError, revoked.get_reason, None)
2897 self.assertRaises(TypeError, revoked.get_reason, 1)
2898 self.assertRaises(TypeError, revoked.get_reason, "foo")
2899
2900
2901
Rick Dean536ba022009-07-24 23:57:27 -05002902class CRLTests(TestCase):
2903 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002904 Tests for :py:obj:`OpenSSL.crypto.CRL`
Rick Dean536ba022009-07-24 23:57:27 -05002905 """
2906 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
2907 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2908
2909 def test_construction(self):
2910 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002911 Confirm we can create :py:obj:`OpenSSL.crypto.CRL`. Check
Rick Dean536ba022009-07-24 23:57:27 -05002912 that it is empty
2913 """
2914 crl = CRL()
2915 self.assertTrue( isinstance(crl, CRL) )
2916 self.assertEqual(crl.get_revoked(), None)
2917
2918
Jean-Paul Calderone2efd03e2010-01-30 13:59:55 -05002919 def test_construction_wrong_args(self):
2920 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002921 Calling :py:obj:`OpenSSL.crypto.CRL` with any number of arguments
2922 results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone2efd03e2010-01-30 13:59:55 -05002923 """
2924 self.assertRaises(TypeError, CRL, 1)
2925 self.assertRaises(TypeError, CRL, "")
2926 self.assertRaises(TypeError, CRL, None)
2927
2928
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002929 def _get_crl(self):
Rick Dean536ba022009-07-24 23:57:27 -05002930 """
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002931 Get a new ``CRL`` with a revocation.
Rick Dean536ba022009-07-24 23:57:27 -05002932 """
2933 crl = CRL()
2934 revoked = Revoked()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002935 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05002936 revoked.set_rev_date(now)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002937 revoked.set_serial(b('3ab'))
2938 revoked.set_reason(b('sUpErSeDEd'))
Rick Dean536ba022009-07-24 23:57:27 -05002939 crl.add_revoked(revoked)
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002940 return crl
Rick Dean536ba022009-07-24 23:57:27 -05002941
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002942
2943 def test_export_pem(self):
2944 """
2945 If not passed a format, ``CRL.export`` returns a "PEM" format string
2946 representing a serial number, a revoked reason, and certificate issuer
2947 information.
2948 """
2949 crl = self._get_crl()
Rick Dean536ba022009-07-24 23:57:27 -05002950 # PEM format
2951 dumped_crl = crl.export(self.cert, self.pkey, days=20)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002952 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002953
2954 # These magic values are based on the way the CRL above was constructed
2955 # and with what certificate it was exported.
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002956 text.index(b('Serial Number: 03AB'))
2957 text.index(b('Superseded'))
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002958 text.index(
2959 b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA')
2960 )
2961
2962
2963 def test_export_der(self):
2964 """
2965 If passed ``FILETYPE_ASN1`` for the format, ``CRL.export`` returns a
2966 "DER" format string representing a serial number, a revoked reason, and
2967 certificate issuer information.
2968 """
2969 crl = self._get_crl()
Rick Dean536ba022009-07-24 23:57:27 -05002970
2971 # DER format
2972 dumped_crl = crl.export(self.cert, self.pkey, FILETYPE_ASN1)
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002973 text = _runopenssl(
2974 dumped_crl, b"crl", b"-noout", b"-text", b"-inform", b"DER"
2975 )
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002976 text.index(b('Serial Number: 03AB'))
2977 text.index(b('Superseded'))
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002978 text.index(
2979 b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA')
2980 )
2981
2982
2983 def test_export_text(self):
2984 """
2985 If passed ``FILETYPE_TEXT`` for the format, ``CRL.export`` returns a
2986 text format string like the one produced by the openssl command line
2987 tool.
2988 """
2989 crl = self._get_crl()
2990
2991 dumped_crl = crl.export(self.cert, self.pkey, FILETYPE_ASN1)
2992 text = _runopenssl(
2993 dumped_crl, b"crl", b"-noout", b"-text", b"-inform", b"DER"
2994 )
Rick Dean536ba022009-07-24 23:57:27 -05002995
2996 # text format
2997 dumped_text = crl.export(self.cert, self.pkey, type=FILETYPE_TEXT)
2998 self.assertEqual(text, dumped_text)
2999
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003000
3001 def test_export_custom_digest(self):
3002 """
3003 If passed the name of a digest function, ``CRL.export`` uses a
3004 signature algorithm based on that digest function.
3005 """
3006 crl = self._get_crl()
Bulat Gaifullin1966c972014-09-22 09:47:20 +04003007 dumped_crl = crl.export(self.cert, self.pkey, digest='sha1')
3008 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
3009 text.index(b('Signature Algorithm: sha1'))
3010
Jean-Paul Calderone60432792015-04-13 12:26:07 -04003011
3012 def test_export_default_digest(self):
3013 """
3014 If not passed the name of a digest function, ``CRL.export`` uses a
3015 signature algorithm based on MD5 and emits a deprecation warning.
3016 """
3017 crl = self._get_crl()
3018 with catch_warnings(record=True) as catcher:
3019 simplefilter("always")
3020 dumped_crl = crl.export(self.cert, self.pkey)
3021 self.assertEqual(
3022 "The default message digest (md5) is deprecated. "
3023 "Pass the name of a message digest explicitly.",
3024 str(catcher[0].message),
3025 )
Bulat Gaifullin1966c972014-09-22 09:47:20 +04003026 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
3027 text.index(b('Signature Algorithm: md5'))
3028
Rick Dean536ba022009-07-24 23:57:27 -05003029
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -04003030 def test_export_invalid(self):
3031 """
3032 If :py:obj:`CRL.export` is used with an uninitialized :py:obj:`X509`
Jean-Paul Calderoneb5871072012-03-09 14:58:00 -08003033 instance, :py:obj:`OpenSSL.crypto.Error` is raised.
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -04003034 """
3035 crl = CRL()
3036 self.assertRaises(Error, crl.export, X509(), PKey())
3037
3038
Jean-Paul Calderone56515342010-01-30 13:49:38 -05003039 def test_add_revoked_keyword(self):
3040 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003041 :py:obj:`OpenSSL.CRL.add_revoked` accepts its single argument as the
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003042 ``revoked`` keyword argument.
Jean-Paul Calderone56515342010-01-30 13:49:38 -05003043 """
3044 crl = CRL()
3045 revoked = Revoked()
3046 crl.add_revoked(revoked=revoked)
3047 self.assertTrue(isinstance(crl.get_revoked()[0], Revoked))
3048
Rick Dean6385faf2009-07-26 00:07:47 -05003049
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05003050 def test_export_wrong_args(self):
3051 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003052 Calling :py:obj:`OpenSSL.CRL.export` with fewer than two or more than
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05003053 four arguments, or with arguments other than the certificate,
3054 private key, integer file type, and integer number of days it
Jonathan Ballet648875f2011-07-16 14:14:58 +09003055 expects, results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05003056 """
3057 crl = CRL()
3058 self.assertRaises(TypeError, crl.export)
3059 self.assertRaises(TypeError, crl.export, self.cert)
Bulat Gaifullin925f7862014-09-22 10:10:44 +04003060 self.assertRaises(TypeError, crl.export, self.cert, self.pkey, FILETYPE_PEM, 10, "md5", "foo")
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05003061
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05003062 self.assertRaises(TypeError, crl.export, None, self.pkey, FILETYPE_PEM, 10)
3063 self.assertRaises(TypeError, crl.export, self.cert, None, FILETYPE_PEM, 10)
3064 self.assertRaises(TypeError, crl.export, self.cert, self.pkey, None, 10)
3065 self.assertRaises(TypeError, crl.export, self.cert, FILETYPE_PEM, None)
3066
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05003067
Jean-Paul Calderoneea198422010-01-30 13:58:23 -05003068 def test_export_unknown_filetype(self):
3069 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003070 Calling :py:obj:`OpenSSL.CRL.export` with a file type other than
3071 :py:obj:`FILETYPE_PEM`, :py:obj:`FILETYPE_ASN1`, or :py:obj:`FILETYPE_TEXT` results
3072 in a :py:obj:`ValueError` being raised.
Jean-Paul Calderoneea198422010-01-30 13:58:23 -05003073 """
3074 crl = CRL()
3075 self.assertRaises(ValueError, crl.export, self.cert, self.pkey, 100, 10)
3076
3077
Bulat Gaifullin925f7862014-09-22 10:10:44 +04003078 def test_export_unknown_digest(self):
Bulat Gaifullin5f9eea42014-09-23 19:35:15 +04003079 """
3080 Calling :py:obj:`OpenSSL.CRL.export` with a unsupported digest results
3081 in a :py:obj:`ValueError` being raised.
3082 """
Bulat Gaifullin925f7862014-09-22 10:10:44 +04003083 crl = CRL()
3084 self.assertRaises(ValueError, crl.export, self.cert, self.pkey, FILETYPE_PEM, 10, "strange-digest")
3085
3086
Rick Dean536ba022009-07-24 23:57:27 -05003087 def test_get_revoked(self):
3088 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05003089 Use python to create a simple CRL with two revocations.
Jonathan Ballet648875f2011-07-16 14:14:58 +09003090 Get back the :py:obj:`Revoked` using :py:obj:`OpenSSL.CRL.get_revoked` and
Rick Dean536ba022009-07-24 23:57:27 -05003091 verify them.
3092 """
3093 crl = CRL()
3094
3095 revoked = Revoked()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003096 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05003097 revoked.set_rev_date(now)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003098 revoked.set_serial(b('3ab'))
Rick Dean536ba022009-07-24 23:57:27 -05003099 crl.add_revoked(revoked)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003100 revoked.set_serial(b('100'))
3101 revoked.set_reason(b('sUpErSeDEd'))
Rick Dean536ba022009-07-24 23:57:27 -05003102 crl.add_revoked(revoked)
3103
3104 revs = crl.get_revoked()
3105 self.assertEqual(len(revs), 2)
3106 self.assertEqual(type(revs[0]), Revoked)
3107 self.assertEqual(type(revs[1]), Revoked)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003108 self.assertEqual(revs[0].get_serial(), b('03AB'))
3109 self.assertEqual(revs[1].get_serial(), b('0100'))
Rick Dean536ba022009-07-24 23:57:27 -05003110 self.assertEqual(revs[0].get_rev_date(), now)
3111 self.assertEqual(revs[1].get_rev_date(), now)
3112
3113
Jean-Paul Calderone46bdce42010-01-30 13:44:16 -05003114 def test_get_revoked_wrong_args(self):
3115 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003116 Calling :py:obj:`OpenSSL.CRL.get_revoked` with any arguments results
3117 in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone46bdce42010-01-30 13:44:16 -05003118 """
3119 crl = CRL()
3120 self.assertRaises(TypeError, crl.get_revoked, None)
3121 self.assertRaises(TypeError, crl.get_revoked, 1)
3122 self.assertRaises(TypeError, crl.get_revoked, "")
3123 self.assertRaises(TypeError, crl.get_revoked, "", 1, None)
3124
3125
Jean-Paul Calderoneecef6fa2010-01-30 13:47:18 -05003126 def test_add_revoked_wrong_args(self):
3127 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003128 Calling :py:obj:`OpenSSL.CRL.add_revoked` with other than one
3129 argument results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderoneecef6fa2010-01-30 13:47:18 -05003130 """
3131 crl = CRL()
3132 self.assertRaises(TypeError, crl.add_revoked)
3133 self.assertRaises(TypeError, crl.add_revoked, 1, 2)
3134 self.assertRaises(TypeError, crl.add_revoked, "foo", "bar")
3135
3136
Rick Dean536ba022009-07-24 23:57:27 -05003137 def test_load_crl(self):
3138 """
3139 Load a known CRL and inspect its revocations. Both
3140 PEM and DER formats are loaded.
3141 """
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003142 crl = load_crl(FILETYPE_PEM, crlData)
Rick Dean536ba022009-07-24 23:57:27 -05003143 revs = crl.get_revoked()
3144 self.assertEqual(len(revs), 2)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003145 self.assertEqual(revs[0].get_serial(), b('03AB'))
Rick Dean6385faf2009-07-26 00:07:47 -05003146 self.assertEqual(revs[0].get_reason(), None)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003147 self.assertEqual(revs[1].get_serial(), b('0100'))
3148 self.assertEqual(revs[1].get_reason(), b('Superseded'))
Rick Dean536ba022009-07-24 23:57:27 -05003149
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003150 der = _runopenssl(crlData, b"crl", b"-outform", b"DER")
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05003151 crl = load_crl(FILETYPE_ASN1, der)
Rick Dean536ba022009-07-24 23:57:27 -05003152 revs = crl.get_revoked()
3153 self.assertEqual(len(revs), 2)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003154 self.assertEqual(revs[0].get_serial(), b('03AB'))
Rick Dean6385faf2009-07-26 00:07:47 -05003155 self.assertEqual(revs[0].get_reason(), None)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003156 self.assertEqual(revs[1].get_serial(), b('0100'))
3157 self.assertEqual(revs[1].get_reason(), b('Superseded'))
Rick Dean536ba022009-07-24 23:57:27 -05003158
3159
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003160 def test_load_crl_wrong_args(self):
3161 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003162 Calling :py:obj:`OpenSSL.crypto.load_crl` with other than two
3163 arguments results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003164 """
3165 self.assertRaises(TypeError, load_crl)
3166 self.assertRaises(TypeError, load_crl, FILETYPE_PEM)
3167 self.assertRaises(TypeError, load_crl, FILETYPE_PEM, crlData, None)
3168
3169
3170 def test_load_crl_bad_filetype(self):
3171 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003172 Calling :py:obj:`OpenSSL.crypto.load_crl` with an unknown file type
3173 raises a :py:obj:`ValueError`.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003174 """
3175 self.assertRaises(ValueError, load_crl, 100, crlData)
3176
3177
3178 def test_load_crl_bad_data(self):
3179 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003180 Calling :py:obj:`OpenSSL.crypto.load_crl` with file data which can't
3181 be loaded raises a :py:obj:`OpenSSL.crypto.Error`.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003182 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003183 self.assertRaises(Error, load_crl, FILETYPE_PEM, b"hello, world")
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003184
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04003185
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -05003186
James Yonan7c2e5d32010-02-27 05:45:50 -07003187class SignVerifyTests(TestCase):
3188 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003189 Tests for :py:obj:`OpenSSL.crypto.sign` and :py:obj:`OpenSSL.crypto.verify`.
James Yonan7c2e5d32010-02-27 05:45:50 -07003190 """
3191 def test_sign_verify(self):
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04003192 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003193 :py:obj:`sign` generates a cryptographic signature which :py:obj:`verify` can check.
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04003194 """
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003195 content = b(
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04003196 "It was a bright cold day in April, and the clocks were striking "
3197 "thirteen. Winston Smith, his chin nuzzled into his breast in an "
3198 "effort to escape the vile wind, slipped quickly through the "
3199 "glass doors of Victory Mansions, though not quickly enough to "
3200 "prevent a swirl of gritty dust from entering along with him.")
3201
3202 # sign the content with this private key
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04003203 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04003204 # verify the content with this cert
3205 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3206 # certificate unrelated to priv_key, used to trigger an error
3207 bad_cert = load_certificate(FILETYPE_PEM, server_cert_pem)
James Yonan7c2e5d32010-02-27 05:45:50 -07003208
Jean-Paul Calderoned08feb02010-10-12 21:53:24 -04003209 for digest in ['md5', 'sha1']:
James Yonan7c2e5d32010-02-27 05:45:50 -07003210 sig = sign(priv_key, content, digest)
3211
3212 # Verify the signature of content, will throw an exception if error.
3213 verify(good_cert, sig, content, digest)
3214
3215 # This should fail because the certificate doesn't match the
3216 # private key that was used to sign the content.
3217 self.assertRaises(Error, verify, bad_cert, sig, content, digest)
3218
3219 # This should fail because we've "tainted" the content after
3220 # signing it.
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003221 self.assertRaises(
3222 Error, verify,
3223 good_cert, sig, content + b("tainted"), digest)
James Yonan7c2e5d32010-02-27 05:45:50 -07003224
3225 # test that unknown digest types fail
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003226 self.assertRaises(
Jean-Paul Calderone9538f142010-10-13 22:13:40 -04003227 ValueError, sign, priv_key, content, "strange-digest")
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003228 self.assertRaises(
Jean-Paul Calderone9538f142010-10-13 22:13:40 -04003229 ValueError, verify, good_cert, sig, content, "strange-digest")
James Yonan7c2e5d32010-02-27 05:45:50 -07003230
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04003231
Jean-Paul Calderone9828f662010-12-08 22:57:26 -05003232 def test_sign_nulls(self):
3233 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003234 :py:obj:`sign` produces a signature for a string with embedded nulls.
Jean-Paul Calderone9828f662010-12-08 22:57:26 -05003235 """
3236 content = b("Watch out! \0 Did you see it?")
3237 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
3238 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3239 sig = sign(priv_key, content, "sha1")
3240 verify(good_cert, sig, content, "sha1")
3241
3242
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003243
3244class EllipticCurveTests(TestCase):
3245 """
3246 Tests for :py:class:`_EllipticCurve`, :py:obj:`get_elliptic_curve`, and
3247 :py:obj:`get_elliptic_curves`.
3248 """
3249 def test_set(self):
3250 """
3251 :py:obj:`get_elliptic_curves` returns a :py:obj:`set`.
3252 """
3253 self.assertIsInstance(get_elliptic_curves(), set)
3254
3255
3256 def test_some_curves(self):
3257 """
3258 If :py:mod:`cryptography` has elliptic curve support then the set
3259 returned by :py:obj:`get_elliptic_curves` has some elliptic curves in
3260 it.
3261
3262 There could be an OpenSSL that violates this assumption. If so, this
3263 test will fail and we'll find out.
3264 """
3265 curves = get_elliptic_curves()
3266 if lib.Cryptography_HAS_EC:
3267 self.assertTrue(curves)
3268 else:
3269 self.assertFalse(curves)
3270
3271
3272 def test_a_curve(self):
3273 """
3274 :py:obj:`get_elliptic_curve` can be used to retrieve a particular
3275 supported curve.
3276 """
3277 curves = get_elliptic_curves()
3278 if curves:
3279 curve = next(iter(curves))
3280 self.assertEqual(curve.name, get_elliptic_curve(curve.name).name)
3281 else:
Jean-Paul Calderoneeb86f3a2014-04-19 09:45:57 -04003282 self.assertRaises(ValueError, get_elliptic_curve, u("prime256v1"))
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003283
3284
3285 def test_not_a_curve(self):
3286 """
3287 :py:obj:`get_elliptic_curve` raises :py:class:`ValueError` if called
3288 with a name which does not identify a supported curve.
3289 """
3290 self.assertRaises(
Jean-Paul Calderone5a82db92014-04-19 09:51:29 -04003291 ValueError, get_elliptic_curve, u("this curve was just invented"))
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003292
3293
3294 def test_repr(self):
3295 """
3296 The string representation of a curve object includes simply states the
3297 object is a curve and what its name is.
3298 """
3299 curves = get_elliptic_curves()
3300 if curves:
3301 curve = next(iter(curves))
3302 self.assertEqual("<Curve %r>" % (curve.name,), repr(curve))
3303
3304
3305 def test_to_EC_KEY(self):
3306 """
3307 The curve object can export a version of itself as an EC_KEY* via the
3308 private :py:meth:`_EllipticCurve._to_EC_KEY`.
3309 """
3310 curves = get_elliptic_curves()
3311 if curves:
3312 curve = next(iter(curves))
3313 # It's not easy to assert anything about this object. However, see
3314 # leakcheck/crypto.py for a test that demonstrates it at least does
3315 # not leak memory.
3316 curve._to_EC_KEY()
3317
3318
Jean-Paul Calderone1be77082014-04-30 18:17:41 -04003319
3320class EllipticCurveFactory(object):
3321 """
3322 A helper to get the names of two curves.
3323 """
3324 def __init__(self):
3325 curves = iter(get_elliptic_curves())
3326 try:
3327 self.curve_name = next(curves).name
3328 self.another_curve_name = next(curves).name
3329 except StopIteration:
3330 self.curve_name = self.another_curve_name = None
3331
3332
3333
3334class EllipticCurveEqualityTests(TestCase, EqualityTestsMixin):
3335 """
3336 Tests :py:type:`_EllipticCurve`\ 's implementation of ``==`` and ``!=``.
3337 """
3338 curve_factory = EllipticCurveFactory()
3339
3340 if curve_factory.curve_name is None:
3341 skip = "There are no curves available there can be no curve objects."
3342
3343
3344 def anInstance(self):
3345 """
3346 Get the curve object for an arbitrary curve supported by the system.
3347 """
3348 return get_elliptic_curve(self.curve_factory.curve_name)
3349
3350
3351 def anotherInstance(self):
3352 """
3353 Get the curve object for an arbitrary curve supported by the system -
3354 but not the one returned by C{anInstance}.
3355 """
3356 return get_elliptic_curve(self.curve_factory.another_curve_name)
3357
3358
3359
Jean-Paul Calderone22c31242014-05-01 07:49:47 -04003360class EllipticCurveHashTests(TestCase):
3361 """
3362 Tests for :py:type:`_EllipticCurve`\ 's implementation of hashing (thus use
3363 as an item in a :py:type:`dict` or :py:type:`set`).
3364 """
3365 curve_factory = EllipticCurveFactory()
3366
3367 if curve_factory.curve_name is None:
3368 skip = "There are no curves available there can be no curve objects."
3369
3370
3371 def test_contains(self):
3372 """
3373 The ``in`` operator reports that a :py:type:`set` containing a curve
3374 does contain that curve.
3375 """
3376 curve = get_elliptic_curve(self.curve_factory.curve_name)
3377 curves = set([curve])
3378 self.assertIn(curve, curves)
3379
3380
3381 def test_does_not_contain(self):
3382 """
3383 The ``in`` operator reports that a :py:type:`set` not containing a
3384 curve does not contain that curve.
3385 """
3386 curve = get_elliptic_curve(self.curve_factory.curve_name)
3387 curves = set([get_elliptic_curve(self.curve_factory.another_curve_name)])
3388 self.assertNotIn(curve, curves)
3389
3390
3391
Rick Dean5b7b6372009-04-01 11:34:06 -05003392if __name__ == '__main__':
3393 main()