blob: 07733424b2da30f5d1c7b429fd492f3fab6b29d8 [file] [log] [blame]
Jean-Paul Calderone8671c852011-03-02 19:26:20 -05001# Copyright (c) Jean-Paul Calderone
2# See LICENSE file for details.
Jean-Paul Calderone8b63d452008-03-21 18:31:12 -04003
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -05004"""
Jonathan Ballet648875f2011-07-16 14:14:58 +09005Unit tests for :py:mod:`OpenSSL.crypto`.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -05006"""
7
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04008from unittest import main
9
Alex Gaynor4b9c96a2014-08-14 09:51:48 -070010import base64
11import os
12import re
Jean-Paul Calderone62ca8da2010-08-11 19:58:08 -040013from subprocess import PIPE, Popen
Rick Dean47262da2009-07-08 16:17:17 -050014from datetime import datetime, timedelta
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -050015
Abraham Martinc5484ba2015-03-25 15:33:05 +000016from six import u, b, binary_type, PY3
17from warnings import simplefilter
18from warnings import catch_warnings
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050019
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -050020from OpenSSL.crypto import TYPE_RSA, TYPE_DSA, Error, PKey, PKeyType
Jean-Paul Calderone78381d22008-03-06 23:35:22 -050021from OpenSSL.crypto import X509, X509Type, X509Name, X509NameType
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080022from OpenSSL.crypto import X509Store, X509StoreType, X509Req, X509ReqType
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -050023from OpenSSL.crypto import X509Extension, X509ExtensionType
Rick Dean5b7b6372009-04-01 11:34:06 -050024from OpenSSL.crypto import load_certificate, load_privatekey
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -040025from OpenSSL.crypto import FILETYPE_PEM, FILETYPE_ASN1, FILETYPE_TEXT
Jean-Paul Calderone71919862009-04-01 13:01:19 -040026from OpenSSL.crypto import dump_certificate, load_certificate_request
27from OpenSSL.crypto import dump_certificate_request, dump_privatekey
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -040028from OpenSSL.crypto import PKCS7Type, load_pkcs7_data
Jean-Paul Calderone9178ee62010-01-25 17:55:30 -050029from OpenSSL.crypto import PKCS12, PKCS12Type, load_pkcs12
Rick Dean536ba022009-07-24 23:57:27 -050030from OpenSSL.crypto import CRL, Revoked, load_crl
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -040031from OpenSSL.crypto import NetscapeSPKI, NetscapeSPKIType
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040032from OpenSSL.crypto import (
33 sign, verify, get_elliptic_curve, get_elliptic_curves)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -040034from OpenSSL.test.util import (
35 EqualityTestsMixin, TestCase, WARNING_TYPE_EXPECTED
36)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040037from OpenSSL._util import native, lib
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040038
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -040039def normalize_certificate_pem(pem):
40 return dump_certificate(FILETYPE_PEM, load_certificate(FILETYPE_PEM, pem))
41
42
43def normalize_privatekey_pem(pem):
44 return dump_privatekey(FILETYPE_PEM, load_privatekey(FILETYPE_PEM, pem))
45
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040046
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050047GOOD_CIPHER = "blowfish"
48BAD_CIPHER = "zippers"
49
50GOOD_DIGEST = "MD5"
51BAD_DIGEST = "monkeys"
52
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040053root_cert_pem = b("""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -050054MIIC7TCCAlagAwIBAgIIPQzE4MbeufQwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE
55BhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdU
56ZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwIhgPMjAwOTAzMjUxMjM2
57NThaGA8yMDE3MDYxMTEyMzY1OFowWDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklM
58MRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9U
59ZXN0aW5nIFJvb3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPmaQumL
60urpE527uSEHdL1pqcDRmWzu+98Y6YHzT/J7KWEamyMCNZ6fRW1JCR782UQ8a07fy
612xXsKy4WdKaxyG8CcatwmXvpvRQ44dSANMihHELpANTdyVp6DCysED6wkQFurHlF
621dshEaJw8b/ypDhmbVIo6Ci1xvCJqivbLFnbAgMBAAGjgbswgbgwHQYDVR0OBBYE
63FINVdy1eIfFJDAkk51QJEo3IfgSuMIGIBgNVHSMEgYAwfoAUg1V3LV4h8UkMCSTn
64VAkSjch+BK6hXKRaMFgxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UE
65BxMHQ2hpY2FnbzEQMA4GA1UEChMHVGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBS
66b290IENBggg9DMTgxt659DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB
67AGGCDazMJGoWNBpc03u6+smc95dEead2KlZXBATOdFT1VesY3+nUOqZhEhTGlDMi
68hkgaZnzoIq/Uamidegk4hirsCT/R+6vsKAAxNTcBjUeZjlykCJWy5ojShGftXIKY
69w/njVbKMXrvc83qmTdGl3TAM0fxQIpqgcglFLveEBgzn
70-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040071""")
Rick Dean94e46fd2009-07-18 14:51:24 -050072
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040073root_key_pem = b("""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -050074MIICXQIBAAKBgQD5mkLpi7q6ROdu7khB3S9aanA0Zls7vvfGOmB80/yeylhGpsjA
75jWen0VtSQke/NlEPGtO38tsV7CsuFnSmschvAnGrcJl76b0UOOHUgDTIoRxC6QDU
763claegwsrBA+sJEBbqx5RdXbIRGicPG/8qQ4Zm1SKOgotcbwiaor2yxZ2wIDAQAB
77AoGBAPCgMpmLxzwDaUmcFbTJUvlLW1hoxNNYSu2jIZm1k/hRAcE60JYwvBkgz3UB
78yMEh0AtLxYe0bFk6EHah11tMUPgscbCq73snJ++8koUw+csk22G65hOs51bVb7Aa
796JBe67oLzdtvgCUFAA2qfrKzWRZzAdhUirQUZgySZk+Xq1pBAkEA/kZG0A6roTSM
80BVnx7LnPfsycKUsTumorpXiylZJjTi9XtmzxhrYN6wgZlDOOwOLgSQhszGpxVoMD
81u3gByT1b2QJBAPtL3mSKdvwRu/+40zaZLwvSJRxaj0mcE4BJOS6Oqs/hS1xRlrNk
82PpQ7WJ4yM6ZOLnXzm2mKyxm50Mv64109FtMCQQDOqS2KkjHaLowTGVxwC0DijMfr
83I9Lf8sSQk32J5VWCySWf5gGTfEnpmUa41gKTMJIbqZZLucNuDcOtzUaeWZlZAkA8
84ttXigLnCqR486JDPTi9ZscoZkZ+w7y6e/hH8t6d5Vjt48JVyfjPIaJY+km58LcN3
856AWSeGAdtRFHVzR7oHjVAkB4hutvxiOeiIVQNBhM6RSI9aBPMI21DoX2JRoxvNW2
86cbvAhow217X9V0dVerEOKxnNYspXRrh36h7k4mQA+sDq
87-----END RSA PRIVATE KEY-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040088""")
Rick Dean94e46fd2009-07-18 14:51:24 -050089
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040090server_cert_pem = b("""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -050091MIICKDCCAZGgAwIBAgIJAJn/HpR21r/8MA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
92BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
93VGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBSb290IENBMCIYDzIwMDkwMzI1MTIz
94NzUzWhgPMjAxNzA2MTExMjM3NTNaMBgxFjAUBgNVBAMTDWxvdmVseSBzZXJ2ZXIw
95gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAL6m+G653V0tpBC/OKl22VxOi2Cv
96lK4TYu9LHSDP9uDVTe7V5D5Tl6qzFoRRx5pfmnkqT5B+W9byp2NU3FC5hLm5zSAr
97b45meUhjEJ/ifkZgbNUjHdBIGP9MAQUHZa5WKdkGIJvGAvs8UzUqlr4TBWQIB24+
98lJ+Ukk/CRgasrYwdAgMBAAGjNjA0MB0GA1UdDgQWBBS4kC7Ij0W1TZXZqXQFAM2e
99gKEG2DATBgNVHSUEDDAKBggrBgEFBQcDATANBgkqhkiG9w0BAQUFAAOBgQBh30Li
100dJ+NlxIOx5343WqIBka3UbsOb2kxWrbkVCrvRapCMLCASO4FqiKWM+L0VDBprqIp
1012mgpFQ6FHpoIENGvJhdEKpptQ5i7KaGhnDNTfdy3x1+h852G99f1iyj0RmbuFcM8
102uzujnS8YXWvM7DM1Ilozk4MzPug8jzFp5uhKCQ==
103-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400104""")
Rick Dean94e46fd2009-07-18 14:51:24 -0500105
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -0400106server_key_pem = normalize_privatekey_pem(b("""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500107MIICWwIBAAKBgQC+pvhuud1dLaQQvzipdtlcTotgr5SuE2LvSx0gz/bg1U3u1eQ+
108U5eqsxaEUceaX5p5Kk+QflvW8qdjVNxQuYS5uc0gK2+OZnlIYxCf4n5GYGzVIx3Q
109SBj/TAEFB2WuVinZBiCbxgL7PFM1Kpa+EwVkCAduPpSflJJPwkYGrK2MHQIDAQAB
110AoGAbwuZ0AR6JveahBaczjfnSpiFHf+mve2UxoQdpyr6ROJ4zg/PLW5K/KXrC48G
111j6f3tXMrfKHcpEoZrQWUfYBRCUsGD5DCazEhD8zlxEHahIsqpwA0WWssJA2VOLEN
112j6DuV2pCFbw67rfTBkTSo32ahfXxEKev5KswZk0JIzH3ooECQQDgzS9AI89h0gs8
113Dt+1m11Rzqo3vZML7ZIyGApUzVan+a7hbc33nbGRkAXjHaUBJO31it/H6dTO+uwX
114msWwNG5ZAkEA2RyFKs5xR5USTFaKLWCgpH/ydV96KPOpBND7TKQx62snDenFNNbn
115FwwOhpahld+vqhYk+pfuWWUpQciE+Bu7ZQJASjfT4sQv4qbbKK/scePicnDdx9th
1164e1EeB9xwb+tXXXUo/6Bor/AcUNwfiQ6Zt9PZOK9sR3lMZSsP7rMi7kzuQJABie6
1171sXXjFH7nNJvRG4S39cIxq8YRYTy68II/dlB2QzGpKxV/POCxbJ/zu0CU79tuYK7
118NaeNCFfH3aeTrX0LyQJAMBWjWmeKM2G2sCExheeQK0ROnaBC8itCECD4Jsve4nqf
119r50+LF74iLXFwqysVCebPKMOpDWp/qQ1BbJQIPs7/A==
120-----END RSA PRIVATE KEY-----
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -0400121"""))
Rick Dean94e46fd2009-07-18 14:51:24 -0500122
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400123client_cert_pem = b("""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500124MIICJjCCAY+gAwIBAgIJAKxpFI5lODkjMA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
125BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
126VGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBSb290IENBMCIYDzIwMDkwMzI1MTIz
127ODA1WhgPMjAxNzA2MTExMjM4MDVaMBYxFDASBgNVBAMTC3VnbHkgY2xpZW50MIGf
128MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDAZh/SRtNm5ntMT4qb6YzEpTroMlq2
129rn+GrRHRiZ+xkCw/CGNhbtPir7/QxaUj26BSmQrHw1bGKEbPsWiW7bdXSespl+xK
130iku4G/KvnnmWdeJHqsiXeUZtqurMELcPQAw9xPHEuhqqUJvvEoMTsnCEqGM+7Dtb
131oCRajYyHfluARQIDAQABozYwNDAdBgNVHQ4EFgQUNQB+qkaOaEVecf1J3TTUtAff
1320fAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQEFBQADgYEAyv/Jh7gM
133Q3OHvmsFEEvRI+hsW8y66zK4K5de239Y44iZrFYkt7Q5nBPMEWDj4F2hLYWL/qtI
1349Zdr0U4UDCU9SmmGYh4o7R4TZ5pGFvBYvjhHbkSFYFQXZxKUi+WUxplP6I0wr2KJ
135PSTJCjJOn3xo2NTKRgV1gaoTf2EhL+RG8TQ=
136-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400137""")
Rick Dean94e46fd2009-07-18 14:51:24 -0500138
Jean-Paul Calderone22cbe502011-05-04 17:01:43 -0400139client_key_pem = normalize_privatekey_pem(b("""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500140MIICXgIBAAKBgQDAZh/SRtNm5ntMT4qb6YzEpTroMlq2rn+GrRHRiZ+xkCw/CGNh
141btPir7/QxaUj26BSmQrHw1bGKEbPsWiW7bdXSespl+xKiku4G/KvnnmWdeJHqsiX
142eUZtqurMELcPQAw9xPHEuhqqUJvvEoMTsnCEqGM+7DtboCRajYyHfluARQIDAQAB
143AoGATkZ+NceY5Glqyl4mD06SdcKfV65814vg2EL7V9t8+/mi9rYL8KztSXGlQWPX
144zuHgtRoMl78yQ4ZJYOBVo+nsx8KZNRCEBlE19bamSbQLCeQMenWnpeYyQUZ908gF
145h6L9qsFVJepgA9RDgAjyDoS5CaWCdCCPCH2lDkdcqC54SVUCQQDseuduc4wi8h4t
146V8AahUn9fn9gYfhoNuM0gdguTA0nPLVWz4hy1yJiWYQe0H7NLNNTmCKiLQaJpAbb
147TC6vE8C7AkEA0Ee8CMJUc20BnGEmxwgWcVuqFWaKCo8jTH1X38FlATUsyR3krjW2
148dL3yDD9NwHxsYP7nTKp/U8MV7U9IBn4y/wJBAJl7H0/BcLeRmuJk7IqJ7b635iYB
149D/9beFUw3MUXmQXZUfyYz39xf6CDZsu1GEdEC5haykeln3Of4M9d/4Kj+FcCQQCY
150si6xwT7GzMDkk/ko684AV3KPc/h6G0yGtFIrMg7J3uExpR/VdH2KgwMkZXisSMvw
151JJEQjOMCVsEJlRk54WWjAkEAzoZNH6UhDdBK5F38rVt/y4SEHgbSfJHIAmPS32Kq
152f6GGcfNpip0Uk7q7udTKuX7Q/buZi/C4YW7u3VKAquv9NA==
153-----END RSA PRIVATE KEY-----
Jean-Paul Calderone22cbe502011-05-04 17:01:43 -0400154"""))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400155
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400156cleartextCertificatePEM = b("""-----BEGIN CERTIFICATE-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400157MIIC7TCCAlagAwIBAgIIPQzE4MbeufQwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE
158BhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdU
159ZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwIhgPMjAwOTAzMjUxMjM2
160NThaGA8yMDE3MDYxMTEyMzY1OFowWDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklM
161MRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9U
162ZXN0aW5nIFJvb3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPmaQumL
163urpE527uSEHdL1pqcDRmWzu+98Y6YHzT/J7KWEamyMCNZ6fRW1JCR782UQ8a07fy
1642xXsKy4WdKaxyG8CcatwmXvpvRQ44dSANMihHELpANTdyVp6DCysED6wkQFurHlF
1651dshEaJw8b/ypDhmbVIo6Ci1xvCJqivbLFnbAgMBAAGjgbswgbgwHQYDVR0OBBYE
166FINVdy1eIfFJDAkk51QJEo3IfgSuMIGIBgNVHSMEgYAwfoAUg1V3LV4h8UkMCSTn
167VAkSjch+BK6hXKRaMFgxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UE
168BxMHQ2hpY2FnbzEQMA4GA1UEChMHVGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBS
169b290IENBggg9DMTgxt659DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB
170AGGCDazMJGoWNBpc03u6+smc95dEead2KlZXBATOdFT1VesY3+nUOqZhEhTGlDMi
171hkgaZnzoIq/Uamidegk4hirsCT/R+6vsKAAxNTcBjUeZjlykCJWy5ojShGftXIKY
172w/njVbKMXrvc83qmTdGl3TAM0fxQIpqgcglFLveEBgzn
173-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400174""")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400175
Jean-Paul Calderoned50d2042011-05-04 17:00:49 -0400176cleartextPrivateKeyPEM = normalize_privatekey_pem(b("""\
177-----BEGIN RSA PRIVATE KEY-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400178MIICXQIBAAKBgQD5mkLpi7q6ROdu7khB3S9aanA0Zls7vvfGOmB80/yeylhGpsjA
179jWen0VtSQke/NlEPGtO38tsV7CsuFnSmschvAnGrcJl76b0UOOHUgDTIoRxC6QDU
1803claegwsrBA+sJEBbqx5RdXbIRGicPG/8qQ4Zm1SKOgotcbwiaor2yxZ2wIDAQAB
181AoGBAPCgMpmLxzwDaUmcFbTJUvlLW1hoxNNYSu2jIZm1k/hRAcE60JYwvBkgz3UB
182yMEh0AtLxYe0bFk6EHah11tMUPgscbCq73snJ++8koUw+csk22G65hOs51bVb7Aa
1836JBe67oLzdtvgCUFAA2qfrKzWRZzAdhUirQUZgySZk+Xq1pBAkEA/kZG0A6roTSM
184BVnx7LnPfsycKUsTumorpXiylZJjTi9XtmzxhrYN6wgZlDOOwOLgSQhszGpxVoMD
185u3gByT1b2QJBAPtL3mSKdvwRu/+40zaZLwvSJRxaj0mcE4BJOS6Oqs/hS1xRlrNk
186PpQ7WJ4yM6ZOLnXzm2mKyxm50Mv64109FtMCQQDOqS2KkjHaLowTGVxwC0DijMfr
187I9Lf8sSQk32J5VWCySWf5gGTfEnpmUa41gKTMJIbqZZLucNuDcOtzUaeWZlZAkA8
188ttXigLnCqR486JDPTi9ZscoZkZ+w7y6e/hH8t6d5Vjt48JVyfjPIaJY+km58LcN3
1896AWSeGAdtRFHVzR7oHjVAkB4hutvxiOeiIVQNBhM6RSI9aBPMI21DoX2JRoxvNW2
190cbvAhow217X9V0dVerEOKxnNYspXRrh36h7k4mQA+sDq
191-----END RSA PRIVATE KEY-----
Jean-Paul Calderoned50d2042011-05-04 17:00:49 -0400192"""))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400193
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400194cleartextCertificateRequestPEM = b("""-----BEGIN CERTIFICATE REQUEST-----
195MIIBnjCCAQcCAQAwXjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQH
196EwdDaGljYWdvMRcwFQYDVQQKEw5NeSBDb21wYW55IEx0ZDEXMBUGA1UEAxMORnJl
197ZGVyaWNrIERlYW4wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANp6Y17WzKSw
198BsUWkXdqg6tnXy8H8hA1msCMWpc+/2KJ4mbv5NyD6UD+/SqagQqulPbF/DFea9nA
199E0zhmHJELcM8gUTIlXv/cgDWnmK4xj8YkjVUiCdqKRAKeuzLG1pGmwwF5lGeJpXN
200xQn5ecR0UYSOWj6TTGXB9VyUMQzCClcBAgMBAAGgADANBgkqhkiG9w0BAQUFAAOB
201gQAAJGuF/R/GGbeC7FbFW+aJgr9ee0Xbl6nlhu7pTe67k+iiKT2dsl2ti68MVTnu
202Vrb3HUNqOkiwsJf6kCtq5oPn3QVYzTa76Dt2y3Rtzv6boRSlmlfrgS92GNma8JfR
203oICQk3nAudi6zl1Dix3BCv1pUp5KMtGn3MeDEi6QFGy2rA==
204-----END CERTIFICATE REQUEST-----
205""")
Rick Dean5b7b6372009-04-01 11:34:06 -0500206
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400207encryptedPrivateKeyPEM = b("""-----BEGIN RSA PRIVATE KEY-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400208Proc-Type: 4,ENCRYPTED
209DEK-Info: DES-EDE3-CBC,9573604A18579E9E
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400210
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400211SHOho56WxDkT0ht10UTeKc0F5u8cqIa01kzFAmETw0MAs8ezYtK15NPdCXUm3X/2
212a17G7LSF5bkxOgZ7vpXyMzun/owrj7CzvLxyncyEFZWvtvzaAhPhvTJtTIB3kf8B
2138+qRcpTGK7NgXEgYBW5bj1y4qZkD4zCL9o9NQzsKI3Ie8i0239jsDOWR38AxjXBH
214mGwAQ4Z6ZN5dnmM4fhMIWsmFf19sNyAML4gHenQCHhmXbjXeVq47aC2ProInJbrm
215+00TcisbAQ40V9aehVbcDKtS4ZbMVDwncAjpXpcncC54G76N6j7F7wL7L/FuXa3A
216fvSVy9n2VfF/pJ3kYSflLHH2G/DFxjF7dl0GxhKPxJjp3IJi9VtuvmN9R2jZWLQF
217tfC8dXgy/P9CfFQhlinqBTEwgH0oZ/d4k4NVFDSdEMaSdmBAjlHpc+Vfdty3HVnV
218rKXj//wslsFNm9kIwJGIgKUa/n2jsOiydrsk1mgH7SmNCb3YHgZhbbnq0qLat/HC
219gHDt3FHpNQ31QzzL3yrenFB2L9osIsnRsDTPFNi4RX4SpDgNroxOQmyzCCV6H+d4
220o1mcnNiZSdxLZxVKccq0AfRpHqpPAFnJcQHP6xyT9MZp6fBa0XkxDnt9kNU8H3Qw
2217SJWZ69VXjBUzMlQViLuaWMgTnL+ZVyFZf9hTF7U/ef4HMLMAVNdiaGG+G+AjCV/
222MbzjS007Oe4qqBnCWaFPSnJX6uLApeTbqAxAeyCql56ULW5x6vDMNC3dwjvS/CEh
22311n8RkgFIQA0AhuKSIg3CbuartRsJnWOLwgLTzsrKYL4yRog1RJrtw==
224-----END RSA PRIVATE KEY-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400225""")
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400226
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400227encryptedPrivateKeyPEMPassphrase = b("foobar")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400228
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400229# Some PKCS#7 stuff. Generated with the openssl command line:
230#
231# openssl crl2pkcs7 -inform pem -outform pem -certfile s.pem -nocrl
232#
233# with a certificate and key (but the key should be irrelevant) in s.pem
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400234pkcs7Data = b("""\
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400235-----BEGIN PKCS7-----
236MIIDNwYJKoZIhvcNAQcCoIIDKDCCAyQCAQExADALBgkqhkiG9w0BBwGgggMKMIID
237BjCCAm+gAwIBAgIBATANBgkqhkiG9w0BAQQFADB7MQswCQYDVQQGEwJTRzERMA8G
238A1UEChMITTJDcnlwdG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtN
239MkNyeXB0byBDZXJ0aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNA
240cG9zdDEuY29tMB4XDTAwMDkxMDA5NTEzMFoXDTAyMDkxMDA5NTEzMFowUzELMAkG
241A1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwlsb2NhbGhvc3Qx
242HTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tMFwwDQYJKoZIhvcNAQEBBQAD
243SwAwSAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh5kwI
244zOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEAAaOCAQQwggEAMAkGA1UdEwQCMAAw
245LAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0G
246A1UdDgQWBBTPhIKSvnsmYsBVNWjj0m3M2z0qVTCBpQYDVR0jBIGdMIGagBT7hyNp
24765w6kxXlxb8pUU/+7Sg4AaF/pH0wezELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0y
248Q3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlwdG8g
249Q2VydGlmaWNhdGUgTWFzdGVyMR0wGwYJKoZIhvcNAQkBFg5uZ3BzQHBvc3QxLmNv
250bYIBADANBgkqhkiG9w0BAQQFAAOBgQA7/CqT6PoHycTdhEStWNZde7M/2Yc6BoJu
251VwnW8YxGO8Sn6UJ4FeffZNcYZddSDKosw8LtPOeWoK3JINjAk5jiPQ2cww++7QGG
252/g5NDjxFZNDJP1dGiLAxPW6JXwov4v0FmdzfLOZ01jDcgQQZqEpYlgpuI5JEWUQ9
253Ho4EzbYCOaEAMQA=
254-----END PKCS7-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400255""")
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400256
Alex Gaynor8fa1dd62014-08-14 09:57:51 -0700257pkcs7DataASN1 = base64.b64decode(b"""
Alex Gaynor4b9c96a2014-08-14 09:51:48 -0700258MIIDNwYJKoZIhvcNAQcCoIIDKDCCAyQCAQExADALBgkqhkiG9w0BBwGgggMKMIID
259BjCCAm+gAwIBAgIBATANBgkqhkiG9w0BAQQFADB7MQswCQYDVQQGEwJTRzERMA8G
260A1UEChMITTJDcnlwdG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtN
261MkNyeXB0byBDZXJ0aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNA
262cG9zdDEuY29tMB4XDTAwMDkxMDA5NTEzMFoXDTAyMDkxMDA5NTEzMFowUzELMAkG
263A1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwlsb2NhbGhvc3Qx
264HTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tMFwwDQYJKoZIhvcNAQEBBQAD
265SwAwSAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh5kwI
266zOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEAAaOCAQQwggEAMAkGA1UdEwQCMAAw
267LAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0G
268A1UdDgQWBBTPhIKSvnsmYsBVNWjj0m3M2z0qVTCBpQYDVR0jBIGdMIGagBT7hyNp
26965w6kxXlxb8pUU/+7Sg4AaF/pH0wezELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0y
270Q3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlwdG8g
271Q2VydGlmaWNhdGUgTWFzdGVyMR0wGwYJKoZIhvcNAQkBFg5uZ3BzQHBvc3QxLmNv
272bYIBADANBgkqhkiG9w0BAQQFAAOBgQA7/CqT6PoHycTdhEStWNZde7M/2Yc6BoJu
273VwnW8YxGO8Sn6UJ4FeffZNcYZddSDKosw8LtPOeWoK3JINjAk5jiPQ2cww++7QGG
274/g5NDjxFZNDJP1dGiLAxPW6JXwov4v0FmdzfLOZ01jDcgQQZqEpYlgpuI5JEWUQ9
275Ho4EzbYCOaEAMQA=
Alex Gaynor8fa1dd62014-08-14 09:57:51 -0700276""")
Alex Gaynor4b9c96a2014-08-14 09:51:48 -0700277
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400278crlData = b("""\
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -0500279-----BEGIN X509 CRL-----
280MIIBWzCBxTANBgkqhkiG9w0BAQQFADBYMQswCQYDVQQGEwJVUzELMAkGA1UECBMC
281SUwxEDAOBgNVBAcTB0NoaWNhZ28xEDAOBgNVBAoTB1Rlc3RpbmcxGDAWBgNVBAMT
282D1Rlc3RpbmcgUm9vdCBDQRcNMDkwNzI2MDQzNDU2WhcNMTIwOTI3MDI0MTUyWjA8
283MBUCAgOrGA8yMDA5MDcyNTIzMzQ1NlowIwICAQAYDzIwMDkwNzI1MjMzNDU2WjAM
284MAoGA1UdFQQDCgEEMA0GCSqGSIb3DQEBBAUAA4GBAEBt7xTs2htdD3d4ErrcGAw1
2854dKcVnIWTutoI7xxen26Wwvh8VCsT7i/UeP+rBl9rC/kfjWjzQk3/zleaarGTpBT
2860yp4HXRFFoRhhSE/hP+eteaPXRgrsNRLHe9ZDd69wmh7J1wMDb0m81RG7kqcbsid
287vrzEeLDRiiPl92dyyWmu
288-----END X509 CRL-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400289""")
Jean-Paul Calderonee890db32010-08-22 16:55:15 -0400290
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400291
292# A broken RSA private key which can be used to test the error path through
293# PKey.check.
294inconsistentPrivateKeyPEM = b("""-----BEGIN RSA PRIVATE KEY-----
295MIIBPAIBAAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh
2965kwIzOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEaAQJBAIqm/bz4NA1H++Vx5Ewx
297OcKp3w19QSaZAwlGRtsUxrP7436QjnREM3Bm8ygU11BjkPVmtrKm6AayQfCHqJoT
298zIECIQDW0BoMoL0HOYM/mrTLhaykYAVqgIeJsPjvkEhTFXWBuQIhAM3deFAvWNu4
299nklUQ37XsCT2c9tmNt1LAT+slG2JOTTRAiAuXDtC/m3NYVwyHfFm+zKHRzHkClk2
300HjubeEgjpj32AQIhAJqMGTaZVOwevTXvvHwNeH+vRWsAYU/gbx+OQB+7VOcBAiEA
301oolb6NMg/R3enNPvS1O4UU1H8wpaF77L4yiSWlE0p4w=
302-----END RSA PRIVATE KEY-----
303""")
304
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -0400305# certificate with NULL bytes in subjectAltName and common name
306
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400307nulbyteSubjectAltNamePEM = b("""-----BEGIN CERTIFICATE-----
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -0400308MIIE2DCCA8CgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBxTELMAkGA1UEBhMCVVMx
309DzANBgNVBAgMBk9yZWdvbjESMBAGA1UEBwwJQmVhdmVydG9uMSMwIQYDVQQKDBpQ
310eXRob24gU29mdHdhcmUgRm91bmRhdGlvbjEgMB4GA1UECwwXUHl0aG9uIENvcmUg
311RGV2ZWxvcG1lbnQxJDAiBgNVBAMMG251bGwucHl0aG9uLm9yZwBleGFtcGxlLm9y
312ZzEkMCIGCSqGSIb3DQEJARYVcHl0aG9uLWRldkBweXRob24ub3JnMB4XDTEzMDgw
313NzEzMTE1MloXDTEzMDgwNzEzMTI1MlowgcUxCzAJBgNVBAYTAlVTMQ8wDQYDVQQI
314DAZPcmVnb24xEjAQBgNVBAcMCUJlYXZlcnRvbjEjMCEGA1UECgwaUHl0aG9uIFNv
315ZnR3YXJlIEZvdW5kYXRpb24xIDAeBgNVBAsMF1B5dGhvbiBDb3JlIERldmVsb3Bt
316ZW50MSQwIgYDVQQDDBtudWxsLnB5dGhvbi5vcmcAZXhhbXBsZS5vcmcxJDAiBgkq
317hkiG9w0BCQEWFXB5dGhvbi1kZXZAcHl0aG9uLm9yZzCCASIwDQYJKoZIhvcNAQEB
318BQADggEPADCCAQoCggEBALXq7cn7Rn1vO3aA3TrzA5QLp6bb7B3f/yN0CJ2XFj+j
319pHs+Gw6WWSUDpybiiKnPec33BFawq3kyblnBMjBU61ioy5HwQqVkJ8vUVjGIUq3P
320vX/wBmQfzCe4o4uM89gpHyUL9UYGG8oCRa17dgqcv7u5rg0Wq2B1rgY+nHwx3JIv
321KRrgSwyRkGzpN8WQ1yrXlxWjgI9de0mPVDDUlywcWze1q2kwaEPTM3hLAmD1PESA
322oY/n8A/RXoeeRs9i/Pm/DGUS8ZPINXk/yOzsR/XvvkTVroIeLZqfmFpnZeF0cHzL
32308LODkVJJ9zjLdT7SA4vnne4FEbAxDbKAq5qkYzaL4UCAwEAAaOB0DCBzTAMBgNV
324HRMBAf8EAjAAMB0GA1UdDgQWBBSIWlXAUv9hzVKjNQ/qWpwkOCL3XDALBgNVHQ8E
325BAMCBeAwgZAGA1UdEQSBiDCBhYIeYWx0bnVsbC5weXRob24ub3JnAGV4YW1wbGUu
326Y29tgSBudWxsQHB5dGhvbi5vcmcAdXNlckBleGFtcGxlLm9yZ4YpaHR0cDovL251
327bGwucHl0aG9uLm9yZwBodHRwOi8vZXhhbXBsZS5vcmeHBMAAAgGHECABDbgAAAAA
328AAAAAAAAAAEwDQYJKoZIhvcNAQEFBQADggEBAKxPRe99SaghcI6IWT7UNkJw9aO9
329i9eo0Fj2MUqxpKbdb9noRDy2CnHWf7EIYZ1gznXPdwzSN4YCjV5d+Q9xtBaowT0j
330HPERs1ZuytCNNJTmhyqZ8q6uzMLoht4IqH/FBfpvgaeC5tBTnTT0rD5A/olXeimk
331kX4LxlEx5RAvpGB2zZVRGr6LobD9rVK91xuHYNIxxxfEGE8tCCWjp0+3ksri9SXx
332VHWBnbM9YaL32u3hxm8sYB/Yb8WSBavJCWJJqRStVRHM1koZlJmXNx2BX4vPo6iW
333RFEIPQsFZRLrtnCAiEhyT8bC2s/Njlu6ly9gtJZWSV46Q3ZjBL4q9sHKqZQ=
334-----END CERTIFICATE-----""")
335
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400336
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400337class X509ExtTests(TestCase):
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400338 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900339 Tests for :py:class:`OpenSSL.crypto.X509Extension`.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400340 """
341
342 def setUp(self):
343 """
344 Create a new private key and start a certificate request (for a test
345 method to finish in one way or another).
346 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -0800347 super(X509ExtTests, self).setUp()
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400348 # Basic setup stuff to generate a certificate
349 self.pkey = PKey()
350 self.pkey.generate_key(TYPE_RSA, 384)
351 self.req = X509Req()
352 self.req.set_pubkey(self.pkey)
353 # Authority good you have.
354 self.req.get_subject().commonName = "Yoda root CA"
355 self.x509 = X509()
356 self.subject = self.x509.get_subject()
357 self.subject.commonName = self.req.get_subject().commonName
358 self.x509.set_issuer(self.subject)
359 self.x509.set_pubkey(self.pkey)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400360 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
361 expire = b((datetime.now() + timedelta(days=100)).strftime("%Y%m%d%H%M%SZ"))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400362 self.x509.set_notBefore(now)
363 self.x509.set_notAfter(expire)
364
365
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -0800366 def tearDown(self):
367 """
368 Forget all of the pyOpenSSL objects so they can be garbage collected,
369 their memory released, and not interfere with the leak detection code.
370 """
371 self.pkey = self.req = self.x509 = self.subject = None
372 super(X509ExtTests, self).tearDown()
373
374
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400375 def test_str(self):
376 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900377 The string representation of :py:class:`X509Extension` instances as returned by
378 :py:data:`str` includes stuff.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400379 """
380 # This isn't necessarily the best string representation. Perhaps it
381 # will be changed/improved in the future.
382 self.assertEquals(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400383 str(X509Extension(b('basicConstraints'), True, b('CA:false'))),
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400384 'CA:FALSE')
385
386
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400387 def test_type(self):
388 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900389 :py:class:`X509Extension` and :py:class:`X509ExtensionType` refer to the same type object
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400390 and can be used to create instances of that type.
391 """
392 self.assertIdentical(X509Extension, X509ExtensionType)
393 self.assertConsistentType(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400394 X509Extension,
395 'X509Extension', b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400396
397
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500398 def test_construction(self):
399 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900400 :py:class:`X509Extension` accepts an extension type name, a critical flag,
401 and an extension value and returns an :py:class:`X509ExtensionType` instance.
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500402 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400403 basic = X509Extension(b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500404 self.assertTrue(
405 isinstance(basic, X509ExtensionType),
406 "%r is of type %r, should be %r" % (
407 basic, type(basic), X509ExtensionType))
408
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400409 comment = X509Extension(
410 b('nsComment'), False, b('pyOpenSSL unit test'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500411 self.assertTrue(
412 isinstance(comment, X509ExtensionType),
413 "%r is of type %r, should be %r" % (
414 comment, type(comment), X509ExtensionType))
415
416
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500417 def test_invalid_extension(self):
418 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900419 :py:class:`X509Extension` raises something if it is passed a bad extension
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500420 name or value.
421 """
422 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400423 Error, X509Extension, b('thisIsMadeUp'), False, b('hi'))
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500424 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400425 Error, X509Extension, b('basicConstraints'), False, b('blah blah'))
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500426
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500427 # Exercise a weird one (an extension which uses the r2i method). This
428 # exercises the codepath that requires a non-NULL ctx to be passed to
429 # X509V3_EXT_nconf. It can't work now because we provide no
430 # configuration database. It might be made to work in the future.
431 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400432 Error, X509Extension, b('proxyCertInfo'), True,
433 b('language:id-ppl-anyLanguage,pathlen:1,policy:text:AB'))
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500434
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500435
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500436 def test_get_critical(self):
437 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900438 :py:meth:`X509ExtensionType.get_critical` returns the value of the
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500439 extension's critical flag.
440 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400441 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500442 self.assertTrue(ext.get_critical())
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400443 ext = X509Extension(b('basicConstraints'), False, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500444 self.assertFalse(ext.get_critical())
445
Jean-Paul Calderone7535dab2008-03-06 18:53:11 -0500446
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500447 def test_get_short_name(self):
448 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900449 :py:meth:`X509ExtensionType.get_short_name` returns a string giving the short
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500450 type name of the extension.
451 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400452 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
453 self.assertEqual(ext.get_short_name(), b('basicConstraints'))
454 ext = X509Extension(b('nsComment'), True, b('foo bar'))
455 self.assertEqual(ext.get_short_name(), b('nsComment'))
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500456
457
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400458 def test_get_data(self):
459 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900460 :py:meth:`X509Extension.get_data` returns a string giving the data of the
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400461 extension.
462 """
463 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
464 # Expect to get back the DER encoded form of CA:true.
465 self.assertEqual(ext.get_data(), b('0\x03\x01\x01\xff'))
466
467
468 def test_get_data_wrong_args(self):
469 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900470 :py:meth:`X509Extension.get_data` raises :py:exc:`TypeError` if passed any arguments.
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400471 """
472 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
473 self.assertRaises(TypeError, ext.get_data, None)
474 self.assertRaises(TypeError, ext.get_data, "foo")
475 self.assertRaises(TypeError, ext.get_data, 7)
476
477
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400478 def test_unused_subject(self):
Rick Dean47262da2009-07-08 16:17:17 -0500479 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900480 The :py:data:`subject` parameter to :py:class:`X509Extension` may be provided for an
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400481 extension which does not use it and is ignored in this case.
Rick Dean47262da2009-07-08 16:17:17 -0500482 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400483 ext1 = X509Extension(
484 b('basicConstraints'), False, b('CA:TRUE'), subject=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400485 self.x509.add_extensions([ext1])
486 self.x509.sign(self.pkey, 'sha1')
487 # This is a little lame. Can we think of a better way?
488 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400489 self.assertTrue(b('X509v3 Basic Constraints:') in text)
490 self.assertTrue(b('CA:TRUE') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400491
492
493 def test_subject(self):
494 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900495 If an extension requires a subject, the :py:data:`subject` parameter to
496 :py:class:`X509Extension` provides its value.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400497 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400498 ext3 = X509Extension(
499 b('subjectKeyIdentifier'), False, b('hash'), subject=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400500 self.x509.add_extensions([ext3])
501 self.x509.sign(self.pkey, 'sha1')
502 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400503 self.assertTrue(b('X509v3 Subject Key Identifier:') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400504
505
506 def test_missing_subject(self):
507 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900508 If an extension requires a subject and the :py:data:`subject` parameter is
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400509 given no value, something happens.
510 """
511 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400512 Error, X509Extension, b('subjectKeyIdentifier'), False, b('hash'))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400513
514
515 def test_invalid_subject(self):
516 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900517 If the :py:data:`subject` parameter is given a value which is not an
518 :py:class:`X509` instance, :py:exc:`TypeError` is raised.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400519 """
520 for badObj in [True, object(), "hello", [], self]:
521 self.assertRaises(
522 TypeError,
523 X509Extension,
524 'basicConstraints', False, 'CA:TRUE', subject=badObj)
525
526
527 def test_unused_issuer(self):
528 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900529 The :py:data:`issuer` parameter to :py:class:`X509Extension` may be provided for an
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400530 extension which does not use it and is ignored in this case.
531 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400532 ext1 = X509Extension(
533 b('basicConstraints'), False, b('CA:TRUE'), issuer=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400534 self.x509.add_extensions([ext1])
535 self.x509.sign(self.pkey, 'sha1')
536 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400537 self.assertTrue(b('X509v3 Basic Constraints:') in text)
538 self.assertTrue(b('CA:TRUE') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400539
540
541 def test_issuer(self):
542 """
Alex Gaynor3b0ee972014-11-15 09:17:33 -0800543 If an extension requires an issuer, the :py:data:`issuer` parameter to
Jonathan Ballet648875f2011-07-16 14:14:58 +0900544 :py:class:`X509Extension` provides its value.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400545 """
546 ext2 = X509Extension(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400547 b('authorityKeyIdentifier'), False, b('issuer:always'),
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400548 issuer=self.x509)
549 self.x509.add_extensions([ext2])
550 self.x509.sign(self.pkey, 'sha1')
551 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400552 self.assertTrue(b('X509v3 Authority Key Identifier:') in text)
553 self.assertTrue(b('DirName:/CN=Yoda root CA') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400554
555
556 def test_missing_issuer(self):
557 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900558 If an extension requires an issue and the :py:data:`issuer` parameter is given
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400559 no value, something happens.
560 """
561 self.assertRaises(
562 Error,
563 X509Extension,
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400564 b('authorityKeyIdentifier'), False,
565 b('keyid:always,issuer:always'))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400566
567
568 def test_invalid_issuer(self):
569 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900570 If the :py:data:`issuer` parameter is given a value which is not an
571 :py:class:`X509` instance, :py:exc:`TypeError` is raised.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400572 """
573 for badObj in [True, object(), "hello", [], self]:
574 self.assertRaises(
575 TypeError,
576 X509Extension,
577 'authorityKeyIdentifier', False, 'keyid:always,issuer:always',
578 issuer=badObj)
Rick Dean47262da2009-07-08 16:17:17 -0500579
580
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500581
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400582class PKeyTests(TestCase):
Jean-Paul Calderoneac930e12008-03-06 18:50:51 -0500583 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900584 Unit tests for :py:class:`OpenSSL.crypto.PKey`.
Jean-Paul Calderoneac930e12008-03-06 18:50:51 -0500585 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400586 def test_type(self):
587 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900588 :py:class:`PKey` and :py:class:`PKeyType` refer to the same type object
589 and can be used to create instances of that type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400590 """
591 self.assertIdentical(PKey, PKeyType)
592 self.assertConsistentType(PKey, 'PKey')
593
594
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500595 def test_construction(self):
596 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900597 :py:class:`PKey` takes no arguments and returns a new :py:class:`PKey` instance.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500598 """
599 self.assertRaises(TypeError, PKey, None)
600 key = PKey()
601 self.assertTrue(
602 isinstance(key, PKeyType),
603 "%r is of type %r, should be %r" % (key, type(key), PKeyType))
604
605
606 def test_pregeneration(self):
607 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900608 :py:attr:`PKeyType.bits` and :py:attr:`PKeyType.type` return :py:data:`0` before the key is
609 generated. :py:attr:`PKeyType.check` raises :py:exc:`TypeError` before the key is
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500610 generated.
611 """
612 key = PKey()
613 self.assertEqual(key.type(), 0)
614 self.assertEqual(key.bits(), 0)
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400615 self.assertRaises(TypeError, key.check)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500616
617
618 def test_failedGeneration(self):
619 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900620 :py:meth:`PKeyType.generate_key` takes two arguments, the first giving the key
621 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 -0500622 number of bits to generate. If an invalid type is specified or
Jonathan Ballet648875f2011-07-16 14:14:58 +0900623 generation fails, :py:exc:`Error` is raised. If an invalid number of bits is
624 specified, :py:exc:`ValueError` or :py:exc:`Error` is raised.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500625 """
626 key = PKey()
627 self.assertRaises(TypeError, key.generate_key)
628 self.assertRaises(TypeError, key.generate_key, 1, 2, 3)
629 self.assertRaises(TypeError, key.generate_key, "foo", "bar")
630 self.assertRaises(Error, key.generate_key, -1, 0)
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500631
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500632 self.assertRaises(ValueError, key.generate_key, TYPE_RSA, -1)
633 self.assertRaises(ValueError, key.generate_key, TYPE_RSA, 0)
Jean-Paul Calderoned71fe982008-03-06 00:31:50 -0500634
635 # XXX RSA generation for small values of bits is fairly buggy in a wide
636 # range of OpenSSL versions. I need to figure out what the safe lower
637 # bound for a reasonable number of OpenSSL versions is and explicitly
638 # check for that in the wrapper. The failure behavior is typically an
639 # infinite loop inside OpenSSL.
640
641 # self.assertRaises(Error, key.generate_key, TYPE_RSA, 2)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500642
643 # XXX DSA generation seems happy with any number of bits. The DSS
644 # says bits must be between 512 and 1024 inclusive. OpenSSL's DSA
645 # generator doesn't seem to care about the upper limit at all. For
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500646 # the lower limit, it uses 512 if anything smaller is specified.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500647 # So, it doesn't seem possible to make generate_key fail for
648 # TYPE_DSA with a bits argument which is at least an int.
649
650 # self.assertRaises(Error, key.generate_key, TYPE_DSA, -7)
651
652
653 def test_rsaGeneration(self):
654 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900655 :py:meth:`PKeyType.generate_key` generates an RSA key when passed
656 :py:data:`TYPE_RSA` as a type and a reasonable number of bits.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500657 """
658 bits = 128
659 key = PKey()
660 key.generate_key(TYPE_RSA, bits)
661 self.assertEqual(key.type(), TYPE_RSA)
662 self.assertEqual(key.bits(), bits)
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -0400663 self.assertTrue(key.check())
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500664
665
666 def test_dsaGeneration(self):
667 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900668 :py:meth:`PKeyType.generate_key` generates a DSA key when passed
669 :py:data:`TYPE_DSA` as a type and a reasonable number of bits.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500670 """
671 # 512 is a magic number. The DSS (Digital Signature Standard)
672 # allows a minimum of 512 bits for DSA. DSA_generate_parameters
673 # will silently promote any value below 512 to 512.
674 bits = 512
675 key = PKey()
676 key.generate_key(TYPE_DSA, bits)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800677 # self.assertEqual(key.type(), TYPE_DSA)
678 # self.assertEqual(key.bits(), bits)
679 # self.assertRaises(TypeError, key.check)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500680
681
682 def test_regeneration(self):
683 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900684 :py:meth:`PKeyType.generate_key` can be called multiple times on the same
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500685 key to generate new keys.
686 """
687 key = PKey()
688 for type, bits in [(TYPE_RSA, 512), (TYPE_DSA, 576)]:
689 key.generate_key(type, bits)
690 self.assertEqual(key.type(), type)
691 self.assertEqual(key.bits(), bits)
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500692
693
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400694 def test_inconsistentKey(self):
695 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900696 :py:`PKeyType.check` returns :py:exc:`Error` if the key is not consistent.
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400697 """
698 key = load_privatekey(FILETYPE_PEM, inconsistentPrivateKeyPEM)
Jean-Paul Calderoned338e4e2009-05-13 15:45:07 -0400699 self.assertRaises(Error, key.check)
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400700
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500701
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400702 def test_check_wrong_args(self):
703 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900704 :py:meth:`PKeyType.check` raises :py:exc:`TypeError` if called with any arguments.
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400705 """
706 self.assertRaises(TypeError, PKey().check, None)
707 self.assertRaises(TypeError, PKey().check, object())
708 self.assertRaises(TypeError, PKey().check, 1)
709
710
Jean-Paul Calderone02d01972011-10-31 10:39:29 -0400711 def test_check_public_key(self):
712 """
713 :py:meth:`PKeyType.check` raises :py:exc:`TypeError` if only the public
714 part of the key is available.
715 """
716 # A trick to get a public-only key
717 key = PKey()
718 key.generate_key(TYPE_RSA, 512)
719 cert = X509()
720 cert.set_pubkey(key)
721 pub = cert.get_pubkey()
722 self.assertRaises(TypeError, pub.check)
723
724
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400725
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400726class X509NameTests(TestCase):
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500727 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900728 Unit tests for :py:class:`OpenSSL.crypto.X509Name`.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500729 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500730 def _x509name(self, **attrs):
731 # XXX There's no other way to get a new X509Name yet.
732 name = X509().get_subject()
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400733 attrs = list(attrs.items())
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500734 # Make the order stable - order matters!
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400735 def key(attr):
736 return attr[1]
737 attrs.sort(key=key)
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500738 for k, v in attrs:
739 setattr(name, k, v)
740 return name
741
742
Rick Deane15b1472009-07-09 15:53:42 -0500743 def test_type(self):
744 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900745 The type of X509Name objects is :py:class:`X509NameType`.
Rick Deane15b1472009-07-09 15:53:42 -0500746 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400747 self.assertIdentical(X509Name, X509NameType)
748 self.assertEqual(X509NameType.__name__, 'X509Name')
749 self.assertTrue(isinstance(X509NameType, type))
750
Rick Deane15b1472009-07-09 15:53:42 -0500751 name = self._x509name()
752 self.assertTrue(
753 isinstance(name, X509NameType),
754 "%r is of type %r, should be %r" % (
755 name, type(name), X509NameType))
Rick Deane15b1472009-07-09 15:53:42 -0500756
757
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400758 def test_onlyStringAttributes(self):
759 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900760 Attempting to set a non-:py:data:`str` attribute name on an :py:class:`X509NameType`
761 instance causes :py:exc:`TypeError` to be raised.
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400762 """
763 name = self._x509name()
764 # Beyond these cases, you may also think that unicode should be
765 # rejected. Sorry, you're wrong. unicode is automatically converted to
766 # str outside of the control of X509Name, so there's no way to reject
767 # it.
Jean-Paul Calderoneff363be2013-03-03 10:21:23 -0800768
769 # Also, this used to test str subclasses, but that test is less relevant
770 # now that the implementation is in Python instead of C. Also PyPy
771 # automatically converts str subclasses to str when they are passed to
772 # setattr, so we can't test it on PyPy. Apparently CPython does this
773 # sometimes as well.
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400774 self.assertRaises(TypeError, setattr, name, None, "hello")
775 self.assertRaises(TypeError, setattr, name, 30, "hello")
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400776
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -0500777
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400778 def test_setInvalidAttribute(self):
779 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900780 Attempting to set any attribute name on an :py:class:`X509NameType` instance for
781 which no corresponding NID is defined causes :py:exc:`AttributeError` to be
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400782 raised.
783 """
784 name = self._x509name()
785 self.assertRaises(AttributeError, setattr, name, "no such thing", None)
786
787
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500788 def test_attributes(self):
789 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900790 :py:class:`X509NameType` instances have attributes for each standard (?)
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500791 X509Name field.
792 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500793 name = self._x509name()
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500794 name.commonName = "foo"
795 self.assertEqual(name.commonName, "foo")
796 self.assertEqual(name.CN, "foo")
797 name.CN = "baz"
798 self.assertEqual(name.commonName, "baz")
799 self.assertEqual(name.CN, "baz")
800 name.commonName = "bar"
801 self.assertEqual(name.commonName, "bar")
802 self.assertEqual(name.CN, "bar")
803 name.CN = "quux"
804 self.assertEqual(name.commonName, "quux")
805 self.assertEqual(name.CN, "quux")
806
807
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500808 def test_copy(self):
809 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900810 :py:class:`X509Name` creates a new :py:class:`X509NameType` instance with all the same
811 attributes as an existing :py:class:`X509NameType` instance when called with
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500812 one.
813 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500814 name = self._x509name(commonName="foo", emailAddress="bar@example.com")
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500815
816 copy = X509Name(name)
817 self.assertEqual(copy.commonName, "foo")
818 self.assertEqual(copy.emailAddress, "bar@example.com")
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500819
820 # Mutate the copy and ensure the original is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500821 copy.commonName = "baz"
822 self.assertEqual(name.commonName, "foo")
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500823
824 # Mutate the original and ensure the copy is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500825 name.emailAddress = "quux@example.com"
826 self.assertEqual(copy.emailAddress, "bar@example.com")
827
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500828
829 def test_repr(self):
830 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900831 :py:func:`repr` passed an :py:class:`X509NameType` instance should return a string
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500832 containing a description of the type and the NIDs which have been set
833 on it.
834 """
835 name = self._x509name(commonName="foo", emailAddress="bar")
836 self.assertEqual(
837 repr(name),
838 "<X509Name object '/emailAddress=bar/CN=foo'>")
839
840
841 def test_comparison(self):
842 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900843 :py:class:`X509NameType` instances should compare based on their NIDs.
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500844 """
845 def _equality(a, b, assertTrue, assertFalse):
846 assertTrue(a == b, "(%r == %r) --> False" % (a, b))
847 assertFalse(a != b)
848 assertTrue(b == a)
849 assertFalse(b != a)
850
851 def assertEqual(a, b):
852 _equality(a, b, self.assertTrue, self.assertFalse)
853
854 # Instances compare equal to themselves.
855 name = self._x509name()
856 assertEqual(name, name)
857
858 # Empty instances should compare equal to each other.
859 assertEqual(self._x509name(), self._x509name())
860
861 # Instances with equal NIDs should compare equal to each other.
862 assertEqual(self._x509name(commonName="foo"),
863 self._x509name(commonName="foo"))
864
865 # Instance with equal NIDs set using different aliases should compare
866 # equal to each other.
867 assertEqual(self._x509name(commonName="foo"),
868 self._x509name(CN="foo"))
869
870 # Instances with more than one NID with the same values should compare
871 # equal to each other.
872 assertEqual(self._x509name(CN="foo", organizationalUnitName="bar"),
873 self._x509name(commonName="foo", OU="bar"))
874
875 def assertNotEqual(a, b):
876 _equality(a, b, self.assertFalse, self.assertTrue)
877
878 # Instances with different values for the same NID should not compare
879 # equal to each other.
880 assertNotEqual(self._x509name(CN="foo"),
881 self._x509name(CN="bar"))
882
883 # Instances with different NIDs should not compare equal to each other.
884 assertNotEqual(self._x509name(CN="foo"),
885 self._x509name(OU="foo"))
886
887 def _inequality(a, b, assertTrue, assertFalse):
888 assertTrue(a < b)
889 assertTrue(a <= b)
890 assertTrue(b > a)
891 assertTrue(b >= a)
892 assertFalse(a > b)
893 assertFalse(a >= b)
894 assertFalse(b < a)
895 assertFalse(b <= a)
896
897 def assertLessThan(a, b):
898 _inequality(a, b, self.assertTrue, self.assertFalse)
899
900 # An X509Name with a NID with a value which sorts less than the value
901 # of the same NID on another X509Name compares less than the other
902 # X509Name.
903 assertLessThan(self._x509name(CN="abc"),
904 self._x509name(CN="def"))
905
906 def assertGreaterThan(a, b):
907 _inequality(a, b, self.assertFalse, self.assertTrue)
908
909 # An X509Name with a NID with a value which sorts greater than the
910 # value of the same NID on another X509Name compares greater than the
911 # other X509Name.
912 assertGreaterThan(self._x509name(CN="def"),
913 self._x509name(CN="abc"))
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -0500914
915
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400916 def test_hash(self):
917 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900918 :py:meth:`X509Name.hash` returns an integer hash based on the value of the
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400919 name.
920 """
921 a = self._x509name(CN="foo")
922 b = self._x509name(CN="foo")
923 self.assertEqual(a.hash(), b.hash())
924 a.CN = "bar"
925 self.assertNotEqual(a.hash(), b.hash())
926
927
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400928 def test_der(self):
929 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900930 :py:meth:`X509Name.der` returns the DER encoded form of the name.
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400931 """
932 a = self._x509name(CN="foo", C="US")
933 self.assertEqual(
934 a.der(),
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -0400935 b('0\x1b1\x0b0\t\x06\x03U\x04\x06\x13\x02US'
936 '1\x0c0\n\x06\x03U\x04\x03\x13\x03foo'))
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400937
938
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400939 def test_get_components(self):
940 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900941 :py:meth:`X509Name.get_components` returns a :py:data:`list` of
942 two-tuples of :py:data:`str`
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400943 giving the NIDs and associated values which make up the name.
944 """
945 a = self._x509name()
946 self.assertEqual(a.get_components(), [])
947 a.CN = "foo"
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -0400948 self.assertEqual(a.get_components(), [(b("CN"), b("foo"))])
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400949 a.organizationalUnitName = "bar"
950 self.assertEqual(
951 a.get_components(),
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -0400952 [(b("CN"), b("foo")), (b("OU"), b("bar"))])
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400953
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400954
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400955 def test_load_nul_byte_attribute(self):
956 """
Jean-Paul Calderone9af07b02013-08-23 16:07:31 -0400957 An :py:class:`OpenSSL.crypto.X509Name` from an
958 :py:class:`OpenSSL.crypto.X509` instance loaded from a file can have a
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400959 NUL byte in the value of one of its attributes.
960 """
961 cert = load_certificate(FILETYPE_PEM, nulbyteSubjectAltNamePEM)
962 subject = cert.get_subject()
963 self.assertEqual(
Jean-Paul Calderone06754fc2013-08-23 15:47:47 -0400964 "null.python.org\x00example.org", subject.commonName)
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400965
966
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -0500967 def test_setAttributeFailure(self):
968 """
969 If the value of an attribute cannot be set for some reason then
970 :py:class:`OpenSSL.crypto.Error` is raised.
971 """
972 name = self._x509name()
973 # This value is too long
974 self.assertRaises(Error, setattr, name, "O", b"x" * 512)
975
976
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400977
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400978class _PKeyInteractionTestsMixin:
979 """
980 Tests which involve another thing and a PKey.
981 """
982 def signable(self):
983 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900984 Return something with a :py:meth:`set_pubkey`, :py:meth:`set_pubkey`,
985 and :py:meth:`sign` method.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400986 """
987 raise NotImplementedError()
988
989
990 def test_signWithUngenerated(self):
991 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900992 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when pass a
993 :py:class:`PKey` with no parts.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400994 """
995 request = self.signable()
996 key = PKey()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500997 self.assertRaises(ValueError, request.sign, key, GOOD_DIGEST)
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400998
999
1000 def test_signWithPublicKey(self):
1001 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001002 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when pass a
1003 :py:class:`PKey` with no private part as the signing key.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001004 """
1005 request = self.signable()
1006 key = PKey()
1007 key.generate_key(TYPE_RSA, 512)
1008 request.set_pubkey(key)
1009 pub = request.get_pubkey()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001010 self.assertRaises(ValueError, request.sign, pub, GOOD_DIGEST)
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001011
1012
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -04001013 def test_signWithUnknownDigest(self):
1014 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001015 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when passed a digest name which is
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -04001016 not known.
1017 """
1018 request = self.signable()
1019 key = PKey()
1020 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001021 self.assertRaises(ValueError, request.sign, key, BAD_DIGEST)
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -04001022
1023
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04001024 def test_sign(self):
1025 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001026 :py:meth:`X509Req.sign` succeeds when passed a private key object and a valid
1027 digest function. :py:meth:`X509Req.verify` can be used to check the signature.
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04001028 """
1029 request = self.signable()
1030 key = PKey()
1031 key.generate_key(TYPE_RSA, 512)
1032 request.set_pubkey(key)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001033 request.sign(key, GOOD_DIGEST)
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04001034 # If the type has a verify method, cover that too.
1035 if getattr(request, 'verify', None) is not None:
1036 pub = request.get_pubkey()
1037 self.assertTrue(request.verify(pub))
1038 # Make another key that won't verify.
1039 key = PKey()
1040 key.generate_key(TYPE_RSA, 512)
1041 self.assertRaises(Error, request.verify, key)
1042
1043
1044
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001045
Jean-Paul Calderone18808652009-07-05 12:54:05 -04001046class X509ReqTests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001047 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001048 Tests for :py:class:`OpenSSL.crypto.X509Req`.
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001049 """
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001050 def signable(self):
1051 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001052 Create and return a new :py:class:`X509Req`.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001053 """
1054 return X509Req()
1055
1056
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001057 def test_type(self):
1058 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001059 :py:obj:`X509Req` and :py:obj:`X509ReqType` refer to the same type object and can be
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001060 used to create instances of that type.
1061 """
1062 self.assertIdentical(X509Req, X509ReqType)
1063 self.assertConsistentType(X509Req, 'X509Req')
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001064
1065
1066 def test_construction(self):
1067 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001068 :py:obj:`X509Req` takes no arguments and returns an :py:obj:`X509ReqType` instance.
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001069 """
1070 request = X509Req()
1071 self.assertTrue(
1072 isinstance(request, X509ReqType),
1073 "%r is of type %r, should be %r" % (request, type(request), X509ReqType))
1074
1075
Jean-Paul Calderone8dd19b82008-12-28 20:41:16 -05001076 def test_version(self):
1077 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001078 :py:obj:`X509ReqType.set_version` sets the X.509 version of the certificate
1079 request. :py:obj:`X509ReqType.get_version` returns the X.509 version of
Jean-Paul Calderone8dd19b82008-12-28 20:41:16 -05001080 the certificate request. The initial value of the version is 0.
1081 """
1082 request = X509Req()
1083 self.assertEqual(request.get_version(), 0)
1084 request.set_version(1)
1085 self.assertEqual(request.get_version(), 1)
1086 request.set_version(3)
1087 self.assertEqual(request.get_version(), 3)
1088
1089
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001090 def test_version_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001091 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001092 :py:obj:`X509ReqType.set_version` raises :py:obj:`TypeError` if called with the wrong
1093 number of arguments or with a non-:py:obj:`int` argument.
1094 :py:obj:`X509ReqType.get_version` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001095 arguments.
1096 """
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001097 request = X509Req()
1098 self.assertRaises(TypeError, request.set_version)
1099 self.assertRaises(TypeError, request.set_version, "foo")
1100 self.assertRaises(TypeError, request.set_version, 1, 2)
1101 self.assertRaises(TypeError, request.get_version, None)
1102
1103
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001104 def test_get_subject(self):
1105 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001106 :py:obj:`X509ReqType.get_subject` returns an :py:obj:`X509Name` for the subject of
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001107 the request and which is valid even after the request object is
1108 otherwise dead.
1109 """
1110 request = X509Req()
1111 subject = request.get_subject()
1112 self.assertTrue(
1113 isinstance(subject, X509NameType),
1114 "%r is of type %r, should be %r" % (subject, type(subject), X509NameType))
1115 subject.commonName = "foo"
1116 self.assertEqual(request.get_subject().commonName, "foo")
1117 del request
1118 subject.commonName = "bar"
1119 self.assertEqual(subject.commonName, "bar")
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001120
1121
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001122 def test_get_subject_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001123 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001124 :py:obj:`X509ReqType.get_subject` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001125 arguments.
1126 """
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001127 request = X509Req()
1128 self.assertRaises(TypeError, request.get_subject, None)
1129
1130
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001131 def test_add_extensions(self):
1132 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001133 :py:obj:`X509Req.add_extensions` accepts a :py:obj:`list` of :py:obj:`X509Extension`
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001134 instances and adds them to the X509 request.
1135 """
1136 request = X509Req()
1137 request.add_extensions([
Jean-Paul Calderonee16f9f32010-08-22 19:20:37 -04001138 X509Extension(b('basicConstraints'), True, b('CA:false'))])
Stephen Holsappleca545b72014-01-28 21:43:25 -08001139 exts = request.get_extensions()
Stephen Holsapple7fbdf642014-03-01 20:05:47 -08001140 self.assertEqual(len(exts), 1)
1141 self.assertEqual(exts[0].get_short_name(), b('basicConstraints'))
1142 self.assertEqual(exts[0].get_critical(), 1)
1143 self.assertEqual(exts[0].get_data(), b('0\x00'))
1144
1145
1146 def test_get_extensions(self):
1147 """
1148 :py:obj:`X509Req.get_extensions` returns a :py:obj:`list` of
1149 extensions added to this X509 request.
1150 """
1151 request = X509Req()
1152 exts = request.get_extensions()
1153 self.assertEqual(exts, [])
1154 request.add_extensions([
1155 X509Extension(b('basicConstraints'), True, b('CA:true')),
1156 X509Extension(b('keyUsage'), False, b('digitalSignature'))])
1157 exts = request.get_extensions()
1158 self.assertEqual(len(exts), 2)
1159 self.assertEqual(exts[0].get_short_name(), b('basicConstraints'))
1160 self.assertEqual(exts[0].get_critical(), 1)
1161 self.assertEqual(exts[0].get_data(), b('0\x03\x01\x01\xff'))
1162 self.assertEqual(exts[1].get_short_name(), b('keyUsage'))
1163 self.assertEqual(exts[1].get_critical(), 0)
1164 self.assertEqual(exts[1].get_data(), b('\x03\x02\x07\x80'))
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001165
1166
1167 def test_add_extensions_wrong_args(self):
1168 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001169 :py:obj:`X509Req.add_extensions` raises :py:obj:`TypeError` if called with the wrong
1170 number of arguments or with a non-:py:obj:`list`. Or it raises :py:obj:`ValueError`
1171 if called with a :py:obj:`list` containing objects other than :py:obj:`X509Extension`
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001172 instances.
1173 """
1174 request = X509Req()
1175 self.assertRaises(TypeError, request.add_extensions)
1176 self.assertRaises(TypeError, request.add_extensions, object())
1177 self.assertRaises(ValueError, request.add_extensions, [object()])
1178 self.assertRaises(TypeError, request.add_extensions, [], None)
1179
1180
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001181 def test_verify_wrong_args(self):
1182 """
1183 :py:obj:`X509Req.verify` raises :py:obj:`TypeError` if called with zero
1184 arguments or more than one argument or if passed anything other than a
1185 :py:obj:`PKey` instance as its single argument.
1186 """
1187 request = X509Req()
1188 self.assertRaises(TypeError, request.verify)
1189 self.assertRaises(TypeError, request.verify, object())
1190 self.assertRaises(TypeError, request.verify, PKey(), object())
1191
1192
1193 def test_verify_uninitialized_key(self):
1194 """
1195 :py:obj:`X509Req.verify` raises :py:obj:`OpenSSL.crypto.Error` if called
1196 with a :py:obj:`OpenSSL.crypto.PKey` which contains no key data.
1197 """
1198 request = X509Req()
1199 pkey = PKey()
1200 self.assertRaises(Error, request.verify, pkey)
1201
1202
1203 def test_verify_wrong_key(self):
1204 """
1205 :py:obj:`X509Req.verify` raises :py:obj:`OpenSSL.crypto.Error` if called
1206 with a :py:obj:`OpenSSL.crypto.PKey` which does not represent the public
1207 part of the key which signed the request.
1208 """
1209 request = X509Req()
1210 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001211 request.sign(pkey, GOOD_DIGEST)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001212 another_pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
1213 self.assertRaises(Error, request.verify, another_pkey)
1214
1215
1216 def test_verify_success(self):
1217 """
1218 :py:obj:`X509Req.verify` returns :py:obj:`True` if called with a
Alex Gaynor3b0ee972014-11-15 09:17:33 -08001219 :py:obj:`OpenSSL.crypto.PKey` which represents the public part of the key
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001220 which signed the request.
1221 """
1222 request = X509Req()
1223 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001224 request.sign(pkey, GOOD_DIGEST)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001225 self.assertEqual(True, request.verify(pkey))
1226
1227
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001228
Jean-Paul Calderone18808652009-07-05 12:54:05 -04001229class X509Tests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001230 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001231 Tests for :py:obj:`OpenSSL.crypto.X509`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001232 """
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001233 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
Jean-Paul Calderone8114b452008-03-25 15:27:59 -04001234
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001235 extpem = """
1236-----BEGIN CERTIFICATE-----
1237MIIC3jCCAkegAwIBAgIJAJHFjlcCgnQzMA0GCSqGSIb3DQEBBQUAMEcxCzAJBgNV
1238BAYTAlNFMRUwEwYDVQQIEwxXZXN0ZXJib3R0b20xEjAQBgNVBAoTCUNhdGFsb2dp
1239eDENMAsGA1UEAxMEUm9vdDAeFw0wODA0MjIxNDQ1MzhaFw0wOTA0MjIxNDQ1Mzha
1240MFQxCzAJBgNVBAYTAlNFMQswCQYDVQQIEwJXQjEUMBIGA1UEChMLT3Blbk1ldGFk
1241aXIxIjAgBgNVBAMTGW5vZGUxLm9tMi5vcGVubWV0YWRpci5vcmcwgZ8wDQYJKoZI
1242hvcNAQEBBQADgY0AMIGJAoGBAPIcQMrwbk2nESF/0JKibj9i1x95XYAOwP+LarwT
1243Op4EQbdlI9SY+uqYqlERhF19w7CS+S6oyqx0DRZSk4Y9dZ9j9/xgm2u/f136YS1u
1244zgYFPvfUs6PqYLPSM8Bw+SjJ+7+2+TN+Tkiof9WP1cMjodQwOmdsiRbR0/J7+b1B
1245hec1AgMBAAGjgcQwgcEwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNT
1246TCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFIdHsBcMVVMbAO7j6NCj
124703HgLnHaMB8GA1UdIwQYMBaAFL2h9Bf9Mre4vTdOiHTGAt7BRY/8MEYGA1UdEQQ/
1248MD2CDSouZXhhbXBsZS5vcmeCESoub20yLmV4bWFwbGUuY29thwSC7wgKgRNvbTJA
1249b3Blbm1ldGFkaXIub3JnMA0GCSqGSIb3DQEBBQUAA4GBALd7WdXkp2KvZ7/PuWZA
1250MPlIxyjS+Ly11+BNE0xGQRp9Wz+2lABtpgNqssvU156+HkKd02rGheb2tj7MX9hG
1251uZzbwDAZzJPjzDQDD7d3cWsrVcfIdqVU7epHqIadnOF+X0ghJ39pAm6VVadnSXCt
1252WpOdIpB8KksUTCzV591Nr1wd
1253-----END CERTIFICATE-----
1254 """
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001255 def signable(self):
1256 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001257 Create and return a new :py:obj:`X509`.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001258 """
1259 return X509()
1260
1261
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001262 def test_type(self):
1263 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001264 :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 -04001265 to create instances of that type.
1266 """
1267 self.assertIdentical(X509, X509Type)
1268 self.assertConsistentType(X509, 'X509')
1269
1270
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001271 def test_construction(self):
1272 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001273 :py:obj:`X509` takes no arguments and returns an instance of :py:obj:`X509Type`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001274 """
1275 certificate = X509()
1276 self.assertTrue(
1277 isinstance(certificate, X509Type),
1278 "%r is of type %r, should be %r" % (certificate,
1279 type(certificate),
1280 X509Type))
Rick Deane15b1472009-07-09 15:53:42 -05001281 self.assertEqual(type(X509Type).__name__, 'type')
1282 self.assertEqual(type(certificate).__name__, 'X509')
1283 self.assertEqual(type(certificate), X509Type)
Rick Dean04113e72009-07-16 12:06:35 -05001284 self.assertEqual(type(certificate), X509)
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001285
1286
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001287 def test_get_version_wrong_args(self):
1288 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001289 :py:obj:`X509.get_version` raises :py:obj:`TypeError` if invoked with any arguments.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001290 """
1291 cert = X509()
1292 self.assertRaises(TypeError, cert.get_version, None)
1293
1294
1295 def test_set_version_wrong_args(self):
1296 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001297 :py:obj:`X509.set_version` raises :py:obj:`TypeError` if invoked with the wrong number
1298 of arguments or an argument not of type :py:obj:`int`.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001299 """
1300 cert = X509()
1301 self.assertRaises(TypeError, cert.set_version)
1302 self.assertRaises(TypeError, cert.set_version, None)
1303 self.assertRaises(TypeError, cert.set_version, 1, None)
1304
1305
1306 def test_version(self):
1307 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001308 :py:obj:`X509.set_version` sets the certificate version number.
1309 :py:obj:`X509.get_version` retrieves it.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001310 """
1311 cert = X509()
1312 cert.set_version(1234)
1313 self.assertEquals(cert.get_version(), 1234)
1314
1315
1316 def test_get_serial_number_wrong_args(self):
1317 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001318 :py:obj:`X509.get_serial_number` raises :py:obj:`TypeError` if invoked with any
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001319 arguments.
1320 """
1321 cert = X509()
1322 self.assertRaises(TypeError, cert.get_serial_number, None)
1323
1324
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001325 def test_serial_number(self):
1326 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001327 The serial number of an :py:obj:`X509Type` can be retrieved and modified with
1328 :py:obj:`X509Type.get_serial_number` and :py:obj:`X509Type.set_serial_number`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001329 """
1330 certificate = X509()
1331 self.assertRaises(TypeError, certificate.set_serial_number)
1332 self.assertRaises(TypeError, certificate.set_serial_number, 1, 2)
1333 self.assertRaises(TypeError, certificate.set_serial_number, "1")
1334 self.assertRaises(TypeError, certificate.set_serial_number, 5.5)
1335 self.assertEqual(certificate.get_serial_number(), 0)
1336 certificate.set_serial_number(1)
1337 self.assertEqual(certificate.get_serial_number(), 1)
1338 certificate.set_serial_number(2 ** 32 + 1)
1339 self.assertEqual(certificate.get_serial_number(), 2 ** 32 + 1)
1340 certificate.set_serial_number(2 ** 64 + 1)
1341 self.assertEqual(certificate.get_serial_number(), 2 ** 64 + 1)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001342 certificate.set_serial_number(2 ** 128 + 1)
1343 self.assertEqual(certificate.get_serial_number(), 2 ** 128 + 1)
1344
1345
1346 def _setBoundTest(self, which):
1347 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001348 :py:obj:`X509Type.set_notBefore` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001349 GENERALIZEDTIME and sets the beginning of the certificate's validity
1350 period to it.
1351 """
1352 certificate = X509()
1353 set = getattr(certificate, 'set_not' + which)
1354 get = getattr(certificate, 'get_not' + which)
1355
Jean-Paul Calderonee0615b52008-03-09 21:44:46 -04001356 # Starts with no value.
1357 self.assertEqual(get(), None)
1358
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001359 # GMT (Or is it UTC?) -exarkun
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001360 when = b("20040203040506Z")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001361 set(when)
1362 self.assertEqual(get(), when)
1363
1364 # A plus two hours and thirty minutes offset
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001365 when = b("20040203040506+0530")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001366 set(when)
1367 self.assertEqual(get(), when)
1368
1369 # A minus one hour fifteen minutes offset
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001370 when = b("20040203040506-0115")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001371 set(when)
1372 self.assertEqual(get(), when)
1373
1374 # An invalid string results in a ValueError
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001375 self.assertRaises(ValueError, set, b("foo bar"))
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001376
Jean-Paul Calderone31ca2002010-01-30 15:14:43 -05001377 # The wrong number of arguments results in a TypeError.
1378 self.assertRaises(TypeError, set)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001379 self.assertRaises(TypeError, set, b("20040203040506Z"), b("20040203040506Z"))
1380 self.assertRaises(TypeError, get, b("foo bar"))
1381
Jean-Paul Calderone31ca2002010-01-30 15:14:43 -05001382
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001383 # XXX ASN1_TIME (not GENERALIZEDTIME)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001384
1385 def test_set_notBefore(self):
1386 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001387 :py:obj:`X509Type.set_notBefore` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001388 GENERALIZEDTIME and sets the beginning of the certificate's validity
1389 period to it.
1390 """
1391 self._setBoundTest("Before")
1392
1393
1394 def test_set_notAfter(self):
1395 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001396 :py:obj:`X509Type.set_notAfter` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001397 GENERALIZEDTIME and sets the end of the certificate's validity period
1398 to it.
1399 """
1400 self._setBoundTest("After")
Jean-Paul Calderone76576d52008-03-24 16:04:46 -04001401
1402
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001403 def test_get_notBefore(self):
1404 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001405 :py:obj:`X509Type.get_notBefore` returns a string in the format of an ASN1
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001406 GENERALIZEDTIME even for certificates which store it as UTCTIME
1407 internally.
1408 """
Jean-Paul Calderone8114b452008-03-25 15:27:59 -04001409 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001410 self.assertEqual(cert.get_notBefore(), b("20090325123658Z"))
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001411
Rick Dean38a05c82009-07-18 01:41:30 -05001412
1413 def test_get_notAfter(self):
1414 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001415 :py:obj:`X509Type.get_notAfter` returns a string in the format of an ASN1
Rick Dean38a05c82009-07-18 01:41:30 -05001416 GENERALIZEDTIME even for certificates which store it as UTCTIME
1417 internally.
1418 """
1419 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001420 self.assertEqual(cert.get_notAfter(), b("20170611123658Z"))
Rick Dean38a05c82009-07-18 01:41:30 -05001421
1422
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001423 def test_gmtime_adj_notBefore_wrong_args(self):
1424 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001425 :py:obj:`X509Type.gmtime_adj_notBefore` raises :py:obj:`TypeError` if called with the
1426 wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001427 """
1428 cert = X509()
1429 self.assertRaises(TypeError, cert.gmtime_adj_notBefore)
1430 self.assertRaises(TypeError, cert.gmtime_adj_notBefore, None)
1431 self.assertRaises(TypeError, cert.gmtime_adj_notBefore, 123, None)
1432
1433
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001434 def test_gmtime_adj_notBefore(self):
1435 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001436 :py:obj:`X509Type.gmtime_adj_notBefore` changes the not-before timestamp to be
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001437 the current time plus the number of seconds passed in.
1438 """
1439 cert = load_certificate(FILETYPE_PEM, self.pemData)
1440 now = datetime.utcnow() + timedelta(seconds=100)
1441 cert.gmtime_adj_notBefore(100)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001442 self.assertEqual(cert.get_notBefore(), b(now.strftime("%Y%m%d%H%M%SZ")))
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001443
1444
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001445 def test_gmtime_adj_notAfter_wrong_args(self):
1446 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001447 :py:obj:`X509Type.gmtime_adj_notAfter` raises :py:obj:`TypeError` if called with the
1448 wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001449 """
1450 cert = X509()
1451 self.assertRaises(TypeError, cert.gmtime_adj_notAfter)
1452 self.assertRaises(TypeError, cert.gmtime_adj_notAfter, None)
1453 self.assertRaises(TypeError, cert.gmtime_adj_notAfter, 123, None)
1454
1455
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001456 def test_gmtime_adj_notAfter(self):
1457 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001458 :py:obj:`X509Type.gmtime_adj_notAfter` changes the not-after timestamp to be
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001459 the current time plus the number of seconds passed in.
1460 """
1461 cert = load_certificate(FILETYPE_PEM, self.pemData)
1462 now = datetime.utcnow() + timedelta(seconds=100)
1463 cert.gmtime_adj_notAfter(100)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001464 self.assertEqual(cert.get_notAfter(), b(now.strftime("%Y%m%d%H%M%SZ")))
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001465
1466
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001467 def test_has_expired_wrong_args(self):
1468 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001469 :py:obj:`X509Type.has_expired` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001470 arguments.
1471 """
1472 cert = X509()
1473 self.assertRaises(TypeError, cert.has_expired, None)
1474
1475
1476 def test_has_expired(self):
1477 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001478 :py:obj:`X509Type.has_expired` returns :py:obj:`True` if the certificate's not-after
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001479 time is in the past.
1480 """
1481 cert = X509()
1482 cert.gmtime_adj_notAfter(-1)
1483 self.assertTrue(cert.has_expired())
1484
1485
1486 def test_has_not_expired(self):
1487 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001488 :py:obj:`X509Type.has_expired` returns :py:obj:`False` if the certificate's not-after
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001489 time is in the future.
1490 """
1491 cert = X509()
1492 cert.gmtime_adj_notAfter(2)
1493 self.assertFalse(cert.has_expired())
1494
1495
Rick Dean38a05c82009-07-18 01:41:30 -05001496 def test_digest(self):
1497 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001498 :py:obj:`X509.digest` returns a string giving ":"-separated hex-encoded words
Rick Dean38a05c82009-07-18 01:41:30 -05001499 of the digest of the certificate.
1500 """
1501 cert = X509()
1502 self.assertEqual(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001503 # This is MD5 instead of GOOD_DIGEST because the digest algorithm
1504 # actually matters to the assertion (ie, another arbitrary, good
1505 # digest will not product the same digest).
1506 cert.digest("MD5"),
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001507 b("A8:EB:07:F8:53:25:0A:F2:56:05:C5:A5:C4:C4:C7:15"))
Rick Dean38a05c82009-07-18 01:41:30 -05001508
1509
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001510 def _extcert(self, pkey, extensions):
1511 cert = X509()
1512 cert.set_pubkey(pkey)
1513 cert.get_subject().commonName = "Unit Tests"
1514 cert.get_issuer().commonName = "Unit Tests"
1515 when = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
1516 cert.set_notBefore(when)
1517 cert.set_notAfter(when)
1518
1519 cert.add_extensions(extensions)
1520 return load_certificate(
1521 FILETYPE_PEM, dump_certificate(FILETYPE_PEM, cert))
1522
1523
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001524 def test_extension_count(self):
1525 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001526 :py:obj:`X509.get_extension_count` returns the number of extensions that are
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001527 present in the certificate.
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001528 """
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001529 pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001530 ca = X509Extension(b('basicConstraints'), True, b('CA:FALSE'))
1531 key = X509Extension(b('keyUsage'), True, b('digitalSignature'))
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001532 subjectAltName = X509Extension(
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001533 b('subjectAltName'), True, b('DNS:example.com'))
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001534
1535 # Try a certificate with no extensions at all.
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001536 c = self._extcert(pkey, [])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001537 self.assertEqual(c.get_extension_count(), 0)
1538
1539 # And a certificate with one
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001540 c = self._extcert(pkey, [ca])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001541 self.assertEqual(c.get_extension_count(), 1)
1542
1543 # And a certificate with several
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001544 c = self._extcert(pkey, [ca, key, subjectAltName])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001545 self.assertEqual(c.get_extension_count(), 3)
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001546
1547
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001548 def test_get_extension(self):
1549 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001550 :py:obj:`X509.get_extension` takes an integer and returns an :py:obj:`X509Extension`
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001551 corresponding to the extension at that index.
1552 """
1553 pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001554 ca = X509Extension(b('basicConstraints'), True, b('CA:FALSE'))
1555 key = X509Extension(b('keyUsage'), True, b('digitalSignature'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001556 subjectAltName = X509Extension(
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001557 b('subjectAltName'), False, b('DNS:example.com'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001558
1559 cert = self._extcert(pkey, [ca, key, subjectAltName])
1560
1561 ext = cert.get_extension(0)
1562 self.assertTrue(isinstance(ext, X509Extension))
1563 self.assertTrue(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001564 self.assertEqual(ext.get_short_name(), b('basicConstraints'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001565
1566 ext = cert.get_extension(1)
1567 self.assertTrue(isinstance(ext, X509Extension))
1568 self.assertTrue(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001569 self.assertEqual(ext.get_short_name(), b('keyUsage'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001570
1571 ext = cert.get_extension(2)
1572 self.assertTrue(isinstance(ext, X509Extension))
1573 self.assertFalse(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001574 self.assertEqual(ext.get_short_name(), b('subjectAltName'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001575
1576 self.assertRaises(IndexError, cert.get_extension, -1)
1577 self.assertRaises(IndexError, cert.get_extension, 4)
1578 self.assertRaises(TypeError, cert.get_extension, "hello")
1579
1580
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001581 def test_nullbyte_subjectAltName(self):
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001582 """
Jean-Paul Calderone9af07b02013-08-23 16:07:31 -04001583 The fields of a `subjectAltName` extension on an X509 may contain NUL
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001584 bytes and this value is reflected in the string representation of the
1585 extension object.
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001586 """
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001587 cert = load_certificate(FILETYPE_PEM, nulbyteSubjectAltNamePEM)
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001588
1589 ext = cert.get_extension(3)
1590 self.assertEqual(ext.get_short_name(), b('subjectAltName'))
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001591 self.assertEqual(
1592 b("DNS:altnull.python.org\x00example.com, "
1593 "email:null@python.org\x00user@example.org, "
1594 "URI:http://null.python.org\x00http://example.org, "
1595 "IP Address:192.0.2.1, IP Address:2001:DB8:0:0:0:0:0:1\n"),
1596 b(str(ext)))
1597
Rick Dean38a05c82009-07-18 01:41:30 -05001598
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001599 def test_invalid_digest_algorithm(self):
1600 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001601 :py:obj:`X509.digest` raises :py:obj:`ValueError` if called with an unrecognized hash
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001602 algorithm.
1603 """
1604 cert = X509()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001605 self.assertRaises(ValueError, cert.digest, BAD_DIGEST)
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001606
1607
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001608 def test_get_subject_wrong_args(self):
1609 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001610 :py:obj:`X509.get_subject` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001611 """
1612 cert = X509()
1613 self.assertRaises(TypeError, cert.get_subject, None)
1614
1615
1616 def test_get_subject(self):
1617 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001618 :py:obj:`X509.get_subject` returns an :py:obj:`X509Name` instance.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001619 """
1620 cert = load_certificate(FILETYPE_PEM, self.pemData)
1621 subj = cert.get_subject()
1622 self.assertTrue(isinstance(subj, X509Name))
1623 self.assertEquals(
1624 subj.get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001625 [(b('C'), b('US')), (b('ST'), b('IL')), (b('L'), b('Chicago')),
1626 (b('O'), b('Testing')), (b('CN'), b('Testing Root CA'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001627
1628
1629 def test_set_subject_wrong_args(self):
1630 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001631 :py:obj:`X509.set_subject` raises a :py:obj:`TypeError` if called with the wrong
1632 number of arguments or an argument not of type :py:obj:`X509Name`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001633 """
1634 cert = X509()
1635 self.assertRaises(TypeError, cert.set_subject)
1636 self.assertRaises(TypeError, cert.set_subject, None)
1637 self.assertRaises(TypeError, cert.set_subject, cert.get_subject(), None)
1638
1639
1640 def test_set_subject(self):
1641 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001642 :py:obj:`X509.set_subject` changes the subject of the certificate to the one
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001643 passed in.
1644 """
1645 cert = X509()
1646 name = cert.get_subject()
1647 name.C = 'AU'
1648 name.O = 'Unit Tests'
1649 cert.set_subject(name)
1650 self.assertEquals(
1651 cert.get_subject().get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001652 [(b('C'), b('AU')), (b('O'), b('Unit Tests'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001653
1654
1655 def test_get_issuer_wrong_args(self):
1656 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001657 :py:obj:`X509.get_issuer` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001658 """
1659 cert = X509()
1660 self.assertRaises(TypeError, cert.get_issuer, None)
1661
1662
1663 def test_get_issuer(self):
1664 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001665 :py:obj:`X509.get_issuer` returns an :py:obj:`X509Name` instance.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001666 """
1667 cert = load_certificate(FILETYPE_PEM, self.pemData)
1668 subj = cert.get_issuer()
1669 self.assertTrue(isinstance(subj, X509Name))
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001670 comp = subj.get_components()
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001671 self.assertEquals(
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001672 comp,
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001673 [(b('C'), b('US')), (b('ST'), b('IL')), (b('L'), b('Chicago')),
1674 (b('O'), b('Testing')), (b('CN'), b('Testing Root CA'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001675
1676
1677 def test_set_issuer_wrong_args(self):
1678 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001679 :py:obj:`X509.set_issuer` raises a :py:obj:`TypeError` if called with the wrong
1680 number of arguments or an argument not of type :py:obj:`X509Name`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001681 """
1682 cert = X509()
1683 self.assertRaises(TypeError, cert.set_issuer)
1684 self.assertRaises(TypeError, cert.set_issuer, None)
1685 self.assertRaises(TypeError, cert.set_issuer, cert.get_issuer(), None)
1686
1687
1688 def test_set_issuer(self):
1689 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001690 :py:obj:`X509.set_issuer` changes the issuer of the certificate to the one
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001691 passed in.
1692 """
1693 cert = X509()
1694 name = cert.get_issuer()
1695 name.C = 'AU'
1696 name.O = 'Unit Tests'
1697 cert.set_issuer(name)
1698 self.assertEquals(
1699 cert.get_issuer().get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001700 [(b('C'), b('AU')), (b('O'), b('Unit Tests'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001701
1702
1703 def test_get_pubkey_uninitialized(self):
1704 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001705 When called on a certificate with no public key, :py:obj:`X509.get_pubkey`
1706 raises :py:obj:`OpenSSL.crypto.Error`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001707 """
1708 cert = X509()
1709 self.assertRaises(Error, cert.get_pubkey)
1710
1711
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001712 def test_subject_name_hash_wrong_args(self):
1713 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001714 :py:obj:`X509.subject_name_hash` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001715 arguments.
1716 """
1717 cert = X509()
1718 self.assertRaises(TypeError, cert.subject_name_hash, None)
1719
1720
1721 def test_subject_name_hash(self):
1722 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001723 :py:obj:`X509.subject_name_hash` returns the hash of the certificate's subject
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001724 name.
1725 """
1726 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -04001727 self.assertIn(
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001728 cert.subject_name_hash(),
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -04001729 [3350047874, # OpenSSL 0.9.8, MD5
1730 3278919224, # OpenSSL 1.0.0, SHA1
1731 ])
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001732
1733
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001734 def test_get_signature_algorithm(self):
1735 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001736 :py:obj:`X509Type.get_signature_algorithm` returns a string which means
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001737 the algorithm used to sign the certificate.
1738 """
1739 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001740 self.assertEqual(
1741 b("sha1WithRSAEncryption"), cert.get_signature_algorithm())
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001742
1743
1744 def test_get_undefined_signature_algorithm(self):
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001745 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001746 :py:obj:`X509Type.get_signature_algorithm` raises :py:obj:`ValueError` if the
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001747 signature algorithm is undefined or unknown.
1748 """
1749 # This certificate has been modified to indicate a bogus OID in the
1750 # signature algorithm field so that OpenSSL does not recognize it.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001751 certPEM = b("""\
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001752-----BEGIN CERTIFICATE-----
1753MIIC/zCCAmigAwIBAgIBATAGBgJ8BQUAMHsxCzAJBgNVBAYTAlNHMREwDwYDVQQK
1754EwhNMkNyeXB0bzEUMBIGA1UECxMLTTJDcnlwdG8gQ0ExJDAiBgNVBAMTG00yQ3J5
1755cHRvIENlcnRpZmljYXRlIE1hc3RlcjEdMBsGCSqGSIb3DQEJARYObmdwc0Bwb3N0
1756MS5jb20wHhcNMDAwOTEwMDk1MTMwWhcNMDIwOTEwMDk1MTMwWjBTMQswCQYDVQQG
1757EwJTRzERMA8GA1UEChMITTJDcnlwdG8xEjAQBgNVBAMTCWxvY2FsaG9zdDEdMBsG
1758CSqGSIb3DQEJARYObmdwc0Bwb3N0MS5jb20wXDANBgkqhkiG9w0BAQEFAANLADBI
1759AkEArL57d26W9fNXvOhNlZzlPOACmvwOZ5AdNgLzJ1/MfsQQJ7hHVeHmTAjM664V
1760+fXvwUGJLziCeBo1ysWLRnl8CQIDAQABo4IBBDCCAQAwCQYDVR0TBAIwADAsBglg
1761hkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0O
1762BBYEFM+EgpK+eyZiwFU1aOPSbczbPSpVMIGlBgNVHSMEgZ0wgZqAFPuHI2nrnDqT
1763FeXFvylRT/7tKDgBoX+kfTB7MQswCQYDVQQGEwJTRzERMA8GA1UEChMITTJDcnlw
1764dG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtNMkNyeXB0byBDZXJ0
1765aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tggEA
1766MA0GCSqGSIb3DQEBBAUAA4GBADv8KpPo+gfJxN2ERK1Y1l17sz/ZhzoGgm5XCdbx
1767jEY7xKfpQngV599k1xhl11IMqizDwu0855agrckg2MCTmOI9DZzDD77tAYb+Dk0O
1768PEVk0Mk/V0aIsDE9bolfCi/i/QWZ3N8s5nTWMNyBBBmoSliWCm4jkkRZRD0ejgTN
1769tgI5
1770-----END CERTIFICATE-----
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001771""")
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001772 cert = load_certificate(FILETYPE_PEM, certPEM)
1773 self.assertRaises(ValueError, cert.get_signature_algorithm)
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001774
1775
Rick Dean38a05c82009-07-18 01:41:30 -05001776
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001777class X509StoreTests(TestCase):
1778 """
1779 Test for :py:obj:`OpenSSL.crypto.X509Store`.
1780 """
1781 def test_type(self):
1782 """
1783 :py:obj:`X509StoreType` is a type object.
1784 """
1785 self.assertIdentical(X509Store, X509StoreType)
1786 self.assertConsistentType(X509Store, 'X509Store')
1787
1788
1789 def test_add_cert_wrong_args(self):
1790 store = X509Store()
1791 self.assertRaises(TypeError, store.add_cert)
1792 self.assertRaises(TypeError, store.add_cert, object())
1793 self.assertRaises(TypeError, store.add_cert, X509(), object())
1794
1795
1796 def test_add_cert(self):
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001797 """
1798 :py:obj:`X509Store.add_cert` adds a :py:obj:`X509` instance to the
1799 certificate store.
1800 """
1801 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001802 store = X509Store()
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001803 store.add_cert(cert)
1804
1805
1806 def test_add_cert_rejects_duplicate(self):
1807 """
1808 :py:obj:`X509Store.add_cert` raises :py:obj:`OpenSSL.crypto.Error` if an
1809 attempt is made to add the same certificate to the store more than once.
1810 """
1811 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
1812 store = X509Store()
1813 store.add_cert(cert)
1814 self.assertRaises(Error, store.add_cert, cert)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001815
1816
1817
Rick Dean623ee362009-07-17 12:22:16 -05001818class PKCS12Tests(TestCase):
1819 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001820 Test for :py:obj:`OpenSSL.crypto.PKCS12` and :py:obj:`OpenSSL.crypto.load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001821 """
1822 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
1823
Jean-Paul Calderonec3a41f72009-07-25 12:36:02 -04001824 def test_type(self):
1825 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001826 :py:obj:`PKCS12Type` is a type object.
Jean-Paul Calderonec3a41f72009-07-25 12:36:02 -04001827 """
1828 self.assertIdentical(PKCS12, PKCS12Type)
1829 self.assertConsistentType(PKCS12, 'PKCS12')
1830
1831
Rick Deanf94096c2009-07-18 14:23:06 -05001832 def test_empty_construction(self):
Rick Dean38a05c82009-07-18 01:41:30 -05001833 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001834 :py:obj:`PKCS12` returns a new instance of :py:obj:`PKCS12` with no certificate,
Jean-Paul Calderonedc857b52009-07-25 12:25:07 -04001835 private key, CA certificates, or friendly name.
Rick Dean38a05c82009-07-18 01:41:30 -05001836 """
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001837 p12 = PKCS12()
Rick Dean623ee362009-07-17 12:22:16 -05001838 self.assertEqual(None, p12.get_certificate())
1839 self.assertEqual(None, p12.get_privatekey())
1840 self.assertEqual(None, p12.get_ca_certificates())
Rick Dean42d69e12009-07-20 11:36:08 -05001841 self.assertEqual(None, p12.get_friendlyname())
Rick Dean623ee362009-07-17 12:22:16 -05001842
Rick Dean38a05c82009-07-18 01:41:30 -05001843
Rick Dean623ee362009-07-17 12:22:16 -05001844 def test_type_errors(self):
Rick Dean38a05c82009-07-18 01:41:30 -05001845 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001846 The :py:obj:`PKCS12` setter functions (:py:obj:`set_certificate`, :py:obj:`set_privatekey`,
1847 :py:obj:`set_ca_certificates`, and :py:obj:`set_friendlyname`) raise :py:obj:`TypeError`
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001848 when passed objects of types other than those expected.
Rick Dean38a05c82009-07-18 01:41:30 -05001849 """
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001850 p12 = PKCS12()
Rick Dean623ee362009-07-17 12:22:16 -05001851 self.assertRaises(TypeError, p12.set_certificate, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05001852 self.assertRaises(TypeError, p12.set_certificate, PKey())
1853 self.assertRaises(TypeError, p12.set_certificate, X509)
Rick Dean623ee362009-07-17 12:22:16 -05001854 self.assertRaises(TypeError, p12.set_privatekey, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05001855 self.assertRaises(TypeError, p12.set_privatekey, 'legbone')
1856 self.assertRaises(TypeError, p12.set_privatekey, X509())
Rick Dean623ee362009-07-17 12:22:16 -05001857 self.assertRaises(TypeError, p12.set_ca_certificates, 3)
1858 self.assertRaises(TypeError, p12.set_ca_certificates, X509())
1859 self.assertRaises(TypeError, p12.set_ca_certificates, (3, 4))
Rick Deanf94096c2009-07-18 14:23:06 -05001860 self.assertRaises(TypeError, p12.set_ca_certificates, ( PKey(), ))
Rick Dean42d69e12009-07-20 11:36:08 -05001861 self.assertRaises(TypeError, p12.set_friendlyname, 6)
1862 self.assertRaises(TypeError, p12.set_friendlyname, ('foo', 'bar'))
Rick Dean623ee362009-07-17 12:22:16 -05001863
Rick Dean38a05c82009-07-18 01:41:30 -05001864
Rick Dean623ee362009-07-17 12:22:16 -05001865 def test_key_only(self):
1866 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001867 A :py:obj:`PKCS12` with only a private key can be exported using
1868 :py:obj:`PKCS12.export` and loaded again using :py:obj:`load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001869 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001870 passwd = b"blah"
Rick Dean623ee362009-07-17 12:22:16 -05001871 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001872 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001873 p12.set_privatekey(pkey)
Rick Dean623ee362009-07-17 12:22:16 -05001874 self.assertEqual(None, p12.get_certificate())
1875 self.assertEqual(pkey, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05001876 try:
1877 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
1878 except Error:
1879 # Some versions of OpenSSL will throw an exception
1880 # for this nearly useless PKCS12 we tried to generate:
1881 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
1882 return
Rick Dean623ee362009-07-17 12:22:16 -05001883 p12 = load_pkcs12(dumped_p12, passwd)
1884 self.assertEqual(None, p12.get_ca_certificates())
1885 self.assertEqual(None, p12.get_certificate())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001886
1887 # OpenSSL fails to bring the key back to us. So sad. Perhaps in the
1888 # future this will be improved.
1889 self.assertTrue(isinstance(p12.get_privatekey(), (PKey, type(None))))
Rick Dean623ee362009-07-17 12:22:16 -05001890
Rick Dean38a05c82009-07-18 01:41:30 -05001891
Rick Dean623ee362009-07-17 12:22:16 -05001892 def test_cert_only(self):
1893 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001894 A :py:obj:`PKCS12` with only a certificate can be exported using
1895 :py:obj:`PKCS12.export` and loaded again using :py:obj:`load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001896 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001897 passwd = b"blah"
Rick Dean623ee362009-07-17 12:22:16 -05001898 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001899 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001900 p12.set_certificate(cert)
Rick Dean623ee362009-07-17 12:22:16 -05001901 self.assertEqual(cert, p12.get_certificate())
1902 self.assertEqual(None, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05001903 try:
1904 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
1905 except Error:
1906 # Some versions of OpenSSL will throw an exception
1907 # for this nearly useless PKCS12 we tried to generate:
1908 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
1909 return
Rick Dean623ee362009-07-17 12:22:16 -05001910 p12 = load_pkcs12(dumped_p12, passwd)
1911 self.assertEqual(None, p12.get_privatekey())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001912
1913 # OpenSSL fails to bring the cert back to us. Groany mcgroan.
1914 self.assertTrue(isinstance(p12.get_certificate(), (X509, type(None))))
1915
1916 # Oh ho. It puts the certificate into the ca certificates list, in
1917 # fact. Totally bogus, I would think. Nevertheless, let's exploit
1918 # that to check to see if it reconstructed the certificate we expected
1919 # it to. At some point, hopefully this will change so that
1920 # p12.get_certificate() is actually what returns the loaded
1921 # certificate.
1922 self.assertEqual(
1923 cleartextCertificatePEM,
1924 dump_certificate(FILETYPE_PEM, p12.get_ca_certificates()[0]))
Rick Dean623ee362009-07-17 12:22:16 -05001925
1926
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001927 def gen_pkcs12(self, cert_pem=None, key_pem=None, ca_pem=None, friendly_name=None):
Rick Dean623ee362009-07-17 12:22:16 -05001928 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001929 Generate a PKCS12 object with components from PEM. Verify that the set
1930 functions return None.
Rick Dean623ee362009-07-17 12:22:16 -05001931 """
Rick Deanf94096c2009-07-18 14:23:06 -05001932 p12 = PKCS12()
1933 if cert_pem:
1934 ret = p12.set_certificate(load_certificate(FILETYPE_PEM, cert_pem))
1935 self.assertEqual(ret, None)
1936 if key_pem:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001937 ret = p12.set_privatekey(load_privatekey(FILETYPE_PEM, key_pem))
Rick Deanf94096c2009-07-18 14:23:06 -05001938 self.assertEqual(ret, None)
1939 if ca_pem:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001940 ret = p12.set_ca_certificates((load_certificate(FILETYPE_PEM, ca_pem),))
Rick Deanf94096c2009-07-18 14:23:06 -05001941 self.assertEqual(ret, None)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001942 if friendly_name:
1943 ret = p12.set_friendlyname(friendly_name)
Rick Dean42d69e12009-07-20 11:36:08 -05001944 self.assertEqual(ret, None)
Rick Deanf94096c2009-07-18 14:23:06 -05001945 return p12
1946
1947
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001948 def check_recovery(self, p12_str, key=None, cert=None, ca=None, passwd=b"",
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001949 extra=()):
Rick Deanf94096c2009-07-18 14:23:06 -05001950 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001951 Use openssl program to confirm three components are recoverable from a
1952 PKCS12 string.
Rick Deanf94096c2009-07-18 14:23:06 -05001953 """
1954 if key:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001955 recovered_key = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001956 p12_str, b"pkcs12", b"-nocerts", b"-nodes", b"-passin",
1957 b"pass:" + passwd, *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001958 self.assertEqual(recovered_key[-len(key):], key)
1959 if cert:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001960 recovered_cert = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001961 p12_str, b"pkcs12", b"-clcerts", b"-nodes", b"-passin",
1962 b"pass:" + passwd, b"-nokeys", *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001963 self.assertEqual(recovered_cert[-len(cert):], cert)
1964 if ca:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001965 recovered_cert = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001966 p12_str, b"pkcs12", b"-cacerts", b"-nodes", b"-passin",
1967 b"pass:" + passwd, b"-nokeys", *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001968 self.assertEqual(recovered_cert[-len(ca):], ca)
1969
1970
Stephen Holsapple38482622014-04-05 20:29:34 -07001971 def verify_pkcs12_container(self, p12):
1972 """
1973 Verify that the PKCS#12 container contains the correct client
1974 certificate and private key.
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04001975
1976 :param p12: The PKCS12 instance to verify.
1977 :type p12: :py:class:`PKCS12`
Stephen Holsapple38482622014-04-05 20:29:34 -07001978 """
1979 cert_pem = dump_certificate(FILETYPE_PEM, p12.get_certificate())
1980 key_pem = dump_privatekey(FILETYPE_PEM, p12.get_privatekey())
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04001981 self.assertEqual(
1982 (client_cert_pem, client_key_pem, None),
1983 (cert_pem, key_pem, p12.get_ca_certificates()))
Stephen Holsapple38482622014-04-05 20:29:34 -07001984
1985
Rick Deanf94096c2009-07-18 14:23:06 -05001986 def test_load_pkcs12(self):
1987 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001988 A PKCS12 string generated using the openssl command line can be loaded
Jonathan Ballet648875f2011-07-16 14:14:58 +09001989 with :py:obj:`load_pkcs12` and its components extracted and examined.
Rick Deanf94096c2009-07-18 14:23:06 -05001990 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001991 passwd = b"whatever"
Rick Dean623ee362009-07-17 12:22:16 -05001992 pem = client_key_pem + client_cert_pem
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001993 p12_str = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001994 pem, b"pkcs12", b"-export", b"-clcerts", b"-passout", b"pass:" + passwd)
Stephen Holsapple38482622014-04-05 20:29:34 -07001995 p12 = load_pkcs12(p12_str, passphrase=passwd)
1996 self.verify_pkcs12_container(p12)
1997
1998
Abraham Martinc5484ba2015-03-25 15:33:05 +00001999 def test_load_pkcs12_text_passphrase(self):
2000 """
2001 A PKCS12 string generated using the openssl command line can be loaded
2002 with :py:obj:`load_pkcs12` and its components extracted and examined.
2003 Using text as passphrase instead of bytes. DeprecationWarning expected.
2004 """
2005 pem = client_key_pem + client_cert_pem
2006 passwd = b"whatever"
2007 p12_str = _runopenssl(pem, b"pkcs12", b"-export", b"-clcerts",
2008 b"-passout", b"pass:" + passwd)
2009 with catch_warnings(record=True) as w:
2010 simplefilter("always")
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002011 p12 = load_pkcs12(p12_str, passphrase=u"whatever")
2012
2013 self.assertEqual(
2014 u"{} for passphrase is no longer accepted, use bytes".format(
2015 WARNING_TYPE_EXPECTED
2016 ),
2017 str(w[-1].message)
2018 )
2019 self.assertIs(w[-1].category, DeprecationWarning)
2020
Abraham Martinc5484ba2015-03-25 15:33:05 +00002021 self.verify_pkcs12_container(p12)
2022
2023
Stephen Holsapple38482622014-04-05 20:29:34 -07002024 def test_load_pkcs12_no_passphrase(self):
2025 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002026 A PKCS12 string generated using openssl command line can be loaded with
2027 :py:obj:`load_pkcs12` without a passphrase and its components extracted
2028 and examined.
Stephen Holsapple38482622014-04-05 20:29:34 -07002029 """
2030 pem = client_key_pem + client_cert_pem
2031 p12_str = _runopenssl(
2032 pem, b"pkcs12", b"-export", b"-clcerts", b"-passout", b"pass:")
2033 p12 = load_pkcs12(p12_str)
2034 self.verify_pkcs12_container(p12)
2035
2036
2037 def _dump_and_load(self, dump_passphrase, load_passphrase):
2038 """
2039 A helper method to dump and load a PKCS12 object.
2040 """
2041 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem)
2042 dumped_p12 = p12.export(passphrase=dump_passphrase, iter=2, maciter=3)
2043 return load_pkcs12(dumped_p12, passphrase=load_passphrase)
2044
2045
2046 def test_load_pkcs12_null_passphrase_load_empty(self):
2047 """
2048 A PKCS12 string can be dumped with a null passphrase, loaded with an
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002049 empty passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002050 extracted and examined.
2051 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002052 self.verify_pkcs12_container(
2053 self._dump_and_load(dump_passphrase=None, load_passphrase=b''))
Stephen Holsapple38482622014-04-05 20:29:34 -07002054
2055
2056 def test_load_pkcs12_null_passphrase_load_null(self):
2057 """
2058 A PKCS12 string can be dumped with a null passphrase, loaded with a
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002059 null passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002060 extracted and examined.
2061 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002062 self.verify_pkcs12_container(
2063 self._dump_and_load(dump_passphrase=None, load_passphrase=None))
Stephen Holsapple38482622014-04-05 20:29:34 -07002064
2065
2066 def test_load_pkcs12_empty_passphrase_load_empty(self):
2067 """
2068 A PKCS12 string can be dumped with an empty passphrase, loaded with an
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002069 empty passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002070 extracted and examined.
2071 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002072 self.verify_pkcs12_container(
2073 self._dump_and_load(dump_passphrase=b'', load_passphrase=b''))
Stephen Holsapple38482622014-04-05 20:29:34 -07002074
2075
2076 def test_load_pkcs12_empty_passphrase_load_null(self):
2077 """
2078 A PKCS12 string can be dumped with an empty passphrase, loaded with a
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002079 null passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002080 extracted and examined.
2081 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002082 self.verify_pkcs12_container(
2083 self._dump_and_load(dump_passphrase=b'', load_passphrase=None))
Rick Deanf94096c2009-07-18 14:23:06 -05002084
Rick Deanee568302009-07-24 09:56:29 -05002085
2086 def test_load_pkcs12_garbage(self):
2087 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002088 :py:obj:`load_pkcs12` raises :py:obj:`OpenSSL.crypto.Error` when passed a string
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002089 which is not a PKCS12 dump.
Rick Deanee568302009-07-24 09:56:29 -05002090 """
2091 passwd = 'whatever'
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002092 e = self.assertRaises(Error, load_pkcs12, b'fruit loops', passwd)
Jean-Paul Calderonede075462014-01-18 10:34:12 -05002093 self.assertEqual( e.args[0][0][0], 'asn1 encoding routines')
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -04002094 self.assertEqual( len(e.args[0][0]), 3)
Rick Deanee568302009-07-24 09:56:29 -05002095
2096
Rick Deanf94096c2009-07-18 14:23:06 -05002097 def test_replace(self):
2098 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002099 :py:obj:`PKCS12.set_certificate` replaces the certificate in a PKCS12 cluster.
2100 :py:obj:`PKCS12.set_privatekey` replaces the private key.
2101 :py:obj:`PKCS12.set_ca_certificates` replaces the CA certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05002102 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002103 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
2104 p12.set_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2105 p12.set_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002106 root_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05002107 client_cert = load_certificate(FILETYPE_PEM, client_cert_pem)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002108 p12.set_ca_certificates([root_cert]) # not a tuple
Rick Dean623ee362009-07-17 12:22:16 -05002109 self.assertEqual(1, len(p12.get_ca_certificates()))
2110 self.assertEqual(root_cert, p12.get_ca_certificates()[0])
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002111 p12.set_ca_certificates([client_cert, root_cert])
Rick Deanf94096c2009-07-18 14:23:06 -05002112 self.assertEqual(2, len(p12.get_ca_certificates()))
2113 self.assertEqual(client_cert, p12.get_ca_certificates()[0])
2114 self.assertEqual(root_cert, p12.get_ca_certificates()[1])
2115
2116
2117 def test_friendly_name(self):
2118 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002119 The *friendlyName* of a PKCS12 can be set and retrieved via
Jonathan Ballet648875f2011-07-16 14:14:58 +09002120 :py:obj:`PKCS12.get_friendlyname` and :py:obj:`PKCS12_set_friendlyname`, and a
2121 :py:obj:`PKCS12` with a friendly name set can be dumped with :py:obj:`PKCS12.export`.
Rick Deanf94096c2009-07-18 14:23:06 -05002122 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002123 passwd = b'Dogmeat[]{}!@#$%^&*()~`?/.,<>-_+=";:'
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002124 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -04002125 for friendly_name in [b('Serverlicious'), None, b('###')]:
Rick Dean42d69e12009-07-20 11:36:08 -05002126 p12.set_friendlyname(friendly_name)
2127 self.assertEqual(p12.get_friendlyname(), friendly_name)
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002128 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
Rick Dean42d69e12009-07-20 11:36:08 -05002129 reloaded_p12 = load_pkcs12(dumped_p12, passwd)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002130 self.assertEqual(
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -04002131 p12.get_friendlyname(), reloaded_p12.get_friendlyname())
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002132 # We would use the openssl program to confirm the friendly
2133 # name, but it is not possible. The pkcs12 command
2134 # does not store the friendly name in the cert's
Rick Dean42d69e12009-07-20 11:36:08 -05002135 # alias, which we could then extract.
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002136 self.check_recovery(
2137 dumped_p12, key=server_key_pem, cert=server_cert_pem,
2138 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05002139
2140
2141 def test_various_empty_passphrases(self):
2142 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002143 Test that missing, None, and '' passphrases are identical for PKCS12
2144 export.
Rick Deanf94096c2009-07-18 14:23:06 -05002145 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002146 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002147 passwd = b""
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002148 dumped_p12_empty = p12.export(iter=2, maciter=0, passphrase=passwd)
2149 dumped_p12_none = p12.export(iter=3, maciter=2, passphrase=None)
2150 dumped_p12_nopw = p12.export(iter=9, maciter=4)
2151 for dumped_p12 in [dumped_p12_empty, dumped_p12_none, dumped_p12_nopw]:
2152 self.check_recovery(
2153 dumped_p12, key=client_key_pem, cert=client_cert_pem,
2154 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05002155
2156
2157 def test_removing_ca_cert(self):
2158 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002159 Passing :py:obj:`None` to :py:obj:`PKCS12.set_ca_certificates` removes all CA
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002160 certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05002161 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002162 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
2163 p12.set_ca_certificates(None)
Rick Dean623ee362009-07-17 12:22:16 -05002164 self.assertEqual(None, p12.get_ca_certificates())
Rick Deanf94096c2009-07-18 14:23:06 -05002165
2166
2167 def test_export_without_mac(self):
2168 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002169 Exporting a PKCS12 with a :py:obj:`maciter` of ``-1`` excludes the MAC
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002170 entirely.
Rick Deanf94096c2009-07-18 14:23:06 -05002171 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002172 passwd = b"Lake Michigan"
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002173 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Dean623ee362009-07-17 12:22:16 -05002174 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002175 self.check_recovery(
2176 dumped_p12, key=server_key_pem, cert=server_cert_pem,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002177 passwd=passwd, extra=(b"-nomacver",))
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002178
2179
2180 def test_load_without_mac(self):
2181 """
2182 Loading a PKCS12 without a MAC does something other than crash.
2183 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002184 passwd = b"Lake Michigan"
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002185 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
2186 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Rick Dean321a0512009-08-13 17:21:29 -05002187 try:
2188 recovered_p12 = load_pkcs12(dumped_p12, passwd)
2189 # The person who generated this PCKS12 should be flogged,
2190 # or better yet we should have a means to determine
2191 # whether a PCKS12 had a MAC that was verified.
2192 # Anyway, libopenssl chooses to allow it, so the
2193 # pyopenssl binding does as well.
2194 self.assertTrue(isinstance(recovered_p12, PKCS12))
2195 except Error:
2196 # Failing here with an exception is preferred as some openssl
2197 # versions do.
2198 pass
Rick Dean623ee362009-07-17 12:22:16 -05002199
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002200
Rick Dean25bcc1f2009-07-20 11:53:13 -05002201 def test_zero_len_list_for_ca(self):
2202 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002203 A PKCS12 with an empty CA certificates list can be exported.
Rick Dean25bcc1f2009-07-20 11:53:13 -05002204 """
2205 passwd = 'Hobie 18'
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002206 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002207 # p12.set_ca_certificates([])
2208 # self.assertEqual((), p12.get_ca_certificates())
2209 # dumped_p12 = p12.export(passphrase=passwd, iter=3)
2210 # self.check_recovery(
2211 # dumped_p12, key=server_key_pem, cert=server_cert_pem,
2212 # passwd=passwd)
Rick Dean25bcc1f2009-07-20 11:53:13 -05002213
2214
Rick Deanf94096c2009-07-18 14:23:06 -05002215 def test_export_without_args(self):
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002216 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002217 All the arguments to :py:obj:`PKCS12.export` are optional.
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002218 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002219 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05002220 dumped_p12 = p12.export() # no args
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002221 self.check_recovery(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002222 dumped_p12, key=server_key_pem, cert=server_cert_pem, passwd=b"")
Rick Deanf94096c2009-07-18 14:23:06 -05002223
2224
Abraham Martinc5484ba2015-03-25 15:33:05 +00002225 def test_export_without_bytes(self):
2226 """
2227 Test :py:obj:`PKCS12.export` with text not bytes as passphrase
2228 """
2229 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
2230
2231 with catch_warnings(record=True) as w:
2232 simplefilter("always")
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002233 dumped_p12 = p12.export(passphrase=u"randomtext")
2234 self.assertEqual(
2235 u"{} for passphrase is no longer accepted, use bytes".format(
2236 WARNING_TYPE_EXPECTED
2237 ),
2238 str(w[-1].message)
2239 )
2240 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinc5484ba2015-03-25 15:33:05 +00002241 self.check_recovery(
2242 dumped_p12, key=server_key_pem, cert=server_cert_pem, passwd=b"randomtext")
2243
2244
Rick Deanf94096c2009-07-18 14:23:06 -05002245 def test_key_cert_mismatch(self):
2246 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002247 :py:obj:`PKCS12.export` raises an exception when a key and certificate
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002248 mismatch.
Rick Deanf94096c2009-07-18 14:23:06 -05002249 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002250 p12 = self.gen_pkcs12(server_cert_pem, client_key_pem, root_cert_pem)
2251 self.assertRaises(Error, p12.export)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002252
2253
2254
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002255# These quoting functions taken directly from Twisted's twisted.python.win32.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002256_cmdLineQuoteRe = re.compile(br'(\\*)"')
2257_cmdLineQuoteRe2 = re.compile(br'(\\+)\Z')
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002258def cmdLineQuote(s):
2259 """
2260 Internal method for quoting a single command-line argument.
2261
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002262 See http://www.perlmonks.org/?node_id=764004
2263
Jonathan Ballet648875f2011-07-16 14:14:58 +09002264 :type: :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002265 :param s: A single unquoted string to quote for something that is expecting
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002266 cmd.exe-style quoting
2267
Jonathan Ballet648875f2011-07-16 14:14:58 +09002268 :rtype: :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002269 :return: A cmd.exe-style quoted string
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002270 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002271 s = _cmdLineQuoteRe2.sub(br"\1\1", _cmdLineQuoteRe.sub(br'\1\1\\"', s))
2272 return b'"' + s + b'"'
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002273
2274
2275
2276def quoteArguments(arguments):
2277 """
2278 Quote an iterable of command-line arguments for passing to CreateProcess or
Jonathan Ballet648875f2011-07-16 14:14:58 +09002279 a similar API. This allows the list passed to :py:obj:`reactor.spawnProcess` to
2280 match the child process's :py:obj:`sys.argv` properly.
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002281
Jonathan Ballet648875f2011-07-16 14:14:58 +09002282 :type arguments: :py:obj:`iterable` of :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002283 :param arguments: An iterable of unquoted arguments to quote
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002284
Jonathan Ballet648875f2011-07-16 14:14:58 +09002285 :rtype: :py:obj:`str`
2286 :return: A space-delimited string containing quoted versions of :py:obj:`arguments`
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002287 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002288 return b' '.join(map(cmdLineQuote, arguments))
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002289
2290
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002291
Rick Dean4c9ad612009-07-17 15:05:22 -05002292def _runopenssl(pem, *args):
2293 """
2294 Run the command line openssl tool with the given arguments and write
Rick Dean55d1ce62009-08-13 17:40:24 -05002295 the given PEM to its stdin. Not safe for quotes.
Rick Dean4c9ad612009-07-17 15:05:22 -05002296 """
Jean-Paul Calderone038de952009-08-21 12:16:06 -04002297 if os.name == 'posix':
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002298 command = b"openssl " + b" ".join([
2299 (b"'" + arg.replace(b"'", b"'\\''") + b"'")
2300 for arg in args])
Rick Dean55d1ce62009-08-13 17:40:24 -05002301 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002302 command = b"openssl " + quoteArguments(args)
2303 proc = Popen(native(command), shell=True, stdin=PIPE, stdout=PIPE)
Jean-Paul Calderone62ca8da2010-08-11 19:58:08 -04002304 proc.stdin.write(pem)
2305 proc.stdin.close()
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002306 output = proc.stdout.read()
2307 proc.stdout.close()
2308 proc.wait()
2309 return output
Rick Dean4c9ad612009-07-17 15:05:22 -05002310
2311
2312
Jean-Paul Calderone18808652009-07-05 12:54:05 -04002313class FunctionTests(TestCase):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002314 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002315 Tests for free-functions in the :py:obj:`OpenSSL.crypto` module.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002316 """
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002317
2318 def test_load_privatekey_invalid_format(self):
2319 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002320 :py:obj:`load_privatekey` raises :py:obj:`ValueError` if passed an unknown filetype.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002321 """
2322 self.assertRaises(ValueError, load_privatekey, 100, root_key_pem)
2323
2324
2325 def test_load_privatekey_invalid_passphrase_type(self):
2326 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002327 :py:obj:`load_privatekey` raises :py:obj:`TypeError` if passed a passphrase that is
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002328 neither a :py:obj:`str` nor a callable.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002329 """
2330 self.assertRaises(
2331 TypeError,
2332 load_privatekey,
2333 FILETYPE_PEM, encryptedPrivateKeyPEMPassphrase, object())
2334
2335
2336 def test_load_privatekey_wrong_args(self):
2337 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002338 :py:obj:`load_privatekey` raises :py:obj:`TypeError` if called with the wrong number
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002339 of arguments.
2340 """
2341 self.assertRaises(TypeError, load_privatekey)
2342
2343
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002344 def test_load_privatekey_wrongPassphrase(self):
2345 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002346 :py:obj:`load_privatekey` raises :py:obj:`OpenSSL.crypto.Error` when it is passed an
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002347 encrypted PEM and an incorrect passphrase.
2348 """
2349 self.assertRaises(
2350 Error,
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002351 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, b("quack"))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002352
2353
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002354 def test_load_privatekey_passphraseWrongType(self):
2355 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002356 :py:obj:`load_privatekey` raises :py:obj:`ValueError` when it is passed a passphrase
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002357 with a private key encoded in a format, that doesn't support
2358 encryption.
2359 """
2360 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2361 blob = dump_privatekey(FILETYPE_ASN1, key)
2362 self.assertRaises(ValueError,
2363 load_privatekey, FILETYPE_ASN1, blob, "secret")
2364
2365
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002366 def test_load_privatekey_passphrase(self):
2367 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002368 :py:obj:`load_privatekey` can create a :py:obj:`PKey` object from an encrypted PEM
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002369 string if given the passphrase.
2370 """
2371 key = load_privatekey(
2372 FILETYPE_PEM, encryptedPrivateKeyPEM,
2373 encryptedPrivateKeyPEMPassphrase)
2374 self.assertTrue(isinstance(key, PKeyType))
2375
2376
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002377 def test_load_privatekey_passphrase_exception(self):
2378 """
2379 If the passphrase callback raises an exception, that exception is raised
2380 by :py:obj:`load_privatekey`.
2381 """
2382 def cb(ignored):
2383 raise ArithmeticError
2384
2385 self.assertRaises(ArithmeticError,
2386 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2387
2388
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002389 def test_load_privatekey_wrongPassphraseCallback(self):
2390 """
Jean-Paul Calderoned440a082011-09-14 11:02:05 -04002391 :py:obj:`load_privatekey` raises :py:obj:`OpenSSL.crypto.Error` when it
2392 is passed an encrypted PEM and a passphrase callback which returns an
2393 incorrect passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002394 """
2395 called = []
2396 def cb(*a):
2397 called.append(None)
Jean-Paul Calderoned440a082011-09-14 11:02:05 -04002398 return b("quack")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002399 self.assertRaises(
2400 Error,
2401 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2402 self.assertTrue(called)
2403
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002404
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002405 def test_load_privatekey_passphraseCallback(self):
2406 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002407 :py:obj:`load_privatekey` can create a :py:obj:`PKey` object from an encrypted PEM
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002408 string if given a passphrase callback which returns the correct
2409 password.
2410 """
2411 called = []
2412 def cb(writing):
2413 called.append(writing)
2414 return encryptedPrivateKeyPEMPassphrase
2415 key = load_privatekey(FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2416 self.assertTrue(isinstance(key, PKeyType))
2417 self.assertEqual(called, [False])
2418
2419
Jean-Paul Calderone105cb952011-09-14 10:16:46 -04002420 def test_load_privatekey_passphrase_wrong_return_type(self):
2421 """
2422 :py:obj:`load_privatekey` raises :py:obj:`ValueError` if the passphrase
2423 callback returns something other than a byte string.
2424 """
2425 self.assertRaises(
2426 ValueError,
2427 load_privatekey,
2428 FILETYPE_PEM, encryptedPrivateKeyPEM, lambda *args: 3)
2429
2430
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002431 def test_dump_privatekey_wrong_args(self):
2432 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002433 :py:obj:`dump_privatekey` raises :py:obj:`TypeError` if called with the wrong number
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002434 of arguments.
2435 """
2436 self.assertRaises(TypeError, dump_privatekey)
Jean-Paul Calderone1eeccd82011-09-14 10:18:52 -04002437 # If cipher name is given, password is required.
2438 self.assertRaises(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002439 TypeError, dump_privatekey, FILETYPE_PEM, PKey(), GOOD_CIPHER)
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002440
2441
2442 def test_dump_privatekey_unknown_cipher(self):
2443 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002444 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` if called with an unrecognized
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002445 cipher name.
2446 """
2447 key = PKey()
2448 key.generate_key(TYPE_RSA, 512)
2449 self.assertRaises(
2450 ValueError, dump_privatekey,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002451 FILETYPE_PEM, key, BAD_CIPHER, "passphrase")
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002452
2453
2454 def test_dump_privatekey_invalid_passphrase_type(self):
2455 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002456 :py:obj:`dump_privatekey` raises :py:obj:`TypeError` if called with a passphrase which
2457 is neither a :py:obj:`str` nor a callable.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002458 """
2459 key = PKey()
2460 key.generate_key(TYPE_RSA, 512)
2461 self.assertRaises(
2462 TypeError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002463 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, object())
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002464
2465
2466 def test_dump_privatekey_invalid_filetype(self):
2467 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002468 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` if called with an unrecognized
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002469 filetype.
2470 """
2471 key = PKey()
2472 key.generate_key(TYPE_RSA, 512)
2473 self.assertRaises(ValueError, dump_privatekey, 100, key)
2474
2475
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002476 def test_load_privatekey_passphraseCallbackLength(self):
2477 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002478 :py:obj:`crypto.load_privatekey` should raise an error when the passphrase
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002479 provided by the callback is too long, not silently truncate it.
2480 """
2481 def cb(ignored):
2482 return "a" * 1025
2483
2484 self.assertRaises(ValueError,
2485 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2486
2487
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002488 def test_dump_privatekey_passphrase(self):
2489 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002490 :py:obj:`dump_privatekey` writes an encrypted PEM when given a passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002491 """
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002492 passphrase = b("foo")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002493 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002494 pem = dump_privatekey(FILETYPE_PEM, key, GOOD_CIPHER, passphrase)
2495 self.assertTrue(isinstance(pem, binary_type))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002496 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
2497 self.assertTrue(isinstance(loadedKey, PKeyType))
2498 self.assertEqual(loadedKey.type(), key.type())
2499 self.assertEqual(loadedKey.bits(), key.bits())
2500
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002501
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002502 def test_dump_privatekey_passphraseWrongType(self):
2503 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002504 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` when it is passed a passphrase
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002505 with a private key encoded in a format, that doesn't support
2506 encryption.
2507 """
2508 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2509 self.assertRaises(ValueError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002510 dump_privatekey, FILETYPE_ASN1, key, GOOD_CIPHER, "secret")
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002511
2512
Rick Dean5b7b6372009-04-01 11:34:06 -05002513 def test_dump_certificate(self):
2514 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002515 :py:obj:`dump_certificate` writes PEM, DER, and text.
Rick Dean5b7b6372009-04-01 11:34:06 -05002516 """
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002517 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
Rick Dean5b7b6372009-04-01 11:34:06 -05002518 cert = load_certificate(FILETYPE_PEM, pemData)
2519 dumped_pem = dump_certificate(FILETYPE_PEM, cert)
2520 self.assertEqual(dumped_pem, cleartextCertificatePEM)
2521 dumped_der = dump_certificate(FILETYPE_ASN1, cert)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002522 good_der = _runopenssl(dumped_pem, b"x509", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002523 self.assertEqual(dumped_der, good_der)
2524 cert2 = load_certificate(FILETYPE_ASN1, dumped_der)
2525 dumped_pem2 = dump_certificate(FILETYPE_PEM, cert2)
2526 self.assertEqual(dumped_pem2, cleartextCertificatePEM)
2527 dumped_text = dump_certificate(FILETYPE_TEXT, cert)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002528 good_text = _runopenssl(dumped_pem, b"x509", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002529 self.assertEqual(dumped_text, good_text)
2530
2531
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002532 def test_dump_privatekey_pem(self):
Rick Dean5b7b6372009-04-01 11:34:06 -05002533 """
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002534 :py:obj:`dump_privatekey` writes a PEM
Rick Dean5b7b6372009-04-01 11:34:06 -05002535 """
2536 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -04002537 self.assertTrue(key.check())
Rick Dean5b7b6372009-04-01 11:34:06 -05002538 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2539 self.assertEqual(dumped_pem, cleartextPrivateKeyPEM)
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002540
2541
2542 def test_dump_privatekey_asn1(self):
2543 """
2544 :py:obj:`dump_privatekey` writes a DER
2545 """
2546 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2547 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2548
Rick Dean5b7b6372009-04-01 11:34:06 -05002549 dumped_der = dump_privatekey(FILETYPE_ASN1, key)
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002550 # XXX This OpenSSL call writes "writing RSA key" to standard out. Sad.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002551 good_der = _runopenssl(dumped_pem, b"rsa", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002552 self.assertEqual(dumped_der, good_der)
2553 key2 = load_privatekey(FILETYPE_ASN1, dumped_der)
2554 dumped_pem2 = dump_privatekey(FILETYPE_PEM, key2)
2555 self.assertEqual(dumped_pem2, cleartextPrivateKeyPEM)
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002556
2557
2558 def test_dump_privatekey_text(self):
2559 """
2560 :py:obj:`dump_privatekey` writes a text
2561 """
2562 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2563 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2564
Rick Dean5b7b6372009-04-01 11:34:06 -05002565 dumped_text = dump_privatekey(FILETYPE_TEXT, key)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002566 good_text = _runopenssl(dumped_pem, b"rsa", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002567 self.assertEqual(dumped_text, good_text)
2568
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002569
Rick Dean5b7b6372009-04-01 11:34:06 -05002570 def test_dump_certificate_request(self):
2571 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002572 :py:obj:`dump_certificate_request` writes a PEM, DER, and text.
Rick Dean5b7b6372009-04-01 11:34:06 -05002573 """
2574 req = load_certificate_request(FILETYPE_PEM, cleartextCertificateRequestPEM)
2575 dumped_pem = dump_certificate_request(FILETYPE_PEM, req)
2576 self.assertEqual(dumped_pem, cleartextCertificateRequestPEM)
2577 dumped_der = dump_certificate_request(FILETYPE_ASN1, req)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002578 good_der = _runopenssl(dumped_pem, b"req", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002579 self.assertEqual(dumped_der, good_der)
2580 req2 = load_certificate_request(FILETYPE_ASN1, dumped_der)
2581 dumped_pem2 = dump_certificate_request(FILETYPE_PEM, req2)
2582 self.assertEqual(dumped_pem2, cleartextCertificateRequestPEM)
2583 dumped_text = dump_certificate_request(FILETYPE_TEXT, req)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002584 good_text = _runopenssl(dumped_pem, b"req", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002585 self.assertEqual(dumped_text, good_text)
Jean-Paul Calderoneaf43cdf2010-08-03 18:40:52 -04002586 self.assertRaises(ValueError, dump_certificate_request, 100, req)
Rick Dean5b7b6372009-04-01 11:34:06 -05002587
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002588
2589 def test_dump_privatekey_passphraseCallback(self):
2590 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002591 :py:obj:`dump_privatekey` writes an encrypted PEM when given a callback which
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002592 returns the correct passphrase.
2593 """
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002594 passphrase = b("foo")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002595 called = []
2596 def cb(writing):
2597 called.append(writing)
2598 return passphrase
2599 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002600 pem = dump_privatekey(FILETYPE_PEM, key, GOOD_CIPHER, cb)
2601 self.assertTrue(isinstance(pem, binary_type))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002602 self.assertEqual(called, [True])
2603 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
2604 self.assertTrue(isinstance(loadedKey, PKeyType))
2605 self.assertEqual(loadedKey.type(), key.type())
2606 self.assertEqual(loadedKey.bits(), key.bits())
Rick Dean5b7b6372009-04-01 11:34:06 -05002607
2608
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002609 def test_dump_privatekey_passphrase_exception(self):
2610 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002611 :py:obj:`dump_privatekey` should not overwrite the exception raised
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002612 by the passphrase callback.
2613 """
2614 def cb(ignored):
2615 raise ArithmeticError
2616
2617 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2618 self.assertRaises(ArithmeticError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002619 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, cb)
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002620
2621
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002622 def test_dump_privatekey_passphraseCallbackLength(self):
2623 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002624 :py:obj:`crypto.dump_privatekey` should raise an error when the passphrase
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002625 provided by the callback is too long, not silently truncate it.
2626 """
2627 def cb(ignored):
2628 return "a" * 1025
2629
2630 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2631 self.assertRaises(ValueError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002632 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, cb)
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002633
2634
Alex Gaynor4b9c96a2014-08-14 09:51:48 -07002635 def test_load_pkcs7_data_pem(self):
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002636 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002637 :py:obj:`load_pkcs7_data` accepts a PKCS#7 string and returns an instance of
2638 :py:obj:`PKCS7Type`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002639 """
2640 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2641 self.assertTrue(isinstance(pkcs7, PKCS7Type))
2642
2643
Alex Gaynor4b9c96a2014-08-14 09:51:48 -07002644 def test_load_pkcs7_data_asn1(self):
Alex Gaynor9875a912014-08-14 13:35:05 -07002645 """
2646 :py:obj:`load_pkcs7_data` accepts a bytes containing ASN1 data
2647 representing PKCS#7 and returns an instance of :py:obj`PKCS7Type`.
2648 """
Alex Gaynor4b9c96a2014-08-14 09:51:48 -07002649 pkcs7 = load_pkcs7_data(FILETYPE_ASN1, pkcs7DataASN1)
2650 self.assertTrue(isinstance(pkcs7, PKCS7Type))
2651
2652
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002653 def test_load_pkcs7_data_invalid(self):
2654 """
2655 If the data passed to :py:obj:`load_pkcs7_data` is invalid,
2656 :py:obj:`Error` is raised.
2657 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002658 self.assertRaises(Error, load_pkcs7_data, FILETYPE_PEM, b"foo")
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002659
2660
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002661
Jean-Paul Calderone4a68b402013-12-29 16:54:58 -05002662class LoadCertificateTests(TestCase):
2663 """
2664 Tests for :py:obj:`load_certificate_request`.
2665 """
2666 def test_badFileType(self):
2667 """
2668 If the file type passed to :py:obj:`load_certificate_request` is
2669 neither :py:obj:`FILETYPE_PEM` nor :py:obj:`FILETYPE_ASN1` then
2670 :py:class:`ValueError` is raised.
2671 """
2672 self.assertRaises(ValueError, load_certificate_request, object(), b"")
2673
2674
2675
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002676class PKCS7Tests(TestCase):
2677 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002678 Tests for :py:obj:`PKCS7Type`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002679 """
2680 def test_type(self):
2681 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002682 :py:obj:`PKCS7Type` is a type object.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002683 """
2684 self.assertTrue(isinstance(PKCS7Type, type))
2685 self.assertEqual(PKCS7Type.__name__, 'PKCS7')
2686
2687 # XXX This doesn't currently work.
2688 # self.assertIdentical(PKCS7, PKCS7Type)
2689
2690
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002691 # XXX Opposite results for all these following methods
2692
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002693 def test_type_is_signed_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002694 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002695 :py:obj:`PKCS7Type.type_is_signed` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002696 arguments.
2697 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002698 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2699 self.assertRaises(TypeError, pkcs7.type_is_signed, None)
2700
2701
2702 def test_type_is_signed(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002703 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002704 :py:obj:`PKCS7Type.type_is_signed` returns :py:obj:`True` if the PKCS7 object is of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002705 the type *signed*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002706 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002707 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2708 self.assertTrue(pkcs7.type_is_signed())
2709
2710
2711 def test_type_is_enveloped_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002712 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002713 :py:obj:`PKCS7Type.type_is_enveloped` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002714 arguments.
2715 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002716 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2717 self.assertRaises(TypeError, pkcs7.type_is_enveloped, None)
2718
2719
2720 def test_type_is_enveloped(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002721 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002722 :py:obj:`PKCS7Type.type_is_enveloped` returns :py:obj:`False` if the PKCS7 object is
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002723 not of the type *enveloped*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002724 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002725 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2726 self.assertFalse(pkcs7.type_is_enveloped())
2727
2728
2729 def test_type_is_signedAndEnveloped_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002730 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002731 :py:obj:`PKCS7Type.type_is_signedAndEnveloped` raises :py:obj:`TypeError` if called
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002732 with any arguments.
2733 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002734 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2735 self.assertRaises(TypeError, pkcs7.type_is_signedAndEnveloped, None)
2736
2737
2738 def test_type_is_signedAndEnveloped(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002739 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002740 :py:obj:`PKCS7Type.type_is_signedAndEnveloped` returns :py:obj:`False` if the PKCS7
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002741 object is not of the type *signed and enveloped*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002742 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002743 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2744 self.assertFalse(pkcs7.type_is_signedAndEnveloped())
2745
2746
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002747 def test_type_is_data(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002748 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002749 :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 -04002750 the type data.
2751 """
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002752 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2753 self.assertFalse(pkcs7.type_is_data())
2754
2755
2756 def test_type_is_data_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002757 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002758 :py:obj:`PKCS7Type.type_is_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002759 arguments.
2760 """
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002761 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2762 self.assertRaises(TypeError, pkcs7.type_is_data, None)
2763
2764
Jean-Paul Calderone97b28ca2010-07-30 10:56:07 -04002765 def test_get_type_name_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002766 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002767 :py:obj:`PKCS7Type.get_type_name` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002768 arguments.
2769 """
Jean-Paul Calderone97b28ca2010-07-30 10:56:07 -04002770 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2771 self.assertRaises(TypeError, pkcs7.get_type_name, None)
2772
2773
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002774 def test_get_type_name(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002775 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002776 :py:obj:`PKCS7Type.get_type_name` returns a :py:obj:`str` giving the type name.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002777 """
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002778 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
Jean-Paul Calderone07640f12010-08-22 17:14:43 -04002779 self.assertEquals(pkcs7.get_type_name(), b('pkcs7-signedData'))
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002780
2781
2782 def test_attribute(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002783 """
2784 If an attribute other than one of the methods tested here is accessed on
Jonathan Ballet648875f2011-07-16 14:14:58 +09002785 an instance of :py:obj:`PKCS7Type`, :py:obj:`AttributeError` is raised.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002786 """
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002787 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2788 self.assertRaises(AttributeError, getattr, pkcs7, "foo")
2789
2790
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002791
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002792class NetscapeSPKITests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002793 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002794 Tests for :py:obj:`OpenSSL.crypto.NetscapeSPKI`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002795 """
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002796 def signable(self):
2797 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002798 Return a new :py:obj:`NetscapeSPKI` for use with signing tests.
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002799 """
2800 return NetscapeSPKI()
2801
2802
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002803 def test_type(self):
2804 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002805 :py:obj:`NetscapeSPKI` and :py:obj:`NetscapeSPKIType` refer to the same type object
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002806 and can be used to create instances of that type.
2807 """
2808 self.assertIdentical(NetscapeSPKI, NetscapeSPKIType)
2809 self.assertConsistentType(NetscapeSPKI, 'NetscapeSPKI')
2810
2811
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002812 def test_construction(self):
2813 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002814 :py:obj:`NetscapeSPKI` returns an instance of :py:obj:`NetscapeSPKIType`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002815 """
2816 nspki = NetscapeSPKI()
2817 self.assertTrue(isinstance(nspki, NetscapeSPKIType))
2818
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002819
Jean-Paul Calderone969efaa2010-08-03 18:19:19 -04002820 def test_invalid_attribute(self):
2821 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002822 Accessing a non-existent attribute of a :py:obj:`NetscapeSPKI` instance causes
2823 an :py:obj:`AttributeError` to be raised.
Jean-Paul Calderone969efaa2010-08-03 18:19:19 -04002824 """
2825 nspki = NetscapeSPKI()
2826 self.assertRaises(AttributeError, lambda: nspki.foo)
2827
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002828
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002829 def test_b64_encode(self):
2830 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002831 :py:obj:`NetscapeSPKI.b64_encode` encodes the certificate to a base64 blob.
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002832 """
2833 nspki = NetscapeSPKI()
2834 blob = nspki.b64_encode()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002835 self.assertTrue(isinstance(blob, binary_type))
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002836
2837
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002838
Rick Dean536ba022009-07-24 23:57:27 -05002839class RevokedTests(TestCase):
2840 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002841 Tests for :py:obj:`OpenSSL.crypto.Revoked`
Rick Dean536ba022009-07-24 23:57:27 -05002842 """
2843 def test_construction(self):
2844 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002845 Confirm we can create :py:obj:`OpenSSL.crypto.Revoked`. Check
Rick Dean536ba022009-07-24 23:57:27 -05002846 that it is empty.
2847 """
2848 revoked = Revoked()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002849 self.assertTrue(isinstance(revoked, Revoked))
2850 self.assertEquals(type(revoked), Revoked)
2851 self.assertEquals(revoked.get_serial(), b('00'))
2852 self.assertEquals(revoked.get_rev_date(), None)
2853 self.assertEquals(revoked.get_reason(), None)
Rick Dean536ba022009-07-24 23:57:27 -05002854
2855
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002856 def test_construction_wrong_args(self):
2857 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002858 Calling :py:obj:`OpenSSL.crypto.Revoked` with any arguments results
2859 in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002860 """
2861 self.assertRaises(TypeError, Revoked, None)
2862 self.assertRaises(TypeError, Revoked, 1)
2863 self.assertRaises(TypeError, Revoked, "foo")
2864
2865
Rick Dean536ba022009-07-24 23:57:27 -05002866 def test_serial(self):
2867 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002868 Confirm we can set and get serial numbers from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002869 :py:obj:`OpenSSL.crypto.Revoked`. Confirm errors are handled
Rick Dean536ba022009-07-24 23:57:27 -05002870 with grace.
2871 """
2872 revoked = Revoked()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002873 ret = revoked.set_serial(b('10b'))
2874 self.assertEquals(ret, None)
Rick Dean536ba022009-07-24 23:57:27 -05002875 ser = revoked.get_serial()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002876 self.assertEquals(ser, b('010B'))
Rick Dean536ba022009-07-24 23:57:27 -05002877
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002878 revoked.set_serial(b('31ppp')) # a type error would be nice
Rick Dean536ba022009-07-24 23:57:27 -05002879 ser = revoked.get_serial()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002880 self.assertEquals(ser, b('31'))
Rick Dean536ba022009-07-24 23:57:27 -05002881
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002882 self.assertRaises(ValueError, revoked.set_serial, b('pqrst'))
Rick Dean536ba022009-07-24 23:57:27 -05002883 self.assertRaises(TypeError, revoked.set_serial, 100)
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002884 self.assertRaises(TypeError, revoked.get_serial, 1)
2885 self.assertRaises(TypeError, revoked.get_serial, None)
2886 self.assertRaises(TypeError, revoked.get_serial, "")
Rick Dean536ba022009-07-24 23:57:27 -05002887
2888
2889 def test_date(self):
2890 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002891 Confirm we can set and get revocation dates from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002892 :py:obj:`OpenSSL.crypto.Revoked`. Confirm errors are handled
Rick Dean536ba022009-07-24 23:57:27 -05002893 with grace.
2894 """
2895 revoked = Revoked()
2896 date = revoked.get_rev_date()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002897 self.assertEquals(date, None)
Rick Dean536ba022009-07-24 23:57:27 -05002898
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002899 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05002900 ret = revoked.set_rev_date(now)
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002901 self.assertEqual(ret, None)
Rick Dean536ba022009-07-24 23:57:27 -05002902 date = revoked.get_rev_date()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002903 self.assertEqual(date, now)
Rick Dean536ba022009-07-24 23:57:27 -05002904
2905
Rick Dean6385faf2009-07-26 00:07:47 -05002906 def test_reason(self):
2907 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002908 Confirm we can set and get revocation reasons from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002909 :py:obj:`OpenSSL.crypto.Revoked`. The "get" need to work
Rick Dean6385faf2009-07-26 00:07:47 -05002910 as "set". Likewise, each reason of all_reasons() must work.
2911 """
2912 revoked = Revoked()
2913 for r in revoked.all_reasons():
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002914 for x in range(2):
Rick Dean6385faf2009-07-26 00:07:47 -05002915 ret = revoked.set_reason(r)
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002916 self.assertEquals(ret, None)
Rick Dean6385faf2009-07-26 00:07:47 -05002917 reason = revoked.get_reason()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002918 self.assertEquals(
2919 reason.lower().replace(b(' '), b('')),
2920 r.lower().replace(b(' '), b('')))
Rick Dean6385faf2009-07-26 00:07:47 -05002921 r = reason # again with the resp of get
2922
2923 revoked.set_reason(None)
2924 self.assertEqual(revoked.get_reason(), None)
2925
2926
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002927 def test_set_reason_wrong_arguments(self):
Rick Dean6385faf2009-07-26 00:07:47 -05002928 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002929 Calling :py:obj:`OpenSSL.crypto.Revoked.set_reason` with other than
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002930 one argument, or an argument which isn't a valid reason,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002931 results in :py:obj:`TypeError` or :py:obj:`ValueError` being raised.
Rick Dean6385faf2009-07-26 00:07:47 -05002932 """
2933 revoked = Revoked()
2934 self.assertRaises(TypeError, revoked.set_reason, 100)
Jean-Paul Calderone281b62b2010-08-28 14:22:29 -04002935 self.assertRaises(ValueError, revoked.set_reason, b('blue'))
Rick Dean6385faf2009-07-26 00:07:47 -05002936
Rick Dean536ba022009-07-24 23:57:27 -05002937
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002938 def test_get_reason_wrong_arguments(self):
2939 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002940 Calling :py:obj:`OpenSSL.crypto.Revoked.get_reason` with any
2941 arguments results in :py:obj:`TypeError` being raised.
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002942 """
2943 revoked = Revoked()
2944 self.assertRaises(TypeError, revoked.get_reason, None)
2945 self.assertRaises(TypeError, revoked.get_reason, 1)
2946 self.assertRaises(TypeError, revoked.get_reason, "foo")
2947
2948
2949
Rick Dean536ba022009-07-24 23:57:27 -05002950class CRLTests(TestCase):
2951 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002952 Tests for :py:obj:`OpenSSL.crypto.CRL`
Rick Dean536ba022009-07-24 23:57:27 -05002953 """
2954 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
2955 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2956
2957 def test_construction(self):
2958 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002959 Confirm we can create :py:obj:`OpenSSL.crypto.CRL`. Check
Rick Dean536ba022009-07-24 23:57:27 -05002960 that it is empty
2961 """
2962 crl = CRL()
2963 self.assertTrue( isinstance(crl, CRL) )
2964 self.assertEqual(crl.get_revoked(), None)
2965
2966
Jean-Paul Calderone2efd03e2010-01-30 13:59:55 -05002967 def test_construction_wrong_args(self):
2968 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002969 Calling :py:obj:`OpenSSL.crypto.CRL` with any number of arguments
2970 results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone2efd03e2010-01-30 13:59:55 -05002971 """
2972 self.assertRaises(TypeError, CRL, 1)
2973 self.assertRaises(TypeError, CRL, "")
2974 self.assertRaises(TypeError, CRL, None)
2975
2976
Rick Dean536ba022009-07-24 23:57:27 -05002977 def test_export(self):
2978 """
2979 Use python to create a simple CRL with a revocation, and export
2980 the CRL in formats of PEM, DER and text. Those outputs are verified
2981 with the openssl program.
2982 """
2983 crl = CRL()
2984 revoked = Revoked()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002985 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05002986 revoked.set_rev_date(now)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002987 revoked.set_serial(b('3ab'))
2988 revoked.set_reason(b('sUpErSeDEd'))
Rick Dean536ba022009-07-24 23:57:27 -05002989 crl.add_revoked(revoked)
2990
2991 # PEM format
2992 dumped_crl = crl.export(self.cert, self.pkey, days=20)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002993 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002994 text.index(b('Serial Number: 03AB'))
2995 text.index(b('Superseded'))
2996 text.index(b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA'))
Rick Dean536ba022009-07-24 23:57:27 -05002997
2998 # DER format
2999 dumped_crl = crl.export(self.cert, self.pkey, FILETYPE_ASN1)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003000 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text", b"-inform", b"DER")
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003001 text.index(b('Serial Number: 03AB'))
3002 text.index(b('Superseded'))
3003 text.index(b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA'))
Rick Dean536ba022009-07-24 23:57:27 -05003004
3005 # text format
3006 dumped_text = crl.export(self.cert, self.pkey, type=FILETYPE_TEXT)
3007 self.assertEqual(text, dumped_text)
3008
3009
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -04003010 def test_export_invalid(self):
3011 """
3012 If :py:obj:`CRL.export` is used with an uninitialized :py:obj:`X509`
Jean-Paul Calderoneb5871072012-03-09 14:58:00 -08003013 instance, :py:obj:`OpenSSL.crypto.Error` is raised.
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -04003014 """
3015 crl = CRL()
3016 self.assertRaises(Error, crl.export, X509(), PKey())
3017
3018
Jean-Paul Calderone56515342010-01-30 13:49:38 -05003019 def test_add_revoked_keyword(self):
3020 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003021 :py:obj:`OpenSSL.CRL.add_revoked` accepts its single argument as the
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003022 ``revoked`` keyword argument.
Jean-Paul Calderone56515342010-01-30 13:49:38 -05003023 """
3024 crl = CRL()
3025 revoked = Revoked()
3026 crl.add_revoked(revoked=revoked)
3027 self.assertTrue(isinstance(crl.get_revoked()[0], Revoked))
3028
Rick Dean6385faf2009-07-26 00:07:47 -05003029
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05003030 def test_export_wrong_args(self):
3031 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003032 Calling :py:obj:`OpenSSL.CRL.export` with fewer than two or more than
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05003033 four arguments, or with arguments other than the certificate,
3034 private key, integer file type, and integer number of days it
Jonathan Ballet648875f2011-07-16 14:14:58 +09003035 expects, results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05003036 """
3037 crl = CRL()
3038 self.assertRaises(TypeError, crl.export)
3039 self.assertRaises(TypeError, crl.export, self.cert)
3040 self.assertRaises(TypeError, crl.export, self.cert, self.pkey, FILETYPE_PEM, 10, "foo")
3041
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05003042 self.assertRaises(TypeError, crl.export, None, self.pkey, FILETYPE_PEM, 10)
3043 self.assertRaises(TypeError, crl.export, self.cert, None, FILETYPE_PEM, 10)
3044 self.assertRaises(TypeError, crl.export, self.cert, self.pkey, None, 10)
3045 self.assertRaises(TypeError, crl.export, self.cert, FILETYPE_PEM, None)
3046
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05003047
Jean-Paul Calderoneea198422010-01-30 13:58:23 -05003048 def test_export_unknown_filetype(self):
3049 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003050 Calling :py:obj:`OpenSSL.CRL.export` with a file type other than
3051 :py:obj:`FILETYPE_PEM`, :py:obj:`FILETYPE_ASN1`, or :py:obj:`FILETYPE_TEXT` results
3052 in a :py:obj:`ValueError` being raised.
Jean-Paul Calderoneea198422010-01-30 13:58:23 -05003053 """
3054 crl = CRL()
3055 self.assertRaises(ValueError, crl.export, self.cert, self.pkey, 100, 10)
3056
3057
Rick Dean536ba022009-07-24 23:57:27 -05003058 def test_get_revoked(self):
3059 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05003060 Use python to create a simple CRL with two revocations.
Jonathan Ballet648875f2011-07-16 14:14:58 +09003061 Get back the :py:obj:`Revoked` using :py:obj:`OpenSSL.CRL.get_revoked` and
Rick Dean536ba022009-07-24 23:57:27 -05003062 verify them.
3063 """
3064 crl = CRL()
3065
3066 revoked = Revoked()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003067 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05003068 revoked.set_rev_date(now)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003069 revoked.set_serial(b('3ab'))
Rick Dean536ba022009-07-24 23:57:27 -05003070 crl.add_revoked(revoked)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003071 revoked.set_serial(b('100'))
3072 revoked.set_reason(b('sUpErSeDEd'))
Rick Dean536ba022009-07-24 23:57:27 -05003073 crl.add_revoked(revoked)
3074
3075 revs = crl.get_revoked()
3076 self.assertEqual(len(revs), 2)
3077 self.assertEqual(type(revs[0]), Revoked)
3078 self.assertEqual(type(revs[1]), Revoked)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003079 self.assertEqual(revs[0].get_serial(), b('03AB'))
3080 self.assertEqual(revs[1].get_serial(), b('0100'))
Rick Dean536ba022009-07-24 23:57:27 -05003081 self.assertEqual(revs[0].get_rev_date(), now)
3082 self.assertEqual(revs[1].get_rev_date(), now)
3083
3084
Jean-Paul Calderone46bdce42010-01-30 13:44:16 -05003085 def test_get_revoked_wrong_args(self):
3086 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003087 Calling :py:obj:`OpenSSL.CRL.get_revoked` with any arguments results
3088 in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone46bdce42010-01-30 13:44:16 -05003089 """
3090 crl = CRL()
3091 self.assertRaises(TypeError, crl.get_revoked, None)
3092 self.assertRaises(TypeError, crl.get_revoked, 1)
3093 self.assertRaises(TypeError, crl.get_revoked, "")
3094 self.assertRaises(TypeError, crl.get_revoked, "", 1, None)
3095
3096
Jean-Paul Calderoneecef6fa2010-01-30 13:47:18 -05003097 def test_add_revoked_wrong_args(self):
3098 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003099 Calling :py:obj:`OpenSSL.CRL.add_revoked` with other than one
3100 argument results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderoneecef6fa2010-01-30 13:47:18 -05003101 """
3102 crl = CRL()
3103 self.assertRaises(TypeError, crl.add_revoked)
3104 self.assertRaises(TypeError, crl.add_revoked, 1, 2)
3105 self.assertRaises(TypeError, crl.add_revoked, "foo", "bar")
3106
3107
Rick Dean536ba022009-07-24 23:57:27 -05003108 def test_load_crl(self):
3109 """
3110 Load a known CRL and inspect its revocations. Both
3111 PEM and DER formats are loaded.
3112 """
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003113 crl = load_crl(FILETYPE_PEM, crlData)
Rick Dean536ba022009-07-24 23:57:27 -05003114 revs = crl.get_revoked()
3115 self.assertEqual(len(revs), 2)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003116 self.assertEqual(revs[0].get_serial(), b('03AB'))
Rick Dean6385faf2009-07-26 00:07:47 -05003117 self.assertEqual(revs[0].get_reason(), None)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003118 self.assertEqual(revs[1].get_serial(), b('0100'))
3119 self.assertEqual(revs[1].get_reason(), b('Superseded'))
Rick Dean536ba022009-07-24 23:57:27 -05003120
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003121 der = _runopenssl(crlData, b"crl", b"-outform", b"DER")
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05003122 crl = load_crl(FILETYPE_ASN1, der)
Rick Dean536ba022009-07-24 23:57:27 -05003123 revs = crl.get_revoked()
3124 self.assertEqual(len(revs), 2)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003125 self.assertEqual(revs[0].get_serial(), b('03AB'))
Rick Dean6385faf2009-07-26 00:07:47 -05003126 self.assertEqual(revs[0].get_reason(), None)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003127 self.assertEqual(revs[1].get_serial(), b('0100'))
3128 self.assertEqual(revs[1].get_reason(), b('Superseded'))
Rick Dean536ba022009-07-24 23:57:27 -05003129
3130
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003131 def test_load_crl_wrong_args(self):
3132 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003133 Calling :py:obj:`OpenSSL.crypto.load_crl` with other than two
3134 arguments results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003135 """
3136 self.assertRaises(TypeError, load_crl)
3137 self.assertRaises(TypeError, load_crl, FILETYPE_PEM)
3138 self.assertRaises(TypeError, load_crl, FILETYPE_PEM, crlData, None)
3139
3140
3141 def test_load_crl_bad_filetype(self):
3142 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003143 Calling :py:obj:`OpenSSL.crypto.load_crl` with an unknown file type
3144 raises a :py:obj:`ValueError`.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003145 """
3146 self.assertRaises(ValueError, load_crl, 100, crlData)
3147
3148
3149 def test_load_crl_bad_data(self):
3150 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003151 Calling :py:obj:`OpenSSL.crypto.load_crl` with file data which can't
3152 be loaded raises a :py:obj:`OpenSSL.crypto.Error`.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003153 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003154 self.assertRaises(Error, load_crl, FILETYPE_PEM, b"hello, world")
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003155
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04003156
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -05003157
James Yonan7c2e5d32010-02-27 05:45:50 -07003158class SignVerifyTests(TestCase):
3159 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003160 Tests for :py:obj:`OpenSSL.crypto.sign` and :py:obj:`OpenSSL.crypto.verify`.
James Yonan7c2e5d32010-02-27 05:45:50 -07003161 """
3162 def test_sign_verify(self):
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04003163 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003164 :py:obj:`sign` generates a cryptographic signature which :py:obj:`verify` can check.
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04003165 """
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003166 content = b(
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04003167 "It was a bright cold day in April, and the clocks were striking "
3168 "thirteen. Winston Smith, his chin nuzzled into his breast in an "
3169 "effort to escape the vile wind, slipped quickly through the "
3170 "glass doors of Victory Mansions, though not quickly enough to "
3171 "prevent a swirl of gritty dust from entering along with him.")
3172
3173 # sign the content with this private key
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04003174 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04003175 # verify the content with this cert
3176 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3177 # certificate unrelated to priv_key, used to trigger an error
3178 bad_cert = load_certificate(FILETYPE_PEM, server_cert_pem)
James Yonan7c2e5d32010-02-27 05:45:50 -07003179
Jean-Paul Calderoned08feb02010-10-12 21:53:24 -04003180 for digest in ['md5', 'sha1']:
James Yonan7c2e5d32010-02-27 05:45:50 -07003181 sig = sign(priv_key, content, digest)
3182
3183 # Verify the signature of content, will throw an exception if error.
3184 verify(good_cert, sig, content, digest)
3185
3186 # This should fail because the certificate doesn't match the
3187 # private key that was used to sign the content.
3188 self.assertRaises(Error, verify, bad_cert, sig, content, digest)
3189
3190 # This should fail because we've "tainted" the content after
3191 # signing it.
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003192 self.assertRaises(
3193 Error, verify,
3194 good_cert, sig, content + b("tainted"), digest)
James Yonan7c2e5d32010-02-27 05:45:50 -07003195
3196 # test that unknown digest types fail
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003197 self.assertRaises(
Jean-Paul Calderone9538f142010-10-13 22:13:40 -04003198 ValueError, sign, priv_key, content, "strange-digest")
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003199 self.assertRaises(
Jean-Paul Calderone9538f142010-10-13 22:13:40 -04003200 ValueError, verify, good_cert, sig, content, "strange-digest")
James Yonan7c2e5d32010-02-27 05:45:50 -07003201
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04003202
Abraham Martinc5484ba2015-03-25 15:33:05 +00003203 def test_sign_verify_with_text(self):
3204 """
3205 :py:obj:`sign` generates a cryptographic signature which :py:obj:`verify` can check.
3206 Deprecation warnings raised because using text instead of bytes as content
3207 """
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003208 content = (
3209 u"It was a bright cold day in April, and the clocks were striking "
3210 u"thirteen. Winston Smith, his chin nuzzled into his breast in an "
3211 u"effort to escape the vile wind, slipped quickly through the "
3212 u"glass doors of Victory Mansions, though not quickly enough to "
3213 u"prevent a swirl of gritty dust from entering along with him."
3214 )
Abraham Martinc5484ba2015-03-25 15:33:05 +00003215
3216 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
3217 cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3218 for digest in ['md5', 'sha1']:
3219 with catch_warnings(record=True) as w:
3220 simplefilter("always")
3221 sig = sign(priv_key, content, digest)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003222
3223 self.assertEqual(
3224 u"{} for data is no longer accepted, use bytes".format(
3225 WARNING_TYPE_EXPECTED
3226 ),
3227 str(w[-1].message)
3228 )
3229 self.assertIs(w[-1].category, DeprecationWarning)
3230
Abraham Martinc5484ba2015-03-25 15:33:05 +00003231 with catch_warnings(record=True) as w:
3232 simplefilter("always")
3233 verify(cert, sig, content, digest)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003234
3235 self.assertEqual(
3236 u"{} for data is no longer accepted, use bytes".format(
3237 WARNING_TYPE_EXPECTED
3238 ),
3239 str(w[-1].message)
3240 )
3241 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinc5484ba2015-03-25 15:33:05 +00003242
3243
Jean-Paul Calderone9828f662010-12-08 22:57:26 -05003244 def test_sign_nulls(self):
3245 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003246 :py:obj:`sign` produces a signature for a string with embedded nulls.
Jean-Paul Calderone9828f662010-12-08 22:57:26 -05003247 """
3248 content = b("Watch out! \0 Did you see it?")
3249 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
3250 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3251 sig = sign(priv_key, content, "sha1")
3252 verify(good_cert, sig, content, "sha1")
3253
3254
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003255
3256class EllipticCurveTests(TestCase):
3257 """
3258 Tests for :py:class:`_EllipticCurve`, :py:obj:`get_elliptic_curve`, and
3259 :py:obj:`get_elliptic_curves`.
3260 """
3261 def test_set(self):
3262 """
3263 :py:obj:`get_elliptic_curves` returns a :py:obj:`set`.
3264 """
3265 self.assertIsInstance(get_elliptic_curves(), set)
3266
3267
3268 def test_some_curves(self):
3269 """
3270 If :py:mod:`cryptography` has elliptic curve support then the set
3271 returned by :py:obj:`get_elliptic_curves` has some elliptic curves in
3272 it.
3273
3274 There could be an OpenSSL that violates this assumption. If so, this
3275 test will fail and we'll find out.
3276 """
3277 curves = get_elliptic_curves()
3278 if lib.Cryptography_HAS_EC:
3279 self.assertTrue(curves)
3280 else:
3281 self.assertFalse(curves)
3282
3283
3284 def test_a_curve(self):
3285 """
3286 :py:obj:`get_elliptic_curve` can be used to retrieve a particular
3287 supported curve.
3288 """
3289 curves = get_elliptic_curves()
3290 if curves:
3291 curve = next(iter(curves))
3292 self.assertEqual(curve.name, get_elliptic_curve(curve.name).name)
3293 else:
Jean-Paul Calderoneeb86f3a2014-04-19 09:45:57 -04003294 self.assertRaises(ValueError, get_elliptic_curve, u("prime256v1"))
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003295
3296
3297 def test_not_a_curve(self):
3298 """
3299 :py:obj:`get_elliptic_curve` raises :py:class:`ValueError` if called
3300 with a name which does not identify a supported curve.
3301 """
3302 self.assertRaises(
Jean-Paul Calderone5a82db92014-04-19 09:51:29 -04003303 ValueError, get_elliptic_curve, u("this curve was just invented"))
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003304
3305
3306 def test_repr(self):
3307 """
3308 The string representation of a curve object includes simply states the
3309 object is a curve and what its name is.
3310 """
3311 curves = get_elliptic_curves()
3312 if curves:
3313 curve = next(iter(curves))
3314 self.assertEqual("<Curve %r>" % (curve.name,), repr(curve))
3315
3316
3317 def test_to_EC_KEY(self):
3318 """
3319 The curve object can export a version of itself as an EC_KEY* via the
3320 private :py:meth:`_EllipticCurve._to_EC_KEY`.
3321 """
3322 curves = get_elliptic_curves()
3323 if curves:
3324 curve = next(iter(curves))
3325 # It's not easy to assert anything about this object. However, see
3326 # leakcheck/crypto.py for a test that demonstrates it at least does
3327 # not leak memory.
3328 curve._to_EC_KEY()
3329
3330
Jean-Paul Calderone1be77082014-04-30 18:17:41 -04003331
3332class EllipticCurveFactory(object):
3333 """
3334 A helper to get the names of two curves.
3335 """
3336 def __init__(self):
3337 curves = iter(get_elliptic_curves())
3338 try:
3339 self.curve_name = next(curves).name
3340 self.another_curve_name = next(curves).name
3341 except StopIteration:
3342 self.curve_name = self.another_curve_name = None
3343
3344
3345
3346class EllipticCurveEqualityTests(TestCase, EqualityTestsMixin):
3347 """
3348 Tests :py:type:`_EllipticCurve`\ 's implementation of ``==`` and ``!=``.
3349 """
3350 curve_factory = EllipticCurveFactory()
3351
3352 if curve_factory.curve_name is None:
3353 skip = "There are no curves available there can be no curve objects."
3354
3355
3356 def anInstance(self):
3357 """
3358 Get the curve object for an arbitrary curve supported by the system.
3359 """
3360 return get_elliptic_curve(self.curve_factory.curve_name)
3361
3362
3363 def anotherInstance(self):
3364 """
3365 Get the curve object for an arbitrary curve supported by the system -
3366 but not the one returned by C{anInstance}.
3367 """
3368 return get_elliptic_curve(self.curve_factory.another_curve_name)
3369
3370
3371
Jean-Paul Calderone22c31242014-05-01 07:49:47 -04003372class EllipticCurveHashTests(TestCase):
3373 """
3374 Tests for :py:type:`_EllipticCurve`\ 's implementation of hashing (thus use
3375 as an item in a :py:type:`dict` or :py:type:`set`).
3376 """
3377 curve_factory = EllipticCurveFactory()
3378
3379 if curve_factory.curve_name is None:
3380 skip = "There are no curves available there can be no curve objects."
3381
3382
3383 def test_contains(self):
3384 """
3385 The ``in`` operator reports that a :py:type:`set` containing a curve
3386 does contain that curve.
3387 """
3388 curve = get_elliptic_curve(self.curve_factory.curve_name)
3389 curves = set([curve])
3390 self.assertIn(curve, curves)
3391
3392
3393 def test_does_not_contain(self):
3394 """
3395 The ``in`` operator reports that a :py:type:`set` not containing a
3396 curve does not contain that curve.
3397 """
3398 curve = get_elliptic_curve(self.curve_factory.curve_name)
3399 curves = set([get_elliptic_curve(self.curve_factory.another_curve_name)])
3400 self.assertNotIn(curve, curves)
3401
3402
3403
Rick Dean5b7b6372009-04-01 11:34:06 -05003404if __name__ == '__main__':
3405 main()