blob: d451c9c73b1b5d9dbdf4bda4db21f5521b154ad5 [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
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -040010import os, re
Jean-Paul Calderone62ca8da2010-08-11 19:58:08 -040011from subprocess import PIPE, Popen
Rick Dean47262da2009-07-08 16:17:17 -050012from datetime import datetime, timedelta
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -050013
14from OpenSSL.crypto import TYPE_RSA, TYPE_DSA, Error, PKey, PKeyType
Jean-Paul Calderone78381d22008-03-06 23:35:22 -050015from OpenSSL.crypto import X509, X509Type, X509Name, X509NameType
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080016from OpenSSL.crypto import X509Store, X509StoreType, X509Req, X509ReqType
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -050017from OpenSSL.crypto import X509Extension, X509ExtensionType
Rick Dean5b7b6372009-04-01 11:34:06 -050018from OpenSSL.crypto import load_certificate, load_privatekey
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -040019from OpenSSL.crypto import FILETYPE_PEM, FILETYPE_ASN1, FILETYPE_TEXT
Jean-Paul Calderone71919862009-04-01 13:01:19 -040020from OpenSSL.crypto import dump_certificate, load_certificate_request
21from OpenSSL.crypto import dump_certificate_request, dump_privatekey
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -040022from OpenSSL.crypto import PKCS7Type, load_pkcs7_data
Jean-Paul Calderone9178ee62010-01-25 17:55:30 -050023from OpenSSL.crypto import PKCS12, PKCS12Type, load_pkcs12
Rick Dean536ba022009-07-24 23:57:27 -050024from OpenSSL.crypto import CRL, Revoked, load_crl
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -040025from OpenSSL.crypto import NetscapeSPKI, NetscapeSPKIType
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -040026from OpenSSL.crypto import sign, verify
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -040027from OpenSSL.test.util import TestCase, bytes, b
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040028
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -040029def normalize_certificate_pem(pem):
30 return dump_certificate(FILETYPE_PEM, load_certificate(FILETYPE_PEM, pem))
31
32
33def normalize_privatekey_pem(pem):
34 return dump_privatekey(FILETYPE_PEM, load_privatekey(FILETYPE_PEM, pem))
35
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040036
37root_cert_pem = b("""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -050038MIIC7TCCAlagAwIBAgIIPQzE4MbeufQwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE
39BhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdU
40ZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwIhgPMjAwOTAzMjUxMjM2
41NThaGA8yMDE3MDYxMTEyMzY1OFowWDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklM
42MRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9U
43ZXN0aW5nIFJvb3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPmaQumL
44urpE527uSEHdL1pqcDRmWzu+98Y6YHzT/J7KWEamyMCNZ6fRW1JCR782UQ8a07fy
452xXsKy4WdKaxyG8CcatwmXvpvRQ44dSANMihHELpANTdyVp6DCysED6wkQFurHlF
461dshEaJw8b/ypDhmbVIo6Ci1xvCJqivbLFnbAgMBAAGjgbswgbgwHQYDVR0OBBYE
47FINVdy1eIfFJDAkk51QJEo3IfgSuMIGIBgNVHSMEgYAwfoAUg1V3LV4h8UkMCSTn
48VAkSjch+BK6hXKRaMFgxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UE
49BxMHQ2hpY2FnbzEQMA4GA1UEChMHVGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBS
50b290IENBggg9DMTgxt659DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB
51AGGCDazMJGoWNBpc03u6+smc95dEead2KlZXBATOdFT1VesY3+nUOqZhEhTGlDMi
52hkgaZnzoIq/Uamidegk4hirsCT/R+6vsKAAxNTcBjUeZjlykCJWy5ojShGftXIKY
53w/njVbKMXrvc83qmTdGl3TAM0fxQIpqgcglFLveEBgzn
54-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040055""")
Rick Dean94e46fd2009-07-18 14:51:24 -050056
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040057root_key_pem = b("""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -050058MIICXQIBAAKBgQD5mkLpi7q6ROdu7khB3S9aanA0Zls7vvfGOmB80/yeylhGpsjA
59jWen0VtSQke/NlEPGtO38tsV7CsuFnSmschvAnGrcJl76b0UOOHUgDTIoRxC6QDU
603claegwsrBA+sJEBbqx5RdXbIRGicPG/8qQ4Zm1SKOgotcbwiaor2yxZ2wIDAQAB
61AoGBAPCgMpmLxzwDaUmcFbTJUvlLW1hoxNNYSu2jIZm1k/hRAcE60JYwvBkgz3UB
62yMEh0AtLxYe0bFk6EHah11tMUPgscbCq73snJ++8koUw+csk22G65hOs51bVb7Aa
636JBe67oLzdtvgCUFAA2qfrKzWRZzAdhUirQUZgySZk+Xq1pBAkEA/kZG0A6roTSM
64BVnx7LnPfsycKUsTumorpXiylZJjTi9XtmzxhrYN6wgZlDOOwOLgSQhszGpxVoMD
65u3gByT1b2QJBAPtL3mSKdvwRu/+40zaZLwvSJRxaj0mcE4BJOS6Oqs/hS1xRlrNk
66PpQ7WJ4yM6ZOLnXzm2mKyxm50Mv64109FtMCQQDOqS2KkjHaLowTGVxwC0DijMfr
67I9Lf8sSQk32J5VWCySWf5gGTfEnpmUa41gKTMJIbqZZLucNuDcOtzUaeWZlZAkA8
68ttXigLnCqR486JDPTi9ZscoZkZ+w7y6e/hH8t6d5Vjt48JVyfjPIaJY+km58LcN3
696AWSeGAdtRFHVzR7oHjVAkB4hutvxiOeiIVQNBhM6RSI9aBPMI21DoX2JRoxvNW2
70cbvAhow217X9V0dVerEOKxnNYspXRrh36h7k4mQA+sDq
71-----END RSA PRIVATE KEY-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040072""")
Rick Dean94e46fd2009-07-18 14:51:24 -050073
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040074server_cert_pem = b("""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -050075MIICKDCCAZGgAwIBAgIJAJn/HpR21r/8MA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
76BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
77VGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBSb290IENBMCIYDzIwMDkwMzI1MTIz
78NzUzWhgPMjAxNzA2MTExMjM3NTNaMBgxFjAUBgNVBAMTDWxvdmVseSBzZXJ2ZXIw
79gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAL6m+G653V0tpBC/OKl22VxOi2Cv
80lK4TYu9LHSDP9uDVTe7V5D5Tl6qzFoRRx5pfmnkqT5B+W9byp2NU3FC5hLm5zSAr
81b45meUhjEJ/ifkZgbNUjHdBIGP9MAQUHZa5WKdkGIJvGAvs8UzUqlr4TBWQIB24+
82lJ+Ukk/CRgasrYwdAgMBAAGjNjA0MB0GA1UdDgQWBBS4kC7Ij0W1TZXZqXQFAM2e
83gKEG2DATBgNVHSUEDDAKBggrBgEFBQcDATANBgkqhkiG9w0BAQUFAAOBgQBh30Li
84dJ+NlxIOx5343WqIBka3UbsOb2kxWrbkVCrvRapCMLCASO4FqiKWM+L0VDBprqIp
852mgpFQ6FHpoIENGvJhdEKpptQ5i7KaGhnDNTfdy3x1+h852G99f1iyj0RmbuFcM8
86uzujnS8YXWvM7DM1Ilozk4MzPug8jzFp5uhKCQ==
87-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040088""")
Rick Dean94e46fd2009-07-18 14:51:24 -050089
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -040090server_key_pem = normalize_privatekey_pem(b("""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -050091MIICWwIBAAKBgQC+pvhuud1dLaQQvzipdtlcTotgr5SuE2LvSx0gz/bg1U3u1eQ+
92U5eqsxaEUceaX5p5Kk+QflvW8qdjVNxQuYS5uc0gK2+OZnlIYxCf4n5GYGzVIx3Q
93SBj/TAEFB2WuVinZBiCbxgL7PFM1Kpa+EwVkCAduPpSflJJPwkYGrK2MHQIDAQAB
94AoGAbwuZ0AR6JveahBaczjfnSpiFHf+mve2UxoQdpyr6ROJ4zg/PLW5K/KXrC48G
95j6f3tXMrfKHcpEoZrQWUfYBRCUsGD5DCazEhD8zlxEHahIsqpwA0WWssJA2VOLEN
96j6DuV2pCFbw67rfTBkTSo32ahfXxEKev5KswZk0JIzH3ooECQQDgzS9AI89h0gs8
97Dt+1m11Rzqo3vZML7ZIyGApUzVan+a7hbc33nbGRkAXjHaUBJO31it/H6dTO+uwX
98msWwNG5ZAkEA2RyFKs5xR5USTFaKLWCgpH/ydV96KPOpBND7TKQx62snDenFNNbn
99FwwOhpahld+vqhYk+pfuWWUpQciE+Bu7ZQJASjfT4sQv4qbbKK/scePicnDdx9th
1004e1EeB9xwb+tXXXUo/6Bor/AcUNwfiQ6Zt9PZOK9sR3lMZSsP7rMi7kzuQJABie6
1011sXXjFH7nNJvRG4S39cIxq8YRYTy68II/dlB2QzGpKxV/POCxbJ/zu0CU79tuYK7
102NaeNCFfH3aeTrX0LyQJAMBWjWmeKM2G2sCExheeQK0ROnaBC8itCECD4Jsve4nqf
103r50+LF74iLXFwqysVCebPKMOpDWp/qQ1BbJQIPs7/A==
104-----END RSA PRIVATE KEY-----
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -0400105"""))
Rick Dean94e46fd2009-07-18 14:51:24 -0500106
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400107client_cert_pem = b("""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500108MIICJjCCAY+gAwIBAgIJAKxpFI5lODkjMA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
109BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
110VGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBSb290IENBMCIYDzIwMDkwMzI1MTIz
111ODA1WhgPMjAxNzA2MTExMjM4MDVaMBYxFDASBgNVBAMTC3VnbHkgY2xpZW50MIGf
112MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDAZh/SRtNm5ntMT4qb6YzEpTroMlq2
113rn+GrRHRiZ+xkCw/CGNhbtPir7/QxaUj26BSmQrHw1bGKEbPsWiW7bdXSespl+xK
114iku4G/KvnnmWdeJHqsiXeUZtqurMELcPQAw9xPHEuhqqUJvvEoMTsnCEqGM+7Dtb
115oCRajYyHfluARQIDAQABozYwNDAdBgNVHQ4EFgQUNQB+qkaOaEVecf1J3TTUtAff
1160fAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQEFBQADgYEAyv/Jh7gM
117Q3OHvmsFEEvRI+hsW8y66zK4K5de239Y44iZrFYkt7Q5nBPMEWDj4F2hLYWL/qtI
1189Zdr0U4UDCU9SmmGYh4o7R4TZ5pGFvBYvjhHbkSFYFQXZxKUi+WUxplP6I0wr2KJ
119PSTJCjJOn3xo2NTKRgV1gaoTf2EhL+RG8TQ=
120-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400121""")
Rick Dean94e46fd2009-07-18 14:51:24 -0500122
Jean-Paul Calderone22cbe502011-05-04 17:01:43 -0400123client_key_pem = normalize_privatekey_pem(b("""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500124MIICXgIBAAKBgQDAZh/SRtNm5ntMT4qb6YzEpTroMlq2rn+GrRHRiZ+xkCw/CGNh
125btPir7/QxaUj26BSmQrHw1bGKEbPsWiW7bdXSespl+xKiku4G/KvnnmWdeJHqsiX
126eUZtqurMELcPQAw9xPHEuhqqUJvvEoMTsnCEqGM+7DtboCRajYyHfluARQIDAQAB
127AoGATkZ+NceY5Glqyl4mD06SdcKfV65814vg2EL7V9t8+/mi9rYL8KztSXGlQWPX
128zuHgtRoMl78yQ4ZJYOBVo+nsx8KZNRCEBlE19bamSbQLCeQMenWnpeYyQUZ908gF
129h6L9qsFVJepgA9RDgAjyDoS5CaWCdCCPCH2lDkdcqC54SVUCQQDseuduc4wi8h4t
130V8AahUn9fn9gYfhoNuM0gdguTA0nPLVWz4hy1yJiWYQe0H7NLNNTmCKiLQaJpAbb
131TC6vE8C7AkEA0Ee8CMJUc20BnGEmxwgWcVuqFWaKCo8jTH1X38FlATUsyR3krjW2
132dL3yDD9NwHxsYP7nTKp/U8MV7U9IBn4y/wJBAJl7H0/BcLeRmuJk7IqJ7b635iYB
133D/9beFUw3MUXmQXZUfyYz39xf6CDZsu1GEdEC5haykeln3Of4M9d/4Kj+FcCQQCY
134si6xwT7GzMDkk/ko684AV3KPc/h6G0yGtFIrMg7J3uExpR/VdH2KgwMkZXisSMvw
135JJEQjOMCVsEJlRk54WWjAkEAzoZNH6UhDdBK5F38rVt/y4SEHgbSfJHIAmPS32Kq
136f6GGcfNpip0Uk7q7udTKuX7Q/buZi/C4YW7u3VKAquv9NA==
137-----END RSA PRIVATE KEY-----
Jean-Paul Calderone22cbe502011-05-04 17:01:43 -0400138"""))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400139
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400140cleartextCertificatePEM = b("""-----BEGIN CERTIFICATE-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400141MIIC7TCCAlagAwIBAgIIPQzE4MbeufQwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE
142BhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdU
143ZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwIhgPMjAwOTAzMjUxMjM2
144NThaGA8yMDE3MDYxMTEyMzY1OFowWDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklM
145MRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9U
146ZXN0aW5nIFJvb3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPmaQumL
147urpE527uSEHdL1pqcDRmWzu+98Y6YHzT/J7KWEamyMCNZ6fRW1JCR782UQ8a07fy
1482xXsKy4WdKaxyG8CcatwmXvpvRQ44dSANMihHELpANTdyVp6DCysED6wkQFurHlF
1491dshEaJw8b/ypDhmbVIo6Ci1xvCJqivbLFnbAgMBAAGjgbswgbgwHQYDVR0OBBYE
150FINVdy1eIfFJDAkk51QJEo3IfgSuMIGIBgNVHSMEgYAwfoAUg1V3LV4h8UkMCSTn
151VAkSjch+BK6hXKRaMFgxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UE
152BxMHQ2hpY2FnbzEQMA4GA1UEChMHVGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBS
153b290IENBggg9DMTgxt659DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB
154AGGCDazMJGoWNBpc03u6+smc95dEead2KlZXBATOdFT1VesY3+nUOqZhEhTGlDMi
155hkgaZnzoIq/Uamidegk4hirsCT/R+6vsKAAxNTcBjUeZjlykCJWy5ojShGftXIKY
156w/njVbKMXrvc83qmTdGl3TAM0fxQIpqgcglFLveEBgzn
157-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400158""")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400159
Jean-Paul Calderoned50d2042011-05-04 17:00:49 -0400160cleartextPrivateKeyPEM = normalize_privatekey_pem(b("""\
161-----BEGIN RSA PRIVATE KEY-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400162MIICXQIBAAKBgQD5mkLpi7q6ROdu7khB3S9aanA0Zls7vvfGOmB80/yeylhGpsjA
163jWen0VtSQke/NlEPGtO38tsV7CsuFnSmschvAnGrcJl76b0UOOHUgDTIoRxC6QDU
1643claegwsrBA+sJEBbqx5RdXbIRGicPG/8qQ4Zm1SKOgotcbwiaor2yxZ2wIDAQAB
165AoGBAPCgMpmLxzwDaUmcFbTJUvlLW1hoxNNYSu2jIZm1k/hRAcE60JYwvBkgz3UB
166yMEh0AtLxYe0bFk6EHah11tMUPgscbCq73snJ++8koUw+csk22G65hOs51bVb7Aa
1676JBe67oLzdtvgCUFAA2qfrKzWRZzAdhUirQUZgySZk+Xq1pBAkEA/kZG0A6roTSM
168BVnx7LnPfsycKUsTumorpXiylZJjTi9XtmzxhrYN6wgZlDOOwOLgSQhszGpxVoMD
169u3gByT1b2QJBAPtL3mSKdvwRu/+40zaZLwvSJRxaj0mcE4BJOS6Oqs/hS1xRlrNk
170PpQ7WJ4yM6ZOLnXzm2mKyxm50Mv64109FtMCQQDOqS2KkjHaLowTGVxwC0DijMfr
171I9Lf8sSQk32J5VWCySWf5gGTfEnpmUa41gKTMJIbqZZLucNuDcOtzUaeWZlZAkA8
172ttXigLnCqR486JDPTi9ZscoZkZ+w7y6e/hH8t6d5Vjt48JVyfjPIaJY+km58LcN3
1736AWSeGAdtRFHVzR7oHjVAkB4hutvxiOeiIVQNBhM6RSI9aBPMI21DoX2JRoxvNW2
174cbvAhow217X9V0dVerEOKxnNYspXRrh36h7k4mQA+sDq
175-----END RSA PRIVATE KEY-----
Jean-Paul Calderoned50d2042011-05-04 17:00:49 -0400176"""))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400177
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400178cleartextCertificateRequestPEM = b("""-----BEGIN CERTIFICATE REQUEST-----
179MIIBnjCCAQcCAQAwXjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQH
180EwdDaGljYWdvMRcwFQYDVQQKEw5NeSBDb21wYW55IEx0ZDEXMBUGA1UEAxMORnJl
181ZGVyaWNrIERlYW4wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANp6Y17WzKSw
182BsUWkXdqg6tnXy8H8hA1msCMWpc+/2KJ4mbv5NyD6UD+/SqagQqulPbF/DFea9nA
183E0zhmHJELcM8gUTIlXv/cgDWnmK4xj8YkjVUiCdqKRAKeuzLG1pGmwwF5lGeJpXN
184xQn5ecR0UYSOWj6TTGXB9VyUMQzCClcBAgMBAAGgADANBgkqhkiG9w0BAQUFAAOB
185gQAAJGuF/R/GGbeC7FbFW+aJgr9ee0Xbl6nlhu7pTe67k+iiKT2dsl2ti68MVTnu
186Vrb3HUNqOkiwsJf6kCtq5oPn3QVYzTa76Dt2y3Rtzv6boRSlmlfrgS92GNma8JfR
187oICQk3nAudi6zl1Dix3BCv1pUp5KMtGn3MeDEi6QFGy2rA==
188-----END CERTIFICATE REQUEST-----
189""")
Rick Dean5b7b6372009-04-01 11:34:06 -0500190
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400191encryptedPrivateKeyPEM = b("""-----BEGIN RSA PRIVATE KEY-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400192Proc-Type: 4,ENCRYPTED
193DEK-Info: DES-EDE3-CBC,9573604A18579E9E
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400194
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400195SHOho56WxDkT0ht10UTeKc0F5u8cqIa01kzFAmETw0MAs8ezYtK15NPdCXUm3X/2
196a17G7LSF5bkxOgZ7vpXyMzun/owrj7CzvLxyncyEFZWvtvzaAhPhvTJtTIB3kf8B
1978+qRcpTGK7NgXEgYBW5bj1y4qZkD4zCL9o9NQzsKI3Ie8i0239jsDOWR38AxjXBH
198mGwAQ4Z6ZN5dnmM4fhMIWsmFf19sNyAML4gHenQCHhmXbjXeVq47aC2ProInJbrm
199+00TcisbAQ40V9aehVbcDKtS4ZbMVDwncAjpXpcncC54G76N6j7F7wL7L/FuXa3A
200fvSVy9n2VfF/pJ3kYSflLHH2G/DFxjF7dl0GxhKPxJjp3IJi9VtuvmN9R2jZWLQF
201tfC8dXgy/P9CfFQhlinqBTEwgH0oZ/d4k4NVFDSdEMaSdmBAjlHpc+Vfdty3HVnV
202rKXj//wslsFNm9kIwJGIgKUa/n2jsOiydrsk1mgH7SmNCb3YHgZhbbnq0qLat/HC
203gHDt3FHpNQ31QzzL3yrenFB2L9osIsnRsDTPFNi4RX4SpDgNroxOQmyzCCV6H+d4
204o1mcnNiZSdxLZxVKccq0AfRpHqpPAFnJcQHP6xyT9MZp6fBa0XkxDnt9kNU8H3Qw
2057SJWZ69VXjBUzMlQViLuaWMgTnL+ZVyFZf9hTF7U/ef4HMLMAVNdiaGG+G+AjCV/
206MbzjS007Oe4qqBnCWaFPSnJX6uLApeTbqAxAeyCql56ULW5x6vDMNC3dwjvS/CEh
20711n8RkgFIQA0AhuKSIg3CbuartRsJnWOLwgLTzsrKYL4yRog1RJrtw==
208-----END RSA PRIVATE KEY-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400209""")
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400210
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400211encryptedPrivateKeyPEMPassphrase = b("foobar")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400212
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400213# Some PKCS#7 stuff. Generated with the openssl command line:
214#
215# openssl crl2pkcs7 -inform pem -outform pem -certfile s.pem -nocrl
216#
217# with a certificate and key (but the key should be irrelevant) in s.pem
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400218pkcs7Data = b("""\
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400219-----BEGIN PKCS7-----
220MIIDNwYJKoZIhvcNAQcCoIIDKDCCAyQCAQExADALBgkqhkiG9w0BBwGgggMKMIID
221BjCCAm+gAwIBAgIBATANBgkqhkiG9w0BAQQFADB7MQswCQYDVQQGEwJTRzERMA8G
222A1UEChMITTJDcnlwdG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtN
223MkNyeXB0byBDZXJ0aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNA
224cG9zdDEuY29tMB4XDTAwMDkxMDA5NTEzMFoXDTAyMDkxMDA5NTEzMFowUzELMAkG
225A1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwlsb2NhbGhvc3Qx
226HTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tMFwwDQYJKoZIhvcNAQEBBQAD
227SwAwSAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh5kwI
228zOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEAAaOCAQQwggEAMAkGA1UdEwQCMAAw
229LAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0G
230A1UdDgQWBBTPhIKSvnsmYsBVNWjj0m3M2z0qVTCBpQYDVR0jBIGdMIGagBT7hyNp
23165w6kxXlxb8pUU/+7Sg4AaF/pH0wezELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0y
232Q3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlwdG8g
233Q2VydGlmaWNhdGUgTWFzdGVyMR0wGwYJKoZIhvcNAQkBFg5uZ3BzQHBvc3QxLmNv
234bYIBADANBgkqhkiG9w0BAQQFAAOBgQA7/CqT6PoHycTdhEStWNZde7M/2Yc6BoJu
235VwnW8YxGO8Sn6UJ4FeffZNcYZddSDKosw8LtPOeWoK3JINjAk5jiPQ2cww++7QGG
236/g5NDjxFZNDJP1dGiLAxPW6JXwov4v0FmdzfLOZ01jDcgQQZqEpYlgpuI5JEWUQ9
237Ho4EzbYCOaEAMQA=
238-----END PKCS7-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400239""")
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400240
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400241crlData = b("""\
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -0500242-----BEGIN X509 CRL-----
243MIIBWzCBxTANBgkqhkiG9w0BAQQFADBYMQswCQYDVQQGEwJVUzELMAkGA1UECBMC
244SUwxEDAOBgNVBAcTB0NoaWNhZ28xEDAOBgNVBAoTB1Rlc3RpbmcxGDAWBgNVBAMT
245D1Rlc3RpbmcgUm9vdCBDQRcNMDkwNzI2MDQzNDU2WhcNMTIwOTI3MDI0MTUyWjA8
246MBUCAgOrGA8yMDA5MDcyNTIzMzQ1NlowIwICAQAYDzIwMDkwNzI1MjMzNDU2WjAM
247MAoGA1UdFQQDCgEEMA0GCSqGSIb3DQEBBAUAA4GBAEBt7xTs2htdD3d4ErrcGAw1
2484dKcVnIWTutoI7xxen26Wwvh8VCsT7i/UeP+rBl9rC/kfjWjzQk3/zleaarGTpBT
2490yp4HXRFFoRhhSE/hP+eteaPXRgrsNRLHe9ZDd69wmh7J1wMDb0m81RG7kqcbsid
250vrzEeLDRiiPl92dyyWmu
251-----END X509 CRL-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400252""")
Jean-Paul Calderonee890db32010-08-22 16:55:15 -0400253
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400254
255# A broken RSA private key which can be used to test the error path through
256# PKey.check.
257inconsistentPrivateKeyPEM = b("""-----BEGIN RSA PRIVATE KEY-----
258MIIBPAIBAAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh
2595kwIzOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEaAQJBAIqm/bz4NA1H++Vx5Ewx
260OcKp3w19QSaZAwlGRtsUxrP7436QjnREM3Bm8ygU11BjkPVmtrKm6AayQfCHqJoT
261zIECIQDW0BoMoL0HOYM/mrTLhaykYAVqgIeJsPjvkEhTFXWBuQIhAM3deFAvWNu4
262nklUQ37XsCT2c9tmNt1LAT+slG2JOTTRAiAuXDtC/m3NYVwyHfFm+zKHRzHkClk2
263HjubeEgjpj32AQIhAJqMGTaZVOwevTXvvHwNeH+vRWsAYU/gbx+OQB+7VOcBAiEA
264oolb6NMg/R3enNPvS1O4UU1H8wpaF77L4yiSWlE0p4w=
265-----END RSA PRIVATE KEY-----
266""")
267
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -0400268# certificate with NULL bytes in subjectAltName and common name
269
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400270nulbyteSubjectAltNamePEM = b("""-----BEGIN CERTIFICATE-----
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -0400271MIIE2DCCA8CgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBxTELMAkGA1UEBhMCVVMx
272DzANBgNVBAgMBk9yZWdvbjESMBAGA1UEBwwJQmVhdmVydG9uMSMwIQYDVQQKDBpQ
273eXRob24gU29mdHdhcmUgRm91bmRhdGlvbjEgMB4GA1UECwwXUHl0aG9uIENvcmUg
274RGV2ZWxvcG1lbnQxJDAiBgNVBAMMG251bGwucHl0aG9uLm9yZwBleGFtcGxlLm9y
275ZzEkMCIGCSqGSIb3DQEJARYVcHl0aG9uLWRldkBweXRob24ub3JnMB4XDTEzMDgw
276NzEzMTE1MloXDTEzMDgwNzEzMTI1MlowgcUxCzAJBgNVBAYTAlVTMQ8wDQYDVQQI
277DAZPcmVnb24xEjAQBgNVBAcMCUJlYXZlcnRvbjEjMCEGA1UECgwaUHl0aG9uIFNv
278ZnR3YXJlIEZvdW5kYXRpb24xIDAeBgNVBAsMF1B5dGhvbiBDb3JlIERldmVsb3Bt
279ZW50MSQwIgYDVQQDDBtudWxsLnB5dGhvbi5vcmcAZXhhbXBsZS5vcmcxJDAiBgkq
280hkiG9w0BCQEWFXB5dGhvbi1kZXZAcHl0aG9uLm9yZzCCASIwDQYJKoZIhvcNAQEB
281BQADggEPADCCAQoCggEBALXq7cn7Rn1vO3aA3TrzA5QLp6bb7B3f/yN0CJ2XFj+j
282pHs+Gw6WWSUDpybiiKnPec33BFawq3kyblnBMjBU61ioy5HwQqVkJ8vUVjGIUq3P
283vX/wBmQfzCe4o4uM89gpHyUL9UYGG8oCRa17dgqcv7u5rg0Wq2B1rgY+nHwx3JIv
284KRrgSwyRkGzpN8WQ1yrXlxWjgI9de0mPVDDUlywcWze1q2kwaEPTM3hLAmD1PESA
285oY/n8A/RXoeeRs9i/Pm/DGUS8ZPINXk/yOzsR/XvvkTVroIeLZqfmFpnZeF0cHzL
28608LODkVJJ9zjLdT7SA4vnne4FEbAxDbKAq5qkYzaL4UCAwEAAaOB0DCBzTAMBgNV
287HRMBAf8EAjAAMB0GA1UdDgQWBBSIWlXAUv9hzVKjNQ/qWpwkOCL3XDALBgNVHQ8E
288BAMCBeAwgZAGA1UdEQSBiDCBhYIeYWx0bnVsbC5weXRob24ub3JnAGV4YW1wbGUu
289Y29tgSBudWxsQHB5dGhvbi5vcmcAdXNlckBleGFtcGxlLm9yZ4YpaHR0cDovL251
290bGwucHl0aG9uLm9yZwBodHRwOi8vZXhhbXBsZS5vcmeHBMAAAgGHECABDbgAAAAA
291AAAAAAAAAAEwDQYJKoZIhvcNAQEFBQADggEBAKxPRe99SaghcI6IWT7UNkJw9aO9
292i9eo0Fj2MUqxpKbdb9noRDy2CnHWf7EIYZ1gznXPdwzSN4YCjV5d+Q9xtBaowT0j
293HPERs1ZuytCNNJTmhyqZ8q6uzMLoht4IqH/FBfpvgaeC5tBTnTT0rD5A/olXeimk
294kX4LxlEx5RAvpGB2zZVRGr6LobD9rVK91xuHYNIxxxfEGE8tCCWjp0+3ksri9SXx
295VHWBnbM9YaL32u3hxm8sYB/Yb8WSBavJCWJJqRStVRHM1koZlJmXNx2BX4vPo6iW
296RFEIPQsFZRLrtnCAiEhyT8bC2s/Njlu6ly9gtJZWSV46Q3ZjBL4q9sHKqZQ=
297-----END CERTIFICATE-----""")
298
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400299
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400300class X509ExtTests(TestCase):
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400301 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900302 Tests for :py:class:`OpenSSL.crypto.X509Extension`.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400303 """
304
305 def setUp(self):
306 """
307 Create a new private key and start a certificate request (for a test
308 method to finish in one way or another).
309 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -0800310 super(X509ExtTests, self).setUp()
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400311 # Basic setup stuff to generate a certificate
312 self.pkey = PKey()
313 self.pkey.generate_key(TYPE_RSA, 384)
314 self.req = X509Req()
315 self.req.set_pubkey(self.pkey)
316 # Authority good you have.
317 self.req.get_subject().commonName = "Yoda root CA"
318 self.x509 = X509()
319 self.subject = self.x509.get_subject()
320 self.subject.commonName = self.req.get_subject().commonName
321 self.x509.set_issuer(self.subject)
322 self.x509.set_pubkey(self.pkey)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400323 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
324 expire = b((datetime.now() + timedelta(days=100)).strftime("%Y%m%d%H%M%SZ"))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400325 self.x509.set_notBefore(now)
326 self.x509.set_notAfter(expire)
327
328
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -0800329 def tearDown(self):
330 """
331 Forget all of the pyOpenSSL objects so they can be garbage collected,
332 their memory released, and not interfere with the leak detection code.
333 """
334 self.pkey = self.req = self.x509 = self.subject = None
335 super(X509ExtTests, self).tearDown()
336
337
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400338 def test_str(self):
339 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900340 The string representation of :py:class:`X509Extension` instances as returned by
341 :py:data:`str` includes stuff.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400342 """
343 # This isn't necessarily the best string representation. Perhaps it
344 # will be changed/improved in the future.
345 self.assertEquals(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400346 str(X509Extension(b('basicConstraints'), True, b('CA:false'))),
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400347 'CA:FALSE')
348
349
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400350 def test_type(self):
351 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900352 :py:class:`X509Extension` and :py:class:`X509ExtensionType` refer to the same type object
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400353 and can be used to create instances of that type.
354 """
355 self.assertIdentical(X509Extension, X509ExtensionType)
356 self.assertConsistentType(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400357 X509Extension,
358 'X509Extension', b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400359
360
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500361 def test_construction(self):
362 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900363 :py:class:`X509Extension` accepts an extension type name, a critical flag,
364 and an extension value and returns an :py:class:`X509ExtensionType` instance.
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500365 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400366 basic = X509Extension(b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500367 self.assertTrue(
368 isinstance(basic, X509ExtensionType),
369 "%r is of type %r, should be %r" % (
370 basic, type(basic), X509ExtensionType))
371
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400372 comment = X509Extension(
373 b('nsComment'), False, b('pyOpenSSL unit test'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500374 self.assertTrue(
375 isinstance(comment, X509ExtensionType),
376 "%r is of type %r, should be %r" % (
377 comment, type(comment), X509ExtensionType))
378
379
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500380 def test_invalid_extension(self):
381 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900382 :py:class:`X509Extension` raises something if it is passed a bad extension
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500383 name or value.
384 """
385 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400386 Error, X509Extension, b('thisIsMadeUp'), False, b('hi'))
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500387 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400388 Error, X509Extension, b('basicConstraints'), False, b('blah blah'))
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500389
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500390 # Exercise a weird one (an extension which uses the r2i method). This
391 # exercises the codepath that requires a non-NULL ctx to be passed to
392 # X509V3_EXT_nconf. It can't work now because we provide no
393 # configuration database. It might be made to work in the future.
394 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400395 Error, X509Extension, b('proxyCertInfo'), True,
396 b('language:id-ppl-anyLanguage,pathlen:1,policy:text:AB'))
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500397
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500398
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500399 def test_get_critical(self):
400 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900401 :py:meth:`X509ExtensionType.get_critical` returns the value of the
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500402 extension's critical flag.
403 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400404 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500405 self.assertTrue(ext.get_critical())
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400406 ext = X509Extension(b('basicConstraints'), False, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500407 self.assertFalse(ext.get_critical())
408
Jean-Paul Calderone7535dab2008-03-06 18:53:11 -0500409
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500410 def test_get_short_name(self):
411 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900412 :py:meth:`X509ExtensionType.get_short_name` returns a string giving the short
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500413 type name of the extension.
414 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400415 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
416 self.assertEqual(ext.get_short_name(), b('basicConstraints'))
417 ext = X509Extension(b('nsComment'), True, b('foo bar'))
418 self.assertEqual(ext.get_short_name(), b('nsComment'))
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500419
420
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400421 def test_get_data(self):
422 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900423 :py:meth:`X509Extension.get_data` returns a string giving the data of the
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400424 extension.
425 """
426 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
427 # Expect to get back the DER encoded form of CA:true.
428 self.assertEqual(ext.get_data(), b('0\x03\x01\x01\xff'))
429
430
431 def test_get_data_wrong_args(self):
432 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900433 :py:meth:`X509Extension.get_data` raises :py:exc:`TypeError` if passed any arguments.
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400434 """
435 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
436 self.assertRaises(TypeError, ext.get_data, None)
437 self.assertRaises(TypeError, ext.get_data, "foo")
438 self.assertRaises(TypeError, ext.get_data, 7)
439
440
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400441 def test_unused_subject(self):
Rick Dean47262da2009-07-08 16:17:17 -0500442 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900443 The :py:data:`subject` parameter to :py:class:`X509Extension` may be provided for an
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400444 extension which does not use it and is ignored in this case.
Rick Dean47262da2009-07-08 16:17:17 -0500445 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400446 ext1 = X509Extension(
447 b('basicConstraints'), False, b('CA:TRUE'), subject=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400448 self.x509.add_extensions([ext1])
449 self.x509.sign(self.pkey, 'sha1')
450 # This is a little lame. Can we think of a better way?
451 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400452 self.assertTrue(b('X509v3 Basic Constraints:') in text)
453 self.assertTrue(b('CA:TRUE') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400454
455
456 def test_subject(self):
457 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900458 If an extension requires a subject, the :py:data:`subject` parameter to
459 :py:class:`X509Extension` provides its value.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400460 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400461 ext3 = X509Extension(
462 b('subjectKeyIdentifier'), False, b('hash'), subject=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400463 self.x509.add_extensions([ext3])
464 self.x509.sign(self.pkey, 'sha1')
465 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400466 self.assertTrue(b('X509v3 Subject Key Identifier:') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400467
468
469 def test_missing_subject(self):
470 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900471 If an extension requires a subject and the :py:data:`subject` parameter is
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400472 given no value, something happens.
473 """
474 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400475 Error, X509Extension, b('subjectKeyIdentifier'), False, b('hash'))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400476
477
478 def test_invalid_subject(self):
479 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900480 If the :py:data:`subject` parameter is given a value which is not an
481 :py:class:`X509` instance, :py:exc:`TypeError` is raised.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400482 """
483 for badObj in [True, object(), "hello", [], self]:
484 self.assertRaises(
485 TypeError,
486 X509Extension,
487 'basicConstraints', False, 'CA:TRUE', subject=badObj)
488
489
490 def test_unused_issuer(self):
491 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900492 The :py:data:`issuer` parameter to :py:class:`X509Extension` may be provided for an
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400493 extension which does not use it and is ignored in this case.
494 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400495 ext1 = X509Extension(
496 b('basicConstraints'), False, b('CA:TRUE'), issuer=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400497 self.x509.add_extensions([ext1])
498 self.x509.sign(self.pkey, 'sha1')
499 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400500 self.assertTrue(b('X509v3 Basic Constraints:') in text)
501 self.assertTrue(b('CA:TRUE') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400502
503
504 def test_issuer(self):
505 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900506 If an extension requires a issuer, the :py:data:`issuer` parameter to
507 :py:class:`X509Extension` provides its value.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400508 """
509 ext2 = X509Extension(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400510 b('authorityKeyIdentifier'), False, b('issuer:always'),
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400511 issuer=self.x509)
512 self.x509.add_extensions([ext2])
513 self.x509.sign(self.pkey, 'sha1')
514 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400515 self.assertTrue(b('X509v3 Authority Key Identifier:') in text)
516 self.assertTrue(b('DirName:/CN=Yoda root CA') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400517
518
519 def test_missing_issuer(self):
520 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900521 If an extension requires an issue and the :py:data:`issuer` parameter is given
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400522 no value, something happens.
523 """
524 self.assertRaises(
525 Error,
526 X509Extension,
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400527 b('authorityKeyIdentifier'), False,
528 b('keyid:always,issuer:always'))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400529
530
531 def test_invalid_issuer(self):
532 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900533 If the :py:data:`issuer` parameter is given a value which is not an
534 :py:class:`X509` instance, :py:exc:`TypeError` is raised.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400535 """
536 for badObj in [True, object(), "hello", [], self]:
537 self.assertRaises(
538 TypeError,
539 X509Extension,
540 'authorityKeyIdentifier', False, 'keyid:always,issuer:always',
541 issuer=badObj)
Rick Dean47262da2009-07-08 16:17:17 -0500542
543
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500544
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400545class PKeyTests(TestCase):
Jean-Paul Calderoneac930e12008-03-06 18:50:51 -0500546 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900547 Unit tests for :py:class:`OpenSSL.crypto.PKey`.
Jean-Paul Calderoneac930e12008-03-06 18:50:51 -0500548 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400549 def test_type(self):
550 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900551 :py:class:`PKey` and :py:class:`PKeyType` refer to the same type object
552 and can be used to create instances of that type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400553 """
554 self.assertIdentical(PKey, PKeyType)
555 self.assertConsistentType(PKey, 'PKey')
556
557
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500558 def test_construction(self):
559 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900560 :py:class:`PKey` takes no arguments and returns a new :py:class:`PKey` instance.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500561 """
562 self.assertRaises(TypeError, PKey, None)
563 key = PKey()
564 self.assertTrue(
565 isinstance(key, PKeyType),
566 "%r is of type %r, should be %r" % (key, type(key), PKeyType))
567
568
569 def test_pregeneration(self):
570 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900571 :py:attr:`PKeyType.bits` and :py:attr:`PKeyType.type` return :py:data:`0` before the key is
572 generated. :py:attr:`PKeyType.check` raises :py:exc:`TypeError` before the key is
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500573 generated.
574 """
575 key = PKey()
576 self.assertEqual(key.type(), 0)
577 self.assertEqual(key.bits(), 0)
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400578 self.assertRaises(TypeError, key.check)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500579
580
581 def test_failedGeneration(self):
582 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900583 :py:meth:`PKeyType.generate_key` takes two arguments, the first giving the key
584 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 -0500585 number of bits to generate. If an invalid type is specified or
Jonathan Ballet648875f2011-07-16 14:14:58 +0900586 generation fails, :py:exc:`Error` is raised. If an invalid number of bits is
587 specified, :py:exc:`ValueError` or :py:exc:`Error` is raised.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500588 """
589 key = PKey()
590 self.assertRaises(TypeError, key.generate_key)
591 self.assertRaises(TypeError, key.generate_key, 1, 2, 3)
592 self.assertRaises(TypeError, key.generate_key, "foo", "bar")
593 self.assertRaises(Error, key.generate_key, -1, 0)
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500594
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500595 self.assertRaises(ValueError, key.generate_key, TYPE_RSA, -1)
596 self.assertRaises(ValueError, key.generate_key, TYPE_RSA, 0)
Jean-Paul Calderoned71fe982008-03-06 00:31:50 -0500597
598 # XXX RSA generation for small values of bits is fairly buggy in a wide
599 # range of OpenSSL versions. I need to figure out what the safe lower
600 # bound for a reasonable number of OpenSSL versions is and explicitly
601 # check for that in the wrapper. The failure behavior is typically an
602 # infinite loop inside OpenSSL.
603
604 # self.assertRaises(Error, key.generate_key, TYPE_RSA, 2)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500605
606 # XXX DSA generation seems happy with any number of bits. The DSS
607 # says bits must be between 512 and 1024 inclusive. OpenSSL's DSA
608 # generator doesn't seem to care about the upper limit at all. For
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500609 # the lower limit, it uses 512 if anything smaller is specified.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500610 # So, it doesn't seem possible to make generate_key fail for
611 # TYPE_DSA with a bits argument which is at least an int.
612
613 # self.assertRaises(Error, key.generate_key, TYPE_DSA, -7)
614
615
616 def test_rsaGeneration(self):
617 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900618 :py:meth:`PKeyType.generate_key` generates an RSA key when passed
619 :py:data:`TYPE_RSA` as a type and a reasonable number of bits.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500620 """
621 bits = 128
622 key = PKey()
623 key.generate_key(TYPE_RSA, bits)
624 self.assertEqual(key.type(), TYPE_RSA)
625 self.assertEqual(key.bits(), bits)
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -0400626 self.assertTrue(key.check())
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500627
628
629 def test_dsaGeneration(self):
630 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900631 :py:meth:`PKeyType.generate_key` generates a DSA key when passed
632 :py:data:`TYPE_DSA` as a type and a reasonable number of bits.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500633 """
634 # 512 is a magic number. The DSS (Digital Signature Standard)
635 # allows a minimum of 512 bits for DSA. DSA_generate_parameters
636 # will silently promote any value below 512 to 512.
637 bits = 512
638 key = PKey()
639 key.generate_key(TYPE_DSA, bits)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800640 # self.assertEqual(key.type(), TYPE_DSA)
641 # self.assertEqual(key.bits(), bits)
642 # self.assertRaises(TypeError, key.check)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500643
644
645 def test_regeneration(self):
646 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900647 :py:meth:`PKeyType.generate_key` can be called multiple times on the same
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500648 key to generate new keys.
649 """
650 key = PKey()
651 for type, bits in [(TYPE_RSA, 512), (TYPE_DSA, 576)]:
652 key.generate_key(type, bits)
653 self.assertEqual(key.type(), type)
654 self.assertEqual(key.bits(), bits)
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500655
656
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400657 def test_inconsistentKey(self):
658 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900659 :py:`PKeyType.check` returns :py:exc:`Error` if the key is not consistent.
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400660 """
661 key = load_privatekey(FILETYPE_PEM, inconsistentPrivateKeyPEM)
Jean-Paul Calderoned338e4e2009-05-13 15:45:07 -0400662 self.assertRaises(Error, key.check)
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400663
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500664
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400665 def test_check_wrong_args(self):
666 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900667 :py:meth:`PKeyType.check` raises :py:exc:`TypeError` if called with any arguments.
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400668 """
669 self.assertRaises(TypeError, PKey().check, None)
670 self.assertRaises(TypeError, PKey().check, object())
671 self.assertRaises(TypeError, PKey().check, 1)
672
673
Jean-Paul Calderone02d01972011-10-31 10:39:29 -0400674 def test_check_public_key(self):
675 """
676 :py:meth:`PKeyType.check` raises :py:exc:`TypeError` if only the public
677 part of the key is available.
678 """
679 # A trick to get a public-only key
680 key = PKey()
681 key.generate_key(TYPE_RSA, 512)
682 cert = X509()
683 cert.set_pubkey(key)
684 pub = cert.get_pubkey()
685 self.assertRaises(TypeError, pub.check)
686
687
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400688
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400689class X509NameTests(TestCase):
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500690 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900691 Unit tests for :py:class:`OpenSSL.crypto.X509Name`.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500692 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500693 def _x509name(self, **attrs):
694 # XXX There's no other way to get a new X509Name yet.
695 name = X509().get_subject()
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400696 attrs = list(attrs.items())
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500697 # Make the order stable - order matters!
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400698 def key(attr):
699 return attr[1]
700 attrs.sort(key=key)
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500701 for k, v in attrs:
702 setattr(name, k, v)
703 return name
704
705
Rick Deane15b1472009-07-09 15:53:42 -0500706 def test_type(self):
707 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900708 The type of X509Name objects is :py:class:`X509NameType`.
Rick Deane15b1472009-07-09 15:53:42 -0500709 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400710 self.assertIdentical(X509Name, X509NameType)
711 self.assertEqual(X509NameType.__name__, 'X509Name')
712 self.assertTrue(isinstance(X509NameType, type))
713
Rick Deane15b1472009-07-09 15:53:42 -0500714 name = self._x509name()
715 self.assertTrue(
716 isinstance(name, X509NameType),
717 "%r is of type %r, should be %r" % (
718 name, type(name), X509NameType))
Rick Deane15b1472009-07-09 15:53:42 -0500719
720
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400721 def test_onlyStringAttributes(self):
722 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900723 Attempting to set a non-:py:data:`str` attribute name on an :py:class:`X509NameType`
724 instance causes :py:exc:`TypeError` to be raised.
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400725 """
726 name = self._x509name()
727 # Beyond these cases, you may also think that unicode should be
728 # rejected. Sorry, you're wrong. unicode is automatically converted to
729 # str outside of the control of X509Name, so there's no way to reject
730 # it.
Jean-Paul Calderoneff363be2013-03-03 10:21:23 -0800731
732 # Also, this used to test str subclasses, but that test is less relevant
733 # now that the implementation is in Python instead of C. Also PyPy
734 # automatically converts str subclasses to str when they are passed to
735 # setattr, so we can't test it on PyPy. Apparently CPython does this
736 # sometimes as well.
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400737 self.assertRaises(TypeError, setattr, name, None, "hello")
738 self.assertRaises(TypeError, setattr, name, 30, "hello")
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400739
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -0500740
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400741 def test_setInvalidAttribute(self):
742 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900743 Attempting to set any attribute name on an :py:class:`X509NameType` instance for
744 which no corresponding NID is defined causes :py:exc:`AttributeError` to be
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400745 raised.
746 """
747 name = self._x509name()
748 self.assertRaises(AttributeError, setattr, name, "no such thing", None)
749
750
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500751 def test_attributes(self):
752 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900753 :py:class:`X509NameType` instances have attributes for each standard (?)
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500754 X509Name field.
755 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500756 name = self._x509name()
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500757 name.commonName = "foo"
758 self.assertEqual(name.commonName, "foo")
759 self.assertEqual(name.CN, "foo")
760 name.CN = "baz"
761 self.assertEqual(name.commonName, "baz")
762 self.assertEqual(name.CN, "baz")
763 name.commonName = "bar"
764 self.assertEqual(name.commonName, "bar")
765 self.assertEqual(name.CN, "bar")
766 name.CN = "quux"
767 self.assertEqual(name.commonName, "quux")
768 self.assertEqual(name.CN, "quux")
769
770
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500771 def test_copy(self):
772 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900773 :py:class:`X509Name` creates a new :py:class:`X509NameType` instance with all the same
774 attributes as an existing :py:class:`X509NameType` instance when called with
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500775 one.
776 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500777 name = self._x509name(commonName="foo", emailAddress="bar@example.com")
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500778
779 copy = X509Name(name)
780 self.assertEqual(copy.commonName, "foo")
781 self.assertEqual(copy.emailAddress, "bar@example.com")
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500782
783 # Mutate the copy and ensure the original is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500784 copy.commonName = "baz"
785 self.assertEqual(name.commonName, "foo")
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500786
787 # Mutate the original and ensure the copy is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500788 name.emailAddress = "quux@example.com"
789 self.assertEqual(copy.emailAddress, "bar@example.com")
790
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500791
792 def test_repr(self):
793 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900794 :py:func:`repr` passed an :py:class:`X509NameType` instance should return a string
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500795 containing a description of the type and the NIDs which have been set
796 on it.
797 """
798 name = self._x509name(commonName="foo", emailAddress="bar")
799 self.assertEqual(
800 repr(name),
801 "<X509Name object '/emailAddress=bar/CN=foo'>")
802
803
804 def test_comparison(self):
805 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900806 :py:class:`X509NameType` instances should compare based on their NIDs.
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500807 """
808 def _equality(a, b, assertTrue, assertFalse):
809 assertTrue(a == b, "(%r == %r) --> False" % (a, b))
810 assertFalse(a != b)
811 assertTrue(b == a)
812 assertFalse(b != a)
813
814 def assertEqual(a, b):
815 _equality(a, b, self.assertTrue, self.assertFalse)
816
817 # Instances compare equal to themselves.
818 name = self._x509name()
819 assertEqual(name, name)
820
821 # Empty instances should compare equal to each other.
822 assertEqual(self._x509name(), self._x509name())
823
824 # Instances with equal NIDs should compare equal to each other.
825 assertEqual(self._x509name(commonName="foo"),
826 self._x509name(commonName="foo"))
827
828 # Instance with equal NIDs set using different aliases should compare
829 # equal to each other.
830 assertEqual(self._x509name(commonName="foo"),
831 self._x509name(CN="foo"))
832
833 # Instances with more than one NID with the same values should compare
834 # equal to each other.
835 assertEqual(self._x509name(CN="foo", organizationalUnitName="bar"),
836 self._x509name(commonName="foo", OU="bar"))
837
838 def assertNotEqual(a, b):
839 _equality(a, b, self.assertFalse, self.assertTrue)
840
841 # Instances with different values for the same NID should not compare
842 # equal to each other.
843 assertNotEqual(self._x509name(CN="foo"),
844 self._x509name(CN="bar"))
845
846 # Instances with different NIDs should not compare equal to each other.
847 assertNotEqual(self._x509name(CN="foo"),
848 self._x509name(OU="foo"))
849
850 def _inequality(a, b, assertTrue, assertFalse):
851 assertTrue(a < b)
852 assertTrue(a <= b)
853 assertTrue(b > a)
854 assertTrue(b >= a)
855 assertFalse(a > b)
856 assertFalse(a >= b)
857 assertFalse(b < a)
858 assertFalse(b <= a)
859
860 def assertLessThan(a, b):
861 _inequality(a, b, self.assertTrue, self.assertFalse)
862
863 # An X509Name with a NID with a value which sorts less than the value
864 # of the same NID on another X509Name compares less than the other
865 # X509Name.
866 assertLessThan(self._x509name(CN="abc"),
867 self._x509name(CN="def"))
868
869 def assertGreaterThan(a, b):
870 _inequality(a, b, self.assertFalse, self.assertTrue)
871
872 # An X509Name with a NID with a value which sorts greater than the
873 # value of the same NID on another X509Name compares greater than the
874 # other X509Name.
875 assertGreaterThan(self._x509name(CN="def"),
876 self._x509name(CN="abc"))
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -0500877
878
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400879 def test_hash(self):
880 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900881 :py:meth:`X509Name.hash` returns an integer hash based on the value of the
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400882 name.
883 """
884 a = self._x509name(CN="foo")
885 b = self._x509name(CN="foo")
886 self.assertEqual(a.hash(), b.hash())
887 a.CN = "bar"
888 self.assertNotEqual(a.hash(), b.hash())
889
890
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400891 def test_der(self):
892 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900893 :py:meth:`X509Name.der` returns the DER encoded form of the name.
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400894 """
895 a = self._x509name(CN="foo", C="US")
896 self.assertEqual(
897 a.der(),
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -0400898 b('0\x1b1\x0b0\t\x06\x03U\x04\x06\x13\x02US'
899 '1\x0c0\n\x06\x03U\x04\x03\x13\x03foo'))
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400900
901
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400902 def test_get_components(self):
903 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900904 :py:meth:`X509Name.get_components` returns a :py:data:`list` of
905 two-tuples of :py:data:`str`
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400906 giving the NIDs and associated values which make up the name.
907 """
908 a = self._x509name()
909 self.assertEqual(a.get_components(), [])
910 a.CN = "foo"
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -0400911 self.assertEqual(a.get_components(), [(b("CN"), b("foo"))])
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400912 a.organizationalUnitName = "bar"
913 self.assertEqual(
914 a.get_components(),
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -0400915 [(b("CN"), b("foo")), (b("OU"), b("bar"))])
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400916
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400917
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400918 def test_load_nul_byte_attribute(self):
919 """
Jean-Paul Calderone9af07b02013-08-23 16:07:31 -0400920 An :py:class:`OpenSSL.crypto.X509Name` from an
921 :py:class:`OpenSSL.crypto.X509` instance loaded from a file can have a
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400922 NUL byte in the value of one of its attributes.
923 """
924 cert = load_certificate(FILETYPE_PEM, nulbyteSubjectAltNamePEM)
925 subject = cert.get_subject()
926 self.assertEqual(
Jean-Paul Calderone06754fc2013-08-23 15:47:47 -0400927 "null.python.org\x00example.org", subject.commonName)
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400928
929
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -0500930 def test_setAttributeFailure(self):
931 """
932 If the value of an attribute cannot be set for some reason then
933 :py:class:`OpenSSL.crypto.Error` is raised.
934 """
935 name = self._x509name()
936 # This value is too long
937 self.assertRaises(Error, setattr, name, "O", b"x" * 512)
938
939
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400940
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400941class _PKeyInteractionTestsMixin:
942 """
943 Tests which involve another thing and a PKey.
944 """
945 def signable(self):
946 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900947 Return something with a :py:meth:`set_pubkey`, :py:meth:`set_pubkey`,
948 and :py:meth:`sign` method.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400949 """
950 raise NotImplementedError()
951
952
953 def test_signWithUngenerated(self):
954 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900955 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when pass a
956 :py:class:`PKey` with no parts.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400957 """
958 request = self.signable()
959 key = PKey()
960 self.assertRaises(ValueError, request.sign, key, 'MD5')
961
962
963 def test_signWithPublicKey(self):
964 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900965 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when pass a
966 :py:class:`PKey` with no private part as the signing key.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400967 """
968 request = self.signable()
969 key = PKey()
970 key.generate_key(TYPE_RSA, 512)
971 request.set_pubkey(key)
972 pub = request.get_pubkey()
973 self.assertRaises(ValueError, request.sign, pub, 'MD5')
974
975
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -0400976 def test_signWithUnknownDigest(self):
977 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900978 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when passed a digest name which is
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -0400979 not known.
980 """
981 request = self.signable()
982 key = PKey()
983 key.generate_key(TYPE_RSA, 512)
984 self.assertRaises(ValueError, request.sign, key, "monkeys")
985
986
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -0400987 def test_sign(self):
988 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900989 :py:meth:`X509Req.sign` succeeds when passed a private key object and a valid
990 digest function. :py:meth:`X509Req.verify` can be used to check the signature.
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -0400991 """
992 request = self.signable()
993 key = PKey()
994 key.generate_key(TYPE_RSA, 512)
995 request.set_pubkey(key)
996 request.sign(key, 'MD5')
997 # If the type has a verify method, cover that too.
998 if getattr(request, 'verify', None) is not None:
999 pub = request.get_pubkey()
1000 self.assertTrue(request.verify(pub))
1001 # Make another key that won't verify.
1002 key = PKey()
1003 key.generate_key(TYPE_RSA, 512)
1004 self.assertRaises(Error, request.verify, key)
1005
1006
1007
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001008
Jean-Paul Calderone18808652009-07-05 12:54:05 -04001009class X509ReqTests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001010 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001011 Tests for :py:class:`OpenSSL.crypto.X509Req`.
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001012 """
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001013 def signable(self):
1014 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001015 Create and return a new :py:class:`X509Req`.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001016 """
1017 return X509Req()
1018
1019
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001020 def test_type(self):
1021 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001022 :py:obj:`X509Req` and :py:obj:`X509ReqType` refer to the same type object and can be
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001023 used to create instances of that type.
1024 """
1025 self.assertIdentical(X509Req, X509ReqType)
1026 self.assertConsistentType(X509Req, 'X509Req')
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001027
1028
1029 def test_construction(self):
1030 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001031 :py:obj:`X509Req` takes no arguments and returns an :py:obj:`X509ReqType` instance.
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001032 """
1033 request = X509Req()
1034 self.assertTrue(
1035 isinstance(request, X509ReqType),
1036 "%r is of type %r, should be %r" % (request, type(request), X509ReqType))
1037
1038
Jean-Paul Calderone8dd19b82008-12-28 20:41:16 -05001039 def test_version(self):
1040 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001041 :py:obj:`X509ReqType.set_version` sets the X.509 version of the certificate
1042 request. :py:obj:`X509ReqType.get_version` returns the X.509 version of
Jean-Paul Calderone8dd19b82008-12-28 20:41:16 -05001043 the certificate request. The initial value of the version is 0.
1044 """
1045 request = X509Req()
1046 self.assertEqual(request.get_version(), 0)
1047 request.set_version(1)
1048 self.assertEqual(request.get_version(), 1)
1049 request.set_version(3)
1050 self.assertEqual(request.get_version(), 3)
1051
1052
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001053 def test_version_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001054 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001055 :py:obj:`X509ReqType.set_version` raises :py:obj:`TypeError` if called with the wrong
1056 number of arguments or with a non-:py:obj:`int` argument.
1057 :py:obj:`X509ReqType.get_version` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001058 arguments.
1059 """
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001060 request = X509Req()
1061 self.assertRaises(TypeError, request.set_version)
1062 self.assertRaises(TypeError, request.set_version, "foo")
1063 self.assertRaises(TypeError, request.set_version, 1, 2)
1064 self.assertRaises(TypeError, request.get_version, None)
1065
1066
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001067 def test_get_subject(self):
1068 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001069 :py:obj:`X509ReqType.get_subject` returns an :py:obj:`X509Name` for the subject of
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001070 the request and which is valid even after the request object is
1071 otherwise dead.
1072 """
1073 request = X509Req()
1074 subject = request.get_subject()
1075 self.assertTrue(
1076 isinstance(subject, X509NameType),
1077 "%r is of type %r, should be %r" % (subject, type(subject), X509NameType))
1078 subject.commonName = "foo"
1079 self.assertEqual(request.get_subject().commonName, "foo")
1080 del request
1081 subject.commonName = "bar"
1082 self.assertEqual(subject.commonName, "bar")
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001083
1084
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001085 def test_get_subject_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001086 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001087 :py:obj:`X509ReqType.get_subject` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001088 arguments.
1089 """
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001090 request = X509Req()
1091 self.assertRaises(TypeError, request.get_subject, None)
1092
1093
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001094 def test_add_extensions(self):
1095 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001096 :py:obj:`X509Req.add_extensions` accepts a :py:obj:`list` of :py:obj:`X509Extension`
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001097 instances and adds them to the X509 request.
1098 """
1099 request = X509Req()
1100 request.add_extensions([
Jean-Paul Calderonee16f9f32010-08-22 19:20:37 -04001101 X509Extension(b('basicConstraints'), True, b('CA:false'))])
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001102 # XXX Add get_extensions so the rest of this unit test can be written.
1103
1104
1105 def test_add_extensions_wrong_args(self):
1106 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001107 :py:obj:`X509Req.add_extensions` raises :py:obj:`TypeError` if called with the wrong
1108 number of arguments or with a non-:py:obj:`list`. Or it raises :py:obj:`ValueError`
1109 if called with a :py:obj:`list` containing objects other than :py:obj:`X509Extension`
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001110 instances.
1111 """
1112 request = X509Req()
1113 self.assertRaises(TypeError, request.add_extensions)
1114 self.assertRaises(TypeError, request.add_extensions, object())
1115 self.assertRaises(ValueError, request.add_extensions, [object()])
1116 self.assertRaises(TypeError, request.add_extensions, [], None)
1117
1118
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001119 def test_verify_wrong_args(self):
1120 """
1121 :py:obj:`X509Req.verify` raises :py:obj:`TypeError` if called with zero
1122 arguments or more than one argument or if passed anything other than a
1123 :py:obj:`PKey` instance as its single argument.
1124 """
1125 request = X509Req()
1126 self.assertRaises(TypeError, request.verify)
1127 self.assertRaises(TypeError, request.verify, object())
1128 self.assertRaises(TypeError, request.verify, PKey(), object())
1129
1130
1131 def test_verify_uninitialized_key(self):
1132 """
1133 :py:obj:`X509Req.verify` raises :py:obj:`OpenSSL.crypto.Error` if called
1134 with a :py:obj:`OpenSSL.crypto.PKey` which contains no key data.
1135 """
1136 request = X509Req()
1137 pkey = PKey()
1138 self.assertRaises(Error, request.verify, pkey)
1139
1140
1141 def test_verify_wrong_key(self):
1142 """
1143 :py:obj:`X509Req.verify` raises :py:obj:`OpenSSL.crypto.Error` if called
1144 with a :py:obj:`OpenSSL.crypto.PKey` which does not represent the public
1145 part of the key which signed the request.
1146 """
1147 request = X509Req()
1148 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
1149 request.sign(pkey, b"SHA1")
1150 another_pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
1151 self.assertRaises(Error, request.verify, another_pkey)
1152
1153
1154 def test_verify_success(self):
1155 """
1156 :py:obj:`X509Req.verify` returns :py:obj:`True` if called with a
1157 :py:obj:`OpenSSL.crypto.PKey` which represents the public part ofthe key
1158 which signed the request.
1159 """
1160 request = X509Req()
1161 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
1162 request.sign(pkey, b"SHA1")
1163 self.assertEqual(True, request.verify(pkey))
1164
1165
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001166
Jean-Paul Calderone18808652009-07-05 12:54:05 -04001167class X509Tests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001168 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001169 Tests for :py:obj:`OpenSSL.crypto.X509`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001170 """
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001171 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
Jean-Paul Calderone8114b452008-03-25 15:27:59 -04001172
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001173 extpem = """
1174-----BEGIN CERTIFICATE-----
1175MIIC3jCCAkegAwIBAgIJAJHFjlcCgnQzMA0GCSqGSIb3DQEBBQUAMEcxCzAJBgNV
1176BAYTAlNFMRUwEwYDVQQIEwxXZXN0ZXJib3R0b20xEjAQBgNVBAoTCUNhdGFsb2dp
1177eDENMAsGA1UEAxMEUm9vdDAeFw0wODA0MjIxNDQ1MzhaFw0wOTA0MjIxNDQ1Mzha
1178MFQxCzAJBgNVBAYTAlNFMQswCQYDVQQIEwJXQjEUMBIGA1UEChMLT3Blbk1ldGFk
1179aXIxIjAgBgNVBAMTGW5vZGUxLm9tMi5vcGVubWV0YWRpci5vcmcwgZ8wDQYJKoZI
1180hvcNAQEBBQADgY0AMIGJAoGBAPIcQMrwbk2nESF/0JKibj9i1x95XYAOwP+LarwT
1181Op4EQbdlI9SY+uqYqlERhF19w7CS+S6oyqx0DRZSk4Y9dZ9j9/xgm2u/f136YS1u
1182zgYFPvfUs6PqYLPSM8Bw+SjJ+7+2+TN+Tkiof9WP1cMjodQwOmdsiRbR0/J7+b1B
1183hec1AgMBAAGjgcQwgcEwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNT
1184TCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFIdHsBcMVVMbAO7j6NCj
118503HgLnHaMB8GA1UdIwQYMBaAFL2h9Bf9Mre4vTdOiHTGAt7BRY/8MEYGA1UdEQQ/
1186MD2CDSouZXhhbXBsZS5vcmeCESoub20yLmV4bWFwbGUuY29thwSC7wgKgRNvbTJA
1187b3Blbm1ldGFkaXIub3JnMA0GCSqGSIb3DQEBBQUAA4GBALd7WdXkp2KvZ7/PuWZA
1188MPlIxyjS+Ly11+BNE0xGQRp9Wz+2lABtpgNqssvU156+HkKd02rGheb2tj7MX9hG
1189uZzbwDAZzJPjzDQDD7d3cWsrVcfIdqVU7epHqIadnOF+X0ghJ39pAm6VVadnSXCt
1190WpOdIpB8KksUTCzV591Nr1wd
1191-----END CERTIFICATE-----
1192 """
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001193 def signable(self):
1194 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001195 Create and return a new :py:obj:`X509`.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001196 """
1197 return X509()
1198
1199
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001200 def test_type(self):
1201 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001202 :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 -04001203 to create instances of that type.
1204 """
1205 self.assertIdentical(X509, X509Type)
1206 self.assertConsistentType(X509, 'X509')
1207
1208
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001209 def test_construction(self):
1210 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001211 :py:obj:`X509` takes no arguments and returns an instance of :py:obj:`X509Type`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001212 """
1213 certificate = X509()
1214 self.assertTrue(
1215 isinstance(certificate, X509Type),
1216 "%r is of type %r, should be %r" % (certificate,
1217 type(certificate),
1218 X509Type))
Rick Deane15b1472009-07-09 15:53:42 -05001219 self.assertEqual(type(X509Type).__name__, 'type')
1220 self.assertEqual(type(certificate).__name__, 'X509')
1221 self.assertEqual(type(certificate), X509Type)
Rick Dean04113e72009-07-16 12:06:35 -05001222 self.assertEqual(type(certificate), X509)
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001223
1224
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001225 def test_get_version_wrong_args(self):
1226 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001227 :py:obj:`X509.get_version` raises :py:obj:`TypeError` if invoked with any arguments.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001228 """
1229 cert = X509()
1230 self.assertRaises(TypeError, cert.get_version, None)
1231
1232
1233 def test_set_version_wrong_args(self):
1234 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001235 :py:obj:`X509.set_version` raises :py:obj:`TypeError` if invoked with the wrong number
1236 of arguments or an argument not of type :py:obj:`int`.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001237 """
1238 cert = X509()
1239 self.assertRaises(TypeError, cert.set_version)
1240 self.assertRaises(TypeError, cert.set_version, None)
1241 self.assertRaises(TypeError, cert.set_version, 1, None)
1242
1243
1244 def test_version(self):
1245 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001246 :py:obj:`X509.set_version` sets the certificate version number.
1247 :py:obj:`X509.get_version` retrieves it.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001248 """
1249 cert = X509()
1250 cert.set_version(1234)
1251 self.assertEquals(cert.get_version(), 1234)
1252
1253
1254 def test_get_serial_number_wrong_args(self):
1255 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001256 :py:obj:`X509.get_serial_number` raises :py:obj:`TypeError` if invoked with any
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001257 arguments.
1258 """
1259 cert = X509()
1260 self.assertRaises(TypeError, cert.get_serial_number, None)
1261
1262
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001263 def test_serial_number(self):
1264 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001265 The serial number of an :py:obj:`X509Type` can be retrieved and modified with
1266 :py:obj:`X509Type.get_serial_number` and :py:obj:`X509Type.set_serial_number`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001267 """
1268 certificate = X509()
1269 self.assertRaises(TypeError, certificate.set_serial_number)
1270 self.assertRaises(TypeError, certificate.set_serial_number, 1, 2)
1271 self.assertRaises(TypeError, certificate.set_serial_number, "1")
1272 self.assertRaises(TypeError, certificate.set_serial_number, 5.5)
1273 self.assertEqual(certificate.get_serial_number(), 0)
1274 certificate.set_serial_number(1)
1275 self.assertEqual(certificate.get_serial_number(), 1)
1276 certificate.set_serial_number(2 ** 32 + 1)
1277 self.assertEqual(certificate.get_serial_number(), 2 ** 32 + 1)
1278 certificate.set_serial_number(2 ** 64 + 1)
1279 self.assertEqual(certificate.get_serial_number(), 2 ** 64 + 1)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001280 certificate.set_serial_number(2 ** 128 + 1)
1281 self.assertEqual(certificate.get_serial_number(), 2 ** 128 + 1)
1282
1283
1284 def _setBoundTest(self, which):
1285 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001286 :py:obj:`X509Type.set_notBefore` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001287 GENERALIZEDTIME and sets the beginning of the certificate's validity
1288 period to it.
1289 """
1290 certificate = X509()
1291 set = getattr(certificate, 'set_not' + which)
1292 get = getattr(certificate, 'get_not' + which)
1293
Jean-Paul Calderonee0615b52008-03-09 21:44:46 -04001294 # Starts with no value.
1295 self.assertEqual(get(), None)
1296
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001297 # GMT (Or is it UTC?) -exarkun
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001298 when = b("20040203040506Z")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001299 set(when)
1300 self.assertEqual(get(), when)
1301
1302 # A plus two hours and thirty minutes offset
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001303 when = b("20040203040506+0530")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001304 set(when)
1305 self.assertEqual(get(), when)
1306
1307 # A minus one hour fifteen minutes offset
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001308 when = b("20040203040506-0115")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001309 set(when)
1310 self.assertEqual(get(), when)
1311
1312 # An invalid string results in a ValueError
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001313 self.assertRaises(ValueError, set, b("foo bar"))
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001314
Jean-Paul Calderone31ca2002010-01-30 15:14:43 -05001315 # The wrong number of arguments results in a TypeError.
1316 self.assertRaises(TypeError, set)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001317 self.assertRaises(TypeError, set, b("20040203040506Z"), b("20040203040506Z"))
1318 self.assertRaises(TypeError, get, b("foo bar"))
1319
Jean-Paul Calderone31ca2002010-01-30 15:14:43 -05001320
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001321 # XXX ASN1_TIME (not GENERALIZEDTIME)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001322
1323 def test_set_notBefore(self):
1324 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001325 :py:obj:`X509Type.set_notBefore` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001326 GENERALIZEDTIME and sets the beginning of the certificate's validity
1327 period to it.
1328 """
1329 self._setBoundTest("Before")
1330
1331
1332 def test_set_notAfter(self):
1333 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001334 :py:obj:`X509Type.set_notAfter` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001335 GENERALIZEDTIME and sets the end of the certificate's validity period
1336 to it.
1337 """
1338 self._setBoundTest("After")
Jean-Paul Calderone76576d52008-03-24 16:04:46 -04001339
1340
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001341 def test_get_notBefore(self):
1342 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001343 :py:obj:`X509Type.get_notBefore` returns a string in the format of an ASN1
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001344 GENERALIZEDTIME even for certificates which store it as UTCTIME
1345 internally.
1346 """
Jean-Paul Calderone8114b452008-03-25 15:27:59 -04001347 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001348 self.assertEqual(cert.get_notBefore(), b("20090325123658Z"))
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001349
Rick Dean38a05c82009-07-18 01:41:30 -05001350
1351 def test_get_notAfter(self):
1352 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001353 :py:obj:`X509Type.get_notAfter` returns a string in the format of an ASN1
Rick Dean38a05c82009-07-18 01:41:30 -05001354 GENERALIZEDTIME even for certificates which store it as UTCTIME
1355 internally.
1356 """
1357 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001358 self.assertEqual(cert.get_notAfter(), b("20170611123658Z"))
Rick Dean38a05c82009-07-18 01:41:30 -05001359
1360
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001361 def test_gmtime_adj_notBefore_wrong_args(self):
1362 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001363 :py:obj:`X509Type.gmtime_adj_notBefore` raises :py:obj:`TypeError` if called with the
1364 wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001365 """
1366 cert = X509()
1367 self.assertRaises(TypeError, cert.gmtime_adj_notBefore)
1368 self.assertRaises(TypeError, cert.gmtime_adj_notBefore, None)
1369 self.assertRaises(TypeError, cert.gmtime_adj_notBefore, 123, None)
1370
1371
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001372 def test_gmtime_adj_notBefore(self):
1373 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001374 :py:obj:`X509Type.gmtime_adj_notBefore` changes the not-before timestamp to be
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001375 the current time plus the number of seconds passed in.
1376 """
1377 cert = load_certificate(FILETYPE_PEM, self.pemData)
1378 now = datetime.utcnow() + timedelta(seconds=100)
1379 cert.gmtime_adj_notBefore(100)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001380 self.assertEqual(cert.get_notBefore(), b(now.strftime("%Y%m%d%H%M%SZ")))
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001381
1382
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001383 def test_gmtime_adj_notAfter_wrong_args(self):
1384 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001385 :py:obj:`X509Type.gmtime_adj_notAfter` raises :py:obj:`TypeError` if called with the
1386 wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001387 """
1388 cert = X509()
1389 self.assertRaises(TypeError, cert.gmtime_adj_notAfter)
1390 self.assertRaises(TypeError, cert.gmtime_adj_notAfter, None)
1391 self.assertRaises(TypeError, cert.gmtime_adj_notAfter, 123, None)
1392
1393
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001394 def test_gmtime_adj_notAfter(self):
1395 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001396 :py:obj:`X509Type.gmtime_adj_notAfter` changes the not-after timestamp to be
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001397 the current time plus the number of seconds passed in.
1398 """
1399 cert = load_certificate(FILETYPE_PEM, self.pemData)
1400 now = datetime.utcnow() + timedelta(seconds=100)
1401 cert.gmtime_adj_notAfter(100)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001402 self.assertEqual(cert.get_notAfter(), b(now.strftime("%Y%m%d%H%M%SZ")))
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001403
1404
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001405 def test_has_expired_wrong_args(self):
1406 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001407 :py:obj:`X509Type.has_expired` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001408 arguments.
1409 """
1410 cert = X509()
1411 self.assertRaises(TypeError, cert.has_expired, None)
1412
1413
1414 def test_has_expired(self):
1415 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001416 :py:obj:`X509Type.has_expired` returns :py:obj:`True` if the certificate's not-after
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001417 time is in the past.
1418 """
1419 cert = X509()
1420 cert.gmtime_adj_notAfter(-1)
1421 self.assertTrue(cert.has_expired())
1422
1423
1424 def test_has_not_expired(self):
1425 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001426 :py:obj:`X509Type.has_expired` returns :py:obj:`False` if the certificate's not-after
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001427 time is in the future.
1428 """
1429 cert = X509()
1430 cert.gmtime_adj_notAfter(2)
1431 self.assertFalse(cert.has_expired())
1432
1433
Rick Dean38a05c82009-07-18 01:41:30 -05001434 def test_digest(self):
1435 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001436 :py:obj:`X509.digest` returns a string giving ":"-separated hex-encoded words
Rick Dean38a05c82009-07-18 01:41:30 -05001437 of the digest of the certificate.
1438 """
1439 cert = X509()
1440 self.assertEqual(
1441 cert.digest("md5"),
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001442 b("A8:EB:07:F8:53:25:0A:F2:56:05:C5:A5:C4:C4:C7:15"))
Rick Dean38a05c82009-07-18 01:41:30 -05001443
1444
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001445 def _extcert(self, pkey, extensions):
1446 cert = X509()
1447 cert.set_pubkey(pkey)
1448 cert.get_subject().commonName = "Unit Tests"
1449 cert.get_issuer().commonName = "Unit Tests"
1450 when = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
1451 cert.set_notBefore(when)
1452 cert.set_notAfter(when)
1453
1454 cert.add_extensions(extensions)
1455 return load_certificate(
1456 FILETYPE_PEM, dump_certificate(FILETYPE_PEM, cert))
1457
1458
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001459 def test_extension_count(self):
1460 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001461 :py:obj:`X509.get_extension_count` returns the number of extensions that are
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001462 present in the certificate.
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001463 """
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001464 pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001465 ca = X509Extension(b('basicConstraints'), True, b('CA:FALSE'))
1466 key = X509Extension(b('keyUsage'), True, b('digitalSignature'))
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001467 subjectAltName = X509Extension(
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001468 b('subjectAltName'), True, b('DNS:example.com'))
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001469
1470 # Try a certificate with no extensions at all.
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001471 c = self._extcert(pkey, [])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001472 self.assertEqual(c.get_extension_count(), 0)
1473
1474 # And a certificate with one
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001475 c = self._extcert(pkey, [ca])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001476 self.assertEqual(c.get_extension_count(), 1)
1477
1478 # And a certificate with several
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001479 c = self._extcert(pkey, [ca, key, subjectAltName])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001480 self.assertEqual(c.get_extension_count(), 3)
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001481
1482
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001483 def test_get_extension(self):
1484 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001485 :py:obj:`X509.get_extension` takes an integer and returns an :py:obj:`X509Extension`
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001486 corresponding to the extension at that index.
1487 """
1488 pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001489 ca = X509Extension(b('basicConstraints'), True, b('CA:FALSE'))
1490 key = X509Extension(b('keyUsage'), True, b('digitalSignature'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001491 subjectAltName = X509Extension(
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001492 b('subjectAltName'), False, b('DNS:example.com'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001493
1494 cert = self._extcert(pkey, [ca, key, subjectAltName])
1495
1496 ext = cert.get_extension(0)
1497 self.assertTrue(isinstance(ext, X509Extension))
1498 self.assertTrue(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001499 self.assertEqual(ext.get_short_name(), b('basicConstraints'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001500
1501 ext = cert.get_extension(1)
1502 self.assertTrue(isinstance(ext, X509Extension))
1503 self.assertTrue(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001504 self.assertEqual(ext.get_short_name(), b('keyUsage'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001505
1506 ext = cert.get_extension(2)
1507 self.assertTrue(isinstance(ext, X509Extension))
1508 self.assertFalse(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001509 self.assertEqual(ext.get_short_name(), b('subjectAltName'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001510
1511 self.assertRaises(IndexError, cert.get_extension, -1)
1512 self.assertRaises(IndexError, cert.get_extension, 4)
1513 self.assertRaises(TypeError, cert.get_extension, "hello")
1514
1515
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001516 def test_nullbyte_subjectAltName(self):
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001517 """
Jean-Paul Calderone9af07b02013-08-23 16:07:31 -04001518 The fields of a `subjectAltName` extension on an X509 may contain NUL
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001519 bytes and this value is reflected in the string representation of the
1520 extension object.
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001521 """
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001522 cert = load_certificate(FILETYPE_PEM, nulbyteSubjectAltNamePEM)
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001523
1524 ext = cert.get_extension(3)
1525 self.assertEqual(ext.get_short_name(), b('subjectAltName'))
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001526 self.assertEqual(
1527 b("DNS:altnull.python.org\x00example.com, "
1528 "email:null@python.org\x00user@example.org, "
1529 "URI:http://null.python.org\x00http://example.org, "
1530 "IP Address:192.0.2.1, IP Address:2001:DB8:0:0:0:0:0:1\n"),
1531 b(str(ext)))
1532
Rick Dean38a05c82009-07-18 01:41:30 -05001533
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001534 def test_invalid_digest_algorithm(self):
1535 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001536 :py:obj:`X509.digest` raises :py:obj:`ValueError` if called with an unrecognized hash
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001537 algorithm.
1538 """
1539 cert = X509()
1540 self.assertRaises(ValueError, cert.digest, "monkeys")
1541
1542
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001543 def test_get_subject_wrong_args(self):
1544 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001545 :py:obj:`X509.get_subject` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001546 """
1547 cert = X509()
1548 self.assertRaises(TypeError, cert.get_subject, None)
1549
1550
1551 def test_get_subject(self):
1552 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001553 :py:obj:`X509.get_subject` returns an :py:obj:`X509Name` instance.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001554 """
1555 cert = load_certificate(FILETYPE_PEM, self.pemData)
1556 subj = cert.get_subject()
1557 self.assertTrue(isinstance(subj, X509Name))
1558 self.assertEquals(
1559 subj.get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001560 [(b('C'), b('US')), (b('ST'), b('IL')), (b('L'), b('Chicago')),
1561 (b('O'), b('Testing')), (b('CN'), b('Testing Root CA'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001562
1563
1564 def test_set_subject_wrong_args(self):
1565 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001566 :py:obj:`X509.set_subject` raises a :py:obj:`TypeError` if called with the wrong
1567 number of arguments or an argument not of type :py:obj:`X509Name`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001568 """
1569 cert = X509()
1570 self.assertRaises(TypeError, cert.set_subject)
1571 self.assertRaises(TypeError, cert.set_subject, None)
1572 self.assertRaises(TypeError, cert.set_subject, cert.get_subject(), None)
1573
1574
1575 def test_set_subject(self):
1576 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001577 :py:obj:`X509.set_subject` changes the subject of the certificate to the one
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001578 passed in.
1579 """
1580 cert = X509()
1581 name = cert.get_subject()
1582 name.C = 'AU'
1583 name.O = 'Unit Tests'
1584 cert.set_subject(name)
1585 self.assertEquals(
1586 cert.get_subject().get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001587 [(b('C'), b('AU')), (b('O'), b('Unit Tests'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001588
1589
1590 def test_get_issuer_wrong_args(self):
1591 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001592 :py:obj:`X509.get_issuer` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001593 """
1594 cert = X509()
1595 self.assertRaises(TypeError, cert.get_issuer, None)
1596
1597
1598 def test_get_issuer(self):
1599 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001600 :py:obj:`X509.get_issuer` returns an :py:obj:`X509Name` instance.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001601 """
1602 cert = load_certificate(FILETYPE_PEM, self.pemData)
1603 subj = cert.get_issuer()
1604 self.assertTrue(isinstance(subj, X509Name))
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001605 comp = subj.get_components()
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001606 self.assertEquals(
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001607 comp,
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001608 [(b('C'), b('US')), (b('ST'), b('IL')), (b('L'), b('Chicago')),
1609 (b('O'), b('Testing')), (b('CN'), b('Testing Root CA'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001610
1611
1612 def test_set_issuer_wrong_args(self):
1613 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001614 :py:obj:`X509.set_issuer` raises a :py:obj:`TypeError` if called with the wrong
1615 number of arguments or an argument not of type :py:obj:`X509Name`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001616 """
1617 cert = X509()
1618 self.assertRaises(TypeError, cert.set_issuer)
1619 self.assertRaises(TypeError, cert.set_issuer, None)
1620 self.assertRaises(TypeError, cert.set_issuer, cert.get_issuer(), None)
1621
1622
1623 def test_set_issuer(self):
1624 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001625 :py:obj:`X509.set_issuer` changes the issuer of the certificate to the one
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001626 passed in.
1627 """
1628 cert = X509()
1629 name = cert.get_issuer()
1630 name.C = 'AU'
1631 name.O = 'Unit Tests'
1632 cert.set_issuer(name)
1633 self.assertEquals(
1634 cert.get_issuer().get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001635 [(b('C'), b('AU')), (b('O'), b('Unit Tests'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001636
1637
1638 def test_get_pubkey_uninitialized(self):
1639 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001640 When called on a certificate with no public key, :py:obj:`X509.get_pubkey`
1641 raises :py:obj:`OpenSSL.crypto.Error`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001642 """
1643 cert = X509()
1644 self.assertRaises(Error, cert.get_pubkey)
1645
1646
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001647 def test_subject_name_hash_wrong_args(self):
1648 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001649 :py:obj:`X509.subject_name_hash` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001650 arguments.
1651 """
1652 cert = X509()
1653 self.assertRaises(TypeError, cert.subject_name_hash, None)
1654
1655
1656 def test_subject_name_hash(self):
1657 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001658 :py:obj:`X509.subject_name_hash` returns the hash of the certificate's subject
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001659 name.
1660 """
1661 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -04001662 self.assertIn(
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001663 cert.subject_name_hash(),
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -04001664 [3350047874, # OpenSSL 0.9.8, MD5
1665 3278919224, # OpenSSL 1.0.0, SHA1
1666 ])
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001667
1668
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001669 def test_get_signature_algorithm(self):
1670 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001671 :py:obj:`X509Type.get_signature_algorithm` returns a string which means
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001672 the algorithm used to sign the certificate.
1673 """
1674 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001675 self.assertEqual(
1676 b("sha1WithRSAEncryption"), cert.get_signature_algorithm())
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001677
1678
1679 def test_get_undefined_signature_algorithm(self):
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001680 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001681 :py:obj:`X509Type.get_signature_algorithm` raises :py:obj:`ValueError` if the
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001682 signature algorithm is undefined or unknown.
1683 """
1684 # This certificate has been modified to indicate a bogus OID in the
1685 # signature algorithm field so that OpenSSL does not recognize it.
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001686 certPEM = """\
1687-----BEGIN CERTIFICATE-----
1688MIIC/zCCAmigAwIBAgIBATAGBgJ8BQUAMHsxCzAJBgNVBAYTAlNHMREwDwYDVQQK
1689EwhNMkNyeXB0bzEUMBIGA1UECxMLTTJDcnlwdG8gQ0ExJDAiBgNVBAMTG00yQ3J5
1690cHRvIENlcnRpZmljYXRlIE1hc3RlcjEdMBsGCSqGSIb3DQEJARYObmdwc0Bwb3N0
1691MS5jb20wHhcNMDAwOTEwMDk1MTMwWhcNMDIwOTEwMDk1MTMwWjBTMQswCQYDVQQG
1692EwJTRzERMA8GA1UEChMITTJDcnlwdG8xEjAQBgNVBAMTCWxvY2FsaG9zdDEdMBsG
1693CSqGSIb3DQEJARYObmdwc0Bwb3N0MS5jb20wXDANBgkqhkiG9w0BAQEFAANLADBI
1694AkEArL57d26W9fNXvOhNlZzlPOACmvwOZ5AdNgLzJ1/MfsQQJ7hHVeHmTAjM664V
1695+fXvwUGJLziCeBo1ysWLRnl8CQIDAQABo4IBBDCCAQAwCQYDVR0TBAIwADAsBglg
1696hkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0O
1697BBYEFM+EgpK+eyZiwFU1aOPSbczbPSpVMIGlBgNVHSMEgZ0wgZqAFPuHI2nrnDqT
1698FeXFvylRT/7tKDgBoX+kfTB7MQswCQYDVQQGEwJTRzERMA8GA1UEChMITTJDcnlw
1699dG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtNMkNyeXB0byBDZXJ0
1700aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tggEA
1701MA0GCSqGSIb3DQEBBAUAA4GBADv8KpPo+gfJxN2ERK1Y1l17sz/ZhzoGgm5XCdbx
1702jEY7xKfpQngV599k1xhl11IMqizDwu0855agrckg2MCTmOI9DZzDD77tAYb+Dk0O
1703PEVk0Mk/V0aIsDE9bolfCi/i/QWZ3N8s5nTWMNyBBBmoSliWCm4jkkRZRD0ejgTN
1704tgI5
1705-----END CERTIFICATE-----
1706"""
1707 cert = load_certificate(FILETYPE_PEM, certPEM)
1708 self.assertRaises(ValueError, cert.get_signature_algorithm)
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001709
1710
Rick Dean38a05c82009-07-18 01:41:30 -05001711
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001712class X509StoreTests(TestCase):
1713 """
1714 Test for :py:obj:`OpenSSL.crypto.X509Store`.
1715 """
1716 def test_type(self):
1717 """
1718 :py:obj:`X509StoreType` is a type object.
1719 """
1720 self.assertIdentical(X509Store, X509StoreType)
1721 self.assertConsistentType(X509Store, 'X509Store')
1722
1723
1724 def test_add_cert_wrong_args(self):
1725 store = X509Store()
1726 self.assertRaises(TypeError, store.add_cert)
1727 self.assertRaises(TypeError, store.add_cert, object())
1728 self.assertRaises(TypeError, store.add_cert, X509(), object())
1729
1730
1731 def test_add_cert(self):
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001732 """
1733 :py:obj:`X509Store.add_cert` adds a :py:obj:`X509` instance to the
1734 certificate store.
1735 """
1736 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001737 store = X509Store()
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001738 store.add_cert(cert)
1739
1740
1741 def test_add_cert_rejects_duplicate(self):
1742 """
1743 :py:obj:`X509Store.add_cert` raises :py:obj:`OpenSSL.crypto.Error` if an
1744 attempt is made to add the same certificate to the store more than once.
1745 """
1746 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
1747 store = X509Store()
1748 store.add_cert(cert)
1749 self.assertRaises(Error, store.add_cert, cert)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001750
1751
1752
Rick Dean623ee362009-07-17 12:22:16 -05001753class PKCS12Tests(TestCase):
1754 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001755 Test for :py:obj:`OpenSSL.crypto.PKCS12` and :py:obj:`OpenSSL.crypto.load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001756 """
1757 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
1758
Jean-Paul Calderonec3a41f72009-07-25 12:36:02 -04001759 def test_type(self):
1760 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001761 :py:obj:`PKCS12Type` is a type object.
Jean-Paul Calderonec3a41f72009-07-25 12:36:02 -04001762 """
1763 self.assertIdentical(PKCS12, PKCS12Type)
1764 self.assertConsistentType(PKCS12, 'PKCS12')
1765
1766
Rick Deanf94096c2009-07-18 14:23:06 -05001767 def test_empty_construction(self):
Rick Dean38a05c82009-07-18 01:41:30 -05001768 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001769 :py:obj:`PKCS12` returns a new instance of :py:obj:`PKCS12` with no certificate,
Jean-Paul Calderonedc857b52009-07-25 12:25:07 -04001770 private key, CA certificates, or friendly name.
Rick Dean38a05c82009-07-18 01:41:30 -05001771 """
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001772 p12 = PKCS12()
Rick Dean623ee362009-07-17 12:22:16 -05001773 self.assertEqual(None, p12.get_certificate())
1774 self.assertEqual(None, p12.get_privatekey())
1775 self.assertEqual(None, p12.get_ca_certificates())
Rick Dean42d69e12009-07-20 11:36:08 -05001776 self.assertEqual(None, p12.get_friendlyname())
Rick Dean623ee362009-07-17 12:22:16 -05001777
Rick Dean38a05c82009-07-18 01:41:30 -05001778
Rick Dean623ee362009-07-17 12:22:16 -05001779 def test_type_errors(self):
Rick Dean38a05c82009-07-18 01:41:30 -05001780 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001781 The :py:obj:`PKCS12` setter functions (:py:obj:`set_certificate`, :py:obj:`set_privatekey`,
1782 :py:obj:`set_ca_certificates`, and :py:obj:`set_friendlyname`) raise :py:obj:`TypeError`
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001783 when passed objects of types other than those expected.
Rick Dean38a05c82009-07-18 01:41:30 -05001784 """
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001785 p12 = PKCS12()
Rick Dean623ee362009-07-17 12:22:16 -05001786 self.assertRaises(TypeError, p12.set_certificate, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05001787 self.assertRaises(TypeError, p12.set_certificate, PKey())
1788 self.assertRaises(TypeError, p12.set_certificate, X509)
Rick Dean623ee362009-07-17 12:22:16 -05001789 self.assertRaises(TypeError, p12.set_privatekey, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05001790 self.assertRaises(TypeError, p12.set_privatekey, 'legbone')
1791 self.assertRaises(TypeError, p12.set_privatekey, X509())
Rick Dean623ee362009-07-17 12:22:16 -05001792 self.assertRaises(TypeError, p12.set_ca_certificates, 3)
1793 self.assertRaises(TypeError, p12.set_ca_certificates, X509())
1794 self.assertRaises(TypeError, p12.set_ca_certificates, (3, 4))
Rick Deanf94096c2009-07-18 14:23:06 -05001795 self.assertRaises(TypeError, p12.set_ca_certificates, ( PKey(), ))
Rick Dean42d69e12009-07-20 11:36:08 -05001796 self.assertRaises(TypeError, p12.set_friendlyname, 6)
1797 self.assertRaises(TypeError, p12.set_friendlyname, ('foo', 'bar'))
Rick Dean623ee362009-07-17 12:22:16 -05001798
Rick Dean38a05c82009-07-18 01:41:30 -05001799
Rick Dean623ee362009-07-17 12:22:16 -05001800 def test_key_only(self):
1801 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001802 A :py:obj:`PKCS12` with only a private key can be exported using
1803 :py:obj:`PKCS12.export` and loaded again using :py:obj:`load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001804 """
1805 passwd = 'blah'
1806 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001807 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001808 p12.set_privatekey(pkey)
Rick Dean623ee362009-07-17 12:22:16 -05001809 self.assertEqual(None, p12.get_certificate())
1810 self.assertEqual(pkey, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05001811 try:
1812 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
1813 except Error:
1814 # Some versions of OpenSSL will throw an exception
1815 # for this nearly useless PKCS12 we tried to generate:
1816 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
1817 return
Rick Dean623ee362009-07-17 12:22:16 -05001818 p12 = load_pkcs12(dumped_p12, passwd)
1819 self.assertEqual(None, p12.get_ca_certificates())
1820 self.assertEqual(None, p12.get_certificate())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001821
1822 # OpenSSL fails to bring the key back to us. So sad. Perhaps in the
1823 # future this will be improved.
1824 self.assertTrue(isinstance(p12.get_privatekey(), (PKey, type(None))))
Rick Dean623ee362009-07-17 12:22:16 -05001825
Rick Dean38a05c82009-07-18 01:41:30 -05001826
Rick Dean623ee362009-07-17 12:22:16 -05001827 def test_cert_only(self):
1828 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001829 A :py:obj:`PKCS12` with only a certificate can be exported using
1830 :py:obj:`PKCS12.export` and loaded again using :py:obj:`load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001831 """
1832 passwd = 'blah'
1833 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001834 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001835 p12.set_certificate(cert)
Rick Dean623ee362009-07-17 12:22:16 -05001836 self.assertEqual(cert, p12.get_certificate())
1837 self.assertEqual(None, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05001838 try:
1839 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
1840 except Error:
1841 # Some versions of OpenSSL will throw an exception
1842 # for this nearly useless PKCS12 we tried to generate:
1843 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
1844 return
Rick Dean623ee362009-07-17 12:22:16 -05001845 p12 = load_pkcs12(dumped_p12, passwd)
1846 self.assertEqual(None, p12.get_privatekey())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001847
1848 # OpenSSL fails to bring the cert back to us. Groany mcgroan.
1849 self.assertTrue(isinstance(p12.get_certificate(), (X509, type(None))))
1850
1851 # Oh ho. It puts the certificate into the ca certificates list, in
1852 # fact. Totally bogus, I would think. Nevertheless, let's exploit
1853 # that to check to see if it reconstructed the certificate we expected
1854 # it to. At some point, hopefully this will change so that
1855 # p12.get_certificate() is actually what returns the loaded
1856 # certificate.
1857 self.assertEqual(
1858 cleartextCertificatePEM,
1859 dump_certificate(FILETYPE_PEM, p12.get_ca_certificates()[0]))
Rick Dean623ee362009-07-17 12:22:16 -05001860
1861
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001862 def gen_pkcs12(self, cert_pem=None, key_pem=None, ca_pem=None, friendly_name=None):
Rick Dean623ee362009-07-17 12:22:16 -05001863 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001864 Generate a PKCS12 object with components from PEM. Verify that the set
1865 functions return None.
Rick Dean623ee362009-07-17 12:22:16 -05001866 """
Rick Deanf94096c2009-07-18 14:23:06 -05001867 p12 = PKCS12()
1868 if cert_pem:
1869 ret = p12.set_certificate(load_certificate(FILETYPE_PEM, cert_pem))
1870 self.assertEqual(ret, None)
1871 if key_pem:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001872 ret = p12.set_privatekey(load_privatekey(FILETYPE_PEM, key_pem))
Rick Deanf94096c2009-07-18 14:23:06 -05001873 self.assertEqual(ret, None)
1874 if ca_pem:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001875 ret = p12.set_ca_certificates((load_certificate(FILETYPE_PEM, ca_pem),))
Rick Deanf94096c2009-07-18 14:23:06 -05001876 self.assertEqual(ret, None)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001877 if friendly_name:
1878 ret = p12.set_friendlyname(friendly_name)
Rick Dean42d69e12009-07-20 11:36:08 -05001879 self.assertEqual(ret, None)
Rick Deanf94096c2009-07-18 14:23:06 -05001880 return p12
1881
1882
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001883 def check_recovery(self, p12_str, key=None, cert=None, ca=None, passwd='',
1884 extra=()):
Rick Deanf94096c2009-07-18 14:23:06 -05001885 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001886 Use openssl program to confirm three components are recoverable from a
1887 PKCS12 string.
Rick Deanf94096c2009-07-18 14:23:06 -05001888 """
1889 if key:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001890 recovered_key = _runopenssl(
1891 p12_str, "pkcs12", '-nocerts', '-nodes', '-passin',
1892 'pass:' + passwd, *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001893 self.assertEqual(recovered_key[-len(key):], key)
1894 if cert:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001895 recovered_cert = _runopenssl(
1896 p12_str, "pkcs12", '-clcerts', '-nodes', '-passin',
1897 'pass:' + passwd, '-nokeys', *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001898 self.assertEqual(recovered_cert[-len(cert):], cert)
1899 if ca:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001900 recovered_cert = _runopenssl(
1901 p12_str, "pkcs12", '-cacerts', '-nodes', '-passin',
1902 'pass:' + passwd, '-nokeys', *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001903 self.assertEqual(recovered_cert[-len(ca):], ca)
1904
1905
1906 def test_load_pkcs12(self):
1907 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001908 A PKCS12 string generated using the openssl command line can be loaded
Jonathan Ballet648875f2011-07-16 14:14:58 +09001909 with :py:obj:`load_pkcs12` and its components extracted and examined.
Rick Deanf94096c2009-07-18 14:23:06 -05001910 """
Rick Dean623ee362009-07-17 12:22:16 -05001911 passwd = 'whatever'
1912 pem = client_key_pem + client_cert_pem
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001913 p12_str = _runopenssl(
1914 pem, "pkcs12", '-export', '-clcerts', '-passout', 'pass:' + passwd)
Rick Dean623ee362009-07-17 12:22:16 -05001915 p12 = load_pkcs12(p12_str, passwd)
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001916 # verify
Rick Deanf94096c2009-07-18 14:23:06 -05001917 self.assertTrue(isinstance(p12, PKCS12))
Rick Dean623ee362009-07-17 12:22:16 -05001918 cert_pem = dump_certificate(FILETYPE_PEM, p12.get_certificate())
1919 self.assertEqual(cert_pem, client_cert_pem)
1920 key_pem = dump_privatekey(FILETYPE_PEM, p12.get_privatekey())
1921 self.assertEqual(key_pem, client_key_pem)
1922 self.assertEqual(None, p12.get_ca_certificates())
Rick Deanf94096c2009-07-18 14:23:06 -05001923
Rick Deanee568302009-07-24 09:56:29 -05001924
1925 def test_load_pkcs12_garbage(self):
1926 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001927 :py:obj:`load_pkcs12` raises :py:obj:`OpenSSL.crypto.Error` when passed a string
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001928 which is not a PKCS12 dump.
Rick Deanee568302009-07-24 09:56:29 -05001929 """
1930 passwd = 'whatever'
1931 e = self.assertRaises(Error, load_pkcs12, 'fruit loops', passwd)
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -04001932 self.assertEqual( e.args[0][0][0], 'asn1 encoding routines')
1933 self.assertEqual( len(e.args[0][0]), 3)
Rick Deanee568302009-07-24 09:56:29 -05001934
1935
Rick Deanf94096c2009-07-18 14:23:06 -05001936 def test_replace(self):
1937 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001938 :py:obj:`PKCS12.set_certificate` replaces the certificate in a PKCS12 cluster.
1939 :py:obj:`PKCS12.set_privatekey` replaces the private key.
1940 :py:obj:`PKCS12.set_ca_certificates` replaces the CA certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05001941 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001942 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
1943 p12.set_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1944 p12.set_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001945 root_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05001946 client_cert = load_certificate(FILETYPE_PEM, client_cert_pem)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001947 p12.set_ca_certificates([root_cert]) # not a tuple
Rick Dean623ee362009-07-17 12:22:16 -05001948 self.assertEqual(1, len(p12.get_ca_certificates()))
1949 self.assertEqual(root_cert, p12.get_ca_certificates()[0])
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001950 p12.set_ca_certificates([client_cert, root_cert])
Rick Deanf94096c2009-07-18 14:23:06 -05001951 self.assertEqual(2, len(p12.get_ca_certificates()))
1952 self.assertEqual(client_cert, p12.get_ca_certificates()[0])
1953 self.assertEqual(root_cert, p12.get_ca_certificates()[1])
1954
1955
1956 def test_friendly_name(self):
1957 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04001958 The *friendlyName* of a PKCS12 can be set and retrieved via
Jonathan Ballet648875f2011-07-16 14:14:58 +09001959 :py:obj:`PKCS12.get_friendlyname` and :py:obj:`PKCS12_set_friendlyname`, and a
1960 :py:obj:`PKCS12` with a friendly name set can be dumped with :py:obj:`PKCS12.export`.
Rick Deanf94096c2009-07-18 14:23:06 -05001961 """
Rick Deanf94096c2009-07-18 14:23:06 -05001962 passwd = 'Dogmeat[]{}!@#$%^&*()~`?/.,<>-_+=";:'
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001963 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -04001964 for friendly_name in [b('Serverlicious'), None, b('###')]:
Rick Dean42d69e12009-07-20 11:36:08 -05001965 p12.set_friendlyname(friendly_name)
1966 self.assertEqual(p12.get_friendlyname(), friendly_name)
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001967 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
Rick Dean42d69e12009-07-20 11:36:08 -05001968 reloaded_p12 = load_pkcs12(dumped_p12, passwd)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001969 self.assertEqual(
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -04001970 p12.get_friendlyname(), reloaded_p12.get_friendlyname())
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001971 # We would use the openssl program to confirm the friendly
1972 # name, but it is not possible. The pkcs12 command
1973 # does not store the friendly name in the cert's
Rick Dean42d69e12009-07-20 11:36:08 -05001974 # alias, which we could then extract.
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001975 self.check_recovery(
1976 dumped_p12, key=server_key_pem, cert=server_cert_pem,
1977 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05001978
1979
1980 def test_various_empty_passphrases(self):
1981 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001982 Test that missing, None, and '' passphrases are identical for PKCS12
1983 export.
Rick Deanf94096c2009-07-18 14:23:06 -05001984 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001985 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
Rick Dean623ee362009-07-17 12:22:16 -05001986 passwd = ''
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001987 dumped_p12_empty = p12.export(iter=2, maciter=0, passphrase=passwd)
1988 dumped_p12_none = p12.export(iter=3, maciter=2, passphrase=None)
1989 dumped_p12_nopw = p12.export(iter=9, maciter=4)
1990 for dumped_p12 in [dumped_p12_empty, dumped_p12_none, dumped_p12_nopw]:
1991 self.check_recovery(
1992 dumped_p12, key=client_key_pem, cert=client_cert_pem,
1993 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05001994
1995
1996 def test_removing_ca_cert(self):
1997 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001998 Passing :py:obj:`None` to :py:obj:`PKCS12.set_ca_certificates` removes all CA
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001999 certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05002000 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002001 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
2002 p12.set_ca_certificates(None)
Rick Dean623ee362009-07-17 12:22:16 -05002003 self.assertEqual(None, p12.get_ca_certificates())
Rick Deanf94096c2009-07-18 14:23:06 -05002004
2005
2006 def test_export_without_mac(self):
2007 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002008 Exporting a PKCS12 with a :py:obj:`maciter` of ``-1`` excludes the MAC
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002009 entirely.
Rick Deanf94096c2009-07-18 14:23:06 -05002010 """
2011 passwd = 'Lake Michigan'
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002012 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Dean623ee362009-07-17 12:22:16 -05002013 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002014 self.check_recovery(
2015 dumped_p12, key=server_key_pem, cert=server_cert_pem,
2016 passwd=passwd, extra=('-nomacver',))
2017
2018
2019 def test_load_without_mac(self):
2020 """
2021 Loading a PKCS12 without a MAC does something other than crash.
2022 """
2023 passwd = 'Lake Michigan'
2024 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
2025 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Rick Dean321a0512009-08-13 17:21:29 -05002026 try:
2027 recovered_p12 = load_pkcs12(dumped_p12, passwd)
2028 # The person who generated this PCKS12 should be flogged,
2029 # or better yet we should have a means to determine
2030 # whether a PCKS12 had a MAC that was verified.
2031 # Anyway, libopenssl chooses to allow it, so the
2032 # pyopenssl binding does as well.
2033 self.assertTrue(isinstance(recovered_p12, PKCS12))
2034 except Error:
2035 # Failing here with an exception is preferred as some openssl
2036 # versions do.
2037 pass
Rick Dean623ee362009-07-17 12:22:16 -05002038
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002039
Rick Dean25bcc1f2009-07-20 11:53:13 -05002040 def test_zero_len_list_for_ca(self):
2041 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002042 A PKCS12 with an empty CA certificates list can be exported.
Rick Dean25bcc1f2009-07-20 11:53:13 -05002043 """
2044 passwd = 'Hobie 18'
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002045 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002046 # p12.set_ca_certificates([])
2047 # self.assertEqual((), p12.get_ca_certificates())
2048 # dumped_p12 = p12.export(passphrase=passwd, iter=3)
2049 # self.check_recovery(
2050 # dumped_p12, key=server_key_pem, cert=server_cert_pem,
2051 # passwd=passwd)
Rick Dean25bcc1f2009-07-20 11:53:13 -05002052
2053
Rick Deanf94096c2009-07-18 14:23:06 -05002054 def test_export_without_args(self):
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002055 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002056 All the arguments to :py:obj:`PKCS12.export` are optional.
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002057 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002058 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05002059 dumped_p12 = p12.export() # no args
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002060 self.check_recovery(
2061 dumped_p12, key=server_key_pem, cert=server_cert_pem, passwd='')
Rick Deanf94096c2009-07-18 14:23:06 -05002062
2063
2064 def test_key_cert_mismatch(self):
2065 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002066 :py:obj:`PKCS12.export` raises an exception when a key and certificate
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002067 mismatch.
Rick Deanf94096c2009-07-18 14:23:06 -05002068 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002069 p12 = self.gen_pkcs12(server_cert_pem, client_key_pem, root_cert_pem)
2070 self.assertRaises(Error, p12.export)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002071
2072
2073
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002074# These quoting functions taken directly from Twisted's twisted.python.win32.
2075_cmdLineQuoteRe = re.compile(r'(\\*)"')
2076_cmdLineQuoteRe2 = re.compile(r'(\\+)\Z')
2077def cmdLineQuote(s):
2078 """
2079 Internal method for quoting a single command-line argument.
2080
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002081 See http://www.perlmonks.org/?node_id=764004
2082
Jonathan Ballet648875f2011-07-16 14:14:58 +09002083 :type: :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002084 :param s: A single unquoted string to quote for something that is expecting
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002085 cmd.exe-style quoting
2086
Jonathan Ballet648875f2011-07-16 14:14:58 +09002087 :rtype: :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002088 :return: A cmd.exe-style quoted string
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002089 """
2090 s = _cmdLineQuoteRe2.sub(r"\1\1", _cmdLineQuoteRe.sub(r'\1\1\\"', s))
2091 return '"%s"' % s
2092
2093
2094
2095def quoteArguments(arguments):
2096 """
2097 Quote an iterable of command-line arguments for passing to CreateProcess or
Jonathan Ballet648875f2011-07-16 14:14:58 +09002098 a similar API. This allows the list passed to :py:obj:`reactor.spawnProcess` to
2099 match the child process's :py:obj:`sys.argv` properly.
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002100
Jonathan Ballet648875f2011-07-16 14:14:58 +09002101 :type arguments: :py:obj:`iterable` of :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002102 :param arguments: An iterable of unquoted arguments to quote
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002103
Jonathan Ballet648875f2011-07-16 14:14:58 +09002104 :rtype: :py:obj:`str`
2105 :return: A space-delimited string containing quoted versions of :py:obj:`arguments`
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002106 """
2107 return ' '.join(map(cmdLineQuote, arguments))
2108
2109
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002110
Rick Dean4c9ad612009-07-17 15:05:22 -05002111def _runopenssl(pem, *args):
2112 """
2113 Run the command line openssl tool with the given arguments and write
Rick Dean55d1ce62009-08-13 17:40:24 -05002114 the given PEM to its stdin. Not safe for quotes.
Rick Dean4c9ad612009-07-17 15:05:22 -05002115 """
Jean-Paul Calderone038de952009-08-21 12:16:06 -04002116 if os.name == 'posix':
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04002117 command = "openssl " + " ".join([
2118 "'%s'" % (arg.replace("'", "'\\''"),) for arg in args])
Rick Dean55d1ce62009-08-13 17:40:24 -05002119 else:
Jean-Paul Calderone50924502009-08-27 12:47:55 -04002120 command = "openssl " + quoteArguments(args)
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04002121 proc = Popen(command, shell=True, stdin=PIPE, stdout=PIPE)
Jean-Paul Calderone62ca8da2010-08-11 19:58:08 -04002122 proc.stdin.write(pem)
2123 proc.stdin.close()
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002124 output = proc.stdout.read()
2125 proc.stdout.close()
2126 proc.wait()
2127 return output
Rick Dean4c9ad612009-07-17 15:05:22 -05002128
2129
2130
Jean-Paul Calderone18808652009-07-05 12:54:05 -04002131class FunctionTests(TestCase):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002132 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002133 Tests for free-functions in the :py:obj:`OpenSSL.crypto` module.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002134 """
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002135
2136 def test_load_privatekey_invalid_format(self):
2137 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002138 :py:obj:`load_privatekey` raises :py:obj:`ValueError` if passed an unknown filetype.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002139 """
2140 self.assertRaises(ValueError, load_privatekey, 100, root_key_pem)
2141
2142
2143 def test_load_privatekey_invalid_passphrase_type(self):
2144 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002145 :py:obj:`load_privatekey` raises :py:obj:`TypeError` if passed a passphrase that is
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002146 neither a :py:obj:`str` nor a callable.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002147 """
2148 self.assertRaises(
2149 TypeError,
2150 load_privatekey,
2151 FILETYPE_PEM, encryptedPrivateKeyPEMPassphrase, object())
2152
2153
2154 def test_load_privatekey_wrong_args(self):
2155 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002156 :py:obj:`load_privatekey` raises :py:obj:`TypeError` if called with the wrong number
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002157 of arguments.
2158 """
2159 self.assertRaises(TypeError, load_privatekey)
2160
2161
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002162 def test_load_privatekey_wrongPassphrase(self):
2163 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002164 :py:obj:`load_privatekey` raises :py:obj:`OpenSSL.crypto.Error` when it is passed an
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002165 encrypted PEM and an incorrect passphrase.
2166 """
2167 self.assertRaises(
2168 Error,
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002169 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, b("quack"))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002170
2171
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002172 def test_load_privatekey_passphraseWrongType(self):
2173 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002174 :py:obj:`load_privatekey` raises :py:obj:`ValueError` when it is passed a passphrase
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002175 with a private key encoded in a format, that doesn't support
2176 encryption.
2177 """
2178 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2179 blob = dump_privatekey(FILETYPE_ASN1, key)
2180 self.assertRaises(ValueError,
2181 load_privatekey, FILETYPE_ASN1, blob, "secret")
2182
2183
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002184 def test_load_privatekey_passphrase(self):
2185 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002186 :py:obj:`load_privatekey` can create a :py:obj:`PKey` object from an encrypted PEM
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002187 string if given the passphrase.
2188 """
2189 key = load_privatekey(
2190 FILETYPE_PEM, encryptedPrivateKeyPEM,
2191 encryptedPrivateKeyPEMPassphrase)
2192 self.assertTrue(isinstance(key, PKeyType))
2193
2194
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002195 def test_load_privatekey_passphrase_exception(self):
2196 """
2197 If the passphrase callback raises an exception, that exception is raised
2198 by :py:obj:`load_privatekey`.
2199 """
2200 def cb(ignored):
2201 raise ArithmeticError
2202
2203 self.assertRaises(ArithmeticError,
2204 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2205
2206
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002207 def test_load_privatekey_wrongPassphraseCallback(self):
2208 """
Jean-Paul Calderoned440a082011-09-14 11:02:05 -04002209 :py:obj:`load_privatekey` raises :py:obj:`OpenSSL.crypto.Error` when it
2210 is passed an encrypted PEM and a passphrase callback which returns an
2211 incorrect passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002212 """
2213 called = []
2214 def cb(*a):
2215 called.append(None)
Jean-Paul Calderoned440a082011-09-14 11:02:05 -04002216 return b("quack")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002217 self.assertRaises(
2218 Error,
2219 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2220 self.assertTrue(called)
2221
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002222
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002223 def test_load_privatekey_passphraseCallback(self):
2224 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002225 :py:obj:`load_privatekey` can create a :py:obj:`PKey` object from an encrypted PEM
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002226 string if given a passphrase callback which returns the correct
2227 password.
2228 """
2229 called = []
2230 def cb(writing):
2231 called.append(writing)
2232 return encryptedPrivateKeyPEMPassphrase
2233 key = load_privatekey(FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2234 self.assertTrue(isinstance(key, PKeyType))
2235 self.assertEqual(called, [False])
2236
2237
Jean-Paul Calderone105cb952011-09-14 10:16:46 -04002238 def test_load_privatekey_passphrase_wrong_return_type(self):
2239 """
2240 :py:obj:`load_privatekey` raises :py:obj:`ValueError` if the passphrase
2241 callback returns something other than a byte string.
2242 """
2243 self.assertRaises(
2244 ValueError,
2245 load_privatekey,
2246 FILETYPE_PEM, encryptedPrivateKeyPEM, lambda *args: 3)
2247
2248
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002249 def test_dump_privatekey_wrong_args(self):
2250 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002251 :py:obj:`dump_privatekey` raises :py:obj:`TypeError` if called with the wrong number
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002252 of arguments.
2253 """
2254 self.assertRaises(TypeError, dump_privatekey)
Jean-Paul Calderone1eeccd82011-09-14 10:18:52 -04002255 # If cipher name is given, password is required.
2256 self.assertRaises(
2257 ValueError, dump_privatekey, FILETYPE_PEM, PKey(), "foo")
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002258
2259
2260 def test_dump_privatekey_unknown_cipher(self):
2261 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002262 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` if called with an unrecognized
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002263 cipher name.
2264 """
2265 key = PKey()
2266 key.generate_key(TYPE_RSA, 512)
2267 self.assertRaises(
2268 ValueError, dump_privatekey,
2269 FILETYPE_PEM, key, "zippers", "passphrase")
2270
2271
2272 def test_dump_privatekey_invalid_passphrase_type(self):
2273 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002274 :py:obj:`dump_privatekey` raises :py:obj:`TypeError` if called with a passphrase which
2275 is neither a :py:obj:`str` nor a callable.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002276 """
2277 key = PKey()
2278 key.generate_key(TYPE_RSA, 512)
2279 self.assertRaises(
2280 TypeError,
2281 dump_privatekey, FILETYPE_PEM, key, "blowfish", object())
2282
2283
2284 def test_dump_privatekey_invalid_filetype(self):
2285 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002286 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` if called with an unrecognized
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002287 filetype.
2288 """
2289 key = PKey()
2290 key.generate_key(TYPE_RSA, 512)
2291 self.assertRaises(ValueError, dump_privatekey, 100, key)
2292
2293
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002294 def test_load_privatekey_passphraseCallbackLength(self):
2295 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002296 :py:obj:`crypto.load_privatekey` should raise an error when the passphrase
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002297 provided by the callback is too long, not silently truncate it.
2298 """
2299 def cb(ignored):
2300 return "a" * 1025
2301
2302 self.assertRaises(ValueError,
2303 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2304
2305
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002306 def test_dump_privatekey_passphrase(self):
2307 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002308 :py:obj:`dump_privatekey` writes an encrypted PEM when given a passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002309 """
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002310 passphrase = b("foo")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002311 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2312 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002313 self.assertTrue(isinstance(pem, bytes))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002314 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
2315 self.assertTrue(isinstance(loadedKey, PKeyType))
2316 self.assertEqual(loadedKey.type(), key.type())
2317 self.assertEqual(loadedKey.bits(), key.bits())
2318
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002319
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002320 def test_dump_privatekey_passphraseWrongType(self):
2321 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002322 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` when it is passed a passphrase
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002323 with a private key encoded in a format, that doesn't support
2324 encryption.
2325 """
2326 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2327 self.assertRaises(ValueError,
2328 dump_privatekey, FILETYPE_ASN1, key, "blowfish", "secret")
2329
2330
Rick Dean5b7b6372009-04-01 11:34:06 -05002331 def test_dump_certificate(self):
2332 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002333 :py:obj:`dump_certificate` writes PEM, DER, and text.
Rick Dean5b7b6372009-04-01 11:34:06 -05002334 """
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002335 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
Rick Dean5b7b6372009-04-01 11:34:06 -05002336 cert = load_certificate(FILETYPE_PEM, pemData)
2337 dumped_pem = dump_certificate(FILETYPE_PEM, cert)
2338 self.assertEqual(dumped_pem, cleartextCertificatePEM)
2339 dumped_der = dump_certificate(FILETYPE_ASN1, cert)
Rick Dean4c9ad612009-07-17 15:05:22 -05002340 good_der = _runopenssl(dumped_pem, "x509", "-outform", "DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002341 self.assertEqual(dumped_der, good_der)
2342 cert2 = load_certificate(FILETYPE_ASN1, dumped_der)
2343 dumped_pem2 = dump_certificate(FILETYPE_PEM, cert2)
2344 self.assertEqual(dumped_pem2, cleartextCertificatePEM)
2345 dumped_text = dump_certificate(FILETYPE_TEXT, cert)
Rick Dean4c9ad612009-07-17 15:05:22 -05002346 good_text = _runopenssl(dumped_pem, "x509", "-noout", "-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002347 self.assertEqual(dumped_text, good_text)
2348
2349
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002350 def test_dump_privatekey_pem(self):
Rick Dean5b7b6372009-04-01 11:34:06 -05002351 """
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002352 :py:obj:`dump_privatekey` writes a PEM
Rick Dean5b7b6372009-04-01 11:34:06 -05002353 """
2354 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -04002355 self.assertTrue(key.check())
Rick Dean5b7b6372009-04-01 11:34:06 -05002356 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2357 self.assertEqual(dumped_pem, cleartextPrivateKeyPEM)
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002358
2359
2360 def test_dump_privatekey_asn1(self):
2361 """
2362 :py:obj:`dump_privatekey` writes a DER
2363 """
2364 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2365 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2366
Rick Dean5b7b6372009-04-01 11:34:06 -05002367 dumped_der = dump_privatekey(FILETYPE_ASN1, key)
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002368 # XXX This OpenSSL call writes "writing RSA key" to standard out. Sad.
Rick Dean4c9ad612009-07-17 15:05:22 -05002369 good_der = _runopenssl(dumped_pem, "rsa", "-outform", "DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002370 self.assertEqual(dumped_der, good_der)
2371 key2 = load_privatekey(FILETYPE_ASN1, dumped_der)
2372 dumped_pem2 = dump_privatekey(FILETYPE_PEM, key2)
2373 self.assertEqual(dumped_pem2, cleartextPrivateKeyPEM)
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002374
2375
2376 def test_dump_privatekey_text(self):
2377 """
2378 :py:obj:`dump_privatekey` writes a text
2379 """
2380 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2381 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2382
Rick Dean5b7b6372009-04-01 11:34:06 -05002383 dumped_text = dump_privatekey(FILETYPE_TEXT, key)
Rick Dean4c9ad612009-07-17 15:05:22 -05002384 good_text = _runopenssl(dumped_pem, "rsa", "-noout", "-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002385 self.assertEqual(dumped_text, good_text)
2386
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002387
Rick Dean5b7b6372009-04-01 11:34:06 -05002388 def test_dump_certificate_request(self):
2389 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002390 :py:obj:`dump_certificate_request` writes a PEM, DER, and text.
Rick Dean5b7b6372009-04-01 11:34:06 -05002391 """
2392 req = load_certificate_request(FILETYPE_PEM, cleartextCertificateRequestPEM)
2393 dumped_pem = dump_certificate_request(FILETYPE_PEM, req)
2394 self.assertEqual(dumped_pem, cleartextCertificateRequestPEM)
2395 dumped_der = dump_certificate_request(FILETYPE_ASN1, req)
Rick Dean4c9ad612009-07-17 15:05:22 -05002396 good_der = _runopenssl(dumped_pem, "req", "-outform", "DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002397 self.assertEqual(dumped_der, good_der)
2398 req2 = load_certificate_request(FILETYPE_ASN1, dumped_der)
2399 dumped_pem2 = dump_certificate_request(FILETYPE_PEM, req2)
2400 self.assertEqual(dumped_pem2, cleartextCertificateRequestPEM)
2401 dumped_text = dump_certificate_request(FILETYPE_TEXT, req)
Rick Dean4c9ad612009-07-17 15:05:22 -05002402 good_text = _runopenssl(dumped_pem, "req", "-noout", "-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002403 self.assertEqual(dumped_text, good_text)
Jean-Paul Calderoneaf43cdf2010-08-03 18:40:52 -04002404 self.assertRaises(ValueError, dump_certificate_request, 100, req)
Rick Dean5b7b6372009-04-01 11:34:06 -05002405
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002406
2407 def test_dump_privatekey_passphraseCallback(self):
2408 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002409 :py:obj:`dump_privatekey` writes an encrypted PEM when given a callback which
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002410 returns the correct passphrase.
2411 """
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002412 passphrase = b("foo")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002413 called = []
2414 def cb(writing):
2415 called.append(writing)
2416 return passphrase
2417 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2418 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", cb)
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002419 self.assertTrue(isinstance(pem, bytes))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002420 self.assertEqual(called, [True])
2421 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
2422 self.assertTrue(isinstance(loadedKey, PKeyType))
2423 self.assertEqual(loadedKey.type(), key.type())
2424 self.assertEqual(loadedKey.bits(), key.bits())
Rick Dean5b7b6372009-04-01 11:34:06 -05002425
2426
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002427 def test_dump_privatekey_passphrase_exception(self):
2428 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002429 :py:obj:`dump_privatekey` should not overwrite the exception raised
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002430 by the passphrase callback.
2431 """
2432 def cb(ignored):
2433 raise ArithmeticError
2434
2435 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2436 self.assertRaises(ArithmeticError,
2437 dump_privatekey, FILETYPE_PEM, key, "blowfish", cb)
2438
2439
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002440 def test_dump_privatekey_passphraseCallbackLength(self):
2441 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002442 :py:obj:`crypto.dump_privatekey` should raise an error when the passphrase
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002443 provided by the callback is too long, not silently truncate it.
2444 """
2445 def cb(ignored):
2446 return "a" * 1025
2447
2448 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2449 self.assertRaises(ValueError,
2450 dump_privatekey, FILETYPE_PEM, key, "blowfish", cb)
2451
2452
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002453 def test_load_pkcs7_data(self):
2454 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002455 :py:obj:`load_pkcs7_data` accepts a PKCS#7 string and returns an instance of
2456 :py:obj:`PKCS7Type`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002457 """
2458 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2459 self.assertTrue(isinstance(pkcs7, PKCS7Type))
2460
2461
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002462 def test_load_pkcs7_data_invalid(self):
2463 """
2464 If the data passed to :py:obj:`load_pkcs7_data` is invalid,
2465 :py:obj:`Error` is raised.
2466 """
2467 self.assertRaises(Error, load_pkcs7_data, FILETYPE_PEM, "foo")
2468
2469
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002470
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002471class PKCS7Tests(TestCase):
2472 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002473 Tests for :py:obj:`PKCS7Type`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002474 """
2475 def test_type(self):
2476 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002477 :py:obj:`PKCS7Type` is a type object.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002478 """
2479 self.assertTrue(isinstance(PKCS7Type, type))
2480 self.assertEqual(PKCS7Type.__name__, 'PKCS7')
2481
2482 # XXX This doesn't currently work.
2483 # self.assertIdentical(PKCS7, PKCS7Type)
2484
2485
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002486 # XXX Opposite results for all these following methods
2487
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002488 def test_type_is_signed_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002489 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002490 :py:obj:`PKCS7Type.type_is_signed` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002491 arguments.
2492 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002493 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2494 self.assertRaises(TypeError, pkcs7.type_is_signed, None)
2495
2496
2497 def test_type_is_signed(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002498 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002499 :py:obj:`PKCS7Type.type_is_signed` returns :py:obj:`True` if the PKCS7 object is of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002500 the type *signed*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002501 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002502 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2503 self.assertTrue(pkcs7.type_is_signed())
2504
2505
2506 def test_type_is_enveloped_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002507 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002508 :py:obj:`PKCS7Type.type_is_enveloped` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002509 arguments.
2510 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002511 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2512 self.assertRaises(TypeError, pkcs7.type_is_enveloped, None)
2513
2514
2515 def test_type_is_enveloped(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002516 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002517 :py:obj:`PKCS7Type.type_is_enveloped` returns :py:obj:`False` if the PKCS7 object is
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002518 not of the type *enveloped*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002519 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002520 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2521 self.assertFalse(pkcs7.type_is_enveloped())
2522
2523
2524 def test_type_is_signedAndEnveloped_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002525 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002526 :py:obj:`PKCS7Type.type_is_signedAndEnveloped` raises :py:obj:`TypeError` if called
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002527 with any arguments.
2528 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002529 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2530 self.assertRaises(TypeError, pkcs7.type_is_signedAndEnveloped, None)
2531
2532
2533 def test_type_is_signedAndEnveloped(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002534 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002535 :py:obj:`PKCS7Type.type_is_signedAndEnveloped` returns :py:obj:`False` if the PKCS7
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002536 object is not of the type *signed and enveloped*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002537 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002538 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2539 self.assertFalse(pkcs7.type_is_signedAndEnveloped())
2540
2541
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002542 def test_type_is_data(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002543 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002544 :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 -04002545 the type data.
2546 """
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002547 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2548 self.assertFalse(pkcs7.type_is_data())
2549
2550
2551 def test_type_is_data_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002552 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002553 :py:obj:`PKCS7Type.type_is_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002554 arguments.
2555 """
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002556 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2557 self.assertRaises(TypeError, pkcs7.type_is_data, None)
2558
2559
Jean-Paul Calderone97b28ca2010-07-30 10:56:07 -04002560 def test_get_type_name_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002561 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002562 :py:obj:`PKCS7Type.get_type_name` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002563 arguments.
2564 """
Jean-Paul Calderone97b28ca2010-07-30 10:56:07 -04002565 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2566 self.assertRaises(TypeError, pkcs7.get_type_name, None)
2567
2568
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002569 def test_get_type_name(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002570 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002571 :py:obj:`PKCS7Type.get_type_name` returns a :py:obj:`str` giving the type name.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002572 """
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002573 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
Jean-Paul Calderone07640f12010-08-22 17:14:43 -04002574 self.assertEquals(pkcs7.get_type_name(), b('pkcs7-signedData'))
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002575
2576
2577 def test_attribute(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002578 """
2579 If an attribute other than one of the methods tested here is accessed on
Jonathan Ballet648875f2011-07-16 14:14:58 +09002580 an instance of :py:obj:`PKCS7Type`, :py:obj:`AttributeError` is raised.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002581 """
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002582 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2583 self.assertRaises(AttributeError, getattr, pkcs7, "foo")
2584
2585
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002586
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002587class NetscapeSPKITests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002588 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002589 Tests for :py:obj:`OpenSSL.crypto.NetscapeSPKI`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002590 """
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002591 def signable(self):
2592 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002593 Return a new :py:obj:`NetscapeSPKI` for use with signing tests.
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002594 """
2595 return NetscapeSPKI()
2596
2597
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002598 def test_type(self):
2599 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002600 :py:obj:`NetscapeSPKI` and :py:obj:`NetscapeSPKIType` refer to the same type object
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002601 and can be used to create instances of that type.
2602 """
2603 self.assertIdentical(NetscapeSPKI, NetscapeSPKIType)
2604 self.assertConsistentType(NetscapeSPKI, 'NetscapeSPKI')
2605
2606
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002607 def test_construction(self):
2608 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002609 :py:obj:`NetscapeSPKI` returns an instance of :py:obj:`NetscapeSPKIType`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002610 """
2611 nspki = NetscapeSPKI()
2612 self.assertTrue(isinstance(nspki, NetscapeSPKIType))
2613
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002614
Jean-Paul Calderone969efaa2010-08-03 18:19:19 -04002615 def test_invalid_attribute(self):
2616 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002617 Accessing a non-existent attribute of a :py:obj:`NetscapeSPKI` instance causes
2618 an :py:obj:`AttributeError` to be raised.
Jean-Paul Calderone969efaa2010-08-03 18:19:19 -04002619 """
2620 nspki = NetscapeSPKI()
2621 self.assertRaises(AttributeError, lambda: nspki.foo)
2622
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002623
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002624 def test_b64_encode(self):
2625 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002626 :py:obj:`NetscapeSPKI.b64_encode` encodes the certificate to a base64 blob.
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002627 """
2628 nspki = NetscapeSPKI()
2629 blob = nspki.b64_encode()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002630 self.assertTrue(isinstance(blob, bytes))
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002631
2632
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002633
Rick Dean536ba022009-07-24 23:57:27 -05002634class RevokedTests(TestCase):
2635 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002636 Tests for :py:obj:`OpenSSL.crypto.Revoked`
Rick Dean536ba022009-07-24 23:57:27 -05002637 """
2638 def test_construction(self):
2639 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002640 Confirm we can create :py:obj:`OpenSSL.crypto.Revoked`. Check
Rick Dean536ba022009-07-24 23:57:27 -05002641 that it is empty.
2642 """
2643 revoked = Revoked()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002644 self.assertTrue(isinstance(revoked, Revoked))
2645 self.assertEquals(type(revoked), Revoked)
2646 self.assertEquals(revoked.get_serial(), b('00'))
2647 self.assertEquals(revoked.get_rev_date(), None)
2648 self.assertEquals(revoked.get_reason(), None)
Rick Dean536ba022009-07-24 23:57:27 -05002649
2650
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002651 def test_construction_wrong_args(self):
2652 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002653 Calling :py:obj:`OpenSSL.crypto.Revoked` with any arguments results
2654 in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002655 """
2656 self.assertRaises(TypeError, Revoked, None)
2657 self.assertRaises(TypeError, Revoked, 1)
2658 self.assertRaises(TypeError, Revoked, "foo")
2659
2660
Rick Dean536ba022009-07-24 23:57:27 -05002661 def test_serial(self):
2662 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002663 Confirm we can set and get serial numbers from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002664 :py:obj:`OpenSSL.crypto.Revoked`. Confirm errors are handled
Rick Dean536ba022009-07-24 23:57:27 -05002665 with grace.
2666 """
2667 revoked = Revoked()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002668 ret = revoked.set_serial(b('10b'))
2669 self.assertEquals(ret, None)
Rick Dean536ba022009-07-24 23:57:27 -05002670 ser = revoked.get_serial()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002671 self.assertEquals(ser, b('010B'))
Rick Dean536ba022009-07-24 23:57:27 -05002672
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002673 revoked.set_serial(b('31ppp')) # a type error would be nice
Rick Dean536ba022009-07-24 23:57:27 -05002674 ser = revoked.get_serial()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002675 self.assertEquals(ser, b('31'))
Rick Dean536ba022009-07-24 23:57:27 -05002676
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002677 self.assertRaises(ValueError, revoked.set_serial, b('pqrst'))
Rick Dean536ba022009-07-24 23:57:27 -05002678 self.assertRaises(TypeError, revoked.set_serial, 100)
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002679 self.assertRaises(TypeError, revoked.get_serial, 1)
2680 self.assertRaises(TypeError, revoked.get_serial, None)
2681 self.assertRaises(TypeError, revoked.get_serial, "")
Rick Dean536ba022009-07-24 23:57:27 -05002682
2683
2684 def test_date(self):
2685 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002686 Confirm we can set and get revocation dates from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002687 :py:obj:`OpenSSL.crypto.Revoked`. Confirm errors are handled
Rick Dean536ba022009-07-24 23:57:27 -05002688 with grace.
2689 """
2690 revoked = Revoked()
2691 date = revoked.get_rev_date()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002692 self.assertEquals(date, None)
Rick Dean536ba022009-07-24 23:57:27 -05002693
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002694 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05002695 ret = revoked.set_rev_date(now)
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002696 self.assertEqual(ret, None)
Rick Dean536ba022009-07-24 23:57:27 -05002697 date = revoked.get_rev_date()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002698 self.assertEqual(date, now)
Rick Dean536ba022009-07-24 23:57:27 -05002699
2700
Rick Dean6385faf2009-07-26 00:07:47 -05002701 def test_reason(self):
2702 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002703 Confirm we can set and get revocation reasons from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002704 :py:obj:`OpenSSL.crypto.Revoked`. The "get" need to work
Rick Dean6385faf2009-07-26 00:07:47 -05002705 as "set". Likewise, each reason of all_reasons() must work.
2706 """
2707 revoked = Revoked()
2708 for r in revoked.all_reasons():
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002709 for x in range(2):
Rick Dean6385faf2009-07-26 00:07:47 -05002710 ret = revoked.set_reason(r)
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002711 self.assertEquals(ret, None)
Rick Dean6385faf2009-07-26 00:07:47 -05002712 reason = revoked.get_reason()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002713 self.assertEquals(
2714 reason.lower().replace(b(' '), b('')),
2715 r.lower().replace(b(' '), b('')))
Rick Dean6385faf2009-07-26 00:07:47 -05002716 r = reason # again with the resp of get
2717
2718 revoked.set_reason(None)
2719 self.assertEqual(revoked.get_reason(), None)
2720
2721
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002722 def test_set_reason_wrong_arguments(self):
Rick Dean6385faf2009-07-26 00:07:47 -05002723 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002724 Calling :py:obj:`OpenSSL.crypto.Revoked.set_reason` with other than
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002725 one argument, or an argument which isn't a valid reason,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002726 results in :py:obj:`TypeError` or :py:obj:`ValueError` being raised.
Rick Dean6385faf2009-07-26 00:07:47 -05002727 """
2728 revoked = Revoked()
2729 self.assertRaises(TypeError, revoked.set_reason, 100)
Jean-Paul Calderone281b62b2010-08-28 14:22:29 -04002730 self.assertRaises(ValueError, revoked.set_reason, b('blue'))
Rick Dean6385faf2009-07-26 00:07:47 -05002731
Rick Dean536ba022009-07-24 23:57:27 -05002732
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002733 def test_get_reason_wrong_arguments(self):
2734 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002735 Calling :py:obj:`OpenSSL.crypto.Revoked.get_reason` with any
2736 arguments results in :py:obj:`TypeError` being raised.
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002737 """
2738 revoked = Revoked()
2739 self.assertRaises(TypeError, revoked.get_reason, None)
2740 self.assertRaises(TypeError, revoked.get_reason, 1)
2741 self.assertRaises(TypeError, revoked.get_reason, "foo")
2742
2743
2744
Rick Dean536ba022009-07-24 23:57:27 -05002745class CRLTests(TestCase):
2746 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002747 Tests for :py:obj:`OpenSSL.crypto.CRL`
Rick Dean536ba022009-07-24 23:57:27 -05002748 """
2749 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
2750 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2751
2752 def test_construction(self):
2753 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002754 Confirm we can create :py:obj:`OpenSSL.crypto.CRL`. Check
Rick Dean536ba022009-07-24 23:57:27 -05002755 that it is empty
2756 """
2757 crl = CRL()
2758 self.assertTrue( isinstance(crl, CRL) )
2759 self.assertEqual(crl.get_revoked(), None)
2760
2761
Jean-Paul Calderone2efd03e2010-01-30 13:59:55 -05002762 def test_construction_wrong_args(self):
2763 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002764 Calling :py:obj:`OpenSSL.crypto.CRL` with any number of arguments
2765 results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone2efd03e2010-01-30 13:59:55 -05002766 """
2767 self.assertRaises(TypeError, CRL, 1)
2768 self.assertRaises(TypeError, CRL, "")
2769 self.assertRaises(TypeError, CRL, None)
2770
2771
Rick Dean536ba022009-07-24 23:57:27 -05002772 def test_export(self):
2773 """
2774 Use python to create a simple CRL with a revocation, and export
2775 the CRL in formats of PEM, DER and text. Those outputs are verified
2776 with the openssl program.
2777 """
2778 crl = CRL()
2779 revoked = Revoked()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002780 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05002781 revoked.set_rev_date(now)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002782 revoked.set_serial(b('3ab'))
2783 revoked.set_reason(b('sUpErSeDEd'))
Rick Dean536ba022009-07-24 23:57:27 -05002784 crl.add_revoked(revoked)
2785
2786 # PEM format
2787 dumped_crl = crl.export(self.cert, self.pkey, days=20)
2788 text = _runopenssl(dumped_crl, "crl", "-noout", "-text")
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002789 text.index(b('Serial Number: 03AB'))
2790 text.index(b('Superseded'))
2791 text.index(b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA'))
Rick Dean536ba022009-07-24 23:57:27 -05002792
2793 # DER format
2794 dumped_crl = crl.export(self.cert, self.pkey, FILETYPE_ASN1)
2795 text = _runopenssl(dumped_crl, "crl", "-noout", "-text", "-inform", "DER")
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002796 text.index(b('Serial Number: 03AB'))
2797 text.index(b('Superseded'))
2798 text.index(b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA'))
Rick Dean536ba022009-07-24 23:57:27 -05002799
2800 # text format
2801 dumped_text = crl.export(self.cert, self.pkey, type=FILETYPE_TEXT)
2802 self.assertEqual(text, dumped_text)
2803
2804
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -04002805 def test_export_invalid(self):
2806 """
2807 If :py:obj:`CRL.export` is used with an uninitialized :py:obj:`X509`
Jean-Paul Calderoneb5871072012-03-09 14:58:00 -08002808 instance, :py:obj:`OpenSSL.crypto.Error` is raised.
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -04002809 """
2810 crl = CRL()
2811 self.assertRaises(Error, crl.export, X509(), PKey())
2812
2813
Jean-Paul Calderone56515342010-01-30 13:49:38 -05002814 def test_add_revoked_keyword(self):
2815 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002816 :py:obj:`OpenSSL.CRL.add_revoked` accepts its single argument as the
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002817 ``revoked`` keyword argument.
Jean-Paul Calderone56515342010-01-30 13:49:38 -05002818 """
2819 crl = CRL()
2820 revoked = Revoked()
2821 crl.add_revoked(revoked=revoked)
2822 self.assertTrue(isinstance(crl.get_revoked()[0], Revoked))
2823
Rick Dean6385faf2009-07-26 00:07:47 -05002824
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05002825 def test_export_wrong_args(self):
2826 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002827 Calling :py:obj:`OpenSSL.CRL.export` with fewer than two or more than
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05002828 four arguments, or with arguments other than the certificate,
2829 private key, integer file type, and integer number of days it
Jonathan Ballet648875f2011-07-16 14:14:58 +09002830 expects, results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05002831 """
2832 crl = CRL()
2833 self.assertRaises(TypeError, crl.export)
2834 self.assertRaises(TypeError, crl.export, self.cert)
2835 self.assertRaises(TypeError, crl.export, self.cert, self.pkey, FILETYPE_PEM, 10, "foo")
2836
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05002837 self.assertRaises(TypeError, crl.export, None, self.pkey, FILETYPE_PEM, 10)
2838 self.assertRaises(TypeError, crl.export, self.cert, None, FILETYPE_PEM, 10)
2839 self.assertRaises(TypeError, crl.export, self.cert, self.pkey, None, 10)
2840 self.assertRaises(TypeError, crl.export, self.cert, FILETYPE_PEM, None)
2841
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05002842
Jean-Paul Calderoneea198422010-01-30 13:58:23 -05002843 def test_export_unknown_filetype(self):
2844 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002845 Calling :py:obj:`OpenSSL.CRL.export` with a file type other than
2846 :py:obj:`FILETYPE_PEM`, :py:obj:`FILETYPE_ASN1`, or :py:obj:`FILETYPE_TEXT` results
2847 in a :py:obj:`ValueError` being raised.
Jean-Paul Calderoneea198422010-01-30 13:58:23 -05002848 """
2849 crl = CRL()
2850 self.assertRaises(ValueError, crl.export, self.cert, self.pkey, 100, 10)
2851
2852
Rick Dean536ba022009-07-24 23:57:27 -05002853 def test_get_revoked(self):
2854 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002855 Use python to create a simple CRL with two revocations.
Jonathan Ballet648875f2011-07-16 14:14:58 +09002856 Get back the :py:obj:`Revoked` using :py:obj:`OpenSSL.CRL.get_revoked` and
Rick Dean536ba022009-07-24 23:57:27 -05002857 verify them.
2858 """
2859 crl = CRL()
2860
2861 revoked = Revoked()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002862 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05002863 revoked.set_rev_date(now)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002864 revoked.set_serial(b('3ab'))
Rick Dean536ba022009-07-24 23:57:27 -05002865 crl.add_revoked(revoked)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002866 revoked.set_serial(b('100'))
2867 revoked.set_reason(b('sUpErSeDEd'))
Rick Dean536ba022009-07-24 23:57:27 -05002868 crl.add_revoked(revoked)
2869
2870 revs = crl.get_revoked()
2871 self.assertEqual(len(revs), 2)
2872 self.assertEqual(type(revs[0]), Revoked)
2873 self.assertEqual(type(revs[1]), Revoked)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002874 self.assertEqual(revs[0].get_serial(), b('03AB'))
2875 self.assertEqual(revs[1].get_serial(), b('0100'))
Rick Dean536ba022009-07-24 23:57:27 -05002876 self.assertEqual(revs[0].get_rev_date(), now)
2877 self.assertEqual(revs[1].get_rev_date(), now)
2878
2879
Jean-Paul Calderone46bdce42010-01-30 13:44:16 -05002880 def test_get_revoked_wrong_args(self):
2881 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002882 Calling :py:obj:`OpenSSL.CRL.get_revoked` with any arguments results
2883 in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone46bdce42010-01-30 13:44:16 -05002884 """
2885 crl = CRL()
2886 self.assertRaises(TypeError, crl.get_revoked, None)
2887 self.assertRaises(TypeError, crl.get_revoked, 1)
2888 self.assertRaises(TypeError, crl.get_revoked, "")
2889 self.assertRaises(TypeError, crl.get_revoked, "", 1, None)
2890
2891
Jean-Paul Calderoneecef6fa2010-01-30 13:47:18 -05002892 def test_add_revoked_wrong_args(self):
2893 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002894 Calling :py:obj:`OpenSSL.CRL.add_revoked` with other than one
2895 argument results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderoneecef6fa2010-01-30 13:47:18 -05002896 """
2897 crl = CRL()
2898 self.assertRaises(TypeError, crl.add_revoked)
2899 self.assertRaises(TypeError, crl.add_revoked, 1, 2)
2900 self.assertRaises(TypeError, crl.add_revoked, "foo", "bar")
2901
2902
Rick Dean536ba022009-07-24 23:57:27 -05002903 def test_load_crl(self):
2904 """
2905 Load a known CRL and inspect its revocations. Both
2906 PEM and DER formats are loaded.
2907 """
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05002908 crl = load_crl(FILETYPE_PEM, crlData)
Rick Dean536ba022009-07-24 23:57:27 -05002909 revs = crl.get_revoked()
2910 self.assertEqual(len(revs), 2)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002911 self.assertEqual(revs[0].get_serial(), b('03AB'))
Rick Dean6385faf2009-07-26 00:07:47 -05002912 self.assertEqual(revs[0].get_reason(), None)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002913 self.assertEqual(revs[1].get_serial(), b('0100'))
2914 self.assertEqual(revs[1].get_reason(), b('Superseded'))
Rick Dean536ba022009-07-24 23:57:27 -05002915
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05002916 der = _runopenssl(crlData, "crl", "-outform", "DER")
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002917 crl = load_crl(FILETYPE_ASN1, der)
Rick Dean536ba022009-07-24 23:57:27 -05002918 revs = crl.get_revoked()
2919 self.assertEqual(len(revs), 2)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002920 self.assertEqual(revs[0].get_serial(), b('03AB'))
Rick Dean6385faf2009-07-26 00:07:47 -05002921 self.assertEqual(revs[0].get_reason(), None)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002922 self.assertEqual(revs[1].get_serial(), b('0100'))
2923 self.assertEqual(revs[1].get_reason(), b('Superseded'))
Rick Dean536ba022009-07-24 23:57:27 -05002924
2925
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05002926 def test_load_crl_wrong_args(self):
2927 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002928 Calling :py:obj:`OpenSSL.crypto.load_crl` with other than two
2929 arguments results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05002930 """
2931 self.assertRaises(TypeError, load_crl)
2932 self.assertRaises(TypeError, load_crl, FILETYPE_PEM)
2933 self.assertRaises(TypeError, load_crl, FILETYPE_PEM, crlData, None)
2934
2935
2936 def test_load_crl_bad_filetype(self):
2937 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002938 Calling :py:obj:`OpenSSL.crypto.load_crl` with an unknown file type
2939 raises a :py:obj:`ValueError`.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05002940 """
2941 self.assertRaises(ValueError, load_crl, 100, crlData)
2942
2943
2944 def test_load_crl_bad_data(self):
2945 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002946 Calling :py:obj:`OpenSSL.crypto.load_crl` with file data which can't
2947 be loaded raises a :py:obj:`OpenSSL.crypto.Error`.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05002948 """
2949 self.assertRaises(Error, load_crl, FILETYPE_PEM, "hello, world")
2950
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002951
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -05002952
James Yonan7c2e5d32010-02-27 05:45:50 -07002953class SignVerifyTests(TestCase):
2954 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002955 Tests for :py:obj:`OpenSSL.crypto.sign` and :py:obj:`OpenSSL.crypto.verify`.
James Yonan7c2e5d32010-02-27 05:45:50 -07002956 """
2957 def test_sign_verify(self):
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04002958 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002959 :py:obj:`sign` generates a cryptographic signature which :py:obj:`verify` can check.
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04002960 """
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04002961 content = b(
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04002962 "It was a bright cold day in April, and the clocks were striking "
2963 "thirteen. Winston Smith, his chin nuzzled into his breast in an "
2964 "effort to escape the vile wind, slipped quickly through the "
2965 "glass doors of Victory Mansions, though not quickly enough to "
2966 "prevent a swirl of gritty dust from entering along with him.")
2967
2968 # sign the content with this private key
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04002969 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04002970 # verify the content with this cert
2971 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
2972 # certificate unrelated to priv_key, used to trigger an error
2973 bad_cert = load_certificate(FILETYPE_PEM, server_cert_pem)
James Yonan7c2e5d32010-02-27 05:45:50 -07002974
Jean-Paul Calderoned08feb02010-10-12 21:53:24 -04002975 for digest in ['md5', 'sha1']:
James Yonan7c2e5d32010-02-27 05:45:50 -07002976 sig = sign(priv_key, content, digest)
2977
2978 # Verify the signature of content, will throw an exception if error.
2979 verify(good_cert, sig, content, digest)
2980
2981 # This should fail because the certificate doesn't match the
2982 # private key that was used to sign the content.
2983 self.assertRaises(Error, verify, bad_cert, sig, content, digest)
2984
2985 # This should fail because we've "tainted" the content after
2986 # signing it.
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04002987 self.assertRaises(
2988 Error, verify,
2989 good_cert, sig, content + b("tainted"), digest)
James Yonan7c2e5d32010-02-27 05:45:50 -07002990
2991 # test that unknown digest types fail
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04002992 self.assertRaises(
Jean-Paul Calderone9538f142010-10-13 22:13:40 -04002993 ValueError, sign, priv_key, content, "strange-digest")
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04002994 self.assertRaises(
Jean-Paul Calderone9538f142010-10-13 22:13:40 -04002995 ValueError, verify, good_cert, sig, content, "strange-digest")
James Yonan7c2e5d32010-02-27 05:45:50 -07002996
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04002997
Jean-Paul Calderone9828f662010-12-08 22:57:26 -05002998 def test_sign_nulls(self):
2999 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003000 :py:obj:`sign` produces a signature for a string with embedded nulls.
Jean-Paul Calderone9828f662010-12-08 22:57:26 -05003001 """
3002 content = b("Watch out! \0 Did you see it?")
3003 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
3004 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3005 sig = sign(priv_key, content, "sha1")
3006 verify(good_cert, sig, content, "sha1")
3007
3008
Rick Dean5b7b6372009-04-01 11:34:06 -05003009if __name__ == '__main__':
3010 main()