blob: 60f9e6afa7f074e28dacc24a1ee4e917cf422717 [file] [log] [blame]
Jean-Paul Calderone8671c852011-03-02 19:26:20 -05001# Copyright (c) Jean-Paul Calderone
2# See LICENSE file for details.
Jean-Paul Calderone8b63d452008-03-21 18:31:12 -04003
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -05004"""
Jonathan Ballet648875f2011-07-16 14:14:58 +09005Unit tests for :py:mod:`OpenSSL.crypto`.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -05006"""
7
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04008from unittest import main
9
Alex Gaynor4b9c96a2014-08-14 09:51:48 -070010import base64
11import os
12import re
Jean-Paul Calderone62ca8da2010-08-11 19:58:08 -040013from subprocess import PIPE, Popen
Rick Dean47262da2009-07-08 16:17:17 -050014from datetime import datetime, timedelta
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -050015
Jean-Paul Calderoneeb86f3a2014-04-19 09:45:57 -040016from six import u, b, binary_type
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050017
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -050018from OpenSSL.crypto import TYPE_RSA, TYPE_DSA, Error, PKey, PKeyType
Jean-Paul Calderone78381d22008-03-06 23:35:22 -050019from OpenSSL.crypto import X509, X509Type, X509Name, X509NameType
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080020from OpenSSL.crypto import X509Store, X509StoreType, X509Req, X509ReqType
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -050021from OpenSSL.crypto import X509Extension, X509ExtensionType
Rick Dean5b7b6372009-04-01 11:34:06 -050022from OpenSSL.crypto import load_certificate, load_privatekey
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -040023from OpenSSL.crypto import FILETYPE_PEM, FILETYPE_ASN1, FILETYPE_TEXT
Jean-Paul Calderone71919862009-04-01 13:01:19 -040024from OpenSSL.crypto import dump_certificate, load_certificate_request
25from OpenSSL.crypto import dump_certificate_request, dump_privatekey
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -040026from OpenSSL.crypto import PKCS7Type, load_pkcs7_data
Jean-Paul Calderone9178ee62010-01-25 17:55:30 -050027from OpenSSL.crypto import PKCS12, PKCS12Type, load_pkcs12
Rick Dean536ba022009-07-24 23:57:27 -050028from OpenSSL.crypto import CRL, Revoked, load_crl
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -040029from OpenSSL.crypto import NetscapeSPKI, NetscapeSPKIType
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040030from OpenSSL.crypto import (
31 sign, verify, get_elliptic_curve, get_elliptic_curves)
Jean-Paul Calderone1be77082014-04-30 18:17:41 -040032from OpenSSL.test.util import EqualityTestsMixin, TestCase
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040033from OpenSSL._util import native, lib
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040034
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -040035def normalize_certificate_pem(pem):
36 return dump_certificate(FILETYPE_PEM, load_certificate(FILETYPE_PEM, pem))
37
38
39def normalize_privatekey_pem(pem):
40 return dump_privatekey(FILETYPE_PEM, load_privatekey(FILETYPE_PEM, pem))
41
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040042
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050043GOOD_CIPHER = "blowfish"
44BAD_CIPHER = "zippers"
45
46GOOD_DIGEST = "MD5"
47BAD_DIGEST = "monkeys"
48
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040049root_cert_pem = b("""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -050050MIIC7TCCAlagAwIBAgIIPQzE4MbeufQwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE
51BhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdU
52ZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwIhgPMjAwOTAzMjUxMjM2
53NThaGA8yMDE3MDYxMTEyMzY1OFowWDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklM
54MRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9U
55ZXN0aW5nIFJvb3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPmaQumL
56urpE527uSEHdL1pqcDRmWzu+98Y6YHzT/J7KWEamyMCNZ6fRW1JCR782UQ8a07fy
572xXsKy4WdKaxyG8CcatwmXvpvRQ44dSANMihHELpANTdyVp6DCysED6wkQFurHlF
581dshEaJw8b/ypDhmbVIo6Ci1xvCJqivbLFnbAgMBAAGjgbswgbgwHQYDVR0OBBYE
59FINVdy1eIfFJDAkk51QJEo3IfgSuMIGIBgNVHSMEgYAwfoAUg1V3LV4h8UkMCSTn
60VAkSjch+BK6hXKRaMFgxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UE
61BxMHQ2hpY2FnbzEQMA4GA1UEChMHVGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBS
62b290IENBggg9DMTgxt659DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB
63AGGCDazMJGoWNBpc03u6+smc95dEead2KlZXBATOdFT1VesY3+nUOqZhEhTGlDMi
64hkgaZnzoIq/Uamidegk4hirsCT/R+6vsKAAxNTcBjUeZjlykCJWy5ojShGftXIKY
65w/njVbKMXrvc83qmTdGl3TAM0fxQIpqgcglFLveEBgzn
66-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040067""")
Rick Dean94e46fd2009-07-18 14:51:24 -050068
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040069root_key_pem = b("""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -050070MIICXQIBAAKBgQD5mkLpi7q6ROdu7khB3S9aanA0Zls7vvfGOmB80/yeylhGpsjA
71jWen0VtSQke/NlEPGtO38tsV7CsuFnSmschvAnGrcJl76b0UOOHUgDTIoRxC6QDU
723claegwsrBA+sJEBbqx5RdXbIRGicPG/8qQ4Zm1SKOgotcbwiaor2yxZ2wIDAQAB
73AoGBAPCgMpmLxzwDaUmcFbTJUvlLW1hoxNNYSu2jIZm1k/hRAcE60JYwvBkgz3UB
74yMEh0AtLxYe0bFk6EHah11tMUPgscbCq73snJ++8koUw+csk22G65hOs51bVb7Aa
756JBe67oLzdtvgCUFAA2qfrKzWRZzAdhUirQUZgySZk+Xq1pBAkEA/kZG0A6roTSM
76BVnx7LnPfsycKUsTumorpXiylZJjTi9XtmzxhrYN6wgZlDOOwOLgSQhszGpxVoMD
77u3gByT1b2QJBAPtL3mSKdvwRu/+40zaZLwvSJRxaj0mcE4BJOS6Oqs/hS1xRlrNk
78PpQ7WJ4yM6ZOLnXzm2mKyxm50Mv64109FtMCQQDOqS2KkjHaLowTGVxwC0DijMfr
79I9Lf8sSQk32J5VWCySWf5gGTfEnpmUa41gKTMJIbqZZLucNuDcOtzUaeWZlZAkA8
80ttXigLnCqR486JDPTi9ZscoZkZ+w7y6e/hH8t6d5Vjt48JVyfjPIaJY+km58LcN3
816AWSeGAdtRFHVzR7oHjVAkB4hutvxiOeiIVQNBhM6RSI9aBPMI21DoX2JRoxvNW2
82cbvAhow217X9V0dVerEOKxnNYspXRrh36h7k4mQA+sDq
83-----END RSA PRIVATE KEY-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040084""")
Rick Dean94e46fd2009-07-18 14:51:24 -050085
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040086server_cert_pem = b("""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -050087MIICKDCCAZGgAwIBAgIJAJn/HpR21r/8MA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
88BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
89VGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBSb290IENBMCIYDzIwMDkwMzI1MTIz
90NzUzWhgPMjAxNzA2MTExMjM3NTNaMBgxFjAUBgNVBAMTDWxvdmVseSBzZXJ2ZXIw
91gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAL6m+G653V0tpBC/OKl22VxOi2Cv
92lK4TYu9LHSDP9uDVTe7V5D5Tl6qzFoRRx5pfmnkqT5B+W9byp2NU3FC5hLm5zSAr
93b45meUhjEJ/ifkZgbNUjHdBIGP9MAQUHZa5WKdkGIJvGAvs8UzUqlr4TBWQIB24+
94lJ+Ukk/CRgasrYwdAgMBAAGjNjA0MB0GA1UdDgQWBBS4kC7Ij0W1TZXZqXQFAM2e
95gKEG2DATBgNVHSUEDDAKBggrBgEFBQcDATANBgkqhkiG9w0BAQUFAAOBgQBh30Li
96dJ+NlxIOx5343WqIBka3UbsOb2kxWrbkVCrvRapCMLCASO4FqiKWM+L0VDBprqIp
972mgpFQ6FHpoIENGvJhdEKpptQ5i7KaGhnDNTfdy3x1+h852G99f1iyj0RmbuFcM8
98uzujnS8YXWvM7DM1Ilozk4MzPug8jzFp5uhKCQ==
99-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400100""")
Rick Dean94e46fd2009-07-18 14:51:24 -0500101
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -0400102server_key_pem = normalize_privatekey_pem(b("""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500103MIICWwIBAAKBgQC+pvhuud1dLaQQvzipdtlcTotgr5SuE2LvSx0gz/bg1U3u1eQ+
104U5eqsxaEUceaX5p5Kk+QflvW8qdjVNxQuYS5uc0gK2+OZnlIYxCf4n5GYGzVIx3Q
105SBj/TAEFB2WuVinZBiCbxgL7PFM1Kpa+EwVkCAduPpSflJJPwkYGrK2MHQIDAQAB
106AoGAbwuZ0AR6JveahBaczjfnSpiFHf+mve2UxoQdpyr6ROJ4zg/PLW5K/KXrC48G
107j6f3tXMrfKHcpEoZrQWUfYBRCUsGD5DCazEhD8zlxEHahIsqpwA0WWssJA2VOLEN
108j6DuV2pCFbw67rfTBkTSo32ahfXxEKev5KswZk0JIzH3ooECQQDgzS9AI89h0gs8
109Dt+1m11Rzqo3vZML7ZIyGApUzVan+a7hbc33nbGRkAXjHaUBJO31it/H6dTO+uwX
110msWwNG5ZAkEA2RyFKs5xR5USTFaKLWCgpH/ydV96KPOpBND7TKQx62snDenFNNbn
111FwwOhpahld+vqhYk+pfuWWUpQciE+Bu7ZQJASjfT4sQv4qbbKK/scePicnDdx9th
1124e1EeB9xwb+tXXXUo/6Bor/AcUNwfiQ6Zt9PZOK9sR3lMZSsP7rMi7kzuQJABie6
1131sXXjFH7nNJvRG4S39cIxq8YRYTy68II/dlB2QzGpKxV/POCxbJ/zu0CU79tuYK7
114NaeNCFfH3aeTrX0LyQJAMBWjWmeKM2G2sCExheeQK0ROnaBC8itCECD4Jsve4nqf
115r50+LF74iLXFwqysVCebPKMOpDWp/qQ1BbJQIPs7/A==
116-----END RSA PRIVATE KEY-----
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -0400117"""))
Rick Dean94e46fd2009-07-18 14:51:24 -0500118
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400119client_cert_pem = b("""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500120MIICJjCCAY+gAwIBAgIJAKxpFI5lODkjMA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
121BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
122VGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBSb290IENBMCIYDzIwMDkwMzI1MTIz
123ODA1WhgPMjAxNzA2MTExMjM4MDVaMBYxFDASBgNVBAMTC3VnbHkgY2xpZW50MIGf
124MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDAZh/SRtNm5ntMT4qb6YzEpTroMlq2
125rn+GrRHRiZ+xkCw/CGNhbtPir7/QxaUj26BSmQrHw1bGKEbPsWiW7bdXSespl+xK
126iku4G/KvnnmWdeJHqsiXeUZtqurMELcPQAw9xPHEuhqqUJvvEoMTsnCEqGM+7Dtb
127oCRajYyHfluARQIDAQABozYwNDAdBgNVHQ4EFgQUNQB+qkaOaEVecf1J3TTUtAff
1280fAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQEFBQADgYEAyv/Jh7gM
129Q3OHvmsFEEvRI+hsW8y66zK4K5de239Y44iZrFYkt7Q5nBPMEWDj4F2hLYWL/qtI
1309Zdr0U4UDCU9SmmGYh4o7R4TZ5pGFvBYvjhHbkSFYFQXZxKUi+WUxplP6I0wr2KJ
131PSTJCjJOn3xo2NTKRgV1gaoTf2EhL+RG8TQ=
132-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400133""")
Rick Dean94e46fd2009-07-18 14:51:24 -0500134
Jean-Paul Calderone22cbe502011-05-04 17:01:43 -0400135client_key_pem = normalize_privatekey_pem(b("""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500136MIICXgIBAAKBgQDAZh/SRtNm5ntMT4qb6YzEpTroMlq2rn+GrRHRiZ+xkCw/CGNh
137btPir7/QxaUj26BSmQrHw1bGKEbPsWiW7bdXSespl+xKiku4G/KvnnmWdeJHqsiX
138eUZtqurMELcPQAw9xPHEuhqqUJvvEoMTsnCEqGM+7DtboCRajYyHfluARQIDAQAB
139AoGATkZ+NceY5Glqyl4mD06SdcKfV65814vg2EL7V9t8+/mi9rYL8KztSXGlQWPX
140zuHgtRoMl78yQ4ZJYOBVo+nsx8KZNRCEBlE19bamSbQLCeQMenWnpeYyQUZ908gF
141h6L9qsFVJepgA9RDgAjyDoS5CaWCdCCPCH2lDkdcqC54SVUCQQDseuduc4wi8h4t
142V8AahUn9fn9gYfhoNuM0gdguTA0nPLVWz4hy1yJiWYQe0H7NLNNTmCKiLQaJpAbb
143TC6vE8C7AkEA0Ee8CMJUc20BnGEmxwgWcVuqFWaKCo8jTH1X38FlATUsyR3krjW2
144dL3yDD9NwHxsYP7nTKp/U8MV7U9IBn4y/wJBAJl7H0/BcLeRmuJk7IqJ7b635iYB
145D/9beFUw3MUXmQXZUfyYz39xf6CDZsu1GEdEC5haykeln3Of4M9d/4Kj+FcCQQCY
146si6xwT7GzMDkk/ko684AV3KPc/h6G0yGtFIrMg7J3uExpR/VdH2KgwMkZXisSMvw
147JJEQjOMCVsEJlRk54WWjAkEAzoZNH6UhDdBK5F38rVt/y4SEHgbSfJHIAmPS32Kq
148f6GGcfNpip0Uk7q7udTKuX7Q/buZi/C4YW7u3VKAquv9NA==
149-----END RSA PRIVATE KEY-----
Jean-Paul Calderone22cbe502011-05-04 17:01:43 -0400150"""))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400151
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400152cleartextCertificatePEM = b("""-----BEGIN CERTIFICATE-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400153MIIC7TCCAlagAwIBAgIIPQzE4MbeufQwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE
154BhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdU
155ZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwIhgPMjAwOTAzMjUxMjM2
156NThaGA8yMDE3MDYxMTEyMzY1OFowWDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklM
157MRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9U
158ZXN0aW5nIFJvb3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPmaQumL
159urpE527uSEHdL1pqcDRmWzu+98Y6YHzT/J7KWEamyMCNZ6fRW1JCR782UQ8a07fy
1602xXsKy4WdKaxyG8CcatwmXvpvRQ44dSANMihHELpANTdyVp6DCysED6wkQFurHlF
1611dshEaJw8b/ypDhmbVIo6Ci1xvCJqivbLFnbAgMBAAGjgbswgbgwHQYDVR0OBBYE
162FINVdy1eIfFJDAkk51QJEo3IfgSuMIGIBgNVHSMEgYAwfoAUg1V3LV4h8UkMCSTn
163VAkSjch+BK6hXKRaMFgxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UE
164BxMHQ2hpY2FnbzEQMA4GA1UEChMHVGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBS
165b290IENBggg9DMTgxt659DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB
166AGGCDazMJGoWNBpc03u6+smc95dEead2KlZXBATOdFT1VesY3+nUOqZhEhTGlDMi
167hkgaZnzoIq/Uamidegk4hirsCT/R+6vsKAAxNTcBjUeZjlykCJWy5ojShGftXIKY
168w/njVbKMXrvc83qmTdGl3TAM0fxQIpqgcglFLveEBgzn
169-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400170""")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400171
Jean-Paul Calderoned50d2042011-05-04 17:00:49 -0400172cleartextPrivateKeyPEM = normalize_privatekey_pem(b("""\
173-----BEGIN RSA PRIVATE KEY-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400174MIICXQIBAAKBgQD5mkLpi7q6ROdu7khB3S9aanA0Zls7vvfGOmB80/yeylhGpsjA
175jWen0VtSQke/NlEPGtO38tsV7CsuFnSmschvAnGrcJl76b0UOOHUgDTIoRxC6QDU
1763claegwsrBA+sJEBbqx5RdXbIRGicPG/8qQ4Zm1SKOgotcbwiaor2yxZ2wIDAQAB
177AoGBAPCgMpmLxzwDaUmcFbTJUvlLW1hoxNNYSu2jIZm1k/hRAcE60JYwvBkgz3UB
178yMEh0AtLxYe0bFk6EHah11tMUPgscbCq73snJ++8koUw+csk22G65hOs51bVb7Aa
1796JBe67oLzdtvgCUFAA2qfrKzWRZzAdhUirQUZgySZk+Xq1pBAkEA/kZG0A6roTSM
180BVnx7LnPfsycKUsTumorpXiylZJjTi9XtmzxhrYN6wgZlDOOwOLgSQhszGpxVoMD
181u3gByT1b2QJBAPtL3mSKdvwRu/+40zaZLwvSJRxaj0mcE4BJOS6Oqs/hS1xRlrNk
182PpQ7WJ4yM6ZOLnXzm2mKyxm50Mv64109FtMCQQDOqS2KkjHaLowTGVxwC0DijMfr
183I9Lf8sSQk32J5VWCySWf5gGTfEnpmUa41gKTMJIbqZZLucNuDcOtzUaeWZlZAkA8
184ttXigLnCqR486JDPTi9ZscoZkZ+w7y6e/hH8t6d5Vjt48JVyfjPIaJY+km58LcN3
1856AWSeGAdtRFHVzR7oHjVAkB4hutvxiOeiIVQNBhM6RSI9aBPMI21DoX2JRoxvNW2
186cbvAhow217X9V0dVerEOKxnNYspXRrh36h7k4mQA+sDq
187-----END RSA PRIVATE KEY-----
Jean-Paul Calderoned50d2042011-05-04 17:00:49 -0400188"""))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400189
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400190cleartextCertificateRequestPEM = b("""-----BEGIN CERTIFICATE REQUEST-----
191MIIBnjCCAQcCAQAwXjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQH
192EwdDaGljYWdvMRcwFQYDVQQKEw5NeSBDb21wYW55IEx0ZDEXMBUGA1UEAxMORnJl
193ZGVyaWNrIERlYW4wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANp6Y17WzKSw
194BsUWkXdqg6tnXy8H8hA1msCMWpc+/2KJ4mbv5NyD6UD+/SqagQqulPbF/DFea9nA
195E0zhmHJELcM8gUTIlXv/cgDWnmK4xj8YkjVUiCdqKRAKeuzLG1pGmwwF5lGeJpXN
196xQn5ecR0UYSOWj6TTGXB9VyUMQzCClcBAgMBAAGgADANBgkqhkiG9w0BAQUFAAOB
197gQAAJGuF/R/GGbeC7FbFW+aJgr9ee0Xbl6nlhu7pTe67k+iiKT2dsl2ti68MVTnu
198Vrb3HUNqOkiwsJf6kCtq5oPn3QVYzTa76Dt2y3Rtzv6boRSlmlfrgS92GNma8JfR
199oICQk3nAudi6zl1Dix3BCv1pUp5KMtGn3MeDEi6QFGy2rA==
200-----END CERTIFICATE REQUEST-----
201""")
Rick Dean5b7b6372009-04-01 11:34:06 -0500202
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400203encryptedPrivateKeyPEM = b("""-----BEGIN RSA PRIVATE KEY-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400204Proc-Type: 4,ENCRYPTED
205DEK-Info: DES-EDE3-CBC,9573604A18579E9E
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400206
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400207SHOho56WxDkT0ht10UTeKc0F5u8cqIa01kzFAmETw0MAs8ezYtK15NPdCXUm3X/2
208a17G7LSF5bkxOgZ7vpXyMzun/owrj7CzvLxyncyEFZWvtvzaAhPhvTJtTIB3kf8B
2098+qRcpTGK7NgXEgYBW5bj1y4qZkD4zCL9o9NQzsKI3Ie8i0239jsDOWR38AxjXBH
210mGwAQ4Z6ZN5dnmM4fhMIWsmFf19sNyAML4gHenQCHhmXbjXeVq47aC2ProInJbrm
211+00TcisbAQ40V9aehVbcDKtS4ZbMVDwncAjpXpcncC54G76N6j7F7wL7L/FuXa3A
212fvSVy9n2VfF/pJ3kYSflLHH2G/DFxjF7dl0GxhKPxJjp3IJi9VtuvmN9R2jZWLQF
213tfC8dXgy/P9CfFQhlinqBTEwgH0oZ/d4k4NVFDSdEMaSdmBAjlHpc+Vfdty3HVnV
214rKXj//wslsFNm9kIwJGIgKUa/n2jsOiydrsk1mgH7SmNCb3YHgZhbbnq0qLat/HC
215gHDt3FHpNQ31QzzL3yrenFB2L9osIsnRsDTPFNi4RX4SpDgNroxOQmyzCCV6H+d4
216o1mcnNiZSdxLZxVKccq0AfRpHqpPAFnJcQHP6xyT9MZp6fBa0XkxDnt9kNU8H3Qw
2177SJWZ69VXjBUzMlQViLuaWMgTnL+ZVyFZf9hTF7U/ef4HMLMAVNdiaGG+G+AjCV/
218MbzjS007Oe4qqBnCWaFPSnJX6uLApeTbqAxAeyCql56ULW5x6vDMNC3dwjvS/CEh
21911n8RkgFIQA0AhuKSIg3CbuartRsJnWOLwgLTzsrKYL4yRog1RJrtw==
220-----END RSA PRIVATE KEY-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400221""")
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400222
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400223encryptedPrivateKeyPEMPassphrase = b("foobar")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400224
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400225# Some PKCS#7 stuff. Generated with the openssl command line:
226#
227# openssl crl2pkcs7 -inform pem -outform pem -certfile s.pem -nocrl
228#
229# with a certificate and key (but the key should be irrelevant) in s.pem
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400230pkcs7Data = b("""\
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400231-----BEGIN PKCS7-----
232MIIDNwYJKoZIhvcNAQcCoIIDKDCCAyQCAQExADALBgkqhkiG9w0BBwGgggMKMIID
233BjCCAm+gAwIBAgIBATANBgkqhkiG9w0BAQQFADB7MQswCQYDVQQGEwJTRzERMA8G
234A1UEChMITTJDcnlwdG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtN
235MkNyeXB0byBDZXJ0aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNA
236cG9zdDEuY29tMB4XDTAwMDkxMDA5NTEzMFoXDTAyMDkxMDA5NTEzMFowUzELMAkG
237A1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwlsb2NhbGhvc3Qx
238HTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tMFwwDQYJKoZIhvcNAQEBBQAD
239SwAwSAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh5kwI
240zOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEAAaOCAQQwggEAMAkGA1UdEwQCMAAw
241LAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0G
242A1UdDgQWBBTPhIKSvnsmYsBVNWjj0m3M2z0qVTCBpQYDVR0jBIGdMIGagBT7hyNp
24365w6kxXlxb8pUU/+7Sg4AaF/pH0wezELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0y
244Q3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlwdG8g
245Q2VydGlmaWNhdGUgTWFzdGVyMR0wGwYJKoZIhvcNAQkBFg5uZ3BzQHBvc3QxLmNv
246bYIBADANBgkqhkiG9w0BAQQFAAOBgQA7/CqT6PoHycTdhEStWNZde7M/2Yc6BoJu
247VwnW8YxGO8Sn6UJ4FeffZNcYZddSDKosw8LtPOeWoK3JINjAk5jiPQ2cww++7QGG
248/g5NDjxFZNDJP1dGiLAxPW6JXwov4v0FmdzfLOZ01jDcgQQZqEpYlgpuI5JEWUQ9
249Ho4EzbYCOaEAMQA=
250-----END PKCS7-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400251""")
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400252
Alex Gaynor8fa1dd62014-08-14 09:57:51 -0700253pkcs7DataASN1 = base64.b64decode(b"""
Alex Gaynor4b9c96a2014-08-14 09:51:48 -0700254MIIDNwYJKoZIhvcNAQcCoIIDKDCCAyQCAQExADALBgkqhkiG9w0BBwGgggMKMIID
255BjCCAm+gAwIBAgIBATANBgkqhkiG9w0BAQQFADB7MQswCQYDVQQGEwJTRzERMA8G
256A1UEChMITTJDcnlwdG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtN
257MkNyeXB0byBDZXJ0aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNA
258cG9zdDEuY29tMB4XDTAwMDkxMDA5NTEzMFoXDTAyMDkxMDA5NTEzMFowUzELMAkG
259A1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwlsb2NhbGhvc3Qx
260HTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tMFwwDQYJKoZIhvcNAQEBBQAD
261SwAwSAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh5kwI
262zOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEAAaOCAQQwggEAMAkGA1UdEwQCMAAw
263LAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0G
264A1UdDgQWBBTPhIKSvnsmYsBVNWjj0m3M2z0qVTCBpQYDVR0jBIGdMIGagBT7hyNp
26565w6kxXlxb8pUU/+7Sg4AaF/pH0wezELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0y
266Q3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlwdG8g
267Q2VydGlmaWNhdGUgTWFzdGVyMR0wGwYJKoZIhvcNAQkBFg5uZ3BzQHBvc3QxLmNv
268bYIBADANBgkqhkiG9w0BAQQFAAOBgQA7/CqT6PoHycTdhEStWNZde7M/2Yc6BoJu
269VwnW8YxGO8Sn6UJ4FeffZNcYZddSDKosw8LtPOeWoK3JINjAk5jiPQ2cww++7QGG
270/g5NDjxFZNDJP1dGiLAxPW6JXwov4v0FmdzfLOZ01jDcgQQZqEpYlgpuI5JEWUQ9
271Ho4EzbYCOaEAMQA=
Alex Gaynor8fa1dd62014-08-14 09:57:51 -0700272""")
Alex Gaynor4b9c96a2014-08-14 09:51:48 -0700273
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400274crlData = b("""\
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -0500275-----BEGIN X509 CRL-----
276MIIBWzCBxTANBgkqhkiG9w0BAQQFADBYMQswCQYDVQQGEwJVUzELMAkGA1UECBMC
277SUwxEDAOBgNVBAcTB0NoaWNhZ28xEDAOBgNVBAoTB1Rlc3RpbmcxGDAWBgNVBAMT
278D1Rlc3RpbmcgUm9vdCBDQRcNMDkwNzI2MDQzNDU2WhcNMTIwOTI3MDI0MTUyWjA8
279MBUCAgOrGA8yMDA5MDcyNTIzMzQ1NlowIwICAQAYDzIwMDkwNzI1MjMzNDU2WjAM
280MAoGA1UdFQQDCgEEMA0GCSqGSIb3DQEBBAUAA4GBAEBt7xTs2htdD3d4ErrcGAw1
2814dKcVnIWTutoI7xxen26Wwvh8VCsT7i/UeP+rBl9rC/kfjWjzQk3/zleaarGTpBT
2820yp4HXRFFoRhhSE/hP+eteaPXRgrsNRLHe9ZDd69wmh7J1wMDb0m81RG7kqcbsid
283vrzEeLDRiiPl92dyyWmu
284-----END X509 CRL-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400285""")
Jean-Paul Calderonee890db32010-08-22 16:55:15 -0400286
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400287
288# A broken RSA private key which can be used to test the error path through
289# PKey.check.
290inconsistentPrivateKeyPEM = b("""-----BEGIN RSA PRIVATE KEY-----
291MIIBPAIBAAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh
2925kwIzOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEaAQJBAIqm/bz4NA1H++Vx5Ewx
293OcKp3w19QSaZAwlGRtsUxrP7436QjnREM3Bm8ygU11BjkPVmtrKm6AayQfCHqJoT
294zIECIQDW0BoMoL0HOYM/mrTLhaykYAVqgIeJsPjvkEhTFXWBuQIhAM3deFAvWNu4
295nklUQ37XsCT2c9tmNt1LAT+slG2JOTTRAiAuXDtC/m3NYVwyHfFm+zKHRzHkClk2
296HjubeEgjpj32AQIhAJqMGTaZVOwevTXvvHwNeH+vRWsAYU/gbx+OQB+7VOcBAiEA
297oolb6NMg/R3enNPvS1O4UU1H8wpaF77L4yiSWlE0p4w=
298-----END RSA PRIVATE KEY-----
299""")
300
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -0400301# certificate with NULL bytes in subjectAltName and common name
302
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400303nulbyteSubjectAltNamePEM = b("""-----BEGIN CERTIFICATE-----
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -0400304MIIE2DCCA8CgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBxTELMAkGA1UEBhMCVVMx
305DzANBgNVBAgMBk9yZWdvbjESMBAGA1UEBwwJQmVhdmVydG9uMSMwIQYDVQQKDBpQ
306eXRob24gU29mdHdhcmUgRm91bmRhdGlvbjEgMB4GA1UECwwXUHl0aG9uIENvcmUg
307RGV2ZWxvcG1lbnQxJDAiBgNVBAMMG251bGwucHl0aG9uLm9yZwBleGFtcGxlLm9y
308ZzEkMCIGCSqGSIb3DQEJARYVcHl0aG9uLWRldkBweXRob24ub3JnMB4XDTEzMDgw
309NzEzMTE1MloXDTEzMDgwNzEzMTI1MlowgcUxCzAJBgNVBAYTAlVTMQ8wDQYDVQQI
310DAZPcmVnb24xEjAQBgNVBAcMCUJlYXZlcnRvbjEjMCEGA1UECgwaUHl0aG9uIFNv
311ZnR3YXJlIEZvdW5kYXRpb24xIDAeBgNVBAsMF1B5dGhvbiBDb3JlIERldmVsb3Bt
312ZW50MSQwIgYDVQQDDBtudWxsLnB5dGhvbi5vcmcAZXhhbXBsZS5vcmcxJDAiBgkq
313hkiG9w0BCQEWFXB5dGhvbi1kZXZAcHl0aG9uLm9yZzCCASIwDQYJKoZIhvcNAQEB
314BQADggEPADCCAQoCggEBALXq7cn7Rn1vO3aA3TrzA5QLp6bb7B3f/yN0CJ2XFj+j
315pHs+Gw6WWSUDpybiiKnPec33BFawq3kyblnBMjBU61ioy5HwQqVkJ8vUVjGIUq3P
316vX/wBmQfzCe4o4uM89gpHyUL9UYGG8oCRa17dgqcv7u5rg0Wq2B1rgY+nHwx3JIv
317KRrgSwyRkGzpN8WQ1yrXlxWjgI9de0mPVDDUlywcWze1q2kwaEPTM3hLAmD1PESA
318oY/n8A/RXoeeRs9i/Pm/DGUS8ZPINXk/yOzsR/XvvkTVroIeLZqfmFpnZeF0cHzL
31908LODkVJJ9zjLdT7SA4vnne4FEbAxDbKAq5qkYzaL4UCAwEAAaOB0DCBzTAMBgNV
320HRMBAf8EAjAAMB0GA1UdDgQWBBSIWlXAUv9hzVKjNQ/qWpwkOCL3XDALBgNVHQ8E
321BAMCBeAwgZAGA1UdEQSBiDCBhYIeYWx0bnVsbC5weXRob24ub3JnAGV4YW1wbGUu
322Y29tgSBudWxsQHB5dGhvbi5vcmcAdXNlckBleGFtcGxlLm9yZ4YpaHR0cDovL251
323bGwucHl0aG9uLm9yZwBodHRwOi8vZXhhbXBsZS5vcmeHBMAAAgGHECABDbgAAAAA
324AAAAAAAAAAEwDQYJKoZIhvcNAQEFBQADggEBAKxPRe99SaghcI6IWT7UNkJw9aO9
325i9eo0Fj2MUqxpKbdb9noRDy2CnHWf7EIYZ1gznXPdwzSN4YCjV5d+Q9xtBaowT0j
326HPERs1ZuytCNNJTmhyqZ8q6uzMLoht4IqH/FBfpvgaeC5tBTnTT0rD5A/olXeimk
327kX4LxlEx5RAvpGB2zZVRGr6LobD9rVK91xuHYNIxxxfEGE8tCCWjp0+3ksri9SXx
328VHWBnbM9YaL32u3hxm8sYB/Yb8WSBavJCWJJqRStVRHM1koZlJmXNx2BX4vPo6iW
329RFEIPQsFZRLrtnCAiEhyT8bC2s/Njlu6ly9gtJZWSV46Q3ZjBL4q9sHKqZQ=
330-----END CERTIFICATE-----""")
331
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400332
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400333class X509ExtTests(TestCase):
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400334 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900335 Tests for :py:class:`OpenSSL.crypto.X509Extension`.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400336 """
337
338 def setUp(self):
339 """
340 Create a new private key and start a certificate request (for a test
341 method to finish in one way or another).
342 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -0800343 super(X509ExtTests, self).setUp()
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400344 # Basic setup stuff to generate a certificate
345 self.pkey = PKey()
346 self.pkey.generate_key(TYPE_RSA, 384)
347 self.req = X509Req()
348 self.req.set_pubkey(self.pkey)
349 # Authority good you have.
350 self.req.get_subject().commonName = "Yoda root CA"
351 self.x509 = X509()
352 self.subject = self.x509.get_subject()
353 self.subject.commonName = self.req.get_subject().commonName
354 self.x509.set_issuer(self.subject)
355 self.x509.set_pubkey(self.pkey)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400356 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
357 expire = b((datetime.now() + timedelta(days=100)).strftime("%Y%m%d%H%M%SZ"))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400358 self.x509.set_notBefore(now)
359 self.x509.set_notAfter(expire)
360
361
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -0800362 def tearDown(self):
363 """
364 Forget all of the pyOpenSSL objects so they can be garbage collected,
365 their memory released, and not interfere with the leak detection code.
366 """
367 self.pkey = self.req = self.x509 = self.subject = None
368 super(X509ExtTests, self).tearDown()
369
370
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400371 def test_str(self):
372 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900373 The string representation of :py:class:`X509Extension` instances as returned by
374 :py:data:`str` includes stuff.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400375 """
376 # This isn't necessarily the best string representation. Perhaps it
377 # will be changed/improved in the future.
378 self.assertEquals(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400379 str(X509Extension(b('basicConstraints'), True, b('CA:false'))),
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400380 'CA:FALSE')
381
382
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400383 def test_type(self):
384 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900385 :py:class:`X509Extension` and :py:class:`X509ExtensionType` refer to the same type object
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400386 and can be used to create instances of that type.
387 """
388 self.assertIdentical(X509Extension, X509ExtensionType)
389 self.assertConsistentType(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400390 X509Extension,
391 'X509Extension', b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400392
393
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500394 def test_construction(self):
395 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900396 :py:class:`X509Extension` accepts an extension type name, a critical flag,
397 and an extension value and returns an :py:class:`X509ExtensionType` instance.
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500398 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400399 basic = X509Extension(b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500400 self.assertTrue(
401 isinstance(basic, X509ExtensionType),
402 "%r is of type %r, should be %r" % (
403 basic, type(basic), X509ExtensionType))
404
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400405 comment = X509Extension(
406 b('nsComment'), False, b('pyOpenSSL unit test'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500407 self.assertTrue(
408 isinstance(comment, X509ExtensionType),
409 "%r is of type %r, should be %r" % (
410 comment, type(comment), X509ExtensionType))
411
412
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500413 def test_invalid_extension(self):
414 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900415 :py:class:`X509Extension` raises something if it is passed a bad extension
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500416 name or value.
417 """
418 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400419 Error, X509Extension, b('thisIsMadeUp'), False, b('hi'))
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500420 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400421 Error, X509Extension, b('basicConstraints'), False, b('blah blah'))
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500422
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500423 # Exercise a weird one (an extension which uses the r2i method). This
424 # exercises the codepath that requires a non-NULL ctx to be passed to
425 # X509V3_EXT_nconf. It can't work now because we provide no
426 # configuration database. It might be made to work in the future.
427 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400428 Error, X509Extension, b('proxyCertInfo'), True,
429 b('language:id-ppl-anyLanguage,pathlen:1,policy:text:AB'))
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500430
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500431
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500432 def test_get_critical(self):
433 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900434 :py:meth:`X509ExtensionType.get_critical` returns the value of the
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500435 extension's critical flag.
436 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400437 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500438 self.assertTrue(ext.get_critical())
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400439 ext = X509Extension(b('basicConstraints'), False, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500440 self.assertFalse(ext.get_critical())
441
Jean-Paul Calderone7535dab2008-03-06 18:53:11 -0500442
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500443 def test_get_short_name(self):
444 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900445 :py:meth:`X509ExtensionType.get_short_name` returns a string giving the short
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500446 type name of the extension.
447 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400448 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
449 self.assertEqual(ext.get_short_name(), b('basicConstraints'))
450 ext = X509Extension(b('nsComment'), True, b('foo bar'))
451 self.assertEqual(ext.get_short_name(), b('nsComment'))
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500452
453
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400454 def test_get_data(self):
455 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900456 :py:meth:`X509Extension.get_data` returns a string giving the data of the
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400457 extension.
458 """
459 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
460 # Expect to get back the DER encoded form of CA:true.
461 self.assertEqual(ext.get_data(), b('0\x03\x01\x01\xff'))
462
463
464 def test_get_data_wrong_args(self):
465 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900466 :py:meth:`X509Extension.get_data` raises :py:exc:`TypeError` if passed any arguments.
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400467 """
468 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
469 self.assertRaises(TypeError, ext.get_data, None)
470 self.assertRaises(TypeError, ext.get_data, "foo")
471 self.assertRaises(TypeError, ext.get_data, 7)
472
473
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400474 def test_unused_subject(self):
Rick Dean47262da2009-07-08 16:17:17 -0500475 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900476 The :py:data:`subject` parameter to :py:class:`X509Extension` may be provided for an
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400477 extension which does not use it and is ignored in this case.
Rick Dean47262da2009-07-08 16:17:17 -0500478 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400479 ext1 = X509Extension(
480 b('basicConstraints'), False, b('CA:TRUE'), subject=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400481 self.x509.add_extensions([ext1])
482 self.x509.sign(self.pkey, 'sha1')
483 # This is a little lame. Can we think of a better way?
484 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400485 self.assertTrue(b('X509v3 Basic Constraints:') in text)
486 self.assertTrue(b('CA:TRUE') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400487
488
489 def test_subject(self):
490 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900491 If an extension requires a subject, the :py:data:`subject` parameter to
492 :py:class:`X509Extension` provides its value.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400493 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400494 ext3 = X509Extension(
495 b('subjectKeyIdentifier'), False, b('hash'), subject=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400496 self.x509.add_extensions([ext3])
497 self.x509.sign(self.pkey, 'sha1')
498 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400499 self.assertTrue(b('X509v3 Subject Key Identifier:') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400500
501
502 def test_missing_subject(self):
503 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900504 If an extension requires a subject and the :py:data:`subject` parameter is
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400505 given no value, something happens.
506 """
507 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400508 Error, X509Extension, b('subjectKeyIdentifier'), False, b('hash'))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400509
510
511 def test_invalid_subject(self):
512 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900513 If the :py:data:`subject` parameter is given a value which is not an
514 :py:class:`X509` instance, :py:exc:`TypeError` is raised.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400515 """
516 for badObj in [True, object(), "hello", [], self]:
517 self.assertRaises(
518 TypeError,
519 X509Extension,
520 'basicConstraints', False, 'CA:TRUE', subject=badObj)
521
522
523 def test_unused_issuer(self):
524 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900525 The :py:data:`issuer` parameter to :py:class:`X509Extension` may be provided for an
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400526 extension which does not use it and is ignored in this case.
527 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400528 ext1 = X509Extension(
529 b('basicConstraints'), False, b('CA:TRUE'), issuer=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400530 self.x509.add_extensions([ext1])
531 self.x509.sign(self.pkey, 'sha1')
532 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400533 self.assertTrue(b('X509v3 Basic Constraints:') in text)
534 self.assertTrue(b('CA:TRUE') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400535
536
537 def test_issuer(self):
538 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900539 If an extension requires a issuer, the :py:data:`issuer` parameter to
540 :py:class:`X509Extension` provides its value.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400541 """
542 ext2 = X509Extension(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400543 b('authorityKeyIdentifier'), False, b('issuer:always'),
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400544 issuer=self.x509)
545 self.x509.add_extensions([ext2])
546 self.x509.sign(self.pkey, 'sha1')
547 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400548 self.assertTrue(b('X509v3 Authority Key Identifier:') in text)
549 self.assertTrue(b('DirName:/CN=Yoda root CA') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400550
551
552 def test_missing_issuer(self):
553 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900554 If an extension requires an issue and the :py:data:`issuer` parameter is given
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400555 no value, something happens.
556 """
557 self.assertRaises(
558 Error,
559 X509Extension,
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400560 b('authorityKeyIdentifier'), False,
561 b('keyid:always,issuer:always'))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400562
563
564 def test_invalid_issuer(self):
565 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900566 If the :py:data:`issuer` parameter is given a value which is not an
567 :py:class:`X509` instance, :py:exc:`TypeError` is raised.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400568 """
569 for badObj in [True, object(), "hello", [], self]:
570 self.assertRaises(
571 TypeError,
572 X509Extension,
573 'authorityKeyIdentifier', False, 'keyid:always,issuer:always',
574 issuer=badObj)
Rick Dean47262da2009-07-08 16:17:17 -0500575
576
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500577
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400578class PKeyTests(TestCase):
Jean-Paul Calderoneac930e12008-03-06 18:50:51 -0500579 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900580 Unit tests for :py:class:`OpenSSL.crypto.PKey`.
Jean-Paul Calderoneac930e12008-03-06 18:50:51 -0500581 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400582 def test_type(self):
583 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900584 :py:class:`PKey` and :py:class:`PKeyType` refer to the same type object
585 and can be used to create instances of that type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400586 """
587 self.assertIdentical(PKey, PKeyType)
588 self.assertConsistentType(PKey, 'PKey')
589
590
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500591 def test_construction(self):
592 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900593 :py:class:`PKey` takes no arguments and returns a new :py:class:`PKey` instance.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500594 """
595 self.assertRaises(TypeError, PKey, None)
596 key = PKey()
597 self.assertTrue(
598 isinstance(key, PKeyType),
599 "%r is of type %r, should be %r" % (key, type(key), PKeyType))
600
601
602 def test_pregeneration(self):
603 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900604 :py:attr:`PKeyType.bits` and :py:attr:`PKeyType.type` return :py:data:`0` before the key is
605 generated. :py:attr:`PKeyType.check` raises :py:exc:`TypeError` before the key is
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500606 generated.
607 """
608 key = PKey()
609 self.assertEqual(key.type(), 0)
610 self.assertEqual(key.bits(), 0)
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400611 self.assertRaises(TypeError, key.check)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500612
613
614 def test_failedGeneration(self):
615 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900616 :py:meth:`PKeyType.generate_key` takes two arguments, the first giving the key
617 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 -0500618 number of bits to generate. If an invalid type is specified or
Jonathan Ballet648875f2011-07-16 14:14:58 +0900619 generation fails, :py:exc:`Error` is raised. If an invalid number of bits is
620 specified, :py:exc:`ValueError` or :py:exc:`Error` is raised.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500621 """
622 key = PKey()
623 self.assertRaises(TypeError, key.generate_key)
624 self.assertRaises(TypeError, key.generate_key, 1, 2, 3)
625 self.assertRaises(TypeError, key.generate_key, "foo", "bar")
626 self.assertRaises(Error, key.generate_key, -1, 0)
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500627
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500628 self.assertRaises(ValueError, key.generate_key, TYPE_RSA, -1)
629 self.assertRaises(ValueError, key.generate_key, TYPE_RSA, 0)
Jean-Paul Calderoned71fe982008-03-06 00:31:50 -0500630
631 # XXX RSA generation for small values of bits is fairly buggy in a wide
632 # range of OpenSSL versions. I need to figure out what the safe lower
633 # bound for a reasonable number of OpenSSL versions is and explicitly
634 # check for that in the wrapper. The failure behavior is typically an
635 # infinite loop inside OpenSSL.
636
637 # self.assertRaises(Error, key.generate_key, TYPE_RSA, 2)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500638
639 # XXX DSA generation seems happy with any number of bits. The DSS
640 # says bits must be between 512 and 1024 inclusive. OpenSSL's DSA
641 # generator doesn't seem to care about the upper limit at all. For
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500642 # the lower limit, it uses 512 if anything smaller is specified.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500643 # So, it doesn't seem possible to make generate_key fail for
644 # TYPE_DSA with a bits argument which is at least an int.
645
646 # self.assertRaises(Error, key.generate_key, TYPE_DSA, -7)
647
648
649 def test_rsaGeneration(self):
650 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900651 :py:meth:`PKeyType.generate_key` generates an RSA key when passed
652 :py:data:`TYPE_RSA` as a type and a reasonable number of bits.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500653 """
654 bits = 128
655 key = PKey()
656 key.generate_key(TYPE_RSA, bits)
657 self.assertEqual(key.type(), TYPE_RSA)
658 self.assertEqual(key.bits(), bits)
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -0400659 self.assertTrue(key.check())
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500660
661
662 def test_dsaGeneration(self):
663 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900664 :py:meth:`PKeyType.generate_key` generates a DSA key when passed
665 :py:data:`TYPE_DSA` as a type and a reasonable number of bits.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500666 """
667 # 512 is a magic number. The DSS (Digital Signature Standard)
668 # allows a minimum of 512 bits for DSA. DSA_generate_parameters
669 # will silently promote any value below 512 to 512.
670 bits = 512
671 key = PKey()
672 key.generate_key(TYPE_DSA, bits)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800673 # self.assertEqual(key.type(), TYPE_DSA)
674 # self.assertEqual(key.bits(), bits)
675 # self.assertRaises(TypeError, key.check)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500676
677
678 def test_regeneration(self):
679 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900680 :py:meth:`PKeyType.generate_key` can be called multiple times on the same
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500681 key to generate new keys.
682 """
683 key = PKey()
684 for type, bits in [(TYPE_RSA, 512), (TYPE_DSA, 576)]:
685 key.generate_key(type, bits)
686 self.assertEqual(key.type(), type)
687 self.assertEqual(key.bits(), bits)
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500688
689
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400690 def test_inconsistentKey(self):
691 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900692 :py:`PKeyType.check` returns :py:exc:`Error` if the key is not consistent.
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400693 """
694 key = load_privatekey(FILETYPE_PEM, inconsistentPrivateKeyPEM)
Jean-Paul Calderoned338e4e2009-05-13 15:45:07 -0400695 self.assertRaises(Error, key.check)
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400696
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500697
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400698 def test_check_wrong_args(self):
699 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900700 :py:meth:`PKeyType.check` raises :py:exc:`TypeError` if called with any arguments.
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400701 """
702 self.assertRaises(TypeError, PKey().check, None)
703 self.assertRaises(TypeError, PKey().check, object())
704 self.assertRaises(TypeError, PKey().check, 1)
705
706
Jean-Paul Calderone02d01972011-10-31 10:39:29 -0400707 def test_check_public_key(self):
708 """
709 :py:meth:`PKeyType.check` raises :py:exc:`TypeError` if only the public
710 part of the key is available.
711 """
712 # A trick to get a public-only key
713 key = PKey()
714 key.generate_key(TYPE_RSA, 512)
715 cert = X509()
716 cert.set_pubkey(key)
717 pub = cert.get_pubkey()
718 self.assertRaises(TypeError, pub.check)
719
720
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400721
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400722class X509NameTests(TestCase):
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500723 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900724 Unit tests for :py:class:`OpenSSL.crypto.X509Name`.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500725 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500726 def _x509name(self, **attrs):
727 # XXX There's no other way to get a new X509Name yet.
728 name = X509().get_subject()
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400729 attrs = list(attrs.items())
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500730 # Make the order stable - order matters!
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400731 def key(attr):
732 return attr[1]
733 attrs.sort(key=key)
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500734 for k, v in attrs:
735 setattr(name, k, v)
736 return name
737
738
Rick Deane15b1472009-07-09 15:53:42 -0500739 def test_type(self):
740 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900741 The type of X509Name objects is :py:class:`X509NameType`.
Rick Deane15b1472009-07-09 15:53:42 -0500742 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400743 self.assertIdentical(X509Name, X509NameType)
744 self.assertEqual(X509NameType.__name__, 'X509Name')
745 self.assertTrue(isinstance(X509NameType, type))
746
Rick Deane15b1472009-07-09 15:53:42 -0500747 name = self._x509name()
748 self.assertTrue(
749 isinstance(name, X509NameType),
750 "%r is of type %r, should be %r" % (
751 name, type(name), X509NameType))
Rick Deane15b1472009-07-09 15:53:42 -0500752
753
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400754 def test_onlyStringAttributes(self):
755 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900756 Attempting to set a non-:py:data:`str` attribute name on an :py:class:`X509NameType`
757 instance causes :py:exc:`TypeError` to be raised.
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400758 """
759 name = self._x509name()
760 # Beyond these cases, you may also think that unicode should be
761 # rejected. Sorry, you're wrong. unicode is automatically converted to
762 # str outside of the control of X509Name, so there's no way to reject
763 # it.
Jean-Paul Calderoneff363be2013-03-03 10:21:23 -0800764
765 # Also, this used to test str subclasses, but that test is less relevant
766 # now that the implementation is in Python instead of C. Also PyPy
767 # automatically converts str subclasses to str when they are passed to
768 # setattr, so we can't test it on PyPy. Apparently CPython does this
769 # sometimes as well.
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400770 self.assertRaises(TypeError, setattr, name, None, "hello")
771 self.assertRaises(TypeError, setattr, name, 30, "hello")
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400772
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -0500773
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400774 def test_setInvalidAttribute(self):
775 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900776 Attempting to set any attribute name on an :py:class:`X509NameType` instance for
777 which no corresponding NID is defined causes :py:exc:`AttributeError` to be
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400778 raised.
779 """
780 name = self._x509name()
781 self.assertRaises(AttributeError, setattr, name, "no such thing", None)
782
783
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500784 def test_attributes(self):
785 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900786 :py:class:`X509NameType` instances have attributes for each standard (?)
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500787 X509Name field.
788 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500789 name = self._x509name()
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500790 name.commonName = "foo"
791 self.assertEqual(name.commonName, "foo")
792 self.assertEqual(name.CN, "foo")
793 name.CN = "baz"
794 self.assertEqual(name.commonName, "baz")
795 self.assertEqual(name.CN, "baz")
796 name.commonName = "bar"
797 self.assertEqual(name.commonName, "bar")
798 self.assertEqual(name.CN, "bar")
799 name.CN = "quux"
800 self.assertEqual(name.commonName, "quux")
801 self.assertEqual(name.CN, "quux")
802
803
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500804 def test_copy(self):
805 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900806 :py:class:`X509Name` creates a new :py:class:`X509NameType` instance with all the same
807 attributes as an existing :py:class:`X509NameType` instance when called with
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500808 one.
809 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500810 name = self._x509name(commonName="foo", emailAddress="bar@example.com")
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500811
812 copy = X509Name(name)
813 self.assertEqual(copy.commonName, "foo")
814 self.assertEqual(copy.emailAddress, "bar@example.com")
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500815
816 # Mutate the copy and ensure the original is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500817 copy.commonName = "baz"
818 self.assertEqual(name.commonName, "foo")
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500819
820 # Mutate the original and ensure the copy is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500821 name.emailAddress = "quux@example.com"
822 self.assertEqual(copy.emailAddress, "bar@example.com")
823
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500824
825 def test_repr(self):
826 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900827 :py:func:`repr` passed an :py:class:`X509NameType` instance should return a string
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500828 containing a description of the type and the NIDs which have been set
829 on it.
830 """
831 name = self._x509name(commonName="foo", emailAddress="bar")
832 self.assertEqual(
833 repr(name),
834 "<X509Name object '/emailAddress=bar/CN=foo'>")
835
836
837 def test_comparison(self):
838 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900839 :py:class:`X509NameType` instances should compare based on their NIDs.
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500840 """
841 def _equality(a, b, assertTrue, assertFalse):
842 assertTrue(a == b, "(%r == %r) --> False" % (a, b))
843 assertFalse(a != b)
844 assertTrue(b == a)
845 assertFalse(b != a)
846
847 def assertEqual(a, b):
848 _equality(a, b, self.assertTrue, self.assertFalse)
849
850 # Instances compare equal to themselves.
851 name = self._x509name()
852 assertEqual(name, name)
853
854 # Empty instances should compare equal to each other.
855 assertEqual(self._x509name(), self._x509name())
856
857 # Instances with equal NIDs should compare equal to each other.
858 assertEqual(self._x509name(commonName="foo"),
859 self._x509name(commonName="foo"))
860
861 # Instance with equal NIDs set using different aliases should compare
862 # equal to each other.
863 assertEqual(self._x509name(commonName="foo"),
864 self._x509name(CN="foo"))
865
866 # Instances with more than one NID with the same values should compare
867 # equal to each other.
868 assertEqual(self._x509name(CN="foo", organizationalUnitName="bar"),
869 self._x509name(commonName="foo", OU="bar"))
870
871 def assertNotEqual(a, b):
872 _equality(a, b, self.assertFalse, self.assertTrue)
873
874 # Instances with different values for the same NID should not compare
875 # equal to each other.
876 assertNotEqual(self._x509name(CN="foo"),
877 self._x509name(CN="bar"))
878
879 # Instances with different NIDs should not compare equal to each other.
880 assertNotEqual(self._x509name(CN="foo"),
881 self._x509name(OU="foo"))
882
883 def _inequality(a, b, assertTrue, assertFalse):
884 assertTrue(a < b)
885 assertTrue(a <= b)
886 assertTrue(b > a)
887 assertTrue(b >= a)
888 assertFalse(a > b)
889 assertFalse(a >= b)
890 assertFalse(b < a)
891 assertFalse(b <= a)
892
893 def assertLessThan(a, b):
894 _inequality(a, b, self.assertTrue, self.assertFalse)
895
896 # An X509Name with a NID with a value which sorts less than the value
897 # of the same NID on another X509Name compares less than the other
898 # X509Name.
899 assertLessThan(self._x509name(CN="abc"),
900 self._x509name(CN="def"))
901
902 def assertGreaterThan(a, b):
903 _inequality(a, b, self.assertFalse, self.assertTrue)
904
905 # An X509Name with a NID with a value which sorts greater than the
906 # value of the same NID on another X509Name compares greater than the
907 # other X509Name.
908 assertGreaterThan(self._x509name(CN="def"),
909 self._x509name(CN="abc"))
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -0500910
911
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400912 def test_hash(self):
913 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900914 :py:meth:`X509Name.hash` returns an integer hash based on the value of the
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400915 name.
916 """
917 a = self._x509name(CN="foo")
918 b = self._x509name(CN="foo")
919 self.assertEqual(a.hash(), b.hash())
920 a.CN = "bar"
921 self.assertNotEqual(a.hash(), b.hash())
922
923
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400924 def test_der(self):
925 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900926 :py:meth:`X509Name.der` returns the DER encoded form of the name.
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400927 """
928 a = self._x509name(CN="foo", C="US")
929 self.assertEqual(
930 a.der(),
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -0400931 b('0\x1b1\x0b0\t\x06\x03U\x04\x06\x13\x02US'
932 '1\x0c0\n\x06\x03U\x04\x03\x13\x03foo'))
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400933
934
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400935 def test_get_components(self):
936 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900937 :py:meth:`X509Name.get_components` returns a :py:data:`list` of
938 two-tuples of :py:data:`str`
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400939 giving the NIDs and associated values which make up the name.
940 """
941 a = self._x509name()
942 self.assertEqual(a.get_components(), [])
943 a.CN = "foo"
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -0400944 self.assertEqual(a.get_components(), [(b("CN"), b("foo"))])
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400945 a.organizationalUnitName = "bar"
946 self.assertEqual(
947 a.get_components(),
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -0400948 [(b("CN"), b("foo")), (b("OU"), b("bar"))])
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400949
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400950
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400951 def test_load_nul_byte_attribute(self):
952 """
Jean-Paul Calderone9af07b02013-08-23 16:07:31 -0400953 An :py:class:`OpenSSL.crypto.X509Name` from an
954 :py:class:`OpenSSL.crypto.X509` instance loaded from a file can have a
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400955 NUL byte in the value of one of its attributes.
956 """
957 cert = load_certificate(FILETYPE_PEM, nulbyteSubjectAltNamePEM)
958 subject = cert.get_subject()
959 self.assertEqual(
Jean-Paul Calderone06754fc2013-08-23 15:47:47 -0400960 "null.python.org\x00example.org", subject.commonName)
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400961
962
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -0500963 def test_setAttributeFailure(self):
964 """
965 If the value of an attribute cannot be set for some reason then
966 :py:class:`OpenSSL.crypto.Error` is raised.
967 """
968 name = self._x509name()
969 # This value is too long
970 self.assertRaises(Error, setattr, name, "O", b"x" * 512)
971
972
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400973
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400974class _PKeyInteractionTestsMixin:
975 """
976 Tests which involve another thing and a PKey.
977 """
978 def signable(self):
979 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900980 Return something with a :py:meth:`set_pubkey`, :py:meth:`set_pubkey`,
981 and :py:meth:`sign` method.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400982 """
983 raise NotImplementedError()
984
985
986 def test_signWithUngenerated(self):
987 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900988 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when pass a
989 :py:class:`PKey` with no parts.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400990 """
991 request = self.signable()
992 key = PKey()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500993 self.assertRaises(ValueError, request.sign, key, GOOD_DIGEST)
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400994
995
996 def test_signWithPublicKey(self):
997 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900998 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when pass a
999 :py:class:`PKey` with no private part as the signing key.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001000 """
1001 request = self.signable()
1002 key = PKey()
1003 key.generate_key(TYPE_RSA, 512)
1004 request.set_pubkey(key)
1005 pub = request.get_pubkey()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001006 self.assertRaises(ValueError, request.sign, pub, GOOD_DIGEST)
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001007
1008
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -04001009 def test_signWithUnknownDigest(self):
1010 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001011 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when passed a digest name which is
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -04001012 not known.
1013 """
1014 request = self.signable()
1015 key = PKey()
1016 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001017 self.assertRaises(ValueError, request.sign, key, BAD_DIGEST)
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -04001018
1019
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04001020 def test_sign(self):
1021 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001022 :py:meth:`X509Req.sign` succeeds when passed a private key object and a valid
1023 digest function. :py:meth:`X509Req.verify` can be used to check the signature.
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04001024 """
1025 request = self.signable()
1026 key = PKey()
1027 key.generate_key(TYPE_RSA, 512)
1028 request.set_pubkey(key)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001029 request.sign(key, GOOD_DIGEST)
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04001030 # If the type has a verify method, cover that too.
1031 if getattr(request, 'verify', None) is not None:
1032 pub = request.get_pubkey()
1033 self.assertTrue(request.verify(pub))
1034 # Make another key that won't verify.
1035 key = PKey()
1036 key.generate_key(TYPE_RSA, 512)
1037 self.assertRaises(Error, request.verify, key)
1038
1039
1040
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001041
Jean-Paul Calderone18808652009-07-05 12:54:05 -04001042class X509ReqTests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001043 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001044 Tests for :py:class:`OpenSSL.crypto.X509Req`.
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001045 """
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001046 def signable(self):
1047 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001048 Create and return a new :py:class:`X509Req`.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001049 """
1050 return X509Req()
1051
1052
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001053 def test_type(self):
1054 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001055 :py:obj:`X509Req` and :py:obj:`X509ReqType` refer to the same type object and can be
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001056 used to create instances of that type.
1057 """
1058 self.assertIdentical(X509Req, X509ReqType)
1059 self.assertConsistentType(X509Req, 'X509Req')
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001060
1061
1062 def test_construction(self):
1063 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001064 :py:obj:`X509Req` takes no arguments and returns an :py:obj:`X509ReqType` instance.
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001065 """
1066 request = X509Req()
1067 self.assertTrue(
1068 isinstance(request, X509ReqType),
1069 "%r is of type %r, should be %r" % (request, type(request), X509ReqType))
1070
1071
Jean-Paul Calderone8dd19b82008-12-28 20:41:16 -05001072 def test_version(self):
1073 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001074 :py:obj:`X509ReqType.set_version` sets the X.509 version of the certificate
1075 request. :py:obj:`X509ReqType.get_version` returns the X.509 version of
Jean-Paul Calderone8dd19b82008-12-28 20:41:16 -05001076 the certificate request. The initial value of the version is 0.
1077 """
1078 request = X509Req()
1079 self.assertEqual(request.get_version(), 0)
1080 request.set_version(1)
1081 self.assertEqual(request.get_version(), 1)
1082 request.set_version(3)
1083 self.assertEqual(request.get_version(), 3)
1084
1085
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001086 def test_version_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001087 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001088 :py:obj:`X509ReqType.set_version` raises :py:obj:`TypeError` if called with the wrong
1089 number of arguments or with a non-:py:obj:`int` argument.
1090 :py:obj:`X509ReqType.get_version` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001091 arguments.
1092 """
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001093 request = X509Req()
1094 self.assertRaises(TypeError, request.set_version)
1095 self.assertRaises(TypeError, request.set_version, "foo")
1096 self.assertRaises(TypeError, request.set_version, 1, 2)
1097 self.assertRaises(TypeError, request.get_version, None)
1098
1099
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001100 def test_get_subject(self):
1101 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001102 :py:obj:`X509ReqType.get_subject` returns an :py:obj:`X509Name` for the subject of
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001103 the request and which is valid even after the request object is
1104 otherwise dead.
1105 """
1106 request = X509Req()
1107 subject = request.get_subject()
1108 self.assertTrue(
1109 isinstance(subject, X509NameType),
1110 "%r is of type %r, should be %r" % (subject, type(subject), X509NameType))
1111 subject.commonName = "foo"
1112 self.assertEqual(request.get_subject().commonName, "foo")
1113 del request
1114 subject.commonName = "bar"
1115 self.assertEqual(subject.commonName, "bar")
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001116
1117
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001118 def test_get_subject_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001119 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001120 :py:obj:`X509ReqType.get_subject` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001121 arguments.
1122 """
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001123 request = X509Req()
1124 self.assertRaises(TypeError, request.get_subject, None)
1125
1126
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001127 def test_add_extensions(self):
1128 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001129 :py:obj:`X509Req.add_extensions` accepts a :py:obj:`list` of :py:obj:`X509Extension`
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001130 instances and adds them to the X509 request.
1131 """
1132 request = X509Req()
1133 request.add_extensions([
Jean-Paul Calderonee16f9f32010-08-22 19:20:37 -04001134 X509Extension(b('basicConstraints'), True, b('CA:false'))])
Stephen Holsappleca545b72014-01-28 21:43:25 -08001135 exts = request.get_extensions()
Stephen Holsapple7fbdf642014-03-01 20:05:47 -08001136 self.assertEqual(len(exts), 1)
1137 self.assertEqual(exts[0].get_short_name(), b('basicConstraints'))
1138 self.assertEqual(exts[0].get_critical(), 1)
1139 self.assertEqual(exts[0].get_data(), b('0\x00'))
1140
1141
1142 def test_get_extensions(self):
1143 """
1144 :py:obj:`X509Req.get_extensions` returns a :py:obj:`list` of
1145 extensions added to this X509 request.
1146 """
1147 request = X509Req()
1148 exts = request.get_extensions()
1149 self.assertEqual(exts, [])
1150 request.add_extensions([
1151 X509Extension(b('basicConstraints'), True, b('CA:true')),
1152 X509Extension(b('keyUsage'), False, b('digitalSignature'))])
1153 exts = request.get_extensions()
1154 self.assertEqual(len(exts), 2)
1155 self.assertEqual(exts[0].get_short_name(), b('basicConstraints'))
1156 self.assertEqual(exts[0].get_critical(), 1)
1157 self.assertEqual(exts[0].get_data(), b('0\x03\x01\x01\xff'))
1158 self.assertEqual(exts[1].get_short_name(), b('keyUsage'))
1159 self.assertEqual(exts[1].get_critical(), 0)
1160 self.assertEqual(exts[1].get_data(), b('\x03\x02\x07\x80'))
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001161
1162
1163 def test_add_extensions_wrong_args(self):
1164 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001165 :py:obj:`X509Req.add_extensions` raises :py:obj:`TypeError` if called with the wrong
1166 number of arguments or with a non-:py:obj:`list`. Or it raises :py:obj:`ValueError`
1167 if called with a :py:obj:`list` containing objects other than :py:obj:`X509Extension`
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001168 instances.
1169 """
1170 request = X509Req()
1171 self.assertRaises(TypeError, request.add_extensions)
1172 self.assertRaises(TypeError, request.add_extensions, object())
1173 self.assertRaises(ValueError, request.add_extensions, [object()])
1174 self.assertRaises(TypeError, request.add_extensions, [], None)
1175
1176
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001177 def test_verify_wrong_args(self):
1178 """
1179 :py:obj:`X509Req.verify` raises :py:obj:`TypeError` if called with zero
1180 arguments or more than one argument or if passed anything other than a
1181 :py:obj:`PKey` instance as its single argument.
1182 """
1183 request = X509Req()
1184 self.assertRaises(TypeError, request.verify)
1185 self.assertRaises(TypeError, request.verify, object())
1186 self.assertRaises(TypeError, request.verify, PKey(), object())
1187
1188
1189 def test_verify_uninitialized_key(self):
1190 """
1191 :py:obj:`X509Req.verify` raises :py:obj:`OpenSSL.crypto.Error` if called
1192 with a :py:obj:`OpenSSL.crypto.PKey` which contains no key data.
1193 """
1194 request = X509Req()
1195 pkey = PKey()
1196 self.assertRaises(Error, request.verify, pkey)
1197
1198
1199 def test_verify_wrong_key(self):
1200 """
1201 :py:obj:`X509Req.verify` raises :py:obj:`OpenSSL.crypto.Error` if called
1202 with a :py:obj:`OpenSSL.crypto.PKey` which does not represent the public
1203 part of the key which signed the request.
1204 """
1205 request = X509Req()
1206 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001207 request.sign(pkey, GOOD_DIGEST)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001208 another_pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
1209 self.assertRaises(Error, request.verify, another_pkey)
1210
1211
1212 def test_verify_success(self):
1213 """
1214 :py:obj:`X509Req.verify` returns :py:obj:`True` if called with a
1215 :py:obj:`OpenSSL.crypto.PKey` which represents the public part ofthe key
1216 which signed the request.
1217 """
1218 request = X509Req()
1219 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001220 request.sign(pkey, GOOD_DIGEST)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001221 self.assertEqual(True, request.verify(pkey))
1222
1223
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001224
Jean-Paul Calderone18808652009-07-05 12:54:05 -04001225class X509Tests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001226 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001227 Tests for :py:obj:`OpenSSL.crypto.X509`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001228 """
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001229 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
Jean-Paul Calderone8114b452008-03-25 15:27:59 -04001230
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001231 extpem = """
1232-----BEGIN CERTIFICATE-----
1233MIIC3jCCAkegAwIBAgIJAJHFjlcCgnQzMA0GCSqGSIb3DQEBBQUAMEcxCzAJBgNV
1234BAYTAlNFMRUwEwYDVQQIEwxXZXN0ZXJib3R0b20xEjAQBgNVBAoTCUNhdGFsb2dp
1235eDENMAsGA1UEAxMEUm9vdDAeFw0wODA0MjIxNDQ1MzhaFw0wOTA0MjIxNDQ1Mzha
1236MFQxCzAJBgNVBAYTAlNFMQswCQYDVQQIEwJXQjEUMBIGA1UEChMLT3Blbk1ldGFk
1237aXIxIjAgBgNVBAMTGW5vZGUxLm9tMi5vcGVubWV0YWRpci5vcmcwgZ8wDQYJKoZI
1238hvcNAQEBBQADgY0AMIGJAoGBAPIcQMrwbk2nESF/0JKibj9i1x95XYAOwP+LarwT
1239Op4EQbdlI9SY+uqYqlERhF19w7CS+S6oyqx0DRZSk4Y9dZ9j9/xgm2u/f136YS1u
1240zgYFPvfUs6PqYLPSM8Bw+SjJ+7+2+TN+Tkiof9WP1cMjodQwOmdsiRbR0/J7+b1B
1241hec1AgMBAAGjgcQwgcEwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNT
1242TCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFIdHsBcMVVMbAO7j6NCj
124303HgLnHaMB8GA1UdIwQYMBaAFL2h9Bf9Mre4vTdOiHTGAt7BRY/8MEYGA1UdEQQ/
1244MD2CDSouZXhhbXBsZS5vcmeCESoub20yLmV4bWFwbGUuY29thwSC7wgKgRNvbTJA
1245b3Blbm1ldGFkaXIub3JnMA0GCSqGSIb3DQEBBQUAA4GBALd7WdXkp2KvZ7/PuWZA
1246MPlIxyjS+Ly11+BNE0xGQRp9Wz+2lABtpgNqssvU156+HkKd02rGheb2tj7MX9hG
1247uZzbwDAZzJPjzDQDD7d3cWsrVcfIdqVU7epHqIadnOF+X0ghJ39pAm6VVadnSXCt
1248WpOdIpB8KksUTCzV591Nr1wd
1249-----END CERTIFICATE-----
1250 """
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001251 def signable(self):
1252 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001253 Create and return a new :py:obj:`X509`.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001254 """
1255 return X509()
1256
1257
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001258 def test_type(self):
1259 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001260 :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 -04001261 to create instances of that type.
1262 """
1263 self.assertIdentical(X509, X509Type)
1264 self.assertConsistentType(X509, 'X509')
1265
1266
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001267 def test_construction(self):
1268 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001269 :py:obj:`X509` takes no arguments and returns an instance of :py:obj:`X509Type`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001270 """
1271 certificate = X509()
1272 self.assertTrue(
1273 isinstance(certificate, X509Type),
1274 "%r is of type %r, should be %r" % (certificate,
1275 type(certificate),
1276 X509Type))
Rick Deane15b1472009-07-09 15:53:42 -05001277 self.assertEqual(type(X509Type).__name__, 'type')
1278 self.assertEqual(type(certificate).__name__, 'X509')
1279 self.assertEqual(type(certificate), X509Type)
Rick Dean04113e72009-07-16 12:06:35 -05001280 self.assertEqual(type(certificate), X509)
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001281
1282
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001283 def test_get_version_wrong_args(self):
1284 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001285 :py:obj:`X509.get_version` raises :py:obj:`TypeError` if invoked with any arguments.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001286 """
1287 cert = X509()
1288 self.assertRaises(TypeError, cert.get_version, None)
1289
1290
1291 def test_set_version_wrong_args(self):
1292 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001293 :py:obj:`X509.set_version` raises :py:obj:`TypeError` if invoked with the wrong number
1294 of arguments or an argument not of type :py:obj:`int`.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001295 """
1296 cert = X509()
1297 self.assertRaises(TypeError, cert.set_version)
1298 self.assertRaises(TypeError, cert.set_version, None)
1299 self.assertRaises(TypeError, cert.set_version, 1, None)
1300
1301
1302 def test_version(self):
1303 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001304 :py:obj:`X509.set_version` sets the certificate version number.
1305 :py:obj:`X509.get_version` retrieves it.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001306 """
1307 cert = X509()
1308 cert.set_version(1234)
1309 self.assertEquals(cert.get_version(), 1234)
1310
1311
1312 def test_get_serial_number_wrong_args(self):
1313 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001314 :py:obj:`X509.get_serial_number` raises :py:obj:`TypeError` if invoked with any
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001315 arguments.
1316 """
1317 cert = X509()
1318 self.assertRaises(TypeError, cert.get_serial_number, None)
1319
1320
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001321 def test_serial_number(self):
1322 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001323 The serial number of an :py:obj:`X509Type` can be retrieved and modified with
1324 :py:obj:`X509Type.get_serial_number` and :py:obj:`X509Type.set_serial_number`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001325 """
1326 certificate = X509()
1327 self.assertRaises(TypeError, certificate.set_serial_number)
1328 self.assertRaises(TypeError, certificate.set_serial_number, 1, 2)
1329 self.assertRaises(TypeError, certificate.set_serial_number, "1")
1330 self.assertRaises(TypeError, certificate.set_serial_number, 5.5)
1331 self.assertEqual(certificate.get_serial_number(), 0)
1332 certificate.set_serial_number(1)
1333 self.assertEqual(certificate.get_serial_number(), 1)
1334 certificate.set_serial_number(2 ** 32 + 1)
1335 self.assertEqual(certificate.get_serial_number(), 2 ** 32 + 1)
1336 certificate.set_serial_number(2 ** 64 + 1)
1337 self.assertEqual(certificate.get_serial_number(), 2 ** 64 + 1)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001338 certificate.set_serial_number(2 ** 128 + 1)
1339 self.assertEqual(certificate.get_serial_number(), 2 ** 128 + 1)
1340
1341
1342 def _setBoundTest(self, which):
1343 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001344 :py:obj:`X509Type.set_notBefore` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001345 GENERALIZEDTIME and sets the beginning of the certificate's validity
1346 period to it.
1347 """
1348 certificate = X509()
1349 set = getattr(certificate, 'set_not' + which)
1350 get = getattr(certificate, 'get_not' + which)
1351
Jean-Paul Calderonee0615b52008-03-09 21:44:46 -04001352 # Starts with no value.
1353 self.assertEqual(get(), None)
1354
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001355 # GMT (Or is it UTC?) -exarkun
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001356 when = b("20040203040506Z")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001357 set(when)
1358 self.assertEqual(get(), when)
1359
1360 # A plus two hours and thirty minutes offset
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001361 when = b("20040203040506+0530")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001362 set(when)
1363 self.assertEqual(get(), when)
1364
1365 # A minus one hour fifteen minutes offset
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001366 when = b("20040203040506-0115")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001367 set(when)
1368 self.assertEqual(get(), when)
1369
1370 # An invalid string results in a ValueError
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001371 self.assertRaises(ValueError, set, b("foo bar"))
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001372
Jean-Paul Calderone31ca2002010-01-30 15:14:43 -05001373 # The wrong number of arguments results in a TypeError.
1374 self.assertRaises(TypeError, set)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001375 self.assertRaises(TypeError, set, b("20040203040506Z"), b("20040203040506Z"))
1376 self.assertRaises(TypeError, get, b("foo bar"))
1377
Jean-Paul Calderone31ca2002010-01-30 15:14:43 -05001378
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001379 # XXX ASN1_TIME (not GENERALIZEDTIME)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001380
1381 def test_set_notBefore(self):
1382 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001383 :py:obj:`X509Type.set_notBefore` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001384 GENERALIZEDTIME and sets the beginning of the certificate's validity
1385 period to it.
1386 """
1387 self._setBoundTest("Before")
1388
1389
1390 def test_set_notAfter(self):
1391 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001392 :py:obj:`X509Type.set_notAfter` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001393 GENERALIZEDTIME and sets the end of the certificate's validity period
1394 to it.
1395 """
1396 self._setBoundTest("After")
Jean-Paul Calderone76576d52008-03-24 16:04:46 -04001397
1398
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001399 def test_get_notBefore(self):
1400 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001401 :py:obj:`X509Type.get_notBefore` returns a string in the format of an ASN1
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001402 GENERALIZEDTIME even for certificates which store it as UTCTIME
1403 internally.
1404 """
Jean-Paul Calderone8114b452008-03-25 15:27:59 -04001405 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001406 self.assertEqual(cert.get_notBefore(), b("20090325123658Z"))
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001407
Rick Dean38a05c82009-07-18 01:41:30 -05001408
1409 def test_get_notAfter(self):
1410 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001411 :py:obj:`X509Type.get_notAfter` returns a string in the format of an ASN1
Rick Dean38a05c82009-07-18 01:41:30 -05001412 GENERALIZEDTIME even for certificates which store it as UTCTIME
1413 internally.
1414 """
1415 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001416 self.assertEqual(cert.get_notAfter(), b("20170611123658Z"))
Rick Dean38a05c82009-07-18 01:41:30 -05001417
1418
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001419 def test_gmtime_adj_notBefore_wrong_args(self):
1420 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001421 :py:obj:`X509Type.gmtime_adj_notBefore` raises :py:obj:`TypeError` if called with the
1422 wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001423 """
1424 cert = X509()
1425 self.assertRaises(TypeError, cert.gmtime_adj_notBefore)
1426 self.assertRaises(TypeError, cert.gmtime_adj_notBefore, None)
1427 self.assertRaises(TypeError, cert.gmtime_adj_notBefore, 123, None)
1428
1429
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001430 def test_gmtime_adj_notBefore(self):
1431 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001432 :py:obj:`X509Type.gmtime_adj_notBefore` changes the not-before timestamp to be
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001433 the current time plus the number of seconds passed in.
1434 """
1435 cert = load_certificate(FILETYPE_PEM, self.pemData)
1436 now = datetime.utcnow() + timedelta(seconds=100)
1437 cert.gmtime_adj_notBefore(100)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001438 self.assertEqual(cert.get_notBefore(), b(now.strftime("%Y%m%d%H%M%SZ")))
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001439
1440
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001441 def test_gmtime_adj_notAfter_wrong_args(self):
1442 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001443 :py:obj:`X509Type.gmtime_adj_notAfter` raises :py:obj:`TypeError` if called with the
1444 wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001445 """
1446 cert = X509()
1447 self.assertRaises(TypeError, cert.gmtime_adj_notAfter)
1448 self.assertRaises(TypeError, cert.gmtime_adj_notAfter, None)
1449 self.assertRaises(TypeError, cert.gmtime_adj_notAfter, 123, None)
1450
1451
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001452 def test_gmtime_adj_notAfter(self):
1453 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001454 :py:obj:`X509Type.gmtime_adj_notAfter` changes the not-after timestamp to be
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001455 the current time plus the number of seconds passed in.
1456 """
1457 cert = load_certificate(FILETYPE_PEM, self.pemData)
1458 now = datetime.utcnow() + timedelta(seconds=100)
1459 cert.gmtime_adj_notAfter(100)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001460 self.assertEqual(cert.get_notAfter(), b(now.strftime("%Y%m%d%H%M%SZ")))
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001461
1462
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001463 def test_has_expired_wrong_args(self):
1464 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001465 :py:obj:`X509Type.has_expired` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001466 arguments.
1467 """
1468 cert = X509()
1469 self.assertRaises(TypeError, cert.has_expired, None)
1470
1471
1472 def test_has_expired(self):
1473 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001474 :py:obj:`X509Type.has_expired` returns :py:obj:`True` if the certificate's not-after
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001475 time is in the past.
1476 """
1477 cert = X509()
1478 cert.gmtime_adj_notAfter(-1)
1479 self.assertTrue(cert.has_expired())
1480
1481
1482 def test_has_not_expired(self):
1483 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001484 :py:obj:`X509Type.has_expired` returns :py:obj:`False` if the certificate's not-after
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001485 time is in the future.
1486 """
1487 cert = X509()
1488 cert.gmtime_adj_notAfter(2)
1489 self.assertFalse(cert.has_expired())
1490
1491
Rick Dean38a05c82009-07-18 01:41:30 -05001492 def test_digest(self):
1493 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001494 :py:obj:`X509.digest` returns a string giving ":"-separated hex-encoded words
Rick Dean38a05c82009-07-18 01:41:30 -05001495 of the digest of the certificate.
1496 """
1497 cert = X509()
1498 self.assertEqual(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001499 # This is MD5 instead of GOOD_DIGEST because the digest algorithm
1500 # actually matters to the assertion (ie, another arbitrary, good
1501 # digest will not product the same digest).
1502 cert.digest("MD5"),
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001503 b("A8:EB:07:F8:53:25:0A:F2:56:05:C5:A5:C4:C4:C7:15"))
Rick Dean38a05c82009-07-18 01:41:30 -05001504
1505
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001506 def _extcert(self, pkey, extensions):
1507 cert = X509()
1508 cert.set_pubkey(pkey)
1509 cert.get_subject().commonName = "Unit Tests"
1510 cert.get_issuer().commonName = "Unit Tests"
1511 when = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
1512 cert.set_notBefore(when)
1513 cert.set_notAfter(when)
1514
1515 cert.add_extensions(extensions)
1516 return load_certificate(
1517 FILETYPE_PEM, dump_certificate(FILETYPE_PEM, cert))
1518
1519
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001520 def test_extension_count(self):
1521 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001522 :py:obj:`X509.get_extension_count` returns the number of extensions that are
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001523 present in the certificate.
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001524 """
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001525 pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001526 ca = X509Extension(b('basicConstraints'), True, b('CA:FALSE'))
1527 key = X509Extension(b('keyUsage'), True, b('digitalSignature'))
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001528 subjectAltName = X509Extension(
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001529 b('subjectAltName'), True, b('DNS:example.com'))
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001530
1531 # Try a certificate with no extensions at all.
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001532 c = self._extcert(pkey, [])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001533 self.assertEqual(c.get_extension_count(), 0)
1534
1535 # And a certificate with one
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001536 c = self._extcert(pkey, [ca])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001537 self.assertEqual(c.get_extension_count(), 1)
1538
1539 # And a certificate with several
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001540 c = self._extcert(pkey, [ca, key, subjectAltName])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001541 self.assertEqual(c.get_extension_count(), 3)
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001542
1543
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001544 def test_get_extension(self):
1545 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001546 :py:obj:`X509.get_extension` takes an integer and returns an :py:obj:`X509Extension`
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001547 corresponding to the extension at that index.
1548 """
1549 pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001550 ca = X509Extension(b('basicConstraints'), True, b('CA:FALSE'))
1551 key = X509Extension(b('keyUsage'), True, b('digitalSignature'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001552 subjectAltName = X509Extension(
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001553 b('subjectAltName'), False, b('DNS:example.com'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001554
1555 cert = self._extcert(pkey, [ca, key, subjectAltName])
1556
1557 ext = cert.get_extension(0)
1558 self.assertTrue(isinstance(ext, X509Extension))
1559 self.assertTrue(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001560 self.assertEqual(ext.get_short_name(), b('basicConstraints'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001561
1562 ext = cert.get_extension(1)
1563 self.assertTrue(isinstance(ext, X509Extension))
1564 self.assertTrue(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001565 self.assertEqual(ext.get_short_name(), b('keyUsage'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001566
1567 ext = cert.get_extension(2)
1568 self.assertTrue(isinstance(ext, X509Extension))
1569 self.assertFalse(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001570 self.assertEqual(ext.get_short_name(), b('subjectAltName'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001571
1572 self.assertRaises(IndexError, cert.get_extension, -1)
1573 self.assertRaises(IndexError, cert.get_extension, 4)
1574 self.assertRaises(TypeError, cert.get_extension, "hello")
1575
1576
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001577 def test_nullbyte_subjectAltName(self):
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001578 """
Jean-Paul Calderone9af07b02013-08-23 16:07:31 -04001579 The fields of a `subjectAltName` extension on an X509 may contain NUL
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001580 bytes and this value is reflected in the string representation of the
1581 extension object.
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001582 """
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001583 cert = load_certificate(FILETYPE_PEM, nulbyteSubjectAltNamePEM)
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001584
1585 ext = cert.get_extension(3)
1586 self.assertEqual(ext.get_short_name(), b('subjectAltName'))
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001587 self.assertEqual(
1588 b("DNS:altnull.python.org\x00example.com, "
1589 "email:null@python.org\x00user@example.org, "
1590 "URI:http://null.python.org\x00http://example.org, "
1591 "IP Address:192.0.2.1, IP Address:2001:DB8:0:0:0:0:0:1\n"),
1592 b(str(ext)))
1593
Rick Dean38a05c82009-07-18 01:41:30 -05001594
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001595 def test_invalid_digest_algorithm(self):
1596 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001597 :py:obj:`X509.digest` raises :py:obj:`ValueError` if called with an unrecognized hash
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001598 algorithm.
1599 """
1600 cert = X509()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001601 self.assertRaises(ValueError, cert.digest, BAD_DIGEST)
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001602
1603
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001604 def test_get_subject_wrong_args(self):
1605 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001606 :py:obj:`X509.get_subject` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001607 """
1608 cert = X509()
1609 self.assertRaises(TypeError, cert.get_subject, None)
1610
1611
1612 def test_get_subject(self):
1613 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001614 :py:obj:`X509.get_subject` returns an :py:obj:`X509Name` instance.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001615 """
1616 cert = load_certificate(FILETYPE_PEM, self.pemData)
1617 subj = cert.get_subject()
1618 self.assertTrue(isinstance(subj, X509Name))
1619 self.assertEquals(
1620 subj.get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001621 [(b('C'), b('US')), (b('ST'), b('IL')), (b('L'), b('Chicago')),
1622 (b('O'), b('Testing')), (b('CN'), b('Testing Root CA'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001623
1624
1625 def test_set_subject_wrong_args(self):
1626 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001627 :py:obj:`X509.set_subject` raises a :py:obj:`TypeError` if called with the wrong
1628 number of arguments or an argument not of type :py:obj:`X509Name`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001629 """
1630 cert = X509()
1631 self.assertRaises(TypeError, cert.set_subject)
1632 self.assertRaises(TypeError, cert.set_subject, None)
1633 self.assertRaises(TypeError, cert.set_subject, cert.get_subject(), None)
1634
1635
1636 def test_set_subject(self):
1637 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001638 :py:obj:`X509.set_subject` changes the subject of the certificate to the one
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001639 passed in.
1640 """
1641 cert = X509()
1642 name = cert.get_subject()
1643 name.C = 'AU'
1644 name.O = 'Unit Tests'
1645 cert.set_subject(name)
1646 self.assertEquals(
1647 cert.get_subject().get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001648 [(b('C'), b('AU')), (b('O'), b('Unit Tests'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001649
1650
1651 def test_get_issuer_wrong_args(self):
1652 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001653 :py:obj:`X509.get_issuer` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001654 """
1655 cert = X509()
1656 self.assertRaises(TypeError, cert.get_issuer, None)
1657
1658
1659 def test_get_issuer(self):
1660 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001661 :py:obj:`X509.get_issuer` returns an :py:obj:`X509Name` instance.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001662 """
1663 cert = load_certificate(FILETYPE_PEM, self.pemData)
1664 subj = cert.get_issuer()
1665 self.assertTrue(isinstance(subj, X509Name))
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001666 comp = subj.get_components()
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001667 self.assertEquals(
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001668 comp,
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001669 [(b('C'), b('US')), (b('ST'), b('IL')), (b('L'), b('Chicago')),
1670 (b('O'), b('Testing')), (b('CN'), b('Testing Root CA'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001671
1672
1673 def test_set_issuer_wrong_args(self):
1674 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001675 :py:obj:`X509.set_issuer` raises a :py:obj:`TypeError` if called with the wrong
1676 number of arguments or an argument not of type :py:obj:`X509Name`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001677 """
1678 cert = X509()
1679 self.assertRaises(TypeError, cert.set_issuer)
1680 self.assertRaises(TypeError, cert.set_issuer, None)
1681 self.assertRaises(TypeError, cert.set_issuer, cert.get_issuer(), None)
1682
1683
1684 def test_set_issuer(self):
1685 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001686 :py:obj:`X509.set_issuer` changes the issuer of the certificate to the one
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001687 passed in.
1688 """
1689 cert = X509()
1690 name = cert.get_issuer()
1691 name.C = 'AU'
1692 name.O = 'Unit Tests'
1693 cert.set_issuer(name)
1694 self.assertEquals(
1695 cert.get_issuer().get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001696 [(b('C'), b('AU')), (b('O'), b('Unit Tests'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001697
1698
1699 def test_get_pubkey_uninitialized(self):
1700 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001701 When called on a certificate with no public key, :py:obj:`X509.get_pubkey`
1702 raises :py:obj:`OpenSSL.crypto.Error`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001703 """
1704 cert = X509()
1705 self.assertRaises(Error, cert.get_pubkey)
1706
1707
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001708 def test_subject_name_hash_wrong_args(self):
1709 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001710 :py:obj:`X509.subject_name_hash` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001711 arguments.
1712 """
1713 cert = X509()
1714 self.assertRaises(TypeError, cert.subject_name_hash, None)
1715
1716
1717 def test_subject_name_hash(self):
1718 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001719 :py:obj:`X509.subject_name_hash` returns the hash of the certificate's subject
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001720 name.
1721 """
1722 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -04001723 self.assertIn(
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001724 cert.subject_name_hash(),
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -04001725 [3350047874, # OpenSSL 0.9.8, MD5
1726 3278919224, # OpenSSL 1.0.0, SHA1
1727 ])
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001728
1729
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001730 def test_get_signature_algorithm(self):
1731 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001732 :py:obj:`X509Type.get_signature_algorithm` returns a string which means
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001733 the algorithm used to sign the certificate.
1734 """
1735 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001736 self.assertEqual(
1737 b("sha1WithRSAEncryption"), cert.get_signature_algorithm())
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001738
1739
1740 def test_get_undefined_signature_algorithm(self):
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001741 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001742 :py:obj:`X509Type.get_signature_algorithm` raises :py:obj:`ValueError` if the
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001743 signature algorithm is undefined or unknown.
1744 """
1745 # This certificate has been modified to indicate a bogus OID in the
1746 # signature algorithm field so that OpenSSL does not recognize it.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001747 certPEM = b("""\
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001748-----BEGIN CERTIFICATE-----
1749MIIC/zCCAmigAwIBAgIBATAGBgJ8BQUAMHsxCzAJBgNVBAYTAlNHMREwDwYDVQQK
1750EwhNMkNyeXB0bzEUMBIGA1UECxMLTTJDcnlwdG8gQ0ExJDAiBgNVBAMTG00yQ3J5
1751cHRvIENlcnRpZmljYXRlIE1hc3RlcjEdMBsGCSqGSIb3DQEJARYObmdwc0Bwb3N0
1752MS5jb20wHhcNMDAwOTEwMDk1MTMwWhcNMDIwOTEwMDk1MTMwWjBTMQswCQYDVQQG
1753EwJTRzERMA8GA1UEChMITTJDcnlwdG8xEjAQBgNVBAMTCWxvY2FsaG9zdDEdMBsG
1754CSqGSIb3DQEJARYObmdwc0Bwb3N0MS5jb20wXDANBgkqhkiG9w0BAQEFAANLADBI
1755AkEArL57d26W9fNXvOhNlZzlPOACmvwOZ5AdNgLzJ1/MfsQQJ7hHVeHmTAjM664V
1756+fXvwUGJLziCeBo1ysWLRnl8CQIDAQABo4IBBDCCAQAwCQYDVR0TBAIwADAsBglg
1757hkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0O
1758BBYEFM+EgpK+eyZiwFU1aOPSbczbPSpVMIGlBgNVHSMEgZ0wgZqAFPuHI2nrnDqT
1759FeXFvylRT/7tKDgBoX+kfTB7MQswCQYDVQQGEwJTRzERMA8GA1UEChMITTJDcnlw
1760dG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtNMkNyeXB0byBDZXJ0
1761aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tggEA
1762MA0GCSqGSIb3DQEBBAUAA4GBADv8KpPo+gfJxN2ERK1Y1l17sz/ZhzoGgm5XCdbx
1763jEY7xKfpQngV599k1xhl11IMqizDwu0855agrckg2MCTmOI9DZzDD77tAYb+Dk0O
1764PEVk0Mk/V0aIsDE9bolfCi/i/QWZ3N8s5nTWMNyBBBmoSliWCm4jkkRZRD0ejgTN
1765tgI5
1766-----END CERTIFICATE-----
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001767""")
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001768 cert = load_certificate(FILETYPE_PEM, certPEM)
1769 self.assertRaises(ValueError, cert.get_signature_algorithm)
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001770
1771
Rick Dean38a05c82009-07-18 01:41:30 -05001772
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001773class X509StoreTests(TestCase):
1774 """
1775 Test for :py:obj:`OpenSSL.crypto.X509Store`.
1776 """
1777 def test_type(self):
1778 """
1779 :py:obj:`X509StoreType` is a type object.
1780 """
1781 self.assertIdentical(X509Store, X509StoreType)
1782 self.assertConsistentType(X509Store, 'X509Store')
1783
1784
1785 def test_add_cert_wrong_args(self):
1786 store = X509Store()
1787 self.assertRaises(TypeError, store.add_cert)
1788 self.assertRaises(TypeError, store.add_cert, object())
1789 self.assertRaises(TypeError, store.add_cert, X509(), object())
1790
1791
1792 def test_add_cert(self):
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001793 """
1794 :py:obj:`X509Store.add_cert` adds a :py:obj:`X509` instance to the
1795 certificate store.
1796 """
1797 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001798 store = X509Store()
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001799 store.add_cert(cert)
1800
1801
1802 def test_add_cert_rejects_duplicate(self):
1803 """
1804 :py:obj:`X509Store.add_cert` raises :py:obj:`OpenSSL.crypto.Error` if an
1805 attempt is made to add the same certificate to the store more than once.
1806 """
1807 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
1808 store = X509Store()
1809 store.add_cert(cert)
1810 self.assertRaises(Error, store.add_cert, cert)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001811
1812
1813
Rick Dean623ee362009-07-17 12:22:16 -05001814class PKCS12Tests(TestCase):
1815 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001816 Test for :py:obj:`OpenSSL.crypto.PKCS12` and :py:obj:`OpenSSL.crypto.load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001817 """
1818 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
1819
Jean-Paul Calderonec3a41f72009-07-25 12:36:02 -04001820 def test_type(self):
1821 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001822 :py:obj:`PKCS12Type` is a type object.
Jean-Paul Calderonec3a41f72009-07-25 12:36:02 -04001823 """
1824 self.assertIdentical(PKCS12, PKCS12Type)
1825 self.assertConsistentType(PKCS12, 'PKCS12')
1826
1827
Rick Deanf94096c2009-07-18 14:23:06 -05001828 def test_empty_construction(self):
Rick Dean38a05c82009-07-18 01:41:30 -05001829 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001830 :py:obj:`PKCS12` returns a new instance of :py:obj:`PKCS12` with no certificate,
Jean-Paul Calderonedc857b52009-07-25 12:25:07 -04001831 private key, CA certificates, or friendly name.
Rick Dean38a05c82009-07-18 01:41:30 -05001832 """
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001833 p12 = PKCS12()
Rick Dean623ee362009-07-17 12:22:16 -05001834 self.assertEqual(None, p12.get_certificate())
1835 self.assertEqual(None, p12.get_privatekey())
1836 self.assertEqual(None, p12.get_ca_certificates())
Rick Dean42d69e12009-07-20 11:36:08 -05001837 self.assertEqual(None, p12.get_friendlyname())
Rick Dean623ee362009-07-17 12:22:16 -05001838
Rick Dean38a05c82009-07-18 01:41:30 -05001839
Rick Dean623ee362009-07-17 12:22:16 -05001840 def test_type_errors(self):
Rick Dean38a05c82009-07-18 01:41:30 -05001841 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001842 The :py:obj:`PKCS12` setter functions (:py:obj:`set_certificate`, :py:obj:`set_privatekey`,
1843 :py:obj:`set_ca_certificates`, and :py:obj:`set_friendlyname`) raise :py:obj:`TypeError`
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001844 when passed objects of types other than those expected.
Rick Dean38a05c82009-07-18 01:41:30 -05001845 """
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001846 p12 = PKCS12()
Rick Dean623ee362009-07-17 12:22:16 -05001847 self.assertRaises(TypeError, p12.set_certificate, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05001848 self.assertRaises(TypeError, p12.set_certificate, PKey())
1849 self.assertRaises(TypeError, p12.set_certificate, X509)
Rick Dean623ee362009-07-17 12:22:16 -05001850 self.assertRaises(TypeError, p12.set_privatekey, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05001851 self.assertRaises(TypeError, p12.set_privatekey, 'legbone')
1852 self.assertRaises(TypeError, p12.set_privatekey, X509())
Rick Dean623ee362009-07-17 12:22:16 -05001853 self.assertRaises(TypeError, p12.set_ca_certificates, 3)
1854 self.assertRaises(TypeError, p12.set_ca_certificates, X509())
1855 self.assertRaises(TypeError, p12.set_ca_certificates, (3, 4))
Rick Deanf94096c2009-07-18 14:23:06 -05001856 self.assertRaises(TypeError, p12.set_ca_certificates, ( PKey(), ))
Rick Dean42d69e12009-07-20 11:36:08 -05001857 self.assertRaises(TypeError, p12.set_friendlyname, 6)
1858 self.assertRaises(TypeError, p12.set_friendlyname, ('foo', 'bar'))
Rick Dean623ee362009-07-17 12:22:16 -05001859
Rick Dean38a05c82009-07-18 01:41:30 -05001860
Rick Dean623ee362009-07-17 12:22:16 -05001861 def test_key_only(self):
1862 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001863 A :py:obj:`PKCS12` with only a private key can be exported using
1864 :py:obj:`PKCS12.export` and loaded again using :py:obj:`load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001865 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001866 passwd = b"blah"
Rick Dean623ee362009-07-17 12:22:16 -05001867 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001868 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001869 p12.set_privatekey(pkey)
Rick Dean623ee362009-07-17 12:22:16 -05001870 self.assertEqual(None, p12.get_certificate())
1871 self.assertEqual(pkey, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05001872 try:
1873 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
1874 except Error:
1875 # Some versions of OpenSSL will throw an exception
1876 # for this nearly useless PKCS12 we tried to generate:
1877 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
1878 return
Rick Dean623ee362009-07-17 12:22:16 -05001879 p12 = load_pkcs12(dumped_p12, passwd)
1880 self.assertEqual(None, p12.get_ca_certificates())
1881 self.assertEqual(None, p12.get_certificate())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001882
1883 # OpenSSL fails to bring the key back to us. So sad. Perhaps in the
1884 # future this will be improved.
1885 self.assertTrue(isinstance(p12.get_privatekey(), (PKey, type(None))))
Rick Dean623ee362009-07-17 12:22:16 -05001886
Rick Dean38a05c82009-07-18 01:41:30 -05001887
Rick Dean623ee362009-07-17 12:22:16 -05001888 def test_cert_only(self):
1889 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001890 A :py:obj:`PKCS12` with only a certificate can be exported using
1891 :py:obj:`PKCS12.export` and loaded again using :py:obj:`load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001892 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001893 passwd = b"blah"
Rick Dean623ee362009-07-17 12:22:16 -05001894 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001895 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001896 p12.set_certificate(cert)
Rick Dean623ee362009-07-17 12:22:16 -05001897 self.assertEqual(cert, p12.get_certificate())
1898 self.assertEqual(None, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05001899 try:
1900 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
1901 except Error:
1902 # Some versions of OpenSSL will throw an exception
1903 # for this nearly useless PKCS12 we tried to generate:
1904 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
1905 return
Rick Dean623ee362009-07-17 12:22:16 -05001906 p12 = load_pkcs12(dumped_p12, passwd)
1907 self.assertEqual(None, p12.get_privatekey())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001908
1909 # OpenSSL fails to bring the cert back to us. Groany mcgroan.
1910 self.assertTrue(isinstance(p12.get_certificate(), (X509, type(None))))
1911
1912 # Oh ho. It puts the certificate into the ca certificates list, in
1913 # fact. Totally bogus, I would think. Nevertheless, let's exploit
1914 # that to check to see if it reconstructed the certificate we expected
1915 # it to. At some point, hopefully this will change so that
1916 # p12.get_certificate() is actually what returns the loaded
1917 # certificate.
1918 self.assertEqual(
1919 cleartextCertificatePEM,
1920 dump_certificate(FILETYPE_PEM, p12.get_ca_certificates()[0]))
Rick Dean623ee362009-07-17 12:22:16 -05001921
1922
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001923 def gen_pkcs12(self, cert_pem=None, key_pem=None, ca_pem=None, friendly_name=None):
Rick Dean623ee362009-07-17 12:22:16 -05001924 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001925 Generate a PKCS12 object with components from PEM. Verify that the set
1926 functions return None.
Rick Dean623ee362009-07-17 12:22:16 -05001927 """
Rick Deanf94096c2009-07-18 14:23:06 -05001928 p12 = PKCS12()
1929 if cert_pem:
1930 ret = p12.set_certificate(load_certificate(FILETYPE_PEM, cert_pem))
1931 self.assertEqual(ret, None)
1932 if key_pem:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001933 ret = p12.set_privatekey(load_privatekey(FILETYPE_PEM, key_pem))
Rick Deanf94096c2009-07-18 14:23:06 -05001934 self.assertEqual(ret, None)
1935 if ca_pem:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001936 ret = p12.set_ca_certificates((load_certificate(FILETYPE_PEM, ca_pem),))
Rick Deanf94096c2009-07-18 14:23:06 -05001937 self.assertEqual(ret, None)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001938 if friendly_name:
1939 ret = p12.set_friendlyname(friendly_name)
Rick Dean42d69e12009-07-20 11:36:08 -05001940 self.assertEqual(ret, None)
Rick Deanf94096c2009-07-18 14:23:06 -05001941 return p12
1942
1943
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001944 def check_recovery(self, p12_str, key=None, cert=None, ca=None, passwd=b"",
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001945 extra=()):
Rick Deanf94096c2009-07-18 14:23:06 -05001946 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001947 Use openssl program to confirm three components are recoverable from a
1948 PKCS12 string.
Rick Deanf94096c2009-07-18 14:23:06 -05001949 """
1950 if key:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001951 recovered_key = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001952 p12_str, b"pkcs12", b"-nocerts", b"-nodes", b"-passin",
1953 b"pass:" + passwd, *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001954 self.assertEqual(recovered_key[-len(key):], key)
1955 if cert:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001956 recovered_cert = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001957 p12_str, b"pkcs12", b"-clcerts", b"-nodes", b"-passin",
1958 b"pass:" + passwd, b"-nokeys", *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001959 self.assertEqual(recovered_cert[-len(cert):], cert)
1960 if ca:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001961 recovered_cert = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001962 p12_str, b"pkcs12", b"-cacerts", b"-nodes", b"-passin",
1963 b"pass:" + passwd, b"-nokeys", *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001964 self.assertEqual(recovered_cert[-len(ca):], ca)
1965
1966
Stephen Holsapple38482622014-04-05 20:29:34 -07001967 def verify_pkcs12_container(self, p12):
1968 """
1969 Verify that the PKCS#12 container contains the correct client
1970 certificate and private key.
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04001971
1972 :param p12: The PKCS12 instance to verify.
1973 :type p12: :py:class:`PKCS12`
Stephen Holsapple38482622014-04-05 20:29:34 -07001974 """
1975 cert_pem = dump_certificate(FILETYPE_PEM, p12.get_certificate())
1976 key_pem = dump_privatekey(FILETYPE_PEM, p12.get_privatekey())
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04001977 self.assertEqual(
1978 (client_cert_pem, client_key_pem, None),
1979 (cert_pem, key_pem, p12.get_ca_certificates()))
Stephen Holsapple38482622014-04-05 20:29:34 -07001980
1981
Rick Deanf94096c2009-07-18 14:23:06 -05001982 def test_load_pkcs12(self):
1983 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001984 A PKCS12 string generated using the openssl command line can be loaded
Jonathan Ballet648875f2011-07-16 14:14:58 +09001985 with :py:obj:`load_pkcs12` and its components extracted and examined.
Rick Deanf94096c2009-07-18 14:23:06 -05001986 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001987 passwd = b"whatever"
Rick Dean623ee362009-07-17 12:22:16 -05001988 pem = client_key_pem + client_cert_pem
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001989 p12_str = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001990 pem, b"pkcs12", b"-export", b"-clcerts", b"-passout", b"pass:" + passwd)
Stephen Holsapple38482622014-04-05 20:29:34 -07001991 p12 = load_pkcs12(p12_str, passphrase=passwd)
1992 self.verify_pkcs12_container(p12)
1993
1994
1995 def test_load_pkcs12_no_passphrase(self):
1996 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04001997 A PKCS12 string generated using openssl command line can be loaded with
1998 :py:obj:`load_pkcs12` without a passphrase and its components extracted
1999 and examined.
Stephen Holsapple38482622014-04-05 20:29:34 -07002000 """
2001 pem = client_key_pem + client_cert_pem
2002 p12_str = _runopenssl(
2003 pem, b"pkcs12", b"-export", b"-clcerts", b"-passout", b"pass:")
2004 p12 = load_pkcs12(p12_str)
2005 self.verify_pkcs12_container(p12)
2006
2007
2008 def _dump_and_load(self, dump_passphrase, load_passphrase):
2009 """
2010 A helper method to dump and load a PKCS12 object.
2011 """
2012 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem)
2013 dumped_p12 = p12.export(passphrase=dump_passphrase, iter=2, maciter=3)
2014 return load_pkcs12(dumped_p12, passphrase=load_passphrase)
2015
2016
2017 def test_load_pkcs12_null_passphrase_load_empty(self):
2018 """
2019 A PKCS12 string can be dumped with a null passphrase, loaded with an
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002020 empty passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002021 extracted and examined.
2022 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002023 self.verify_pkcs12_container(
2024 self._dump_and_load(dump_passphrase=None, load_passphrase=b''))
Stephen Holsapple38482622014-04-05 20:29:34 -07002025
2026
2027 def test_load_pkcs12_null_passphrase_load_null(self):
2028 """
2029 A PKCS12 string can be dumped with a null passphrase, loaded with a
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002030 null passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002031 extracted and examined.
2032 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002033 self.verify_pkcs12_container(
2034 self._dump_and_load(dump_passphrase=None, load_passphrase=None))
Stephen Holsapple38482622014-04-05 20:29:34 -07002035
2036
2037 def test_load_pkcs12_empty_passphrase_load_empty(self):
2038 """
2039 A PKCS12 string can be dumped with an empty passphrase, loaded with an
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002040 empty passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002041 extracted and examined.
2042 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002043 self.verify_pkcs12_container(
2044 self._dump_and_load(dump_passphrase=b'', load_passphrase=b''))
Stephen Holsapple38482622014-04-05 20:29:34 -07002045
2046
2047 def test_load_pkcs12_empty_passphrase_load_null(self):
2048 """
2049 A PKCS12 string can be dumped with an empty passphrase, loaded with a
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002050 null passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002051 extracted and examined.
2052 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002053 self.verify_pkcs12_container(
2054 self._dump_and_load(dump_passphrase=b'', load_passphrase=None))
Rick Deanf94096c2009-07-18 14:23:06 -05002055
Rick Deanee568302009-07-24 09:56:29 -05002056
2057 def test_load_pkcs12_garbage(self):
2058 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002059 :py:obj:`load_pkcs12` raises :py:obj:`OpenSSL.crypto.Error` when passed a string
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002060 which is not a PKCS12 dump.
Rick Deanee568302009-07-24 09:56:29 -05002061 """
2062 passwd = 'whatever'
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002063 e = self.assertRaises(Error, load_pkcs12, b'fruit loops', passwd)
Jean-Paul Calderonede075462014-01-18 10:34:12 -05002064 self.assertEqual( e.args[0][0][0], 'asn1 encoding routines')
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -04002065 self.assertEqual( len(e.args[0][0]), 3)
Rick Deanee568302009-07-24 09:56:29 -05002066
2067
Rick Deanf94096c2009-07-18 14:23:06 -05002068 def test_replace(self):
2069 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002070 :py:obj:`PKCS12.set_certificate` replaces the certificate in a PKCS12 cluster.
2071 :py:obj:`PKCS12.set_privatekey` replaces the private key.
2072 :py:obj:`PKCS12.set_ca_certificates` replaces the CA certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05002073 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002074 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
2075 p12.set_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2076 p12.set_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002077 root_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05002078 client_cert = load_certificate(FILETYPE_PEM, client_cert_pem)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002079 p12.set_ca_certificates([root_cert]) # not a tuple
Rick Dean623ee362009-07-17 12:22:16 -05002080 self.assertEqual(1, len(p12.get_ca_certificates()))
2081 self.assertEqual(root_cert, p12.get_ca_certificates()[0])
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002082 p12.set_ca_certificates([client_cert, root_cert])
Rick Deanf94096c2009-07-18 14:23:06 -05002083 self.assertEqual(2, len(p12.get_ca_certificates()))
2084 self.assertEqual(client_cert, p12.get_ca_certificates()[0])
2085 self.assertEqual(root_cert, p12.get_ca_certificates()[1])
2086
2087
2088 def test_friendly_name(self):
2089 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002090 The *friendlyName* of a PKCS12 can be set and retrieved via
Jonathan Ballet648875f2011-07-16 14:14:58 +09002091 :py:obj:`PKCS12.get_friendlyname` and :py:obj:`PKCS12_set_friendlyname`, and a
2092 :py:obj:`PKCS12` with a friendly name set can be dumped with :py:obj:`PKCS12.export`.
Rick Deanf94096c2009-07-18 14:23:06 -05002093 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002094 passwd = b'Dogmeat[]{}!@#$%^&*()~`?/.,<>-_+=";:'
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002095 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -04002096 for friendly_name in [b('Serverlicious'), None, b('###')]:
Rick Dean42d69e12009-07-20 11:36:08 -05002097 p12.set_friendlyname(friendly_name)
2098 self.assertEqual(p12.get_friendlyname(), friendly_name)
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002099 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
Rick Dean42d69e12009-07-20 11:36:08 -05002100 reloaded_p12 = load_pkcs12(dumped_p12, passwd)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002101 self.assertEqual(
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -04002102 p12.get_friendlyname(), reloaded_p12.get_friendlyname())
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002103 # We would use the openssl program to confirm the friendly
2104 # name, but it is not possible. The pkcs12 command
2105 # does not store the friendly name in the cert's
Rick Dean42d69e12009-07-20 11:36:08 -05002106 # alias, which we could then extract.
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002107 self.check_recovery(
2108 dumped_p12, key=server_key_pem, cert=server_cert_pem,
2109 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05002110
2111
2112 def test_various_empty_passphrases(self):
2113 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002114 Test that missing, None, and '' passphrases are identical for PKCS12
2115 export.
Rick Deanf94096c2009-07-18 14:23:06 -05002116 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002117 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002118 passwd = b""
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002119 dumped_p12_empty = p12.export(iter=2, maciter=0, passphrase=passwd)
2120 dumped_p12_none = p12.export(iter=3, maciter=2, passphrase=None)
2121 dumped_p12_nopw = p12.export(iter=9, maciter=4)
2122 for dumped_p12 in [dumped_p12_empty, dumped_p12_none, dumped_p12_nopw]:
2123 self.check_recovery(
2124 dumped_p12, key=client_key_pem, cert=client_cert_pem,
2125 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05002126
2127
2128 def test_removing_ca_cert(self):
2129 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002130 Passing :py:obj:`None` to :py:obj:`PKCS12.set_ca_certificates` removes all CA
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002131 certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05002132 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002133 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
2134 p12.set_ca_certificates(None)
Rick Dean623ee362009-07-17 12:22:16 -05002135 self.assertEqual(None, p12.get_ca_certificates())
Rick Deanf94096c2009-07-18 14:23:06 -05002136
2137
2138 def test_export_without_mac(self):
2139 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002140 Exporting a PKCS12 with a :py:obj:`maciter` of ``-1`` excludes the MAC
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002141 entirely.
Rick Deanf94096c2009-07-18 14:23:06 -05002142 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002143 passwd = b"Lake Michigan"
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002144 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Dean623ee362009-07-17 12:22:16 -05002145 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002146 self.check_recovery(
2147 dumped_p12, key=server_key_pem, cert=server_cert_pem,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002148 passwd=passwd, extra=(b"-nomacver",))
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002149
2150
2151 def test_load_without_mac(self):
2152 """
2153 Loading a PKCS12 without a MAC does something other than crash.
2154 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002155 passwd = b"Lake Michigan"
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002156 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
2157 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Rick Dean321a0512009-08-13 17:21:29 -05002158 try:
2159 recovered_p12 = load_pkcs12(dumped_p12, passwd)
2160 # The person who generated this PCKS12 should be flogged,
2161 # or better yet we should have a means to determine
2162 # whether a PCKS12 had a MAC that was verified.
2163 # Anyway, libopenssl chooses to allow it, so the
2164 # pyopenssl binding does as well.
2165 self.assertTrue(isinstance(recovered_p12, PKCS12))
2166 except Error:
2167 # Failing here with an exception is preferred as some openssl
2168 # versions do.
2169 pass
Rick Dean623ee362009-07-17 12:22:16 -05002170
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002171
Rick Dean25bcc1f2009-07-20 11:53:13 -05002172 def test_zero_len_list_for_ca(self):
2173 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002174 A PKCS12 with an empty CA certificates list can be exported.
Rick Dean25bcc1f2009-07-20 11:53:13 -05002175 """
2176 passwd = 'Hobie 18'
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002177 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002178 # p12.set_ca_certificates([])
2179 # self.assertEqual((), p12.get_ca_certificates())
2180 # dumped_p12 = p12.export(passphrase=passwd, iter=3)
2181 # self.check_recovery(
2182 # dumped_p12, key=server_key_pem, cert=server_cert_pem,
2183 # passwd=passwd)
Rick Dean25bcc1f2009-07-20 11:53:13 -05002184
2185
Rick Deanf94096c2009-07-18 14:23:06 -05002186 def test_export_without_args(self):
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002187 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002188 All the arguments to :py:obj:`PKCS12.export` are optional.
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002189 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002190 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05002191 dumped_p12 = p12.export() # no args
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002192 self.check_recovery(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002193 dumped_p12, key=server_key_pem, cert=server_cert_pem, passwd=b"")
Rick Deanf94096c2009-07-18 14:23:06 -05002194
2195
2196 def test_key_cert_mismatch(self):
2197 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002198 :py:obj:`PKCS12.export` raises an exception when a key and certificate
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002199 mismatch.
Rick Deanf94096c2009-07-18 14:23:06 -05002200 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002201 p12 = self.gen_pkcs12(server_cert_pem, client_key_pem, root_cert_pem)
2202 self.assertRaises(Error, p12.export)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002203
2204
2205
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002206# These quoting functions taken directly from Twisted's twisted.python.win32.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002207_cmdLineQuoteRe = re.compile(br'(\\*)"')
2208_cmdLineQuoteRe2 = re.compile(br'(\\+)\Z')
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002209def cmdLineQuote(s):
2210 """
2211 Internal method for quoting a single command-line argument.
2212
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002213 See http://www.perlmonks.org/?node_id=764004
2214
Jonathan Ballet648875f2011-07-16 14:14:58 +09002215 :type: :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002216 :param s: A single unquoted string to quote for something that is expecting
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002217 cmd.exe-style quoting
2218
Jonathan Ballet648875f2011-07-16 14:14:58 +09002219 :rtype: :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002220 :return: A cmd.exe-style quoted string
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002221 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002222 s = _cmdLineQuoteRe2.sub(br"\1\1", _cmdLineQuoteRe.sub(br'\1\1\\"', s))
2223 return b'"' + s + b'"'
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002224
2225
2226
2227def quoteArguments(arguments):
2228 """
2229 Quote an iterable of command-line arguments for passing to CreateProcess or
Jonathan Ballet648875f2011-07-16 14:14:58 +09002230 a similar API. This allows the list passed to :py:obj:`reactor.spawnProcess` to
2231 match the child process's :py:obj:`sys.argv` properly.
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002232
Jonathan Ballet648875f2011-07-16 14:14:58 +09002233 :type arguments: :py:obj:`iterable` of :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002234 :param arguments: An iterable of unquoted arguments to quote
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002235
Jonathan Ballet648875f2011-07-16 14:14:58 +09002236 :rtype: :py:obj:`str`
2237 :return: A space-delimited string containing quoted versions of :py:obj:`arguments`
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002238 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002239 return b' '.join(map(cmdLineQuote, arguments))
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002240
2241
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002242
Rick Dean4c9ad612009-07-17 15:05:22 -05002243def _runopenssl(pem, *args):
2244 """
2245 Run the command line openssl tool with the given arguments and write
Rick Dean55d1ce62009-08-13 17:40:24 -05002246 the given PEM to its stdin. Not safe for quotes.
Rick Dean4c9ad612009-07-17 15:05:22 -05002247 """
Jean-Paul Calderone038de952009-08-21 12:16:06 -04002248 if os.name == 'posix':
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002249 command = b"openssl " + b" ".join([
2250 (b"'" + arg.replace(b"'", b"'\\''") + b"'")
2251 for arg in args])
Rick Dean55d1ce62009-08-13 17:40:24 -05002252 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002253 command = b"openssl " + quoteArguments(args)
2254 proc = Popen(native(command), shell=True, stdin=PIPE, stdout=PIPE)
Jean-Paul Calderone62ca8da2010-08-11 19:58:08 -04002255 proc.stdin.write(pem)
2256 proc.stdin.close()
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002257 output = proc.stdout.read()
2258 proc.stdout.close()
2259 proc.wait()
2260 return output
Rick Dean4c9ad612009-07-17 15:05:22 -05002261
2262
2263
Jean-Paul Calderone18808652009-07-05 12:54:05 -04002264class FunctionTests(TestCase):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002265 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002266 Tests for free-functions in the :py:obj:`OpenSSL.crypto` module.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002267 """
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002268
2269 def test_load_privatekey_invalid_format(self):
2270 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002271 :py:obj:`load_privatekey` raises :py:obj:`ValueError` if passed an unknown filetype.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002272 """
2273 self.assertRaises(ValueError, load_privatekey, 100, root_key_pem)
2274
2275
2276 def test_load_privatekey_invalid_passphrase_type(self):
2277 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002278 :py:obj:`load_privatekey` raises :py:obj:`TypeError` if passed a passphrase that is
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002279 neither a :py:obj:`str` nor a callable.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002280 """
2281 self.assertRaises(
2282 TypeError,
2283 load_privatekey,
2284 FILETYPE_PEM, encryptedPrivateKeyPEMPassphrase, object())
2285
2286
2287 def test_load_privatekey_wrong_args(self):
2288 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002289 :py:obj:`load_privatekey` raises :py:obj:`TypeError` if called with the wrong number
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002290 of arguments.
2291 """
2292 self.assertRaises(TypeError, load_privatekey)
2293
2294
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002295 def test_load_privatekey_wrongPassphrase(self):
2296 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002297 :py:obj:`load_privatekey` raises :py:obj:`OpenSSL.crypto.Error` when it is passed an
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002298 encrypted PEM and an incorrect passphrase.
2299 """
2300 self.assertRaises(
2301 Error,
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002302 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, b("quack"))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002303
2304
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002305 def test_load_privatekey_passphraseWrongType(self):
2306 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002307 :py:obj:`load_privatekey` raises :py:obj:`ValueError` when it is passed a passphrase
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002308 with a private key encoded in a format, that doesn't support
2309 encryption.
2310 """
2311 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2312 blob = dump_privatekey(FILETYPE_ASN1, key)
2313 self.assertRaises(ValueError,
2314 load_privatekey, FILETYPE_ASN1, blob, "secret")
2315
2316
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002317 def test_load_privatekey_passphrase(self):
2318 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002319 :py:obj:`load_privatekey` can create a :py:obj:`PKey` object from an encrypted PEM
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002320 string if given the passphrase.
2321 """
2322 key = load_privatekey(
2323 FILETYPE_PEM, encryptedPrivateKeyPEM,
2324 encryptedPrivateKeyPEMPassphrase)
2325 self.assertTrue(isinstance(key, PKeyType))
2326
2327
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002328 def test_load_privatekey_passphrase_exception(self):
2329 """
2330 If the passphrase callback raises an exception, that exception is raised
2331 by :py:obj:`load_privatekey`.
2332 """
2333 def cb(ignored):
2334 raise ArithmeticError
2335
2336 self.assertRaises(ArithmeticError,
2337 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2338
2339
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002340 def test_load_privatekey_wrongPassphraseCallback(self):
2341 """
Jean-Paul Calderoned440a082011-09-14 11:02:05 -04002342 :py:obj:`load_privatekey` raises :py:obj:`OpenSSL.crypto.Error` when it
2343 is passed an encrypted PEM and a passphrase callback which returns an
2344 incorrect passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002345 """
2346 called = []
2347 def cb(*a):
2348 called.append(None)
Jean-Paul Calderoned440a082011-09-14 11:02:05 -04002349 return b("quack")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002350 self.assertRaises(
2351 Error,
2352 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2353 self.assertTrue(called)
2354
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002355
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002356 def test_load_privatekey_passphraseCallback(self):
2357 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002358 :py:obj:`load_privatekey` can create a :py:obj:`PKey` object from an encrypted PEM
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002359 string if given a passphrase callback which returns the correct
2360 password.
2361 """
2362 called = []
2363 def cb(writing):
2364 called.append(writing)
2365 return encryptedPrivateKeyPEMPassphrase
2366 key = load_privatekey(FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2367 self.assertTrue(isinstance(key, PKeyType))
2368 self.assertEqual(called, [False])
2369
2370
Jean-Paul Calderone105cb952011-09-14 10:16:46 -04002371 def test_load_privatekey_passphrase_wrong_return_type(self):
2372 """
2373 :py:obj:`load_privatekey` raises :py:obj:`ValueError` if the passphrase
2374 callback returns something other than a byte string.
2375 """
2376 self.assertRaises(
2377 ValueError,
2378 load_privatekey,
2379 FILETYPE_PEM, encryptedPrivateKeyPEM, lambda *args: 3)
2380
2381
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002382 def test_dump_privatekey_wrong_args(self):
2383 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002384 :py:obj:`dump_privatekey` raises :py:obj:`TypeError` if called with the wrong number
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002385 of arguments.
2386 """
2387 self.assertRaises(TypeError, dump_privatekey)
Jean-Paul Calderone1eeccd82011-09-14 10:18:52 -04002388 # If cipher name is given, password is required.
2389 self.assertRaises(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002390 TypeError, dump_privatekey, FILETYPE_PEM, PKey(), GOOD_CIPHER)
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002391
2392
2393 def test_dump_privatekey_unknown_cipher(self):
2394 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002395 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` if called with an unrecognized
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002396 cipher name.
2397 """
2398 key = PKey()
2399 key.generate_key(TYPE_RSA, 512)
2400 self.assertRaises(
2401 ValueError, dump_privatekey,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002402 FILETYPE_PEM, key, BAD_CIPHER, "passphrase")
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002403
2404
2405 def test_dump_privatekey_invalid_passphrase_type(self):
2406 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002407 :py:obj:`dump_privatekey` raises :py:obj:`TypeError` if called with a passphrase which
2408 is neither a :py:obj:`str` nor a callable.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002409 """
2410 key = PKey()
2411 key.generate_key(TYPE_RSA, 512)
2412 self.assertRaises(
2413 TypeError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002414 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, object())
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002415
2416
2417 def test_dump_privatekey_invalid_filetype(self):
2418 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002419 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` if called with an unrecognized
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002420 filetype.
2421 """
2422 key = PKey()
2423 key.generate_key(TYPE_RSA, 512)
2424 self.assertRaises(ValueError, dump_privatekey, 100, key)
2425
2426
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002427 def test_load_privatekey_passphraseCallbackLength(self):
2428 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002429 :py:obj:`crypto.load_privatekey` should raise an error when the passphrase
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002430 provided by the callback is too long, not silently truncate it.
2431 """
2432 def cb(ignored):
2433 return "a" * 1025
2434
2435 self.assertRaises(ValueError,
2436 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2437
2438
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002439 def test_dump_privatekey_passphrase(self):
2440 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002441 :py:obj:`dump_privatekey` writes an encrypted PEM when given a passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002442 """
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002443 passphrase = b("foo")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002444 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002445 pem = dump_privatekey(FILETYPE_PEM, key, GOOD_CIPHER, passphrase)
2446 self.assertTrue(isinstance(pem, binary_type))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002447 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
2448 self.assertTrue(isinstance(loadedKey, PKeyType))
2449 self.assertEqual(loadedKey.type(), key.type())
2450 self.assertEqual(loadedKey.bits(), key.bits())
2451
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002452
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002453 def test_dump_privatekey_passphraseWrongType(self):
2454 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002455 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` when it is passed a passphrase
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002456 with a private key encoded in a format, that doesn't support
2457 encryption.
2458 """
2459 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2460 self.assertRaises(ValueError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002461 dump_privatekey, FILETYPE_ASN1, key, GOOD_CIPHER, "secret")
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002462
2463
Rick Dean5b7b6372009-04-01 11:34:06 -05002464 def test_dump_certificate(self):
2465 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002466 :py:obj:`dump_certificate` writes PEM, DER, and text.
Rick Dean5b7b6372009-04-01 11:34:06 -05002467 """
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002468 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
Rick Dean5b7b6372009-04-01 11:34:06 -05002469 cert = load_certificate(FILETYPE_PEM, pemData)
2470 dumped_pem = dump_certificate(FILETYPE_PEM, cert)
2471 self.assertEqual(dumped_pem, cleartextCertificatePEM)
2472 dumped_der = dump_certificate(FILETYPE_ASN1, cert)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002473 good_der = _runopenssl(dumped_pem, b"x509", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002474 self.assertEqual(dumped_der, good_der)
2475 cert2 = load_certificate(FILETYPE_ASN1, dumped_der)
2476 dumped_pem2 = dump_certificate(FILETYPE_PEM, cert2)
2477 self.assertEqual(dumped_pem2, cleartextCertificatePEM)
2478 dumped_text = dump_certificate(FILETYPE_TEXT, cert)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002479 good_text = _runopenssl(dumped_pem, b"x509", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002480 self.assertEqual(dumped_text, good_text)
2481
2482
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002483 def test_dump_privatekey_pem(self):
Rick Dean5b7b6372009-04-01 11:34:06 -05002484 """
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002485 :py:obj:`dump_privatekey` writes a PEM
Rick Dean5b7b6372009-04-01 11:34:06 -05002486 """
2487 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -04002488 self.assertTrue(key.check())
Rick Dean5b7b6372009-04-01 11:34:06 -05002489 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2490 self.assertEqual(dumped_pem, cleartextPrivateKeyPEM)
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002491
2492
2493 def test_dump_privatekey_asn1(self):
2494 """
2495 :py:obj:`dump_privatekey` writes a DER
2496 """
2497 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2498 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2499
Rick Dean5b7b6372009-04-01 11:34:06 -05002500 dumped_der = dump_privatekey(FILETYPE_ASN1, key)
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002501 # XXX This OpenSSL call writes "writing RSA key" to standard out. Sad.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002502 good_der = _runopenssl(dumped_pem, b"rsa", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002503 self.assertEqual(dumped_der, good_der)
2504 key2 = load_privatekey(FILETYPE_ASN1, dumped_der)
2505 dumped_pem2 = dump_privatekey(FILETYPE_PEM, key2)
2506 self.assertEqual(dumped_pem2, cleartextPrivateKeyPEM)
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002507
2508
2509 def test_dump_privatekey_text(self):
2510 """
2511 :py:obj:`dump_privatekey` writes a text
2512 """
2513 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2514 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2515
Rick Dean5b7b6372009-04-01 11:34:06 -05002516 dumped_text = dump_privatekey(FILETYPE_TEXT, key)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002517 good_text = _runopenssl(dumped_pem, b"rsa", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002518 self.assertEqual(dumped_text, good_text)
2519
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002520
Rick Dean5b7b6372009-04-01 11:34:06 -05002521 def test_dump_certificate_request(self):
2522 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002523 :py:obj:`dump_certificate_request` writes a PEM, DER, and text.
Rick Dean5b7b6372009-04-01 11:34:06 -05002524 """
2525 req = load_certificate_request(FILETYPE_PEM, cleartextCertificateRequestPEM)
2526 dumped_pem = dump_certificate_request(FILETYPE_PEM, req)
2527 self.assertEqual(dumped_pem, cleartextCertificateRequestPEM)
2528 dumped_der = dump_certificate_request(FILETYPE_ASN1, req)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002529 good_der = _runopenssl(dumped_pem, b"req", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002530 self.assertEqual(dumped_der, good_der)
2531 req2 = load_certificate_request(FILETYPE_ASN1, dumped_der)
2532 dumped_pem2 = dump_certificate_request(FILETYPE_PEM, req2)
2533 self.assertEqual(dumped_pem2, cleartextCertificateRequestPEM)
2534 dumped_text = dump_certificate_request(FILETYPE_TEXT, req)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002535 good_text = _runopenssl(dumped_pem, b"req", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002536 self.assertEqual(dumped_text, good_text)
Jean-Paul Calderoneaf43cdf2010-08-03 18:40:52 -04002537 self.assertRaises(ValueError, dump_certificate_request, 100, req)
Rick Dean5b7b6372009-04-01 11:34:06 -05002538
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002539
2540 def test_dump_privatekey_passphraseCallback(self):
2541 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002542 :py:obj:`dump_privatekey` writes an encrypted PEM when given a callback which
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002543 returns the correct passphrase.
2544 """
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002545 passphrase = b("foo")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002546 called = []
2547 def cb(writing):
2548 called.append(writing)
2549 return passphrase
2550 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002551 pem = dump_privatekey(FILETYPE_PEM, key, GOOD_CIPHER, cb)
2552 self.assertTrue(isinstance(pem, binary_type))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002553 self.assertEqual(called, [True])
2554 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
2555 self.assertTrue(isinstance(loadedKey, PKeyType))
2556 self.assertEqual(loadedKey.type(), key.type())
2557 self.assertEqual(loadedKey.bits(), key.bits())
Rick Dean5b7b6372009-04-01 11:34:06 -05002558
2559
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002560 def test_dump_privatekey_passphrase_exception(self):
2561 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002562 :py:obj:`dump_privatekey` should not overwrite the exception raised
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002563 by the passphrase callback.
2564 """
2565 def cb(ignored):
2566 raise ArithmeticError
2567
2568 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2569 self.assertRaises(ArithmeticError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002570 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, cb)
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002571
2572
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002573 def test_dump_privatekey_passphraseCallbackLength(self):
2574 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002575 :py:obj:`crypto.dump_privatekey` should raise an error when the passphrase
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002576 provided by the callback is too long, not silently truncate it.
2577 """
2578 def cb(ignored):
2579 return "a" * 1025
2580
2581 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2582 self.assertRaises(ValueError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002583 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, cb)
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002584
2585
Alex Gaynor4b9c96a2014-08-14 09:51:48 -07002586 def test_load_pkcs7_data_pem(self):
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002587 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002588 :py:obj:`load_pkcs7_data` accepts a PKCS#7 string and returns an instance of
2589 :py:obj:`PKCS7Type`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002590 """
2591 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2592 self.assertTrue(isinstance(pkcs7, PKCS7Type))
2593
2594
Alex Gaynor4b9c96a2014-08-14 09:51:48 -07002595 def test_load_pkcs7_data_asn1(self):
Alex Gaynor9875a912014-08-14 13:35:05 -07002596 """
2597 :py:obj:`load_pkcs7_data` accepts a bytes containing ASN1 data
2598 representing PKCS#7 and returns an instance of :py:obj`PKCS7Type`.
2599 """
Alex Gaynor4b9c96a2014-08-14 09:51:48 -07002600 pkcs7 = load_pkcs7_data(FILETYPE_ASN1, pkcs7DataASN1)
2601 self.assertTrue(isinstance(pkcs7, PKCS7Type))
2602
2603
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002604 def test_load_pkcs7_data_invalid(self):
2605 """
2606 If the data passed to :py:obj:`load_pkcs7_data` is invalid,
2607 :py:obj:`Error` is raised.
2608 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002609 self.assertRaises(Error, load_pkcs7_data, FILETYPE_PEM, b"foo")
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002610
2611
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002612
Jean-Paul Calderone4a68b402013-12-29 16:54:58 -05002613class LoadCertificateTests(TestCase):
2614 """
2615 Tests for :py:obj:`load_certificate_request`.
2616 """
2617 def test_badFileType(self):
2618 """
2619 If the file type passed to :py:obj:`load_certificate_request` is
2620 neither :py:obj:`FILETYPE_PEM` nor :py:obj:`FILETYPE_ASN1` then
2621 :py:class:`ValueError` is raised.
2622 """
2623 self.assertRaises(ValueError, load_certificate_request, object(), b"")
2624
2625
2626
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002627class PKCS7Tests(TestCase):
2628 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002629 Tests for :py:obj:`PKCS7Type`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002630 """
2631 def test_type(self):
2632 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002633 :py:obj:`PKCS7Type` is a type object.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002634 """
2635 self.assertTrue(isinstance(PKCS7Type, type))
2636 self.assertEqual(PKCS7Type.__name__, 'PKCS7')
2637
2638 # XXX This doesn't currently work.
2639 # self.assertIdentical(PKCS7, PKCS7Type)
2640
2641
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002642 # XXX Opposite results for all these following methods
2643
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002644 def test_type_is_signed_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002645 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002646 :py:obj:`PKCS7Type.type_is_signed` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002647 arguments.
2648 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002649 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2650 self.assertRaises(TypeError, pkcs7.type_is_signed, None)
2651
2652
2653 def test_type_is_signed(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002654 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002655 :py:obj:`PKCS7Type.type_is_signed` returns :py:obj:`True` if the PKCS7 object is of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002656 the type *signed*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002657 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002658 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2659 self.assertTrue(pkcs7.type_is_signed())
2660
2661
2662 def test_type_is_enveloped_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002663 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002664 :py:obj:`PKCS7Type.type_is_enveloped` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002665 arguments.
2666 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002667 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2668 self.assertRaises(TypeError, pkcs7.type_is_enveloped, None)
2669
2670
2671 def test_type_is_enveloped(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002672 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002673 :py:obj:`PKCS7Type.type_is_enveloped` returns :py:obj:`False` if the PKCS7 object is
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002674 not of the type *enveloped*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002675 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002676 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2677 self.assertFalse(pkcs7.type_is_enveloped())
2678
2679
2680 def test_type_is_signedAndEnveloped_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002681 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002682 :py:obj:`PKCS7Type.type_is_signedAndEnveloped` raises :py:obj:`TypeError` if called
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002683 with any arguments.
2684 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002685 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2686 self.assertRaises(TypeError, pkcs7.type_is_signedAndEnveloped, None)
2687
2688
2689 def test_type_is_signedAndEnveloped(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002690 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002691 :py:obj:`PKCS7Type.type_is_signedAndEnveloped` returns :py:obj:`False` if the PKCS7
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002692 object is not of the type *signed and enveloped*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002693 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002694 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2695 self.assertFalse(pkcs7.type_is_signedAndEnveloped())
2696
2697
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002698 def test_type_is_data(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002699 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002700 :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 -04002701 the type data.
2702 """
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002703 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2704 self.assertFalse(pkcs7.type_is_data())
2705
2706
2707 def test_type_is_data_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002708 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002709 :py:obj:`PKCS7Type.type_is_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002710 arguments.
2711 """
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002712 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2713 self.assertRaises(TypeError, pkcs7.type_is_data, None)
2714
2715
Jean-Paul Calderone97b28ca2010-07-30 10:56:07 -04002716 def test_get_type_name_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002717 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002718 :py:obj:`PKCS7Type.get_type_name` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002719 arguments.
2720 """
Jean-Paul Calderone97b28ca2010-07-30 10:56:07 -04002721 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2722 self.assertRaises(TypeError, pkcs7.get_type_name, None)
2723
2724
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002725 def test_get_type_name(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002726 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002727 :py:obj:`PKCS7Type.get_type_name` returns a :py:obj:`str` giving the type name.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002728 """
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002729 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
Jean-Paul Calderone07640f12010-08-22 17:14:43 -04002730 self.assertEquals(pkcs7.get_type_name(), b('pkcs7-signedData'))
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002731
2732
2733 def test_attribute(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002734 """
2735 If an attribute other than one of the methods tested here is accessed on
Jonathan Ballet648875f2011-07-16 14:14:58 +09002736 an instance of :py:obj:`PKCS7Type`, :py:obj:`AttributeError` is raised.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002737 """
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002738 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2739 self.assertRaises(AttributeError, getattr, pkcs7, "foo")
2740
2741
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002742
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002743class NetscapeSPKITests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002744 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002745 Tests for :py:obj:`OpenSSL.crypto.NetscapeSPKI`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002746 """
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002747 def signable(self):
2748 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002749 Return a new :py:obj:`NetscapeSPKI` for use with signing tests.
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002750 """
2751 return NetscapeSPKI()
2752
2753
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002754 def test_type(self):
2755 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002756 :py:obj:`NetscapeSPKI` and :py:obj:`NetscapeSPKIType` refer to the same type object
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002757 and can be used to create instances of that type.
2758 """
2759 self.assertIdentical(NetscapeSPKI, NetscapeSPKIType)
2760 self.assertConsistentType(NetscapeSPKI, 'NetscapeSPKI')
2761
2762
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002763 def test_construction(self):
2764 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002765 :py:obj:`NetscapeSPKI` returns an instance of :py:obj:`NetscapeSPKIType`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002766 """
2767 nspki = NetscapeSPKI()
2768 self.assertTrue(isinstance(nspki, NetscapeSPKIType))
2769
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002770
Jean-Paul Calderone969efaa2010-08-03 18:19:19 -04002771 def test_invalid_attribute(self):
2772 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002773 Accessing a non-existent attribute of a :py:obj:`NetscapeSPKI` instance causes
2774 an :py:obj:`AttributeError` to be raised.
Jean-Paul Calderone969efaa2010-08-03 18:19:19 -04002775 """
2776 nspki = NetscapeSPKI()
2777 self.assertRaises(AttributeError, lambda: nspki.foo)
2778
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002779
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002780 def test_b64_encode(self):
2781 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002782 :py:obj:`NetscapeSPKI.b64_encode` encodes the certificate to a base64 blob.
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002783 """
2784 nspki = NetscapeSPKI()
2785 blob = nspki.b64_encode()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002786 self.assertTrue(isinstance(blob, binary_type))
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002787
2788
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002789
Rick Dean536ba022009-07-24 23:57:27 -05002790class RevokedTests(TestCase):
2791 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002792 Tests for :py:obj:`OpenSSL.crypto.Revoked`
Rick Dean536ba022009-07-24 23:57:27 -05002793 """
2794 def test_construction(self):
2795 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002796 Confirm we can create :py:obj:`OpenSSL.crypto.Revoked`. Check
Rick Dean536ba022009-07-24 23:57:27 -05002797 that it is empty.
2798 """
2799 revoked = Revoked()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002800 self.assertTrue(isinstance(revoked, Revoked))
2801 self.assertEquals(type(revoked), Revoked)
2802 self.assertEquals(revoked.get_serial(), b('00'))
2803 self.assertEquals(revoked.get_rev_date(), None)
2804 self.assertEquals(revoked.get_reason(), None)
Rick Dean536ba022009-07-24 23:57:27 -05002805
2806
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002807 def test_construction_wrong_args(self):
2808 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002809 Calling :py:obj:`OpenSSL.crypto.Revoked` with any arguments results
2810 in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002811 """
2812 self.assertRaises(TypeError, Revoked, None)
2813 self.assertRaises(TypeError, Revoked, 1)
2814 self.assertRaises(TypeError, Revoked, "foo")
2815
2816
Rick Dean536ba022009-07-24 23:57:27 -05002817 def test_serial(self):
2818 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002819 Confirm we can set and get serial numbers from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002820 :py:obj:`OpenSSL.crypto.Revoked`. Confirm errors are handled
Rick Dean536ba022009-07-24 23:57:27 -05002821 with grace.
2822 """
2823 revoked = Revoked()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002824 ret = revoked.set_serial(b('10b'))
2825 self.assertEquals(ret, None)
Rick Dean536ba022009-07-24 23:57:27 -05002826 ser = revoked.get_serial()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002827 self.assertEquals(ser, b('010B'))
Rick Dean536ba022009-07-24 23:57:27 -05002828
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002829 revoked.set_serial(b('31ppp')) # a type error would be nice
Rick Dean536ba022009-07-24 23:57:27 -05002830 ser = revoked.get_serial()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002831 self.assertEquals(ser, b('31'))
Rick Dean536ba022009-07-24 23:57:27 -05002832
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002833 self.assertRaises(ValueError, revoked.set_serial, b('pqrst'))
Rick Dean536ba022009-07-24 23:57:27 -05002834 self.assertRaises(TypeError, revoked.set_serial, 100)
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002835 self.assertRaises(TypeError, revoked.get_serial, 1)
2836 self.assertRaises(TypeError, revoked.get_serial, None)
2837 self.assertRaises(TypeError, revoked.get_serial, "")
Rick Dean536ba022009-07-24 23:57:27 -05002838
2839
2840 def test_date(self):
2841 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002842 Confirm we can set and get revocation dates from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002843 :py:obj:`OpenSSL.crypto.Revoked`. Confirm errors are handled
Rick Dean536ba022009-07-24 23:57:27 -05002844 with grace.
2845 """
2846 revoked = Revoked()
2847 date = revoked.get_rev_date()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002848 self.assertEquals(date, None)
Rick Dean536ba022009-07-24 23:57:27 -05002849
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002850 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05002851 ret = revoked.set_rev_date(now)
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002852 self.assertEqual(ret, None)
Rick Dean536ba022009-07-24 23:57:27 -05002853 date = revoked.get_rev_date()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002854 self.assertEqual(date, now)
Rick Dean536ba022009-07-24 23:57:27 -05002855
2856
Rick Dean6385faf2009-07-26 00:07:47 -05002857 def test_reason(self):
2858 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002859 Confirm we can set and get revocation reasons from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002860 :py:obj:`OpenSSL.crypto.Revoked`. The "get" need to work
Rick Dean6385faf2009-07-26 00:07:47 -05002861 as "set". Likewise, each reason of all_reasons() must work.
2862 """
2863 revoked = Revoked()
2864 for r in revoked.all_reasons():
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002865 for x in range(2):
Rick Dean6385faf2009-07-26 00:07:47 -05002866 ret = revoked.set_reason(r)
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002867 self.assertEquals(ret, None)
Rick Dean6385faf2009-07-26 00:07:47 -05002868 reason = revoked.get_reason()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002869 self.assertEquals(
2870 reason.lower().replace(b(' '), b('')),
2871 r.lower().replace(b(' '), b('')))
Rick Dean6385faf2009-07-26 00:07:47 -05002872 r = reason # again with the resp of get
2873
2874 revoked.set_reason(None)
2875 self.assertEqual(revoked.get_reason(), None)
2876
2877
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002878 def test_set_reason_wrong_arguments(self):
Rick Dean6385faf2009-07-26 00:07:47 -05002879 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002880 Calling :py:obj:`OpenSSL.crypto.Revoked.set_reason` with other than
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002881 one argument, or an argument which isn't a valid reason,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002882 results in :py:obj:`TypeError` or :py:obj:`ValueError` being raised.
Rick Dean6385faf2009-07-26 00:07:47 -05002883 """
2884 revoked = Revoked()
2885 self.assertRaises(TypeError, revoked.set_reason, 100)
Jean-Paul Calderone281b62b2010-08-28 14:22:29 -04002886 self.assertRaises(ValueError, revoked.set_reason, b('blue'))
Rick Dean6385faf2009-07-26 00:07:47 -05002887
Rick Dean536ba022009-07-24 23:57:27 -05002888
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002889 def test_get_reason_wrong_arguments(self):
2890 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002891 Calling :py:obj:`OpenSSL.crypto.Revoked.get_reason` with any
2892 arguments results in :py:obj:`TypeError` being raised.
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002893 """
2894 revoked = Revoked()
2895 self.assertRaises(TypeError, revoked.get_reason, None)
2896 self.assertRaises(TypeError, revoked.get_reason, 1)
2897 self.assertRaises(TypeError, revoked.get_reason, "foo")
2898
2899
2900
Rick Dean536ba022009-07-24 23:57:27 -05002901class CRLTests(TestCase):
2902 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002903 Tests for :py:obj:`OpenSSL.crypto.CRL`
Rick Dean536ba022009-07-24 23:57:27 -05002904 """
2905 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
2906 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2907
2908 def test_construction(self):
2909 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002910 Confirm we can create :py:obj:`OpenSSL.crypto.CRL`. Check
Rick Dean536ba022009-07-24 23:57:27 -05002911 that it is empty
2912 """
2913 crl = CRL()
2914 self.assertTrue( isinstance(crl, CRL) )
2915 self.assertEqual(crl.get_revoked(), None)
2916
2917
Jean-Paul Calderone2efd03e2010-01-30 13:59:55 -05002918 def test_construction_wrong_args(self):
2919 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002920 Calling :py:obj:`OpenSSL.crypto.CRL` with any number of arguments
2921 results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone2efd03e2010-01-30 13:59:55 -05002922 """
2923 self.assertRaises(TypeError, CRL, 1)
2924 self.assertRaises(TypeError, CRL, "")
2925 self.assertRaises(TypeError, CRL, None)
2926
2927
Rick Dean536ba022009-07-24 23:57:27 -05002928 def test_export(self):
2929 """
2930 Use python to create a simple CRL with a revocation, and export
2931 the CRL in formats of PEM, DER and text. Those outputs are verified
2932 with the openssl program.
2933 """
2934 crl = CRL()
2935 revoked = Revoked()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002936 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05002937 revoked.set_rev_date(now)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002938 revoked.set_serial(b('3ab'))
2939 revoked.set_reason(b('sUpErSeDEd'))
Rick Dean536ba022009-07-24 23:57:27 -05002940 crl.add_revoked(revoked)
2941
2942 # PEM format
2943 dumped_crl = crl.export(self.cert, self.pkey, days=20)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002944 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002945 text.index(b('Serial Number: 03AB'))
2946 text.index(b('Superseded'))
2947 text.index(b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA'))
Rick Dean536ba022009-07-24 23:57:27 -05002948
2949 # DER format
2950 dumped_crl = crl.export(self.cert, self.pkey, FILETYPE_ASN1)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002951 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text", b"-inform", b"DER")
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002952 text.index(b('Serial Number: 03AB'))
2953 text.index(b('Superseded'))
2954 text.index(b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA'))
Rick Dean536ba022009-07-24 23:57:27 -05002955
2956 # text format
2957 dumped_text = crl.export(self.cert, self.pkey, type=FILETYPE_TEXT)
2958 self.assertEqual(text, dumped_text)
2959
2960
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -04002961 def test_export_invalid(self):
2962 """
2963 If :py:obj:`CRL.export` is used with an uninitialized :py:obj:`X509`
Jean-Paul Calderoneb5871072012-03-09 14:58:00 -08002964 instance, :py:obj:`OpenSSL.crypto.Error` is raised.
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -04002965 """
2966 crl = CRL()
2967 self.assertRaises(Error, crl.export, X509(), PKey())
2968
2969
Jean-Paul Calderone56515342010-01-30 13:49:38 -05002970 def test_add_revoked_keyword(self):
2971 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002972 :py:obj:`OpenSSL.CRL.add_revoked` accepts its single argument as the
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002973 ``revoked`` keyword argument.
Jean-Paul Calderone56515342010-01-30 13:49:38 -05002974 """
2975 crl = CRL()
2976 revoked = Revoked()
2977 crl.add_revoked(revoked=revoked)
2978 self.assertTrue(isinstance(crl.get_revoked()[0], Revoked))
2979
Rick Dean6385faf2009-07-26 00:07:47 -05002980
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05002981 def test_export_wrong_args(self):
2982 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002983 Calling :py:obj:`OpenSSL.CRL.export` with fewer than two or more than
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05002984 four arguments, or with arguments other than the certificate,
2985 private key, integer file type, and integer number of days it
Jonathan Ballet648875f2011-07-16 14:14:58 +09002986 expects, results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05002987 """
2988 crl = CRL()
2989 self.assertRaises(TypeError, crl.export)
2990 self.assertRaises(TypeError, crl.export, self.cert)
2991 self.assertRaises(TypeError, crl.export, self.cert, self.pkey, FILETYPE_PEM, 10, "foo")
2992
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05002993 self.assertRaises(TypeError, crl.export, None, self.pkey, FILETYPE_PEM, 10)
2994 self.assertRaises(TypeError, crl.export, self.cert, None, FILETYPE_PEM, 10)
2995 self.assertRaises(TypeError, crl.export, self.cert, self.pkey, None, 10)
2996 self.assertRaises(TypeError, crl.export, self.cert, FILETYPE_PEM, None)
2997
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05002998
Jean-Paul Calderoneea198422010-01-30 13:58:23 -05002999 def test_export_unknown_filetype(self):
3000 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003001 Calling :py:obj:`OpenSSL.CRL.export` with a file type other than
3002 :py:obj:`FILETYPE_PEM`, :py:obj:`FILETYPE_ASN1`, or :py:obj:`FILETYPE_TEXT` results
3003 in a :py:obj:`ValueError` being raised.
Jean-Paul Calderoneea198422010-01-30 13:58:23 -05003004 """
3005 crl = CRL()
3006 self.assertRaises(ValueError, crl.export, self.cert, self.pkey, 100, 10)
3007
3008
Rick Dean536ba022009-07-24 23:57:27 -05003009 def test_get_revoked(self):
3010 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05003011 Use python to create a simple CRL with two revocations.
Jonathan Ballet648875f2011-07-16 14:14:58 +09003012 Get back the :py:obj:`Revoked` using :py:obj:`OpenSSL.CRL.get_revoked` and
Rick Dean536ba022009-07-24 23:57:27 -05003013 verify them.
3014 """
3015 crl = CRL()
3016
3017 revoked = Revoked()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003018 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05003019 revoked.set_rev_date(now)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003020 revoked.set_serial(b('3ab'))
Rick Dean536ba022009-07-24 23:57:27 -05003021 crl.add_revoked(revoked)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003022 revoked.set_serial(b('100'))
3023 revoked.set_reason(b('sUpErSeDEd'))
Rick Dean536ba022009-07-24 23:57:27 -05003024 crl.add_revoked(revoked)
3025
3026 revs = crl.get_revoked()
3027 self.assertEqual(len(revs), 2)
3028 self.assertEqual(type(revs[0]), Revoked)
3029 self.assertEqual(type(revs[1]), Revoked)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003030 self.assertEqual(revs[0].get_serial(), b('03AB'))
3031 self.assertEqual(revs[1].get_serial(), b('0100'))
Rick Dean536ba022009-07-24 23:57:27 -05003032 self.assertEqual(revs[0].get_rev_date(), now)
3033 self.assertEqual(revs[1].get_rev_date(), now)
3034
3035
Jean-Paul Calderone46bdce42010-01-30 13:44:16 -05003036 def test_get_revoked_wrong_args(self):
3037 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003038 Calling :py:obj:`OpenSSL.CRL.get_revoked` with any arguments results
3039 in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone46bdce42010-01-30 13:44:16 -05003040 """
3041 crl = CRL()
3042 self.assertRaises(TypeError, crl.get_revoked, None)
3043 self.assertRaises(TypeError, crl.get_revoked, 1)
3044 self.assertRaises(TypeError, crl.get_revoked, "")
3045 self.assertRaises(TypeError, crl.get_revoked, "", 1, None)
3046
3047
Jean-Paul Calderoneecef6fa2010-01-30 13:47:18 -05003048 def test_add_revoked_wrong_args(self):
3049 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003050 Calling :py:obj:`OpenSSL.CRL.add_revoked` with other than one
3051 argument results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderoneecef6fa2010-01-30 13:47:18 -05003052 """
3053 crl = CRL()
3054 self.assertRaises(TypeError, crl.add_revoked)
3055 self.assertRaises(TypeError, crl.add_revoked, 1, 2)
3056 self.assertRaises(TypeError, crl.add_revoked, "foo", "bar")
3057
3058
Rick Dean536ba022009-07-24 23:57:27 -05003059 def test_load_crl(self):
3060 """
3061 Load a known CRL and inspect its revocations. Both
3062 PEM and DER formats are loaded.
3063 """
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003064 crl = load_crl(FILETYPE_PEM, crlData)
Rick Dean536ba022009-07-24 23:57:27 -05003065 revs = crl.get_revoked()
3066 self.assertEqual(len(revs), 2)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003067 self.assertEqual(revs[0].get_serial(), b('03AB'))
Rick Dean6385faf2009-07-26 00:07:47 -05003068 self.assertEqual(revs[0].get_reason(), None)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003069 self.assertEqual(revs[1].get_serial(), b('0100'))
3070 self.assertEqual(revs[1].get_reason(), b('Superseded'))
Rick Dean536ba022009-07-24 23:57:27 -05003071
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003072 der = _runopenssl(crlData, b"crl", b"-outform", b"DER")
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05003073 crl = load_crl(FILETYPE_ASN1, der)
Rick Dean536ba022009-07-24 23:57:27 -05003074 revs = crl.get_revoked()
3075 self.assertEqual(len(revs), 2)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003076 self.assertEqual(revs[0].get_serial(), b('03AB'))
Rick Dean6385faf2009-07-26 00:07:47 -05003077 self.assertEqual(revs[0].get_reason(), None)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003078 self.assertEqual(revs[1].get_serial(), b('0100'))
3079 self.assertEqual(revs[1].get_reason(), b('Superseded'))
Rick Dean536ba022009-07-24 23:57:27 -05003080
3081
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003082 def test_load_crl_wrong_args(self):
3083 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003084 Calling :py:obj:`OpenSSL.crypto.load_crl` with other than two
3085 arguments results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003086 """
3087 self.assertRaises(TypeError, load_crl)
3088 self.assertRaises(TypeError, load_crl, FILETYPE_PEM)
3089 self.assertRaises(TypeError, load_crl, FILETYPE_PEM, crlData, None)
3090
3091
3092 def test_load_crl_bad_filetype(self):
3093 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003094 Calling :py:obj:`OpenSSL.crypto.load_crl` with an unknown file type
3095 raises a :py:obj:`ValueError`.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003096 """
3097 self.assertRaises(ValueError, load_crl, 100, crlData)
3098
3099
3100 def test_load_crl_bad_data(self):
3101 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003102 Calling :py:obj:`OpenSSL.crypto.load_crl` with file data which can't
3103 be loaded raises a :py:obj:`OpenSSL.crypto.Error`.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003104 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003105 self.assertRaises(Error, load_crl, FILETYPE_PEM, b"hello, world")
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003106
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04003107
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -05003108
James Yonan7c2e5d32010-02-27 05:45:50 -07003109class SignVerifyTests(TestCase):
3110 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003111 Tests for :py:obj:`OpenSSL.crypto.sign` and :py:obj:`OpenSSL.crypto.verify`.
James Yonan7c2e5d32010-02-27 05:45:50 -07003112 """
3113 def test_sign_verify(self):
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04003114 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003115 :py:obj:`sign` generates a cryptographic signature which :py:obj:`verify` can check.
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04003116 """
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003117 content = b(
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04003118 "It was a bright cold day in April, and the clocks were striking "
3119 "thirteen. Winston Smith, his chin nuzzled into his breast in an "
3120 "effort to escape the vile wind, slipped quickly through the "
3121 "glass doors of Victory Mansions, though not quickly enough to "
3122 "prevent a swirl of gritty dust from entering along with him.")
3123
3124 # sign the content with this private key
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04003125 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04003126 # verify the content with this cert
3127 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3128 # certificate unrelated to priv_key, used to trigger an error
3129 bad_cert = load_certificate(FILETYPE_PEM, server_cert_pem)
James Yonan7c2e5d32010-02-27 05:45:50 -07003130
Jean-Paul Calderoned08feb02010-10-12 21:53:24 -04003131 for digest in ['md5', 'sha1']:
James Yonan7c2e5d32010-02-27 05:45:50 -07003132 sig = sign(priv_key, content, digest)
3133
3134 # Verify the signature of content, will throw an exception if error.
3135 verify(good_cert, sig, content, digest)
3136
3137 # This should fail because the certificate doesn't match the
3138 # private key that was used to sign the content.
3139 self.assertRaises(Error, verify, bad_cert, sig, content, digest)
3140
3141 # This should fail because we've "tainted" the content after
3142 # signing it.
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003143 self.assertRaises(
3144 Error, verify,
3145 good_cert, sig, content + b("tainted"), digest)
James Yonan7c2e5d32010-02-27 05:45:50 -07003146
3147 # test that unknown digest types fail
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003148 self.assertRaises(
Jean-Paul Calderone9538f142010-10-13 22:13:40 -04003149 ValueError, sign, priv_key, content, "strange-digest")
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003150 self.assertRaises(
Jean-Paul Calderone9538f142010-10-13 22:13:40 -04003151 ValueError, verify, good_cert, sig, content, "strange-digest")
James Yonan7c2e5d32010-02-27 05:45:50 -07003152
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04003153
Jean-Paul Calderone9828f662010-12-08 22:57:26 -05003154 def test_sign_nulls(self):
3155 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003156 :py:obj:`sign` produces a signature for a string with embedded nulls.
Jean-Paul Calderone9828f662010-12-08 22:57:26 -05003157 """
3158 content = b("Watch out! \0 Did you see it?")
3159 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
3160 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3161 sig = sign(priv_key, content, "sha1")
3162 verify(good_cert, sig, content, "sha1")
3163
3164
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003165
3166class EllipticCurveTests(TestCase):
3167 """
3168 Tests for :py:class:`_EllipticCurve`, :py:obj:`get_elliptic_curve`, and
3169 :py:obj:`get_elliptic_curves`.
3170 """
3171 def test_set(self):
3172 """
3173 :py:obj:`get_elliptic_curves` returns a :py:obj:`set`.
3174 """
3175 self.assertIsInstance(get_elliptic_curves(), set)
3176
3177
3178 def test_some_curves(self):
3179 """
3180 If :py:mod:`cryptography` has elliptic curve support then the set
3181 returned by :py:obj:`get_elliptic_curves` has some elliptic curves in
3182 it.
3183
3184 There could be an OpenSSL that violates this assumption. If so, this
3185 test will fail and we'll find out.
3186 """
3187 curves = get_elliptic_curves()
3188 if lib.Cryptography_HAS_EC:
3189 self.assertTrue(curves)
3190 else:
3191 self.assertFalse(curves)
3192
3193
3194 def test_a_curve(self):
3195 """
3196 :py:obj:`get_elliptic_curve` can be used to retrieve a particular
3197 supported curve.
3198 """
3199 curves = get_elliptic_curves()
3200 if curves:
3201 curve = next(iter(curves))
3202 self.assertEqual(curve.name, get_elliptic_curve(curve.name).name)
3203 else:
Jean-Paul Calderoneeb86f3a2014-04-19 09:45:57 -04003204 self.assertRaises(ValueError, get_elliptic_curve, u("prime256v1"))
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003205
3206
3207 def test_not_a_curve(self):
3208 """
3209 :py:obj:`get_elliptic_curve` raises :py:class:`ValueError` if called
3210 with a name which does not identify a supported curve.
3211 """
3212 self.assertRaises(
Jean-Paul Calderone5a82db92014-04-19 09:51:29 -04003213 ValueError, get_elliptic_curve, u("this curve was just invented"))
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003214
3215
3216 def test_repr(self):
3217 """
3218 The string representation of a curve object includes simply states the
3219 object is a curve and what its name is.
3220 """
3221 curves = get_elliptic_curves()
3222 if curves:
3223 curve = next(iter(curves))
3224 self.assertEqual("<Curve %r>" % (curve.name,), repr(curve))
3225
3226
3227 def test_to_EC_KEY(self):
3228 """
3229 The curve object can export a version of itself as an EC_KEY* via the
3230 private :py:meth:`_EllipticCurve._to_EC_KEY`.
3231 """
3232 curves = get_elliptic_curves()
3233 if curves:
3234 curve = next(iter(curves))
3235 # It's not easy to assert anything about this object. However, see
3236 # leakcheck/crypto.py for a test that demonstrates it at least does
3237 # not leak memory.
3238 curve._to_EC_KEY()
3239
3240
Jean-Paul Calderone1be77082014-04-30 18:17:41 -04003241
3242class EllipticCurveFactory(object):
3243 """
3244 A helper to get the names of two curves.
3245 """
3246 def __init__(self):
3247 curves = iter(get_elliptic_curves())
3248 try:
3249 self.curve_name = next(curves).name
3250 self.another_curve_name = next(curves).name
3251 except StopIteration:
3252 self.curve_name = self.another_curve_name = None
3253
3254
3255
3256class EllipticCurveEqualityTests(TestCase, EqualityTestsMixin):
3257 """
3258 Tests :py:type:`_EllipticCurve`\ 's implementation of ``==`` and ``!=``.
3259 """
3260 curve_factory = EllipticCurveFactory()
3261
3262 if curve_factory.curve_name is None:
3263 skip = "There are no curves available there can be no curve objects."
3264
3265
3266 def anInstance(self):
3267 """
3268 Get the curve object for an arbitrary curve supported by the system.
3269 """
3270 return get_elliptic_curve(self.curve_factory.curve_name)
3271
3272
3273 def anotherInstance(self):
3274 """
3275 Get the curve object for an arbitrary curve supported by the system -
3276 but not the one returned by C{anInstance}.
3277 """
3278 return get_elliptic_curve(self.curve_factory.another_curve_name)
3279
3280
3281
Jean-Paul Calderone22c31242014-05-01 07:49:47 -04003282class EllipticCurveHashTests(TestCase):
3283 """
3284 Tests for :py:type:`_EllipticCurve`\ 's implementation of hashing (thus use
3285 as an item in a :py:type:`dict` or :py:type:`set`).
3286 """
3287 curve_factory = EllipticCurveFactory()
3288
3289 if curve_factory.curve_name is None:
3290 skip = "There are no curves available there can be no curve objects."
3291
3292
3293 def test_contains(self):
3294 """
3295 The ``in`` operator reports that a :py:type:`set` containing a curve
3296 does contain that curve.
3297 """
3298 curve = get_elliptic_curve(self.curve_factory.curve_name)
3299 curves = set([curve])
3300 self.assertIn(curve, curves)
3301
3302
3303 def test_does_not_contain(self):
3304 """
3305 The ``in`` operator reports that a :py:type:`set` not containing a
3306 curve does not contain that curve.
3307 """
3308 curve = get_elliptic_curve(self.curve_factory.curve_name)
3309 curves = set([get_elliptic_curve(self.curve_factory.another_curve_name)])
3310 self.assertNotIn(curve, curves)
3311
3312
3313
Rick Dean5b7b6372009-04-01 11:34:06 -05003314if __name__ == '__main__':
3315 main()