blob: 7fb2d2501130cee762f19f2a00ca0826704b1567 [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
Ziga Seilnacht781295a2009-12-22 14:58:01 +010010import os, re, sys
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
268
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400269class X509ExtTests(TestCase):
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400270 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900271 Tests for :py:class:`OpenSSL.crypto.X509Extension`.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400272 """
273
274 def setUp(self):
275 """
276 Create a new private key and start a certificate request (for a test
277 method to finish in one way or another).
278 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -0800279 super(X509ExtTests, self).setUp()
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400280 # Basic setup stuff to generate a certificate
281 self.pkey = PKey()
282 self.pkey.generate_key(TYPE_RSA, 384)
283 self.req = X509Req()
284 self.req.set_pubkey(self.pkey)
285 # Authority good you have.
286 self.req.get_subject().commonName = "Yoda root CA"
287 self.x509 = X509()
288 self.subject = self.x509.get_subject()
289 self.subject.commonName = self.req.get_subject().commonName
290 self.x509.set_issuer(self.subject)
291 self.x509.set_pubkey(self.pkey)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400292 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
293 expire = b((datetime.now() + timedelta(days=100)).strftime("%Y%m%d%H%M%SZ"))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400294 self.x509.set_notBefore(now)
295 self.x509.set_notAfter(expire)
296
297
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -0800298 def tearDown(self):
299 """
300 Forget all of the pyOpenSSL objects so they can be garbage collected,
301 their memory released, and not interfere with the leak detection code.
302 """
303 self.pkey = self.req = self.x509 = self.subject = None
304 super(X509ExtTests, self).tearDown()
305
306
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400307 def test_str(self):
308 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900309 The string representation of :py:class:`X509Extension` instances as returned by
310 :py:data:`str` includes stuff.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400311 """
312 # This isn't necessarily the best string representation. Perhaps it
313 # will be changed/improved in the future.
314 self.assertEquals(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400315 str(X509Extension(b('basicConstraints'), True, b('CA:false'))),
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400316 'CA:FALSE')
317
318
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400319 def test_type(self):
320 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900321 :py:class:`X509Extension` and :py:class:`X509ExtensionType` refer to the same type object
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400322 and can be used to create instances of that type.
323 """
324 self.assertIdentical(X509Extension, X509ExtensionType)
325 self.assertConsistentType(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400326 X509Extension,
327 'X509Extension', b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400328
329
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500330 def test_construction(self):
331 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900332 :py:class:`X509Extension` accepts an extension type name, a critical flag,
333 and an extension value and returns an :py:class:`X509ExtensionType` instance.
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500334 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400335 basic = X509Extension(b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500336 self.assertTrue(
337 isinstance(basic, X509ExtensionType),
338 "%r is of type %r, should be %r" % (
339 basic, type(basic), X509ExtensionType))
340
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400341 comment = X509Extension(
342 b('nsComment'), False, b('pyOpenSSL unit test'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500343 self.assertTrue(
344 isinstance(comment, X509ExtensionType),
345 "%r is of type %r, should be %r" % (
346 comment, type(comment), X509ExtensionType))
347
348
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500349 def test_invalid_extension(self):
350 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900351 :py:class:`X509Extension` raises something if it is passed a bad extension
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500352 name or value.
353 """
354 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400355 Error, X509Extension, b('thisIsMadeUp'), False, b('hi'))
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500356 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400357 Error, X509Extension, b('basicConstraints'), False, b('blah blah'))
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500358
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500359 # Exercise a weird one (an extension which uses the r2i method). This
360 # exercises the codepath that requires a non-NULL ctx to be passed to
361 # X509V3_EXT_nconf. It can't work now because we provide no
362 # configuration database. It might be made to work in the future.
363 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400364 Error, X509Extension, b('proxyCertInfo'), True,
365 b('language:id-ppl-anyLanguage,pathlen:1,policy:text:AB'))
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500366
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500367
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500368 def test_get_critical(self):
369 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900370 :py:meth:`X509ExtensionType.get_critical` returns the value of the
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500371 extension's critical flag.
372 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400373 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500374 self.assertTrue(ext.get_critical())
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400375 ext = X509Extension(b('basicConstraints'), False, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500376 self.assertFalse(ext.get_critical())
377
Jean-Paul Calderone7535dab2008-03-06 18:53:11 -0500378
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500379 def test_get_short_name(self):
380 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900381 :py:meth:`X509ExtensionType.get_short_name` returns a string giving the short
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500382 type name of the extension.
383 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400384 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
385 self.assertEqual(ext.get_short_name(), b('basicConstraints'))
386 ext = X509Extension(b('nsComment'), True, b('foo bar'))
387 self.assertEqual(ext.get_short_name(), b('nsComment'))
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500388
389
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400390 def test_get_data(self):
391 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900392 :py:meth:`X509Extension.get_data` returns a string giving the data of the
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400393 extension.
394 """
395 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
396 # Expect to get back the DER encoded form of CA:true.
397 self.assertEqual(ext.get_data(), b('0\x03\x01\x01\xff'))
398
399
400 def test_get_data_wrong_args(self):
401 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900402 :py:meth:`X509Extension.get_data` raises :py:exc:`TypeError` if passed any arguments.
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400403 """
404 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
405 self.assertRaises(TypeError, ext.get_data, None)
406 self.assertRaises(TypeError, ext.get_data, "foo")
407 self.assertRaises(TypeError, ext.get_data, 7)
408
409
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400410 def test_unused_subject(self):
Rick Dean47262da2009-07-08 16:17:17 -0500411 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900412 The :py:data:`subject` parameter to :py:class:`X509Extension` may be provided for an
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400413 extension which does not use it and is ignored in this case.
Rick Dean47262da2009-07-08 16:17:17 -0500414 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400415 ext1 = X509Extension(
416 b('basicConstraints'), False, b('CA:TRUE'), subject=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400417 self.x509.add_extensions([ext1])
418 self.x509.sign(self.pkey, 'sha1')
419 # This is a little lame. Can we think of a better way?
420 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400421 self.assertTrue(b('X509v3 Basic Constraints:') in text)
422 self.assertTrue(b('CA:TRUE') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400423
424
425 def test_subject(self):
426 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900427 If an extension requires a subject, the :py:data:`subject` parameter to
428 :py:class:`X509Extension` provides its value.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400429 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400430 ext3 = X509Extension(
431 b('subjectKeyIdentifier'), False, b('hash'), subject=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400432 self.x509.add_extensions([ext3])
433 self.x509.sign(self.pkey, 'sha1')
434 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400435 self.assertTrue(b('X509v3 Subject Key Identifier:') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400436
437
438 def test_missing_subject(self):
439 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900440 If an extension requires a subject and the :py:data:`subject` parameter is
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400441 given no value, something happens.
442 """
443 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400444 Error, X509Extension, b('subjectKeyIdentifier'), False, b('hash'))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400445
446
447 def test_invalid_subject(self):
448 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900449 If the :py:data:`subject` parameter is given a value which is not an
450 :py:class:`X509` instance, :py:exc:`TypeError` is raised.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400451 """
452 for badObj in [True, object(), "hello", [], self]:
453 self.assertRaises(
454 TypeError,
455 X509Extension,
456 'basicConstraints', False, 'CA:TRUE', subject=badObj)
457
458
459 def test_unused_issuer(self):
460 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900461 The :py:data:`issuer` parameter to :py:class:`X509Extension` may be provided for an
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400462 extension which does not use it and is ignored in this case.
463 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400464 ext1 = X509Extension(
465 b('basicConstraints'), False, b('CA:TRUE'), issuer=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400466 self.x509.add_extensions([ext1])
467 self.x509.sign(self.pkey, 'sha1')
468 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400469 self.assertTrue(b('X509v3 Basic Constraints:') in text)
470 self.assertTrue(b('CA:TRUE') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400471
472
473 def test_issuer(self):
474 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900475 If an extension requires a issuer, the :py:data:`issuer` parameter to
476 :py:class:`X509Extension` provides its value.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400477 """
478 ext2 = X509Extension(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400479 b('authorityKeyIdentifier'), False, b('issuer:always'),
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400480 issuer=self.x509)
481 self.x509.add_extensions([ext2])
482 self.x509.sign(self.pkey, 'sha1')
483 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400484 self.assertTrue(b('X509v3 Authority Key Identifier:') in text)
485 self.assertTrue(b('DirName:/CN=Yoda root CA') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400486
487
488 def test_missing_issuer(self):
489 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900490 If an extension requires an issue and the :py:data:`issuer` parameter is given
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400491 no value, something happens.
492 """
493 self.assertRaises(
494 Error,
495 X509Extension,
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400496 b('authorityKeyIdentifier'), False,
497 b('keyid:always,issuer:always'))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400498
499
500 def test_invalid_issuer(self):
501 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900502 If the :py:data:`issuer` parameter is given a value which is not an
503 :py:class:`X509` instance, :py:exc:`TypeError` is raised.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400504 """
505 for badObj in [True, object(), "hello", [], self]:
506 self.assertRaises(
507 TypeError,
508 X509Extension,
509 'authorityKeyIdentifier', False, 'keyid:always,issuer:always',
510 issuer=badObj)
Rick Dean47262da2009-07-08 16:17:17 -0500511
512
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500513
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400514class PKeyTests(TestCase):
Jean-Paul Calderoneac930e12008-03-06 18:50:51 -0500515 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900516 Unit tests for :py:class:`OpenSSL.crypto.PKey`.
Jean-Paul Calderoneac930e12008-03-06 18:50:51 -0500517 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400518 def test_type(self):
519 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900520 :py:class:`PKey` and :py:class:`PKeyType` refer to the same type object
521 and can be used to create instances of that type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400522 """
523 self.assertIdentical(PKey, PKeyType)
524 self.assertConsistentType(PKey, 'PKey')
525
526
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500527 def test_construction(self):
528 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900529 :py:class:`PKey` takes no arguments and returns a new :py:class:`PKey` instance.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500530 """
531 self.assertRaises(TypeError, PKey, None)
532 key = PKey()
533 self.assertTrue(
534 isinstance(key, PKeyType),
535 "%r is of type %r, should be %r" % (key, type(key), PKeyType))
536
537
538 def test_pregeneration(self):
539 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900540 :py:attr:`PKeyType.bits` and :py:attr:`PKeyType.type` return :py:data:`0` before the key is
541 generated. :py:attr:`PKeyType.check` raises :py:exc:`TypeError` before the key is
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500542 generated.
543 """
544 key = PKey()
545 self.assertEqual(key.type(), 0)
546 self.assertEqual(key.bits(), 0)
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400547 self.assertRaises(TypeError, key.check)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500548
549
550 def test_failedGeneration(self):
551 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900552 :py:meth:`PKeyType.generate_key` takes two arguments, the first giving the key
553 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 -0500554 number of bits to generate. If an invalid type is specified or
Jonathan Ballet648875f2011-07-16 14:14:58 +0900555 generation fails, :py:exc:`Error` is raised. If an invalid number of bits is
556 specified, :py:exc:`ValueError` or :py:exc:`Error` is raised.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500557 """
558 key = PKey()
559 self.assertRaises(TypeError, key.generate_key)
560 self.assertRaises(TypeError, key.generate_key, 1, 2, 3)
561 self.assertRaises(TypeError, key.generate_key, "foo", "bar")
562 self.assertRaises(Error, key.generate_key, -1, 0)
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500563
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500564 self.assertRaises(ValueError, key.generate_key, TYPE_RSA, -1)
565 self.assertRaises(ValueError, key.generate_key, TYPE_RSA, 0)
Jean-Paul Calderoned71fe982008-03-06 00:31:50 -0500566
567 # XXX RSA generation for small values of bits is fairly buggy in a wide
568 # range of OpenSSL versions. I need to figure out what the safe lower
569 # bound for a reasonable number of OpenSSL versions is and explicitly
570 # check for that in the wrapper. The failure behavior is typically an
571 # infinite loop inside OpenSSL.
572
573 # self.assertRaises(Error, key.generate_key, TYPE_RSA, 2)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500574
575 # XXX DSA generation seems happy with any number of bits. The DSS
576 # says bits must be between 512 and 1024 inclusive. OpenSSL's DSA
577 # generator doesn't seem to care about the upper limit at all. For
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500578 # the lower limit, it uses 512 if anything smaller is specified.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500579 # So, it doesn't seem possible to make generate_key fail for
580 # TYPE_DSA with a bits argument which is at least an int.
581
582 # self.assertRaises(Error, key.generate_key, TYPE_DSA, -7)
583
584
585 def test_rsaGeneration(self):
586 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900587 :py:meth:`PKeyType.generate_key` generates an RSA key when passed
588 :py:data:`TYPE_RSA` as a type and a reasonable number of bits.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500589 """
590 bits = 128
591 key = PKey()
592 key.generate_key(TYPE_RSA, bits)
593 self.assertEqual(key.type(), TYPE_RSA)
594 self.assertEqual(key.bits(), bits)
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -0400595 self.assertTrue(key.check())
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500596
597
598 def test_dsaGeneration(self):
599 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900600 :py:meth:`PKeyType.generate_key` generates a DSA key when passed
601 :py:data:`TYPE_DSA` as a type and a reasonable number of bits.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500602 """
603 # 512 is a magic number. The DSS (Digital Signature Standard)
604 # allows a minimum of 512 bits for DSA. DSA_generate_parameters
605 # will silently promote any value below 512 to 512.
606 bits = 512
607 key = PKey()
608 key.generate_key(TYPE_DSA, bits)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800609 # self.assertEqual(key.type(), TYPE_DSA)
610 # self.assertEqual(key.bits(), bits)
611 # self.assertRaises(TypeError, key.check)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500612
613
614 def test_regeneration(self):
615 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900616 :py:meth:`PKeyType.generate_key` can be called multiple times on the same
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500617 key to generate new keys.
618 """
619 key = PKey()
620 for type, bits in [(TYPE_RSA, 512), (TYPE_DSA, 576)]:
621 key.generate_key(type, bits)
622 self.assertEqual(key.type(), type)
623 self.assertEqual(key.bits(), bits)
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500624
625
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400626 def test_inconsistentKey(self):
627 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900628 :py:`PKeyType.check` returns :py:exc:`Error` if the key is not consistent.
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400629 """
630 key = load_privatekey(FILETYPE_PEM, inconsistentPrivateKeyPEM)
Jean-Paul Calderoned338e4e2009-05-13 15:45:07 -0400631 self.assertRaises(Error, key.check)
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400632
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500633
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400634 def test_check_wrong_args(self):
635 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900636 :py:meth:`PKeyType.check` raises :py:exc:`TypeError` if called with any arguments.
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400637 """
638 self.assertRaises(TypeError, PKey().check, None)
639 self.assertRaises(TypeError, PKey().check, object())
640 self.assertRaises(TypeError, PKey().check, 1)
641
642
Jean-Paul Calderone02d01972011-10-31 10:39:29 -0400643 def test_check_public_key(self):
644 """
645 :py:meth:`PKeyType.check` raises :py:exc:`TypeError` if only the public
646 part of the key is available.
647 """
648 # A trick to get a public-only key
649 key = PKey()
650 key.generate_key(TYPE_RSA, 512)
651 cert = X509()
652 cert.set_pubkey(key)
653 pub = cert.get_pubkey()
654 self.assertRaises(TypeError, pub.check)
655
656
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400657
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400658class X509NameTests(TestCase):
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500659 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900660 Unit tests for :py:class:`OpenSSL.crypto.X509Name`.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500661 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500662 def _x509name(self, **attrs):
663 # XXX There's no other way to get a new X509Name yet.
664 name = X509().get_subject()
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400665 attrs = list(attrs.items())
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500666 # Make the order stable - order matters!
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400667 def key(attr):
668 return attr[1]
669 attrs.sort(key=key)
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500670 for k, v in attrs:
671 setattr(name, k, v)
672 return name
673
674
Rick Deane15b1472009-07-09 15:53:42 -0500675 def test_type(self):
676 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900677 The type of X509Name objects is :py:class:`X509NameType`.
Rick Deane15b1472009-07-09 15:53:42 -0500678 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400679 self.assertIdentical(X509Name, X509NameType)
680 self.assertEqual(X509NameType.__name__, 'X509Name')
681 self.assertTrue(isinstance(X509NameType, type))
682
Rick Deane15b1472009-07-09 15:53:42 -0500683 name = self._x509name()
684 self.assertTrue(
685 isinstance(name, X509NameType),
686 "%r is of type %r, should be %r" % (
687 name, type(name), X509NameType))
Rick Deane15b1472009-07-09 15:53:42 -0500688
689
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400690 def test_onlyStringAttributes(self):
691 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900692 Attempting to set a non-:py:data:`str` attribute name on an :py:class:`X509NameType`
693 instance causes :py:exc:`TypeError` to be raised.
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400694 """
695 name = self._x509name()
696 # Beyond these cases, you may also think that unicode should be
697 # rejected. Sorry, you're wrong. unicode is automatically converted to
698 # str outside of the control of X509Name, so there's no way to reject
699 # it.
Jean-Paul Calderoneff363be2013-03-03 10:21:23 -0800700
701 # Also, this used to test str subclasses, but that test is less relevant
702 # now that the implementation is in Python instead of C. Also PyPy
703 # automatically converts str subclasses to str when they are passed to
704 # setattr, so we can't test it on PyPy. Apparently CPython does this
705 # sometimes as well.
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400706 self.assertRaises(TypeError, setattr, name, None, "hello")
707 self.assertRaises(TypeError, setattr, name, 30, "hello")
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400708
709 def test_setInvalidAttribute(self):
710 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900711 Attempting to set any attribute name on an :py:class:`X509NameType` instance for
712 which no corresponding NID is defined causes :py:exc:`AttributeError` to be
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400713 raised.
714 """
715 name = self._x509name()
716 self.assertRaises(AttributeError, setattr, name, "no such thing", None)
717
718
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500719 def test_attributes(self):
720 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900721 :py:class:`X509NameType` instances have attributes for each standard (?)
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500722 X509Name field.
723 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500724 name = self._x509name()
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500725 name.commonName = "foo"
726 self.assertEqual(name.commonName, "foo")
727 self.assertEqual(name.CN, "foo")
728 name.CN = "baz"
729 self.assertEqual(name.commonName, "baz")
730 self.assertEqual(name.CN, "baz")
731 name.commonName = "bar"
732 self.assertEqual(name.commonName, "bar")
733 self.assertEqual(name.CN, "bar")
734 name.CN = "quux"
735 self.assertEqual(name.commonName, "quux")
736 self.assertEqual(name.CN, "quux")
737
738
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500739 def test_copy(self):
740 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900741 :py:class:`X509Name` creates a new :py:class:`X509NameType` instance with all the same
742 attributes as an existing :py:class:`X509NameType` instance when called with
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500743 one.
744 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500745 name = self._x509name(commonName="foo", emailAddress="bar@example.com")
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500746
747 copy = X509Name(name)
748 self.assertEqual(copy.commonName, "foo")
749 self.assertEqual(copy.emailAddress, "bar@example.com")
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500750
751 # Mutate the copy and ensure the original is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500752 copy.commonName = "baz"
753 self.assertEqual(name.commonName, "foo")
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500754
755 # Mutate the original and ensure the copy is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500756 name.emailAddress = "quux@example.com"
757 self.assertEqual(copy.emailAddress, "bar@example.com")
758
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500759
760 def test_repr(self):
761 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900762 :py:func:`repr` passed an :py:class:`X509NameType` instance should return a string
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500763 containing a description of the type and the NIDs which have been set
764 on it.
765 """
766 name = self._x509name(commonName="foo", emailAddress="bar")
767 self.assertEqual(
768 repr(name),
769 "<X509Name object '/emailAddress=bar/CN=foo'>")
770
771
772 def test_comparison(self):
773 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900774 :py:class:`X509NameType` instances should compare based on their NIDs.
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500775 """
776 def _equality(a, b, assertTrue, assertFalse):
777 assertTrue(a == b, "(%r == %r) --> False" % (a, b))
778 assertFalse(a != b)
779 assertTrue(b == a)
780 assertFalse(b != a)
781
782 def assertEqual(a, b):
783 _equality(a, b, self.assertTrue, self.assertFalse)
784
785 # Instances compare equal to themselves.
786 name = self._x509name()
787 assertEqual(name, name)
788
789 # Empty instances should compare equal to each other.
790 assertEqual(self._x509name(), self._x509name())
791
792 # Instances with equal NIDs should compare equal to each other.
793 assertEqual(self._x509name(commonName="foo"),
794 self._x509name(commonName="foo"))
795
796 # Instance with equal NIDs set using different aliases should compare
797 # equal to each other.
798 assertEqual(self._x509name(commonName="foo"),
799 self._x509name(CN="foo"))
800
801 # Instances with more than one NID with the same values should compare
802 # equal to each other.
803 assertEqual(self._x509name(CN="foo", organizationalUnitName="bar"),
804 self._x509name(commonName="foo", OU="bar"))
805
806 def assertNotEqual(a, b):
807 _equality(a, b, self.assertFalse, self.assertTrue)
808
809 # Instances with different values for the same NID should not compare
810 # equal to each other.
811 assertNotEqual(self._x509name(CN="foo"),
812 self._x509name(CN="bar"))
813
814 # Instances with different NIDs should not compare equal to each other.
815 assertNotEqual(self._x509name(CN="foo"),
816 self._x509name(OU="foo"))
817
818 def _inequality(a, b, assertTrue, assertFalse):
819 assertTrue(a < b)
820 assertTrue(a <= b)
821 assertTrue(b > a)
822 assertTrue(b >= a)
823 assertFalse(a > b)
824 assertFalse(a >= b)
825 assertFalse(b < a)
826 assertFalse(b <= a)
827
828 def assertLessThan(a, b):
829 _inequality(a, b, self.assertTrue, self.assertFalse)
830
831 # An X509Name with a NID with a value which sorts less than the value
832 # of the same NID on another X509Name compares less than the other
833 # X509Name.
834 assertLessThan(self._x509name(CN="abc"),
835 self._x509name(CN="def"))
836
837 def assertGreaterThan(a, b):
838 _inequality(a, b, self.assertFalse, self.assertTrue)
839
840 # An X509Name with a NID with a value which sorts greater than the
841 # value of the same NID on another X509Name compares greater than the
842 # other X509Name.
843 assertGreaterThan(self._x509name(CN="def"),
844 self._x509name(CN="abc"))
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -0500845
846
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400847 def test_hash(self):
848 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900849 :py:meth:`X509Name.hash` returns an integer hash based on the value of the
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400850 name.
851 """
852 a = self._x509name(CN="foo")
853 b = self._x509name(CN="foo")
854 self.assertEqual(a.hash(), b.hash())
855 a.CN = "bar"
856 self.assertNotEqual(a.hash(), b.hash())
857
858
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400859 def test_der(self):
860 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900861 :py:meth:`X509Name.der` returns the DER encoded form of the name.
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400862 """
863 a = self._x509name(CN="foo", C="US")
864 self.assertEqual(
865 a.der(),
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -0400866 b('0\x1b1\x0b0\t\x06\x03U\x04\x06\x13\x02US'
867 '1\x0c0\n\x06\x03U\x04\x03\x13\x03foo'))
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400868
869
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400870 def test_get_components(self):
871 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900872 :py:meth:`X509Name.get_components` returns a :py:data:`list` of
873 two-tuples of :py:data:`str`
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400874 giving the NIDs and associated values which make up the name.
875 """
876 a = self._x509name()
877 self.assertEqual(a.get_components(), [])
878 a.CN = "foo"
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -0400879 self.assertEqual(a.get_components(), [(b("CN"), b("foo"))])
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400880 a.organizationalUnitName = "bar"
881 self.assertEqual(
882 a.get_components(),
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -0400883 [(b("CN"), b("foo")), (b("OU"), b("bar"))])
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400884
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400885
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400886class _PKeyInteractionTestsMixin:
887 """
888 Tests which involve another thing and a PKey.
889 """
890 def signable(self):
891 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900892 Return something with a :py:meth:`set_pubkey`, :py:meth:`set_pubkey`,
893 and :py:meth:`sign` method.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400894 """
895 raise NotImplementedError()
896
897
898 def test_signWithUngenerated(self):
899 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900900 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when pass a
901 :py:class:`PKey` with no parts.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400902 """
903 request = self.signable()
904 key = PKey()
905 self.assertRaises(ValueError, request.sign, key, 'MD5')
906
907
908 def test_signWithPublicKey(self):
909 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900910 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when pass a
911 :py:class:`PKey` with no private part as the signing key.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400912 """
913 request = self.signable()
914 key = PKey()
915 key.generate_key(TYPE_RSA, 512)
916 request.set_pubkey(key)
917 pub = request.get_pubkey()
918 self.assertRaises(ValueError, request.sign, pub, 'MD5')
919
920
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -0400921 def test_signWithUnknownDigest(self):
922 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900923 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when passed a digest name which is
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -0400924 not known.
925 """
926 request = self.signable()
927 key = PKey()
928 key.generate_key(TYPE_RSA, 512)
929 self.assertRaises(ValueError, request.sign, key, "monkeys")
930
931
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -0400932 def test_sign(self):
933 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900934 :py:meth:`X509Req.sign` succeeds when passed a private key object and a valid
935 digest function. :py:meth:`X509Req.verify` can be used to check the signature.
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -0400936 """
937 request = self.signable()
938 key = PKey()
939 key.generate_key(TYPE_RSA, 512)
940 request.set_pubkey(key)
941 request.sign(key, 'MD5')
942 # If the type has a verify method, cover that too.
943 if getattr(request, 'verify', None) is not None:
944 pub = request.get_pubkey()
945 self.assertTrue(request.verify(pub))
946 # Make another key that won't verify.
947 key = PKey()
948 key.generate_key(TYPE_RSA, 512)
949 self.assertRaises(Error, request.verify, key)
950
951
952
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400953
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400954class X509ReqTests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -0500955 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900956 Tests for :py:class:`OpenSSL.crypto.X509Req`.
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -0500957 """
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400958 def signable(self):
959 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900960 Create and return a new :py:class:`X509Req`.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400961 """
962 return X509Req()
963
964
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400965 def test_type(self):
966 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900967 :py:obj:`X509Req` and :py:obj:`X509ReqType` refer to the same type object and can be
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400968 used to create instances of that type.
969 """
970 self.assertIdentical(X509Req, X509ReqType)
971 self.assertConsistentType(X509Req, 'X509Req')
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -0500972
973
974 def test_construction(self):
975 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900976 :py:obj:`X509Req` takes no arguments and returns an :py:obj:`X509ReqType` instance.
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -0500977 """
978 request = X509Req()
979 self.assertTrue(
980 isinstance(request, X509ReqType),
981 "%r is of type %r, should be %r" % (request, type(request), X509ReqType))
982
983
Jean-Paul Calderone8dd19b82008-12-28 20:41:16 -0500984 def test_version(self):
985 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900986 :py:obj:`X509ReqType.set_version` sets the X.509 version of the certificate
987 request. :py:obj:`X509ReqType.get_version` returns the X.509 version of
Jean-Paul Calderone8dd19b82008-12-28 20:41:16 -0500988 the certificate request. The initial value of the version is 0.
989 """
990 request = X509Req()
991 self.assertEqual(request.get_version(), 0)
992 request.set_version(1)
993 self.assertEqual(request.get_version(), 1)
994 request.set_version(3)
995 self.assertEqual(request.get_version(), 3)
996
997
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -0400998 def test_version_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -0400999 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001000 :py:obj:`X509ReqType.set_version` raises :py:obj:`TypeError` if called with the wrong
1001 number of arguments or with a non-:py:obj:`int` argument.
1002 :py:obj:`X509ReqType.get_version` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001003 arguments.
1004 """
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001005 request = X509Req()
1006 self.assertRaises(TypeError, request.set_version)
1007 self.assertRaises(TypeError, request.set_version, "foo")
1008 self.assertRaises(TypeError, request.set_version, 1, 2)
1009 self.assertRaises(TypeError, request.get_version, None)
1010
1011
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001012 def test_get_subject(self):
1013 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001014 :py:obj:`X509ReqType.get_subject` returns an :py:obj:`X509Name` for the subject of
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001015 the request and which is valid even after the request object is
1016 otherwise dead.
1017 """
1018 request = X509Req()
1019 subject = request.get_subject()
1020 self.assertTrue(
1021 isinstance(subject, X509NameType),
1022 "%r is of type %r, should be %r" % (subject, type(subject), X509NameType))
1023 subject.commonName = "foo"
1024 self.assertEqual(request.get_subject().commonName, "foo")
1025 del request
1026 subject.commonName = "bar"
1027 self.assertEqual(subject.commonName, "bar")
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001028
1029
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001030 def test_get_subject_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001031 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001032 :py:obj:`X509ReqType.get_subject` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001033 arguments.
1034 """
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001035 request = X509Req()
1036 self.assertRaises(TypeError, request.get_subject, None)
1037
1038
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001039 def test_add_extensions(self):
1040 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001041 :py:obj:`X509Req.add_extensions` accepts a :py:obj:`list` of :py:obj:`X509Extension`
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001042 instances and adds them to the X509 request.
1043 """
1044 request = X509Req()
1045 request.add_extensions([
Jean-Paul Calderonee16f9f32010-08-22 19:20:37 -04001046 X509Extension(b('basicConstraints'), True, b('CA:false'))])
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001047 # XXX Add get_extensions so the rest of this unit test can be written.
1048
1049
1050 def test_add_extensions_wrong_args(self):
1051 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001052 :py:obj:`X509Req.add_extensions` raises :py:obj:`TypeError` if called with the wrong
1053 number of arguments or with a non-:py:obj:`list`. Or it raises :py:obj:`ValueError`
1054 if called with a :py:obj:`list` containing objects other than :py:obj:`X509Extension`
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001055 instances.
1056 """
1057 request = X509Req()
1058 self.assertRaises(TypeError, request.add_extensions)
1059 self.assertRaises(TypeError, request.add_extensions, object())
1060 self.assertRaises(ValueError, request.add_extensions, [object()])
1061 self.assertRaises(TypeError, request.add_extensions, [], None)
1062
1063
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001064 def test_verify_wrong_args(self):
1065 """
1066 :py:obj:`X509Req.verify` raises :py:obj:`TypeError` if called with zero
1067 arguments or more than one argument or if passed anything other than a
1068 :py:obj:`PKey` instance as its single argument.
1069 """
1070 request = X509Req()
1071 self.assertRaises(TypeError, request.verify)
1072 self.assertRaises(TypeError, request.verify, object())
1073 self.assertRaises(TypeError, request.verify, PKey(), object())
1074
1075
1076 def test_verify_uninitialized_key(self):
1077 """
1078 :py:obj:`X509Req.verify` raises :py:obj:`OpenSSL.crypto.Error` if called
1079 with a :py:obj:`OpenSSL.crypto.PKey` which contains no key data.
1080 """
1081 request = X509Req()
1082 pkey = PKey()
1083 self.assertRaises(Error, request.verify, pkey)
1084
1085
1086 def test_verify_wrong_key(self):
1087 """
1088 :py:obj:`X509Req.verify` raises :py:obj:`OpenSSL.crypto.Error` if called
1089 with a :py:obj:`OpenSSL.crypto.PKey` which does not represent the public
1090 part of the key which signed the request.
1091 """
1092 request = X509Req()
1093 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
1094 request.sign(pkey, b"SHA1")
1095 another_pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
1096 self.assertRaises(Error, request.verify, another_pkey)
1097
1098
1099 def test_verify_success(self):
1100 """
1101 :py:obj:`X509Req.verify` returns :py:obj:`True` if called with a
1102 :py:obj:`OpenSSL.crypto.PKey` which represents the public part ofthe key
1103 which signed the request.
1104 """
1105 request = X509Req()
1106 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
1107 request.sign(pkey, b"SHA1")
1108 self.assertEqual(True, request.verify(pkey))
1109
1110
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001111
Jean-Paul Calderone18808652009-07-05 12:54:05 -04001112class X509Tests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001113 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001114 Tests for :py:obj:`OpenSSL.crypto.X509`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001115 """
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001116 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
Jean-Paul Calderone8114b452008-03-25 15:27:59 -04001117
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001118 extpem = """
1119-----BEGIN CERTIFICATE-----
1120MIIC3jCCAkegAwIBAgIJAJHFjlcCgnQzMA0GCSqGSIb3DQEBBQUAMEcxCzAJBgNV
1121BAYTAlNFMRUwEwYDVQQIEwxXZXN0ZXJib3R0b20xEjAQBgNVBAoTCUNhdGFsb2dp
1122eDENMAsGA1UEAxMEUm9vdDAeFw0wODA0MjIxNDQ1MzhaFw0wOTA0MjIxNDQ1Mzha
1123MFQxCzAJBgNVBAYTAlNFMQswCQYDVQQIEwJXQjEUMBIGA1UEChMLT3Blbk1ldGFk
1124aXIxIjAgBgNVBAMTGW5vZGUxLm9tMi5vcGVubWV0YWRpci5vcmcwgZ8wDQYJKoZI
1125hvcNAQEBBQADgY0AMIGJAoGBAPIcQMrwbk2nESF/0JKibj9i1x95XYAOwP+LarwT
1126Op4EQbdlI9SY+uqYqlERhF19w7CS+S6oyqx0DRZSk4Y9dZ9j9/xgm2u/f136YS1u
1127zgYFPvfUs6PqYLPSM8Bw+SjJ+7+2+TN+Tkiof9WP1cMjodQwOmdsiRbR0/J7+b1B
1128hec1AgMBAAGjgcQwgcEwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNT
1129TCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFIdHsBcMVVMbAO7j6NCj
113003HgLnHaMB8GA1UdIwQYMBaAFL2h9Bf9Mre4vTdOiHTGAt7BRY/8MEYGA1UdEQQ/
1131MD2CDSouZXhhbXBsZS5vcmeCESoub20yLmV4bWFwbGUuY29thwSC7wgKgRNvbTJA
1132b3Blbm1ldGFkaXIub3JnMA0GCSqGSIb3DQEBBQUAA4GBALd7WdXkp2KvZ7/PuWZA
1133MPlIxyjS+Ly11+BNE0xGQRp9Wz+2lABtpgNqssvU156+HkKd02rGheb2tj7MX9hG
1134uZzbwDAZzJPjzDQDD7d3cWsrVcfIdqVU7epHqIadnOF+X0ghJ39pAm6VVadnSXCt
1135WpOdIpB8KksUTCzV591Nr1wd
1136-----END CERTIFICATE-----
1137 """
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001138 def signable(self):
1139 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001140 Create and return a new :py:obj:`X509`.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001141 """
1142 return X509()
1143
1144
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001145 def test_type(self):
1146 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001147 :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 -04001148 to create instances of that type.
1149 """
1150 self.assertIdentical(X509, X509Type)
1151 self.assertConsistentType(X509, 'X509')
1152
1153
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001154 def test_construction(self):
1155 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001156 :py:obj:`X509` takes no arguments and returns an instance of :py:obj:`X509Type`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001157 """
1158 certificate = X509()
1159 self.assertTrue(
1160 isinstance(certificate, X509Type),
1161 "%r is of type %r, should be %r" % (certificate,
1162 type(certificate),
1163 X509Type))
Rick Deane15b1472009-07-09 15:53:42 -05001164 self.assertEqual(type(X509Type).__name__, 'type')
1165 self.assertEqual(type(certificate).__name__, 'X509')
1166 self.assertEqual(type(certificate), X509Type)
Rick Dean04113e72009-07-16 12:06:35 -05001167 self.assertEqual(type(certificate), X509)
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001168
1169
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001170 def test_get_version_wrong_args(self):
1171 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001172 :py:obj:`X509.get_version` raises :py:obj:`TypeError` if invoked with any arguments.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001173 """
1174 cert = X509()
1175 self.assertRaises(TypeError, cert.get_version, None)
1176
1177
1178 def test_set_version_wrong_args(self):
1179 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001180 :py:obj:`X509.set_version` raises :py:obj:`TypeError` if invoked with the wrong number
1181 of arguments or an argument not of type :py:obj:`int`.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001182 """
1183 cert = X509()
1184 self.assertRaises(TypeError, cert.set_version)
1185 self.assertRaises(TypeError, cert.set_version, None)
1186 self.assertRaises(TypeError, cert.set_version, 1, None)
1187
1188
1189 def test_version(self):
1190 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001191 :py:obj:`X509.set_version` sets the certificate version number.
1192 :py:obj:`X509.get_version` retrieves it.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001193 """
1194 cert = X509()
1195 cert.set_version(1234)
1196 self.assertEquals(cert.get_version(), 1234)
1197
1198
1199 def test_get_serial_number_wrong_args(self):
1200 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001201 :py:obj:`X509.get_serial_number` raises :py:obj:`TypeError` if invoked with any
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001202 arguments.
1203 """
1204 cert = X509()
1205 self.assertRaises(TypeError, cert.get_serial_number, None)
1206
1207
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001208 def test_serial_number(self):
1209 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001210 The serial number of an :py:obj:`X509Type` can be retrieved and modified with
1211 :py:obj:`X509Type.get_serial_number` and :py:obj:`X509Type.set_serial_number`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001212 """
1213 certificate = X509()
1214 self.assertRaises(TypeError, certificate.set_serial_number)
1215 self.assertRaises(TypeError, certificate.set_serial_number, 1, 2)
1216 self.assertRaises(TypeError, certificate.set_serial_number, "1")
1217 self.assertRaises(TypeError, certificate.set_serial_number, 5.5)
1218 self.assertEqual(certificate.get_serial_number(), 0)
1219 certificate.set_serial_number(1)
1220 self.assertEqual(certificate.get_serial_number(), 1)
1221 certificate.set_serial_number(2 ** 32 + 1)
1222 self.assertEqual(certificate.get_serial_number(), 2 ** 32 + 1)
1223 certificate.set_serial_number(2 ** 64 + 1)
1224 self.assertEqual(certificate.get_serial_number(), 2 ** 64 + 1)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001225 certificate.set_serial_number(2 ** 128 + 1)
1226 self.assertEqual(certificate.get_serial_number(), 2 ** 128 + 1)
1227
1228
1229 def _setBoundTest(self, which):
1230 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001231 :py:obj:`X509Type.set_notBefore` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001232 GENERALIZEDTIME and sets the beginning of the certificate's validity
1233 period to it.
1234 """
1235 certificate = X509()
1236 set = getattr(certificate, 'set_not' + which)
1237 get = getattr(certificate, 'get_not' + which)
1238
Jean-Paul Calderonee0615b52008-03-09 21:44:46 -04001239 # Starts with no value.
1240 self.assertEqual(get(), None)
1241
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001242 # GMT (Or is it UTC?) -exarkun
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001243 when = b("20040203040506Z")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001244 set(when)
1245 self.assertEqual(get(), when)
1246
1247 # A plus two hours and thirty minutes offset
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001248 when = b("20040203040506+0530")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001249 set(when)
1250 self.assertEqual(get(), when)
1251
1252 # A minus one hour fifteen minutes offset
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001253 when = b("20040203040506-0115")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001254 set(when)
1255 self.assertEqual(get(), when)
1256
1257 # An invalid string results in a ValueError
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001258 self.assertRaises(ValueError, set, b("foo bar"))
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001259
Jean-Paul Calderone31ca2002010-01-30 15:14:43 -05001260 # The wrong number of arguments results in a TypeError.
1261 self.assertRaises(TypeError, set)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001262 self.assertRaises(TypeError, set, b("20040203040506Z"), b("20040203040506Z"))
1263 self.assertRaises(TypeError, get, b("foo bar"))
1264
Jean-Paul Calderone31ca2002010-01-30 15:14:43 -05001265
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001266 # XXX ASN1_TIME (not GENERALIZEDTIME)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001267
1268 def test_set_notBefore(self):
1269 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001270 :py:obj:`X509Type.set_notBefore` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001271 GENERALIZEDTIME and sets the beginning of the certificate's validity
1272 period to it.
1273 """
1274 self._setBoundTest("Before")
1275
1276
1277 def test_set_notAfter(self):
1278 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001279 :py:obj:`X509Type.set_notAfter` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001280 GENERALIZEDTIME and sets the end of the certificate's validity period
1281 to it.
1282 """
1283 self._setBoundTest("After")
Jean-Paul Calderone76576d52008-03-24 16:04:46 -04001284
1285
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001286 def test_get_notBefore(self):
1287 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001288 :py:obj:`X509Type.get_notBefore` returns a string in the format of an ASN1
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001289 GENERALIZEDTIME even for certificates which store it as UTCTIME
1290 internally.
1291 """
Jean-Paul Calderone8114b452008-03-25 15:27:59 -04001292 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001293 self.assertEqual(cert.get_notBefore(), b("20090325123658Z"))
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001294
Rick Dean38a05c82009-07-18 01:41:30 -05001295
1296 def test_get_notAfter(self):
1297 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001298 :py:obj:`X509Type.get_notAfter` returns a string in the format of an ASN1
Rick Dean38a05c82009-07-18 01:41:30 -05001299 GENERALIZEDTIME even for certificates which store it as UTCTIME
1300 internally.
1301 """
1302 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001303 self.assertEqual(cert.get_notAfter(), b("20170611123658Z"))
Rick Dean38a05c82009-07-18 01:41:30 -05001304
1305
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001306 def test_gmtime_adj_notBefore_wrong_args(self):
1307 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001308 :py:obj:`X509Type.gmtime_adj_notBefore` raises :py:obj:`TypeError` if called with the
1309 wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001310 """
1311 cert = X509()
1312 self.assertRaises(TypeError, cert.gmtime_adj_notBefore)
1313 self.assertRaises(TypeError, cert.gmtime_adj_notBefore, None)
1314 self.assertRaises(TypeError, cert.gmtime_adj_notBefore, 123, None)
1315
1316
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001317 def test_gmtime_adj_notBefore(self):
1318 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001319 :py:obj:`X509Type.gmtime_adj_notBefore` changes the not-before timestamp to be
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001320 the current time plus the number of seconds passed in.
1321 """
1322 cert = load_certificate(FILETYPE_PEM, self.pemData)
1323 now = datetime.utcnow() + timedelta(seconds=100)
1324 cert.gmtime_adj_notBefore(100)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001325 self.assertEqual(cert.get_notBefore(), b(now.strftime("%Y%m%d%H%M%SZ")))
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001326
1327
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001328 def test_gmtime_adj_notAfter_wrong_args(self):
1329 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001330 :py:obj:`X509Type.gmtime_adj_notAfter` raises :py:obj:`TypeError` if called with the
1331 wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001332 """
1333 cert = X509()
1334 self.assertRaises(TypeError, cert.gmtime_adj_notAfter)
1335 self.assertRaises(TypeError, cert.gmtime_adj_notAfter, None)
1336 self.assertRaises(TypeError, cert.gmtime_adj_notAfter, 123, None)
1337
1338
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001339 def test_gmtime_adj_notAfter(self):
1340 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001341 :py:obj:`X509Type.gmtime_adj_notAfter` changes the not-after timestamp to be
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001342 the current time plus the number of seconds passed in.
1343 """
1344 cert = load_certificate(FILETYPE_PEM, self.pemData)
1345 now = datetime.utcnow() + timedelta(seconds=100)
1346 cert.gmtime_adj_notAfter(100)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001347 self.assertEqual(cert.get_notAfter(), b(now.strftime("%Y%m%d%H%M%SZ")))
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001348
1349
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001350 def test_has_expired_wrong_args(self):
1351 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001352 :py:obj:`X509Type.has_expired` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001353 arguments.
1354 """
1355 cert = X509()
1356 self.assertRaises(TypeError, cert.has_expired, None)
1357
1358
1359 def test_has_expired(self):
1360 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001361 :py:obj:`X509Type.has_expired` returns :py:obj:`True` if the certificate's not-after
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001362 time is in the past.
1363 """
1364 cert = X509()
1365 cert.gmtime_adj_notAfter(-1)
1366 self.assertTrue(cert.has_expired())
1367
1368
1369 def test_has_not_expired(self):
1370 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001371 :py:obj:`X509Type.has_expired` returns :py:obj:`False` if the certificate's not-after
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001372 time is in the future.
1373 """
1374 cert = X509()
1375 cert.gmtime_adj_notAfter(2)
1376 self.assertFalse(cert.has_expired())
1377
1378
Rick Dean38a05c82009-07-18 01:41:30 -05001379 def test_digest(self):
1380 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001381 :py:obj:`X509.digest` returns a string giving ":"-separated hex-encoded words
Rick Dean38a05c82009-07-18 01:41:30 -05001382 of the digest of the certificate.
1383 """
1384 cert = X509()
1385 self.assertEqual(
1386 cert.digest("md5"),
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001387 b("A8:EB:07:F8:53:25:0A:F2:56:05:C5:A5:C4:C4:C7:15"))
Rick Dean38a05c82009-07-18 01:41:30 -05001388
1389
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001390 def _extcert(self, pkey, extensions):
1391 cert = X509()
1392 cert.set_pubkey(pkey)
1393 cert.get_subject().commonName = "Unit Tests"
1394 cert.get_issuer().commonName = "Unit Tests"
1395 when = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
1396 cert.set_notBefore(when)
1397 cert.set_notAfter(when)
1398
1399 cert.add_extensions(extensions)
1400 return load_certificate(
1401 FILETYPE_PEM, dump_certificate(FILETYPE_PEM, cert))
1402
1403
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001404 def test_extension_count(self):
1405 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001406 :py:obj:`X509.get_extension_count` returns the number of extensions that are
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001407 present in the certificate.
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001408 """
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001409 pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001410 ca = X509Extension(b('basicConstraints'), True, b('CA:FALSE'))
1411 key = X509Extension(b('keyUsage'), True, b('digitalSignature'))
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001412 subjectAltName = X509Extension(
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001413 b('subjectAltName'), True, b('DNS:example.com'))
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001414
1415 # Try a certificate with no extensions at all.
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001416 c = self._extcert(pkey, [])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001417 self.assertEqual(c.get_extension_count(), 0)
1418
1419 # And a certificate with one
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001420 c = self._extcert(pkey, [ca])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001421 self.assertEqual(c.get_extension_count(), 1)
1422
1423 # And a certificate with several
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001424 c = self._extcert(pkey, [ca, key, subjectAltName])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001425 self.assertEqual(c.get_extension_count(), 3)
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001426
1427
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001428 def test_get_extension(self):
1429 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001430 :py:obj:`X509.get_extension` takes an integer and returns an :py:obj:`X509Extension`
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001431 corresponding to the extension at that index.
1432 """
1433 pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001434 ca = X509Extension(b('basicConstraints'), True, b('CA:FALSE'))
1435 key = X509Extension(b('keyUsage'), True, b('digitalSignature'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001436 subjectAltName = X509Extension(
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001437 b('subjectAltName'), False, b('DNS:example.com'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001438
1439 cert = self._extcert(pkey, [ca, key, subjectAltName])
1440
1441 ext = cert.get_extension(0)
1442 self.assertTrue(isinstance(ext, X509Extension))
1443 self.assertTrue(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001444 self.assertEqual(ext.get_short_name(), b('basicConstraints'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001445
1446 ext = cert.get_extension(1)
1447 self.assertTrue(isinstance(ext, X509Extension))
1448 self.assertTrue(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001449 self.assertEqual(ext.get_short_name(), b('keyUsage'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001450
1451 ext = cert.get_extension(2)
1452 self.assertTrue(isinstance(ext, X509Extension))
1453 self.assertFalse(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001454 self.assertEqual(ext.get_short_name(), b('subjectAltName'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001455
1456 self.assertRaises(IndexError, cert.get_extension, -1)
1457 self.assertRaises(IndexError, cert.get_extension, 4)
1458 self.assertRaises(TypeError, cert.get_extension, "hello")
1459
1460
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001461 def test_invalid_digest_algorithm(self):
1462 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001463 :py:obj:`X509.digest` raises :py:obj:`ValueError` if called with an unrecognized hash
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001464 algorithm.
1465 """
1466 cert = X509()
1467 self.assertRaises(ValueError, cert.digest, "monkeys")
1468
1469
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001470 def test_get_subject_wrong_args(self):
1471 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001472 :py:obj:`X509.get_subject` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001473 """
1474 cert = X509()
1475 self.assertRaises(TypeError, cert.get_subject, None)
1476
1477
1478 def test_get_subject(self):
1479 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001480 :py:obj:`X509.get_subject` returns an :py:obj:`X509Name` instance.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001481 """
1482 cert = load_certificate(FILETYPE_PEM, self.pemData)
1483 subj = cert.get_subject()
1484 self.assertTrue(isinstance(subj, X509Name))
1485 self.assertEquals(
1486 subj.get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001487 [(b('C'), b('US')), (b('ST'), b('IL')), (b('L'), b('Chicago')),
1488 (b('O'), b('Testing')), (b('CN'), b('Testing Root CA'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001489
1490
1491 def test_set_subject_wrong_args(self):
1492 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001493 :py:obj:`X509.set_subject` raises a :py:obj:`TypeError` if called with the wrong
1494 number of arguments or an argument not of type :py:obj:`X509Name`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001495 """
1496 cert = X509()
1497 self.assertRaises(TypeError, cert.set_subject)
1498 self.assertRaises(TypeError, cert.set_subject, None)
1499 self.assertRaises(TypeError, cert.set_subject, cert.get_subject(), None)
1500
1501
1502 def test_set_subject(self):
1503 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001504 :py:obj:`X509.set_subject` changes the subject of the certificate to the one
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001505 passed in.
1506 """
1507 cert = X509()
1508 name = cert.get_subject()
1509 name.C = 'AU'
1510 name.O = 'Unit Tests'
1511 cert.set_subject(name)
1512 self.assertEquals(
1513 cert.get_subject().get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001514 [(b('C'), b('AU')), (b('O'), b('Unit Tests'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001515
1516
1517 def test_get_issuer_wrong_args(self):
1518 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001519 :py:obj:`X509.get_issuer` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001520 """
1521 cert = X509()
1522 self.assertRaises(TypeError, cert.get_issuer, None)
1523
1524
1525 def test_get_issuer(self):
1526 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001527 :py:obj:`X509.get_issuer` returns an :py:obj:`X509Name` instance.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001528 """
1529 cert = load_certificate(FILETYPE_PEM, self.pemData)
1530 subj = cert.get_issuer()
1531 self.assertTrue(isinstance(subj, X509Name))
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001532 comp = subj.get_components()
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001533 self.assertEquals(
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001534 comp,
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001535 [(b('C'), b('US')), (b('ST'), b('IL')), (b('L'), b('Chicago')),
1536 (b('O'), b('Testing')), (b('CN'), b('Testing Root CA'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001537
1538
1539 def test_set_issuer_wrong_args(self):
1540 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001541 :py:obj:`X509.set_issuer` raises a :py:obj:`TypeError` if called with the wrong
1542 number of arguments or an argument not of type :py:obj:`X509Name`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001543 """
1544 cert = X509()
1545 self.assertRaises(TypeError, cert.set_issuer)
1546 self.assertRaises(TypeError, cert.set_issuer, None)
1547 self.assertRaises(TypeError, cert.set_issuer, cert.get_issuer(), None)
1548
1549
1550 def test_set_issuer(self):
1551 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001552 :py:obj:`X509.set_issuer` changes the issuer of the certificate to the one
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001553 passed in.
1554 """
1555 cert = X509()
1556 name = cert.get_issuer()
1557 name.C = 'AU'
1558 name.O = 'Unit Tests'
1559 cert.set_issuer(name)
1560 self.assertEquals(
1561 cert.get_issuer().get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001562 [(b('C'), b('AU')), (b('O'), b('Unit Tests'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001563
1564
1565 def test_get_pubkey_uninitialized(self):
1566 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001567 When called on a certificate with no public key, :py:obj:`X509.get_pubkey`
1568 raises :py:obj:`OpenSSL.crypto.Error`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001569 """
1570 cert = X509()
1571 self.assertRaises(Error, cert.get_pubkey)
1572
1573
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001574 def test_subject_name_hash_wrong_args(self):
1575 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001576 :py:obj:`X509.subject_name_hash` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001577 arguments.
1578 """
1579 cert = X509()
1580 self.assertRaises(TypeError, cert.subject_name_hash, None)
1581
1582
1583 def test_subject_name_hash(self):
1584 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001585 :py:obj:`X509.subject_name_hash` returns the hash of the certificate's subject
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001586 name.
1587 """
1588 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -04001589 self.assertIn(
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001590 cert.subject_name_hash(),
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -04001591 [3350047874, # OpenSSL 0.9.8, MD5
1592 3278919224, # OpenSSL 1.0.0, SHA1
1593 ])
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001594
1595
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001596 def test_get_signature_algorithm(self):
1597 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001598 :py:obj:`X509Type.get_signature_algorithm` returns a string which means
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001599 the algorithm used to sign the certificate.
1600 """
1601 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001602 self.assertEqual(
1603 b("sha1WithRSAEncryption"), cert.get_signature_algorithm())
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001604
1605
1606 def test_get_undefined_signature_algorithm(self):
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001607 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001608 :py:obj:`X509Type.get_signature_algorithm` raises :py:obj:`ValueError` if the
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001609 signature algorithm is undefined or unknown.
1610 """
1611 # This certificate has been modified to indicate a bogus OID in the
1612 # signature algorithm field so that OpenSSL does not recognize it.
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001613 certPEM = """\
1614-----BEGIN CERTIFICATE-----
1615MIIC/zCCAmigAwIBAgIBATAGBgJ8BQUAMHsxCzAJBgNVBAYTAlNHMREwDwYDVQQK
1616EwhNMkNyeXB0bzEUMBIGA1UECxMLTTJDcnlwdG8gQ0ExJDAiBgNVBAMTG00yQ3J5
1617cHRvIENlcnRpZmljYXRlIE1hc3RlcjEdMBsGCSqGSIb3DQEJARYObmdwc0Bwb3N0
1618MS5jb20wHhcNMDAwOTEwMDk1MTMwWhcNMDIwOTEwMDk1MTMwWjBTMQswCQYDVQQG
1619EwJTRzERMA8GA1UEChMITTJDcnlwdG8xEjAQBgNVBAMTCWxvY2FsaG9zdDEdMBsG
1620CSqGSIb3DQEJARYObmdwc0Bwb3N0MS5jb20wXDANBgkqhkiG9w0BAQEFAANLADBI
1621AkEArL57d26W9fNXvOhNlZzlPOACmvwOZ5AdNgLzJ1/MfsQQJ7hHVeHmTAjM664V
1622+fXvwUGJLziCeBo1ysWLRnl8CQIDAQABo4IBBDCCAQAwCQYDVR0TBAIwADAsBglg
1623hkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0O
1624BBYEFM+EgpK+eyZiwFU1aOPSbczbPSpVMIGlBgNVHSMEgZ0wgZqAFPuHI2nrnDqT
1625FeXFvylRT/7tKDgBoX+kfTB7MQswCQYDVQQGEwJTRzERMA8GA1UEChMITTJDcnlw
1626dG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtNMkNyeXB0byBDZXJ0
1627aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tggEA
1628MA0GCSqGSIb3DQEBBAUAA4GBADv8KpPo+gfJxN2ERK1Y1l17sz/ZhzoGgm5XCdbx
1629jEY7xKfpQngV599k1xhl11IMqizDwu0855agrckg2MCTmOI9DZzDD77tAYb+Dk0O
1630PEVk0Mk/V0aIsDE9bolfCi/i/QWZ3N8s5nTWMNyBBBmoSliWCm4jkkRZRD0ejgTN
1631tgI5
1632-----END CERTIFICATE-----
1633"""
1634 cert = load_certificate(FILETYPE_PEM, certPEM)
1635 self.assertRaises(ValueError, cert.get_signature_algorithm)
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001636
1637
Rick Dean38a05c82009-07-18 01:41:30 -05001638
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001639class X509StoreTests(TestCase):
1640 """
1641 Test for :py:obj:`OpenSSL.crypto.X509Store`.
1642 """
1643 def test_type(self):
1644 """
1645 :py:obj:`X509StoreType` is a type object.
1646 """
1647 self.assertIdentical(X509Store, X509StoreType)
1648 self.assertConsistentType(X509Store, 'X509Store')
1649
1650
1651 def test_add_cert_wrong_args(self):
1652 store = X509Store()
1653 self.assertRaises(TypeError, store.add_cert)
1654 self.assertRaises(TypeError, store.add_cert, object())
1655 self.assertRaises(TypeError, store.add_cert, X509(), object())
1656
1657
1658 def test_add_cert(self):
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001659 """
1660 :py:obj:`X509Store.add_cert` adds a :py:obj:`X509` instance to the
1661 certificate store.
1662 """
1663 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001664 store = X509Store()
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001665 store.add_cert(cert)
1666
1667
1668 def test_add_cert_rejects_duplicate(self):
1669 """
1670 :py:obj:`X509Store.add_cert` raises :py:obj:`OpenSSL.crypto.Error` if an
1671 attempt is made to add the same certificate to the store more than once.
1672 """
1673 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
1674 store = X509Store()
1675 store.add_cert(cert)
1676 self.assertRaises(Error, store.add_cert, cert)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001677
1678
1679
Rick Dean623ee362009-07-17 12:22:16 -05001680class PKCS12Tests(TestCase):
1681 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001682 Test for :py:obj:`OpenSSL.crypto.PKCS12` and :py:obj:`OpenSSL.crypto.load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001683 """
1684 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
1685
Jean-Paul Calderonec3a41f72009-07-25 12:36:02 -04001686 def test_type(self):
1687 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001688 :py:obj:`PKCS12Type` is a type object.
Jean-Paul Calderonec3a41f72009-07-25 12:36:02 -04001689 """
1690 self.assertIdentical(PKCS12, PKCS12Type)
1691 self.assertConsistentType(PKCS12, 'PKCS12')
1692
1693
Rick Deanf94096c2009-07-18 14:23:06 -05001694 def test_empty_construction(self):
Rick Dean38a05c82009-07-18 01:41:30 -05001695 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001696 :py:obj:`PKCS12` returns a new instance of :py:obj:`PKCS12` with no certificate,
Jean-Paul Calderonedc857b52009-07-25 12:25:07 -04001697 private key, CA certificates, or friendly name.
Rick Dean38a05c82009-07-18 01:41:30 -05001698 """
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001699 p12 = PKCS12()
Rick Dean623ee362009-07-17 12:22:16 -05001700 self.assertEqual(None, p12.get_certificate())
1701 self.assertEqual(None, p12.get_privatekey())
1702 self.assertEqual(None, p12.get_ca_certificates())
Rick Dean42d69e12009-07-20 11:36:08 -05001703 self.assertEqual(None, p12.get_friendlyname())
Rick Dean623ee362009-07-17 12:22:16 -05001704
Rick Dean38a05c82009-07-18 01:41:30 -05001705
Rick Dean623ee362009-07-17 12:22:16 -05001706 def test_type_errors(self):
Rick Dean38a05c82009-07-18 01:41:30 -05001707 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001708 The :py:obj:`PKCS12` setter functions (:py:obj:`set_certificate`, :py:obj:`set_privatekey`,
1709 :py:obj:`set_ca_certificates`, and :py:obj:`set_friendlyname`) raise :py:obj:`TypeError`
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001710 when passed objects of types other than those expected.
Rick Dean38a05c82009-07-18 01:41:30 -05001711 """
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001712 p12 = PKCS12()
Rick Dean623ee362009-07-17 12:22:16 -05001713 self.assertRaises(TypeError, p12.set_certificate, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05001714 self.assertRaises(TypeError, p12.set_certificate, PKey())
1715 self.assertRaises(TypeError, p12.set_certificate, X509)
Rick Dean623ee362009-07-17 12:22:16 -05001716 self.assertRaises(TypeError, p12.set_privatekey, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05001717 self.assertRaises(TypeError, p12.set_privatekey, 'legbone')
1718 self.assertRaises(TypeError, p12.set_privatekey, X509())
Rick Dean623ee362009-07-17 12:22:16 -05001719 self.assertRaises(TypeError, p12.set_ca_certificates, 3)
1720 self.assertRaises(TypeError, p12.set_ca_certificates, X509())
1721 self.assertRaises(TypeError, p12.set_ca_certificates, (3, 4))
Rick Deanf94096c2009-07-18 14:23:06 -05001722 self.assertRaises(TypeError, p12.set_ca_certificates, ( PKey(), ))
Rick Dean42d69e12009-07-20 11:36:08 -05001723 self.assertRaises(TypeError, p12.set_friendlyname, 6)
1724 self.assertRaises(TypeError, p12.set_friendlyname, ('foo', 'bar'))
Rick Dean623ee362009-07-17 12:22:16 -05001725
Rick Dean38a05c82009-07-18 01:41:30 -05001726
Rick Dean623ee362009-07-17 12:22:16 -05001727 def test_key_only(self):
1728 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001729 A :py:obj:`PKCS12` with only a private key can be exported using
1730 :py:obj:`PKCS12.export` and loaded again using :py:obj:`load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001731 """
1732 passwd = 'blah'
1733 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001734 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001735 p12.set_privatekey(pkey)
Rick Dean623ee362009-07-17 12:22:16 -05001736 self.assertEqual(None, p12.get_certificate())
1737 self.assertEqual(pkey, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05001738 try:
1739 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
1740 except Error:
1741 # Some versions of OpenSSL will throw an exception
1742 # for this nearly useless PKCS12 we tried to generate:
1743 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
1744 return
Rick Dean623ee362009-07-17 12:22:16 -05001745 p12 = load_pkcs12(dumped_p12, passwd)
1746 self.assertEqual(None, p12.get_ca_certificates())
1747 self.assertEqual(None, p12.get_certificate())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001748
1749 # OpenSSL fails to bring the key back to us. So sad. Perhaps in the
1750 # future this will be improved.
1751 self.assertTrue(isinstance(p12.get_privatekey(), (PKey, type(None))))
Rick Dean623ee362009-07-17 12:22:16 -05001752
Rick Dean38a05c82009-07-18 01:41:30 -05001753
Rick Dean623ee362009-07-17 12:22:16 -05001754 def test_cert_only(self):
1755 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001756 A :py:obj:`PKCS12` with only a certificate can be exported using
1757 :py:obj:`PKCS12.export` and loaded again using :py:obj:`load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001758 """
1759 passwd = 'blah'
1760 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001761 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001762 p12.set_certificate(cert)
Rick Dean623ee362009-07-17 12:22:16 -05001763 self.assertEqual(cert, p12.get_certificate())
1764 self.assertEqual(None, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05001765 try:
1766 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
1767 except Error:
1768 # Some versions of OpenSSL will throw an exception
1769 # for this nearly useless PKCS12 we tried to generate:
1770 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
1771 return
Rick Dean623ee362009-07-17 12:22:16 -05001772 p12 = load_pkcs12(dumped_p12, passwd)
1773 self.assertEqual(None, p12.get_privatekey())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001774
1775 # OpenSSL fails to bring the cert back to us. Groany mcgroan.
1776 self.assertTrue(isinstance(p12.get_certificate(), (X509, type(None))))
1777
1778 # Oh ho. It puts the certificate into the ca certificates list, in
1779 # fact. Totally bogus, I would think. Nevertheless, let's exploit
1780 # that to check to see if it reconstructed the certificate we expected
1781 # it to. At some point, hopefully this will change so that
1782 # p12.get_certificate() is actually what returns the loaded
1783 # certificate.
1784 self.assertEqual(
1785 cleartextCertificatePEM,
1786 dump_certificate(FILETYPE_PEM, p12.get_ca_certificates()[0]))
Rick Dean623ee362009-07-17 12:22:16 -05001787
1788
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001789 def gen_pkcs12(self, cert_pem=None, key_pem=None, ca_pem=None, friendly_name=None):
Rick Dean623ee362009-07-17 12:22:16 -05001790 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001791 Generate a PKCS12 object with components from PEM. Verify that the set
1792 functions return None.
Rick Dean623ee362009-07-17 12:22:16 -05001793 """
Rick Deanf94096c2009-07-18 14:23:06 -05001794 p12 = PKCS12()
1795 if cert_pem:
1796 ret = p12.set_certificate(load_certificate(FILETYPE_PEM, cert_pem))
1797 self.assertEqual(ret, None)
1798 if key_pem:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001799 ret = p12.set_privatekey(load_privatekey(FILETYPE_PEM, key_pem))
Rick Deanf94096c2009-07-18 14:23:06 -05001800 self.assertEqual(ret, None)
1801 if ca_pem:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001802 ret = p12.set_ca_certificates((load_certificate(FILETYPE_PEM, ca_pem),))
Rick Deanf94096c2009-07-18 14:23:06 -05001803 self.assertEqual(ret, None)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001804 if friendly_name:
1805 ret = p12.set_friendlyname(friendly_name)
Rick Dean42d69e12009-07-20 11:36:08 -05001806 self.assertEqual(ret, None)
Rick Deanf94096c2009-07-18 14:23:06 -05001807 return p12
1808
1809
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001810 def check_recovery(self, p12_str, key=None, cert=None, ca=None, passwd='',
1811 extra=()):
Rick Deanf94096c2009-07-18 14:23:06 -05001812 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001813 Use openssl program to confirm three components are recoverable from a
1814 PKCS12 string.
Rick Deanf94096c2009-07-18 14:23:06 -05001815 """
1816 if key:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001817 recovered_key = _runopenssl(
1818 p12_str, "pkcs12", '-nocerts', '-nodes', '-passin',
1819 'pass:' + passwd, *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001820 self.assertEqual(recovered_key[-len(key):], key)
1821 if cert:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001822 recovered_cert = _runopenssl(
1823 p12_str, "pkcs12", '-clcerts', '-nodes', '-passin',
1824 'pass:' + passwd, '-nokeys', *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001825 self.assertEqual(recovered_cert[-len(cert):], cert)
1826 if ca:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001827 recovered_cert = _runopenssl(
1828 p12_str, "pkcs12", '-cacerts', '-nodes', '-passin',
1829 'pass:' + passwd, '-nokeys', *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001830 self.assertEqual(recovered_cert[-len(ca):], ca)
1831
1832
1833 def test_load_pkcs12(self):
1834 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001835 A PKCS12 string generated using the openssl command line can be loaded
Jonathan Ballet648875f2011-07-16 14:14:58 +09001836 with :py:obj:`load_pkcs12` and its components extracted and examined.
Rick Deanf94096c2009-07-18 14:23:06 -05001837 """
Rick Dean623ee362009-07-17 12:22:16 -05001838 passwd = 'whatever'
1839 pem = client_key_pem + client_cert_pem
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001840 p12_str = _runopenssl(
1841 pem, "pkcs12", '-export', '-clcerts', '-passout', 'pass:' + passwd)
Rick Dean623ee362009-07-17 12:22:16 -05001842 p12 = load_pkcs12(p12_str, passwd)
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001843 # verify
Rick Deanf94096c2009-07-18 14:23:06 -05001844 self.assertTrue(isinstance(p12, PKCS12))
Rick Dean623ee362009-07-17 12:22:16 -05001845 cert_pem = dump_certificate(FILETYPE_PEM, p12.get_certificate())
1846 self.assertEqual(cert_pem, client_cert_pem)
1847 key_pem = dump_privatekey(FILETYPE_PEM, p12.get_privatekey())
1848 self.assertEqual(key_pem, client_key_pem)
1849 self.assertEqual(None, p12.get_ca_certificates())
Rick Deanf94096c2009-07-18 14:23:06 -05001850
Rick Deanee568302009-07-24 09:56:29 -05001851
1852 def test_load_pkcs12_garbage(self):
1853 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001854 :py:obj:`load_pkcs12` raises :py:obj:`OpenSSL.crypto.Error` when passed a string
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001855 which is not a PKCS12 dump.
Rick Deanee568302009-07-24 09:56:29 -05001856 """
1857 passwd = 'whatever'
1858 e = self.assertRaises(Error, load_pkcs12, 'fruit loops', passwd)
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -04001859 self.assertEqual( e.args[0][0][0], 'asn1 encoding routines')
1860 self.assertEqual( len(e.args[0][0]), 3)
Rick Deanee568302009-07-24 09:56:29 -05001861
1862
Rick Deanf94096c2009-07-18 14:23:06 -05001863 def test_replace(self):
1864 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001865 :py:obj:`PKCS12.set_certificate` replaces the certificate in a PKCS12 cluster.
1866 :py:obj:`PKCS12.set_privatekey` replaces the private key.
1867 :py:obj:`PKCS12.set_ca_certificates` replaces the CA certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05001868 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001869 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
1870 p12.set_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1871 p12.set_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001872 root_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05001873 client_cert = load_certificate(FILETYPE_PEM, client_cert_pem)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001874 p12.set_ca_certificates([root_cert]) # not a tuple
Rick Dean623ee362009-07-17 12:22:16 -05001875 self.assertEqual(1, len(p12.get_ca_certificates()))
1876 self.assertEqual(root_cert, p12.get_ca_certificates()[0])
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001877 p12.set_ca_certificates([client_cert, root_cert])
Rick Deanf94096c2009-07-18 14:23:06 -05001878 self.assertEqual(2, len(p12.get_ca_certificates()))
1879 self.assertEqual(client_cert, p12.get_ca_certificates()[0])
1880 self.assertEqual(root_cert, p12.get_ca_certificates()[1])
1881
1882
1883 def test_friendly_name(self):
1884 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04001885 The *friendlyName* of a PKCS12 can be set and retrieved via
Jonathan Ballet648875f2011-07-16 14:14:58 +09001886 :py:obj:`PKCS12.get_friendlyname` and :py:obj:`PKCS12_set_friendlyname`, and a
1887 :py:obj:`PKCS12` with a friendly name set can be dumped with :py:obj:`PKCS12.export`.
Rick Deanf94096c2009-07-18 14:23:06 -05001888 """
Rick Deanf94096c2009-07-18 14:23:06 -05001889 passwd = 'Dogmeat[]{}!@#$%^&*()~`?/.,<>-_+=";:'
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001890 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -04001891 for friendly_name in [b('Serverlicious'), None, b('###')]:
Rick Dean42d69e12009-07-20 11:36:08 -05001892 p12.set_friendlyname(friendly_name)
1893 self.assertEqual(p12.get_friendlyname(), friendly_name)
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001894 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
Rick Dean42d69e12009-07-20 11:36:08 -05001895 reloaded_p12 = load_pkcs12(dumped_p12, passwd)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001896 self.assertEqual(
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -04001897 p12.get_friendlyname(), reloaded_p12.get_friendlyname())
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001898 # We would use the openssl program to confirm the friendly
1899 # name, but it is not possible. The pkcs12 command
1900 # does not store the friendly name in the cert's
Rick Dean42d69e12009-07-20 11:36:08 -05001901 # alias, which we could then extract.
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001902 self.check_recovery(
1903 dumped_p12, key=server_key_pem, cert=server_cert_pem,
1904 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05001905
1906
1907 def test_various_empty_passphrases(self):
1908 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001909 Test that missing, None, and '' passphrases are identical for PKCS12
1910 export.
Rick Deanf94096c2009-07-18 14:23:06 -05001911 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001912 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
Rick Dean623ee362009-07-17 12:22:16 -05001913 passwd = ''
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001914 dumped_p12_empty = p12.export(iter=2, maciter=0, passphrase=passwd)
1915 dumped_p12_none = p12.export(iter=3, maciter=2, passphrase=None)
1916 dumped_p12_nopw = p12.export(iter=9, maciter=4)
1917 for dumped_p12 in [dumped_p12_empty, dumped_p12_none, dumped_p12_nopw]:
1918 self.check_recovery(
1919 dumped_p12, key=client_key_pem, cert=client_cert_pem,
1920 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05001921
1922
1923 def test_removing_ca_cert(self):
1924 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001925 Passing :py:obj:`None` to :py:obj:`PKCS12.set_ca_certificates` removes all CA
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001926 certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05001927 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001928 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
1929 p12.set_ca_certificates(None)
Rick Dean623ee362009-07-17 12:22:16 -05001930 self.assertEqual(None, p12.get_ca_certificates())
Rick Deanf94096c2009-07-18 14:23:06 -05001931
1932
1933 def test_export_without_mac(self):
1934 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04001935 Exporting a PKCS12 with a :py:obj:`maciter` of ``-1`` excludes the MAC
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001936 entirely.
Rick Deanf94096c2009-07-18 14:23:06 -05001937 """
1938 passwd = 'Lake Michigan'
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001939 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Dean623ee362009-07-17 12:22:16 -05001940 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001941 self.check_recovery(
1942 dumped_p12, key=server_key_pem, cert=server_cert_pem,
1943 passwd=passwd, extra=('-nomacver',))
1944
1945
1946 def test_load_without_mac(self):
1947 """
1948 Loading a PKCS12 without a MAC does something other than crash.
1949 """
1950 passwd = 'Lake Michigan'
1951 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
1952 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Rick Dean321a0512009-08-13 17:21:29 -05001953 try:
1954 recovered_p12 = load_pkcs12(dumped_p12, passwd)
1955 # The person who generated this PCKS12 should be flogged,
1956 # or better yet we should have a means to determine
1957 # whether a PCKS12 had a MAC that was verified.
1958 # Anyway, libopenssl chooses to allow it, so the
1959 # pyopenssl binding does as well.
1960 self.assertTrue(isinstance(recovered_p12, PKCS12))
1961 except Error:
1962 # Failing here with an exception is preferred as some openssl
1963 # versions do.
1964 pass
Rick Dean623ee362009-07-17 12:22:16 -05001965
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001966
Rick Dean25bcc1f2009-07-20 11:53:13 -05001967 def test_zero_len_list_for_ca(self):
1968 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04001969 A PKCS12 with an empty CA certificates list can be exported.
Rick Dean25bcc1f2009-07-20 11:53:13 -05001970 """
1971 passwd = 'Hobie 18'
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04001972 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001973 # p12.set_ca_certificates([])
1974 # self.assertEqual((), p12.get_ca_certificates())
1975 # dumped_p12 = p12.export(passphrase=passwd, iter=3)
1976 # self.check_recovery(
1977 # dumped_p12, key=server_key_pem, cert=server_cert_pem,
1978 # passwd=passwd)
Rick Dean25bcc1f2009-07-20 11:53:13 -05001979
1980
Rick Deanf94096c2009-07-18 14:23:06 -05001981 def test_export_without_args(self):
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001982 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001983 All the arguments to :py:obj:`PKCS12.export` are optional.
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001984 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04001985 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05001986 dumped_p12 = p12.export() # no args
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04001987 self.check_recovery(
1988 dumped_p12, key=server_key_pem, cert=server_cert_pem, passwd='')
Rick Deanf94096c2009-07-18 14:23:06 -05001989
1990
1991 def test_key_cert_mismatch(self):
1992 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001993 :py:obj:`PKCS12.export` raises an exception when a key and certificate
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04001994 mismatch.
Rick Deanf94096c2009-07-18 14:23:06 -05001995 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04001996 p12 = self.gen_pkcs12(server_cert_pem, client_key_pem, root_cert_pem)
1997 self.assertRaises(Error, p12.export)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04001998
1999
2000
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002001# These quoting functions taken directly from Twisted's twisted.python.win32.
2002_cmdLineQuoteRe = re.compile(r'(\\*)"')
2003_cmdLineQuoteRe2 = re.compile(r'(\\+)\Z')
2004def cmdLineQuote(s):
2005 """
2006 Internal method for quoting a single command-line argument.
2007
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002008 See http://www.perlmonks.org/?node_id=764004
2009
Jonathan Ballet648875f2011-07-16 14:14:58 +09002010 :type: :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002011 :param s: A single unquoted string to quote for something that is expecting
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002012 cmd.exe-style quoting
2013
Jonathan Ballet648875f2011-07-16 14:14:58 +09002014 :rtype: :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002015 :return: A cmd.exe-style quoted string
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002016 """
2017 s = _cmdLineQuoteRe2.sub(r"\1\1", _cmdLineQuoteRe.sub(r'\1\1\\"', s))
2018 return '"%s"' % s
2019
2020
2021
2022def quoteArguments(arguments):
2023 """
2024 Quote an iterable of command-line arguments for passing to CreateProcess or
Jonathan Ballet648875f2011-07-16 14:14:58 +09002025 a similar API. This allows the list passed to :py:obj:`reactor.spawnProcess` to
2026 match the child process's :py:obj:`sys.argv` properly.
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002027
Jonathan Ballet648875f2011-07-16 14:14:58 +09002028 :type arguments: :py:obj:`iterable` of :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002029 :param arguments: An iterable of unquoted arguments to quote
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002030
Jonathan Ballet648875f2011-07-16 14:14:58 +09002031 :rtype: :py:obj:`str`
2032 :return: A space-delimited string containing quoted versions of :py:obj:`arguments`
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002033 """
2034 return ' '.join(map(cmdLineQuote, arguments))
2035
2036
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002037
Rick Dean4c9ad612009-07-17 15:05:22 -05002038def _runopenssl(pem, *args):
2039 """
2040 Run the command line openssl tool with the given arguments and write
Rick Dean55d1ce62009-08-13 17:40:24 -05002041 the given PEM to its stdin. Not safe for quotes.
Rick Dean4c9ad612009-07-17 15:05:22 -05002042 """
Jean-Paul Calderone038de952009-08-21 12:16:06 -04002043 if os.name == 'posix':
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04002044 command = "openssl " + " ".join([
2045 "'%s'" % (arg.replace("'", "'\\''"),) for arg in args])
Rick Dean55d1ce62009-08-13 17:40:24 -05002046 else:
Jean-Paul Calderone50924502009-08-27 12:47:55 -04002047 command = "openssl " + quoteArguments(args)
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04002048 proc = Popen(command, shell=True, stdin=PIPE, stdout=PIPE)
Jean-Paul Calderone62ca8da2010-08-11 19:58:08 -04002049 proc.stdin.write(pem)
2050 proc.stdin.close()
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002051 output = proc.stdout.read()
2052 proc.stdout.close()
2053 proc.wait()
2054 return output
Rick Dean4c9ad612009-07-17 15:05:22 -05002055
2056
2057
Jean-Paul Calderone18808652009-07-05 12:54:05 -04002058class FunctionTests(TestCase):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002059 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002060 Tests for free-functions in the :py:obj:`OpenSSL.crypto` module.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002061 """
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002062
2063 def test_load_privatekey_invalid_format(self):
2064 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002065 :py:obj:`load_privatekey` raises :py:obj:`ValueError` if passed an unknown filetype.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002066 """
2067 self.assertRaises(ValueError, load_privatekey, 100, root_key_pem)
2068
2069
2070 def test_load_privatekey_invalid_passphrase_type(self):
2071 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002072 :py:obj:`load_privatekey` raises :py:obj:`TypeError` if passed a passphrase that is
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002073 neither a :py:obj:`str` nor a callable.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002074 """
2075 self.assertRaises(
2076 TypeError,
2077 load_privatekey,
2078 FILETYPE_PEM, encryptedPrivateKeyPEMPassphrase, object())
2079
2080
2081 def test_load_privatekey_wrong_args(self):
2082 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002083 :py:obj:`load_privatekey` raises :py:obj:`TypeError` if called with the wrong number
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002084 of arguments.
2085 """
2086 self.assertRaises(TypeError, load_privatekey)
2087
2088
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002089 def test_load_privatekey_wrongPassphrase(self):
2090 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002091 :py:obj:`load_privatekey` raises :py:obj:`OpenSSL.crypto.Error` when it is passed an
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002092 encrypted PEM and an incorrect passphrase.
2093 """
2094 self.assertRaises(
2095 Error,
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002096 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, b("quack"))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002097
2098
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002099 def test_load_privatekey_passphraseWrongType(self):
2100 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002101 :py:obj:`load_privatekey` raises :py:obj:`ValueError` when it is passed a passphrase
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002102 with a private key encoded in a format, that doesn't support
2103 encryption.
2104 """
2105 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2106 blob = dump_privatekey(FILETYPE_ASN1, key)
2107 self.assertRaises(ValueError,
2108 load_privatekey, FILETYPE_ASN1, blob, "secret")
2109
2110
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002111 def test_load_privatekey_passphrase(self):
2112 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002113 :py:obj:`load_privatekey` can create a :py:obj:`PKey` object from an encrypted PEM
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002114 string if given the passphrase.
2115 """
2116 key = load_privatekey(
2117 FILETYPE_PEM, encryptedPrivateKeyPEM,
2118 encryptedPrivateKeyPEMPassphrase)
2119 self.assertTrue(isinstance(key, PKeyType))
2120
2121
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002122 def test_load_privatekey_passphrase_exception(self):
2123 """
2124 If the passphrase callback raises an exception, that exception is raised
2125 by :py:obj:`load_privatekey`.
2126 """
2127 def cb(ignored):
2128 raise ArithmeticError
2129
2130 self.assertRaises(ArithmeticError,
2131 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2132
2133
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002134 def test_load_privatekey_wrongPassphraseCallback(self):
2135 """
Jean-Paul Calderoned440a082011-09-14 11:02:05 -04002136 :py:obj:`load_privatekey` raises :py:obj:`OpenSSL.crypto.Error` when it
2137 is passed an encrypted PEM and a passphrase callback which returns an
2138 incorrect passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002139 """
2140 called = []
2141 def cb(*a):
2142 called.append(None)
Jean-Paul Calderoned440a082011-09-14 11:02:05 -04002143 return b("quack")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002144 self.assertRaises(
2145 Error,
2146 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2147 self.assertTrue(called)
2148
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002149
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002150 def test_load_privatekey_passphraseCallback(self):
2151 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002152 :py:obj:`load_privatekey` can create a :py:obj:`PKey` object from an encrypted PEM
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002153 string if given a passphrase callback which returns the correct
2154 password.
2155 """
2156 called = []
2157 def cb(writing):
2158 called.append(writing)
2159 return encryptedPrivateKeyPEMPassphrase
2160 key = load_privatekey(FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2161 self.assertTrue(isinstance(key, PKeyType))
2162 self.assertEqual(called, [False])
2163
2164
Jean-Paul Calderone105cb952011-09-14 10:16:46 -04002165 def test_load_privatekey_passphrase_wrong_return_type(self):
2166 """
2167 :py:obj:`load_privatekey` raises :py:obj:`ValueError` if the passphrase
2168 callback returns something other than a byte string.
2169 """
2170 self.assertRaises(
2171 ValueError,
2172 load_privatekey,
2173 FILETYPE_PEM, encryptedPrivateKeyPEM, lambda *args: 3)
2174
2175
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002176 def test_dump_privatekey_wrong_args(self):
2177 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002178 :py:obj:`dump_privatekey` raises :py:obj:`TypeError` if called with the wrong number
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002179 of arguments.
2180 """
2181 self.assertRaises(TypeError, dump_privatekey)
Jean-Paul Calderone1eeccd82011-09-14 10:18:52 -04002182 # If cipher name is given, password is required.
2183 self.assertRaises(
2184 ValueError, dump_privatekey, FILETYPE_PEM, PKey(), "foo")
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002185
2186
2187 def test_dump_privatekey_unknown_cipher(self):
2188 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002189 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` if called with an unrecognized
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002190 cipher name.
2191 """
2192 key = PKey()
2193 key.generate_key(TYPE_RSA, 512)
2194 self.assertRaises(
2195 ValueError, dump_privatekey,
2196 FILETYPE_PEM, key, "zippers", "passphrase")
2197
2198
2199 def test_dump_privatekey_invalid_passphrase_type(self):
2200 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002201 :py:obj:`dump_privatekey` raises :py:obj:`TypeError` if called with a passphrase which
2202 is neither a :py:obj:`str` nor a callable.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002203 """
2204 key = PKey()
2205 key.generate_key(TYPE_RSA, 512)
2206 self.assertRaises(
2207 TypeError,
2208 dump_privatekey, FILETYPE_PEM, key, "blowfish", object())
2209
2210
2211 def test_dump_privatekey_invalid_filetype(self):
2212 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002213 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` if called with an unrecognized
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002214 filetype.
2215 """
2216 key = PKey()
2217 key.generate_key(TYPE_RSA, 512)
2218 self.assertRaises(ValueError, dump_privatekey, 100, key)
2219
2220
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002221 def test_load_privatekey_passphraseCallbackLength(self):
2222 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002223 :py:obj:`crypto.load_privatekey` should raise an error when the passphrase
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002224 provided by the callback is too long, not silently truncate it.
2225 """
2226 def cb(ignored):
2227 return "a" * 1025
2228
2229 self.assertRaises(ValueError,
2230 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2231
2232
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002233 def test_dump_privatekey_passphrase(self):
2234 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002235 :py:obj:`dump_privatekey` writes an encrypted PEM when given a passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002236 """
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002237 passphrase = b("foo")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002238 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2239 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002240 self.assertTrue(isinstance(pem, bytes))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002241 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
2242 self.assertTrue(isinstance(loadedKey, PKeyType))
2243 self.assertEqual(loadedKey.type(), key.type())
2244 self.assertEqual(loadedKey.bits(), key.bits())
2245
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002246
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002247 def test_dump_privatekey_passphraseWrongType(self):
2248 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002249 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` when it is passed a passphrase
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002250 with a private key encoded in a format, that doesn't support
2251 encryption.
2252 """
2253 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2254 self.assertRaises(ValueError,
2255 dump_privatekey, FILETYPE_ASN1, key, "blowfish", "secret")
2256
2257
Rick Dean5b7b6372009-04-01 11:34:06 -05002258 def test_dump_certificate(self):
2259 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002260 :py:obj:`dump_certificate` writes PEM, DER, and text.
Rick Dean5b7b6372009-04-01 11:34:06 -05002261 """
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002262 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
Rick Dean5b7b6372009-04-01 11:34:06 -05002263 cert = load_certificate(FILETYPE_PEM, pemData)
2264 dumped_pem = dump_certificate(FILETYPE_PEM, cert)
2265 self.assertEqual(dumped_pem, cleartextCertificatePEM)
2266 dumped_der = dump_certificate(FILETYPE_ASN1, cert)
Rick Dean4c9ad612009-07-17 15:05:22 -05002267 good_der = _runopenssl(dumped_pem, "x509", "-outform", "DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002268 self.assertEqual(dumped_der, good_der)
2269 cert2 = load_certificate(FILETYPE_ASN1, dumped_der)
2270 dumped_pem2 = dump_certificate(FILETYPE_PEM, cert2)
2271 self.assertEqual(dumped_pem2, cleartextCertificatePEM)
2272 dumped_text = dump_certificate(FILETYPE_TEXT, cert)
Rick Dean4c9ad612009-07-17 15:05:22 -05002273 good_text = _runopenssl(dumped_pem, "x509", "-noout", "-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002274 self.assertEqual(dumped_text, good_text)
2275
2276
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002277 def test_dump_privatekey_pem(self):
Rick Dean5b7b6372009-04-01 11:34:06 -05002278 """
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002279 :py:obj:`dump_privatekey` writes a PEM
Rick Dean5b7b6372009-04-01 11:34:06 -05002280 """
2281 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -04002282 self.assertTrue(key.check())
Rick Dean5b7b6372009-04-01 11:34:06 -05002283 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2284 self.assertEqual(dumped_pem, cleartextPrivateKeyPEM)
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002285
2286
2287 def test_dump_privatekey_asn1(self):
2288 """
2289 :py:obj:`dump_privatekey` writes a DER
2290 """
2291 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2292 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2293
Rick Dean5b7b6372009-04-01 11:34:06 -05002294 dumped_der = dump_privatekey(FILETYPE_ASN1, key)
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002295 # XXX This OpenSSL call writes "writing RSA key" to standard out. Sad.
Rick Dean4c9ad612009-07-17 15:05:22 -05002296 good_der = _runopenssl(dumped_pem, "rsa", "-outform", "DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002297 self.assertEqual(dumped_der, good_der)
2298 key2 = load_privatekey(FILETYPE_ASN1, dumped_der)
2299 dumped_pem2 = dump_privatekey(FILETYPE_PEM, key2)
2300 self.assertEqual(dumped_pem2, cleartextPrivateKeyPEM)
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002301
2302
2303 def test_dump_privatekey_text(self):
2304 """
2305 :py:obj:`dump_privatekey` writes a text
2306 """
2307 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2308 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2309
Rick Dean5b7b6372009-04-01 11:34:06 -05002310 dumped_text = dump_privatekey(FILETYPE_TEXT, key)
Rick Dean4c9ad612009-07-17 15:05:22 -05002311 good_text = _runopenssl(dumped_pem, "rsa", "-noout", "-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002312 self.assertEqual(dumped_text, good_text)
2313
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002314
Rick Dean5b7b6372009-04-01 11:34:06 -05002315 def test_dump_certificate_request(self):
2316 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002317 :py:obj:`dump_certificate_request` writes a PEM, DER, and text.
Rick Dean5b7b6372009-04-01 11:34:06 -05002318 """
2319 req = load_certificate_request(FILETYPE_PEM, cleartextCertificateRequestPEM)
2320 dumped_pem = dump_certificate_request(FILETYPE_PEM, req)
2321 self.assertEqual(dumped_pem, cleartextCertificateRequestPEM)
2322 dumped_der = dump_certificate_request(FILETYPE_ASN1, req)
Rick Dean4c9ad612009-07-17 15:05:22 -05002323 good_der = _runopenssl(dumped_pem, "req", "-outform", "DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002324 self.assertEqual(dumped_der, good_der)
2325 req2 = load_certificate_request(FILETYPE_ASN1, dumped_der)
2326 dumped_pem2 = dump_certificate_request(FILETYPE_PEM, req2)
2327 self.assertEqual(dumped_pem2, cleartextCertificateRequestPEM)
2328 dumped_text = dump_certificate_request(FILETYPE_TEXT, req)
Rick Dean4c9ad612009-07-17 15:05:22 -05002329 good_text = _runopenssl(dumped_pem, "req", "-noout", "-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002330 self.assertEqual(dumped_text, good_text)
Jean-Paul Calderoneaf43cdf2010-08-03 18:40:52 -04002331 self.assertRaises(ValueError, dump_certificate_request, 100, req)
Rick Dean5b7b6372009-04-01 11:34:06 -05002332
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002333
2334 def test_dump_privatekey_passphraseCallback(self):
2335 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002336 :py:obj:`dump_privatekey` writes an encrypted PEM when given a callback which
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002337 returns the correct passphrase.
2338 """
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002339 passphrase = b("foo")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002340 called = []
2341 def cb(writing):
2342 called.append(writing)
2343 return passphrase
2344 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2345 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", cb)
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002346 self.assertTrue(isinstance(pem, bytes))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002347 self.assertEqual(called, [True])
2348 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
2349 self.assertTrue(isinstance(loadedKey, PKeyType))
2350 self.assertEqual(loadedKey.type(), key.type())
2351 self.assertEqual(loadedKey.bits(), key.bits())
Rick Dean5b7b6372009-04-01 11:34:06 -05002352
2353
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002354 def test_dump_privatekey_passphrase_exception(self):
2355 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002356 :py:obj:`dump_privatekey` should not overwrite the exception raised
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002357 by the passphrase callback.
2358 """
2359 def cb(ignored):
2360 raise ArithmeticError
2361
2362 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2363 self.assertRaises(ArithmeticError,
2364 dump_privatekey, FILETYPE_PEM, key, "blowfish", cb)
2365
2366
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002367 def test_dump_privatekey_passphraseCallbackLength(self):
2368 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002369 :py:obj:`crypto.dump_privatekey` should raise an error when the passphrase
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002370 provided by the callback is too long, not silently truncate it.
2371 """
2372 def cb(ignored):
2373 return "a" * 1025
2374
2375 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2376 self.assertRaises(ValueError,
2377 dump_privatekey, FILETYPE_PEM, key, "blowfish", cb)
2378
2379
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002380 def test_load_pkcs7_data(self):
2381 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002382 :py:obj:`load_pkcs7_data` accepts a PKCS#7 string and returns an instance of
2383 :py:obj:`PKCS7Type`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002384 """
2385 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2386 self.assertTrue(isinstance(pkcs7, PKCS7Type))
2387
2388
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002389 def test_load_pkcs7_data_invalid(self):
2390 """
2391 If the data passed to :py:obj:`load_pkcs7_data` is invalid,
2392 :py:obj:`Error` is raised.
2393 """
2394 self.assertRaises(Error, load_pkcs7_data, FILETYPE_PEM, "foo")
2395
2396
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002397
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002398class PKCS7Tests(TestCase):
2399 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002400 Tests for :py:obj:`PKCS7Type`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002401 """
2402 def test_type(self):
2403 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002404 :py:obj:`PKCS7Type` is a type object.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002405 """
2406 self.assertTrue(isinstance(PKCS7Type, type))
2407 self.assertEqual(PKCS7Type.__name__, 'PKCS7')
2408
2409 # XXX This doesn't currently work.
2410 # self.assertIdentical(PKCS7, PKCS7Type)
2411
2412
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002413 # XXX Opposite results for all these following methods
2414
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002415 def test_type_is_signed_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002416 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002417 :py:obj:`PKCS7Type.type_is_signed` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002418 arguments.
2419 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002420 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2421 self.assertRaises(TypeError, pkcs7.type_is_signed, None)
2422
2423
2424 def test_type_is_signed(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002425 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002426 :py:obj:`PKCS7Type.type_is_signed` returns :py:obj:`True` if the PKCS7 object is of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002427 the type *signed*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002428 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002429 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2430 self.assertTrue(pkcs7.type_is_signed())
2431
2432
2433 def test_type_is_enveloped_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002434 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002435 :py:obj:`PKCS7Type.type_is_enveloped` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002436 arguments.
2437 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002438 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2439 self.assertRaises(TypeError, pkcs7.type_is_enveloped, None)
2440
2441
2442 def test_type_is_enveloped(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002443 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002444 :py:obj:`PKCS7Type.type_is_enveloped` returns :py:obj:`False` if the PKCS7 object is
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002445 not of the type *enveloped*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002446 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002447 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2448 self.assertFalse(pkcs7.type_is_enveloped())
2449
2450
2451 def test_type_is_signedAndEnveloped_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002452 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002453 :py:obj:`PKCS7Type.type_is_signedAndEnveloped` raises :py:obj:`TypeError` if called
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002454 with any arguments.
2455 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002456 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2457 self.assertRaises(TypeError, pkcs7.type_is_signedAndEnveloped, None)
2458
2459
2460 def test_type_is_signedAndEnveloped(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002461 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002462 :py:obj:`PKCS7Type.type_is_signedAndEnveloped` returns :py:obj:`False` if the PKCS7
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002463 object is not of the type *signed and enveloped*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002464 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002465 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2466 self.assertFalse(pkcs7.type_is_signedAndEnveloped())
2467
2468
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002469 def test_type_is_data(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002470 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002471 :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 -04002472 the type data.
2473 """
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002474 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2475 self.assertFalse(pkcs7.type_is_data())
2476
2477
2478 def test_type_is_data_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002479 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002480 :py:obj:`PKCS7Type.type_is_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002481 arguments.
2482 """
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002483 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2484 self.assertRaises(TypeError, pkcs7.type_is_data, None)
2485
2486
Jean-Paul Calderone97b28ca2010-07-30 10:56:07 -04002487 def test_get_type_name_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002488 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002489 :py:obj:`PKCS7Type.get_type_name` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002490 arguments.
2491 """
Jean-Paul Calderone97b28ca2010-07-30 10:56:07 -04002492 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2493 self.assertRaises(TypeError, pkcs7.get_type_name, None)
2494
2495
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002496 def test_get_type_name(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002497 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002498 :py:obj:`PKCS7Type.get_type_name` returns a :py:obj:`str` giving the type name.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002499 """
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002500 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
Jean-Paul Calderone07640f12010-08-22 17:14:43 -04002501 self.assertEquals(pkcs7.get_type_name(), b('pkcs7-signedData'))
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002502
2503
2504 def test_attribute(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002505 """
2506 If an attribute other than one of the methods tested here is accessed on
Jonathan Ballet648875f2011-07-16 14:14:58 +09002507 an instance of :py:obj:`PKCS7Type`, :py:obj:`AttributeError` is raised.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002508 """
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002509 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2510 self.assertRaises(AttributeError, getattr, pkcs7, "foo")
2511
2512
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002513
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002514class NetscapeSPKITests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002515 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002516 Tests for :py:obj:`OpenSSL.crypto.NetscapeSPKI`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002517 """
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002518 def signable(self):
2519 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002520 Return a new :py:obj:`NetscapeSPKI` for use with signing tests.
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002521 """
2522 return NetscapeSPKI()
2523
2524
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002525 def test_type(self):
2526 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002527 :py:obj:`NetscapeSPKI` and :py:obj:`NetscapeSPKIType` refer to the same type object
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002528 and can be used to create instances of that type.
2529 """
2530 self.assertIdentical(NetscapeSPKI, NetscapeSPKIType)
2531 self.assertConsistentType(NetscapeSPKI, 'NetscapeSPKI')
2532
2533
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002534 def test_construction(self):
2535 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002536 :py:obj:`NetscapeSPKI` returns an instance of :py:obj:`NetscapeSPKIType`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002537 """
2538 nspki = NetscapeSPKI()
2539 self.assertTrue(isinstance(nspki, NetscapeSPKIType))
2540
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002541
Jean-Paul Calderone969efaa2010-08-03 18:19:19 -04002542 def test_invalid_attribute(self):
2543 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002544 Accessing a non-existent attribute of a :py:obj:`NetscapeSPKI` instance causes
2545 an :py:obj:`AttributeError` to be raised.
Jean-Paul Calderone969efaa2010-08-03 18:19:19 -04002546 """
2547 nspki = NetscapeSPKI()
2548 self.assertRaises(AttributeError, lambda: nspki.foo)
2549
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002550
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002551 def test_b64_encode(self):
2552 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002553 :py:obj:`NetscapeSPKI.b64_encode` encodes the certificate to a base64 blob.
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002554 """
2555 nspki = NetscapeSPKI()
2556 blob = nspki.b64_encode()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002557 self.assertTrue(isinstance(blob, bytes))
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002558
2559
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002560
Rick Dean536ba022009-07-24 23:57:27 -05002561class RevokedTests(TestCase):
2562 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002563 Tests for :py:obj:`OpenSSL.crypto.Revoked`
Rick Dean536ba022009-07-24 23:57:27 -05002564 """
2565 def test_construction(self):
2566 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002567 Confirm we can create :py:obj:`OpenSSL.crypto.Revoked`. Check
Rick Dean536ba022009-07-24 23:57:27 -05002568 that it is empty.
2569 """
2570 revoked = Revoked()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002571 self.assertTrue(isinstance(revoked, Revoked))
2572 self.assertEquals(type(revoked), Revoked)
2573 self.assertEquals(revoked.get_serial(), b('00'))
2574 self.assertEquals(revoked.get_rev_date(), None)
2575 self.assertEquals(revoked.get_reason(), None)
Rick Dean536ba022009-07-24 23:57:27 -05002576
2577
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002578 def test_construction_wrong_args(self):
2579 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002580 Calling :py:obj:`OpenSSL.crypto.Revoked` with any arguments results
2581 in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002582 """
2583 self.assertRaises(TypeError, Revoked, None)
2584 self.assertRaises(TypeError, Revoked, 1)
2585 self.assertRaises(TypeError, Revoked, "foo")
2586
2587
Rick Dean536ba022009-07-24 23:57:27 -05002588 def test_serial(self):
2589 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002590 Confirm we can set and get serial numbers from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002591 :py:obj:`OpenSSL.crypto.Revoked`. Confirm errors are handled
Rick Dean536ba022009-07-24 23:57:27 -05002592 with grace.
2593 """
2594 revoked = Revoked()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002595 ret = revoked.set_serial(b('10b'))
2596 self.assertEquals(ret, None)
Rick Dean536ba022009-07-24 23:57:27 -05002597 ser = revoked.get_serial()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002598 self.assertEquals(ser, b('010B'))
Rick Dean536ba022009-07-24 23:57:27 -05002599
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002600 revoked.set_serial(b('31ppp')) # a type error would be nice
Rick Dean536ba022009-07-24 23:57:27 -05002601 ser = revoked.get_serial()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002602 self.assertEquals(ser, b('31'))
Rick Dean536ba022009-07-24 23:57:27 -05002603
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002604 self.assertRaises(ValueError, revoked.set_serial, b('pqrst'))
Rick Dean536ba022009-07-24 23:57:27 -05002605 self.assertRaises(TypeError, revoked.set_serial, 100)
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002606 self.assertRaises(TypeError, revoked.get_serial, 1)
2607 self.assertRaises(TypeError, revoked.get_serial, None)
2608 self.assertRaises(TypeError, revoked.get_serial, "")
Rick Dean536ba022009-07-24 23:57:27 -05002609
2610
2611 def test_date(self):
2612 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002613 Confirm we can set and get revocation dates from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002614 :py:obj:`OpenSSL.crypto.Revoked`. Confirm errors are handled
Rick Dean536ba022009-07-24 23:57:27 -05002615 with grace.
2616 """
2617 revoked = Revoked()
2618 date = revoked.get_rev_date()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002619 self.assertEquals(date, None)
Rick Dean536ba022009-07-24 23:57:27 -05002620
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002621 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05002622 ret = revoked.set_rev_date(now)
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002623 self.assertEqual(ret, None)
Rick Dean536ba022009-07-24 23:57:27 -05002624 date = revoked.get_rev_date()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002625 self.assertEqual(date, now)
Rick Dean536ba022009-07-24 23:57:27 -05002626
2627
Rick Dean6385faf2009-07-26 00:07:47 -05002628 def test_reason(self):
2629 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002630 Confirm we can set and get revocation reasons from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002631 :py:obj:`OpenSSL.crypto.Revoked`. The "get" need to work
Rick Dean6385faf2009-07-26 00:07:47 -05002632 as "set". Likewise, each reason of all_reasons() must work.
2633 """
2634 revoked = Revoked()
2635 for r in revoked.all_reasons():
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002636 for x in range(2):
Rick Dean6385faf2009-07-26 00:07:47 -05002637 ret = revoked.set_reason(r)
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002638 self.assertEquals(ret, None)
Rick Dean6385faf2009-07-26 00:07:47 -05002639 reason = revoked.get_reason()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002640 self.assertEquals(
2641 reason.lower().replace(b(' '), b('')),
2642 r.lower().replace(b(' '), b('')))
Rick Dean6385faf2009-07-26 00:07:47 -05002643 r = reason # again with the resp of get
2644
2645 revoked.set_reason(None)
2646 self.assertEqual(revoked.get_reason(), None)
2647
2648
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002649 def test_set_reason_wrong_arguments(self):
Rick Dean6385faf2009-07-26 00:07:47 -05002650 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002651 Calling :py:obj:`OpenSSL.crypto.Revoked.set_reason` with other than
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002652 one argument, or an argument which isn't a valid reason,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002653 results in :py:obj:`TypeError` or :py:obj:`ValueError` being raised.
Rick Dean6385faf2009-07-26 00:07:47 -05002654 """
2655 revoked = Revoked()
2656 self.assertRaises(TypeError, revoked.set_reason, 100)
Jean-Paul Calderone281b62b2010-08-28 14:22:29 -04002657 self.assertRaises(ValueError, revoked.set_reason, b('blue'))
Rick Dean6385faf2009-07-26 00:07:47 -05002658
Rick Dean536ba022009-07-24 23:57:27 -05002659
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002660 def test_get_reason_wrong_arguments(self):
2661 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002662 Calling :py:obj:`OpenSSL.crypto.Revoked.get_reason` with any
2663 arguments results in :py:obj:`TypeError` being raised.
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002664 """
2665 revoked = Revoked()
2666 self.assertRaises(TypeError, revoked.get_reason, None)
2667 self.assertRaises(TypeError, revoked.get_reason, 1)
2668 self.assertRaises(TypeError, revoked.get_reason, "foo")
2669
2670
2671
Rick Dean536ba022009-07-24 23:57:27 -05002672class CRLTests(TestCase):
2673 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002674 Tests for :py:obj:`OpenSSL.crypto.CRL`
Rick Dean536ba022009-07-24 23:57:27 -05002675 """
2676 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
2677 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2678
2679 def test_construction(self):
2680 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002681 Confirm we can create :py:obj:`OpenSSL.crypto.CRL`. Check
Rick Dean536ba022009-07-24 23:57:27 -05002682 that it is empty
2683 """
2684 crl = CRL()
2685 self.assertTrue( isinstance(crl, CRL) )
2686 self.assertEqual(crl.get_revoked(), None)
2687
2688
Jean-Paul Calderone2efd03e2010-01-30 13:59:55 -05002689 def test_construction_wrong_args(self):
2690 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002691 Calling :py:obj:`OpenSSL.crypto.CRL` with any number of arguments
2692 results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone2efd03e2010-01-30 13:59:55 -05002693 """
2694 self.assertRaises(TypeError, CRL, 1)
2695 self.assertRaises(TypeError, CRL, "")
2696 self.assertRaises(TypeError, CRL, None)
2697
2698
Rick Dean536ba022009-07-24 23:57:27 -05002699 def test_export(self):
2700 """
2701 Use python to create a simple CRL with a revocation, and export
2702 the CRL in formats of PEM, DER and text. Those outputs are verified
2703 with the openssl program.
2704 """
2705 crl = CRL()
2706 revoked = Revoked()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002707 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05002708 revoked.set_rev_date(now)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002709 revoked.set_serial(b('3ab'))
2710 revoked.set_reason(b('sUpErSeDEd'))
Rick Dean536ba022009-07-24 23:57:27 -05002711 crl.add_revoked(revoked)
2712
2713 # PEM format
2714 dumped_crl = crl.export(self.cert, self.pkey, days=20)
2715 text = _runopenssl(dumped_crl, "crl", "-noout", "-text")
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002716 text.index(b('Serial Number: 03AB'))
2717 text.index(b('Superseded'))
2718 text.index(b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA'))
Rick Dean536ba022009-07-24 23:57:27 -05002719
2720 # DER format
2721 dumped_crl = crl.export(self.cert, self.pkey, FILETYPE_ASN1)
2722 text = _runopenssl(dumped_crl, "crl", "-noout", "-text", "-inform", "DER")
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002723 text.index(b('Serial Number: 03AB'))
2724 text.index(b('Superseded'))
2725 text.index(b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA'))
Rick Dean536ba022009-07-24 23:57:27 -05002726
2727 # text format
2728 dumped_text = crl.export(self.cert, self.pkey, type=FILETYPE_TEXT)
2729 self.assertEqual(text, dumped_text)
2730
2731
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -04002732 def test_export_invalid(self):
2733 """
2734 If :py:obj:`CRL.export` is used with an uninitialized :py:obj:`X509`
Jean-Paul Calderoneb5871072012-03-09 14:58:00 -08002735 instance, :py:obj:`OpenSSL.crypto.Error` is raised.
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -04002736 """
2737 crl = CRL()
2738 self.assertRaises(Error, crl.export, X509(), PKey())
2739
2740
Jean-Paul Calderone56515342010-01-30 13:49:38 -05002741 def test_add_revoked_keyword(self):
2742 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002743 :py:obj:`OpenSSL.CRL.add_revoked` accepts its single argument as the
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002744 ``revoked`` keyword argument.
Jean-Paul Calderone56515342010-01-30 13:49:38 -05002745 """
2746 crl = CRL()
2747 revoked = Revoked()
2748 crl.add_revoked(revoked=revoked)
2749 self.assertTrue(isinstance(crl.get_revoked()[0], Revoked))
2750
Rick Dean6385faf2009-07-26 00:07:47 -05002751
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05002752 def test_export_wrong_args(self):
2753 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002754 Calling :py:obj:`OpenSSL.CRL.export` with fewer than two or more than
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05002755 four arguments, or with arguments other than the certificate,
2756 private key, integer file type, and integer number of days it
Jonathan Ballet648875f2011-07-16 14:14:58 +09002757 expects, results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05002758 """
2759 crl = CRL()
2760 self.assertRaises(TypeError, crl.export)
2761 self.assertRaises(TypeError, crl.export, self.cert)
2762 self.assertRaises(TypeError, crl.export, self.cert, self.pkey, FILETYPE_PEM, 10, "foo")
2763
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05002764 self.assertRaises(TypeError, crl.export, None, self.pkey, FILETYPE_PEM, 10)
2765 self.assertRaises(TypeError, crl.export, self.cert, None, FILETYPE_PEM, 10)
2766 self.assertRaises(TypeError, crl.export, self.cert, self.pkey, None, 10)
2767 self.assertRaises(TypeError, crl.export, self.cert, FILETYPE_PEM, None)
2768
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05002769
Jean-Paul Calderoneea198422010-01-30 13:58:23 -05002770 def test_export_unknown_filetype(self):
2771 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002772 Calling :py:obj:`OpenSSL.CRL.export` with a file type other than
2773 :py:obj:`FILETYPE_PEM`, :py:obj:`FILETYPE_ASN1`, or :py:obj:`FILETYPE_TEXT` results
2774 in a :py:obj:`ValueError` being raised.
Jean-Paul Calderoneea198422010-01-30 13:58:23 -05002775 """
2776 crl = CRL()
2777 self.assertRaises(ValueError, crl.export, self.cert, self.pkey, 100, 10)
2778
2779
Rick Dean536ba022009-07-24 23:57:27 -05002780 def test_get_revoked(self):
2781 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002782 Use python to create a simple CRL with two revocations.
Jonathan Ballet648875f2011-07-16 14:14:58 +09002783 Get back the :py:obj:`Revoked` using :py:obj:`OpenSSL.CRL.get_revoked` and
Rick Dean536ba022009-07-24 23:57:27 -05002784 verify them.
2785 """
2786 crl = CRL()
2787
2788 revoked = Revoked()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002789 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05002790 revoked.set_rev_date(now)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002791 revoked.set_serial(b('3ab'))
Rick Dean536ba022009-07-24 23:57:27 -05002792 crl.add_revoked(revoked)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002793 revoked.set_serial(b('100'))
2794 revoked.set_reason(b('sUpErSeDEd'))
Rick Dean536ba022009-07-24 23:57:27 -05002795 crl.add_revoked(revoked)
2796
2797 revs = crl.get_revoked()
2798 self.assertEqual(len(revs), 2)
2799 self.assertEqual(type(revs[0]), Revoked)
2800 self.assertEqual(type(revs[1]), Revoked)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002801 self.assertEqual(revs[0].get_serial(), b('03AB'))
2802 self.assertEqual(revs[1].get_serial(), b('0100'))
Rick Dean536ba022009-07-24 23:57:27 -05002803 self.assertEqual(revs[0].get_rev_date(), now)
2804 self.assertEqual(revs[1].get_rev_date(), now)
2805
2806
Jean-Paul Calderone46bdce42010-01-30 13:44:16 -05002807 def test_get_revoked_wrong_args(self):
2808 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002809 Calling :py:obj:`OpenSSL.CRL.get_revoked` with any arguments results
2810 in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone46bdce42010-01-30 13:44:16 -05002811 """
2812 crl = CRL()
2813 self.assertRaises(TypeError, crl.get_revoked, None)
2814 self.assertRaises(TypeError, crl.get_revoked, 1)
2815 self.assertRaises(TypeError, crl.get_revoked, "")
2816 self.assertRaises(TypeError, crl.get_revoked, "", 1, None)
2817
2818
Jean-Paul Calderoneecef6fa2010-01-30 13:47:18 -05002819 def test_add_revoked_wrong_args(self):
2820 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002821 Calling :py:obj:`OpenSSL.CRL.add_revoked` with other than one
2822 argument results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderoneecef6fa2010-01-30 13:47:18 -05002823 """
2824 crl = CRL()
2825 self.assertRaises(TypeError, crl.add_revoked)
2826 self.assertRaises(TypeError, crl.add_revoked, 1, 2)
2827 self.assertRaises(TypeError, crl.add_revoked, "foo", "bar")
2828
2829
Rick Dean536ba022009-07-24 23:57:27 -05002830 def test_load_crl(self):
2831 """
2832 Load a known CRL and inspect its revocations. Both
2833 PEM and DER formats are loaded.
2834 """
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05002835 crl = load_crl(FILETYPE_PEM, crlData)
Rick Dean536ba022009-07-24 23:57:27 -05002836 revs = crl.get_revoked()
2837 self.assertEqual(len(revs), 2)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002838 self.assertEqual(revs[0].get_serial(), b('03AB'))
Rick Dean6385faf2009-07-26 00:07:47 -05002839 self.assertEqual(revs[0].get_reason(), None)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002840 self.assertEqual(revs[1].get_serial(), b('0100'))
2841 self.assertEqual(revs[1].get_reason(), b('Superseded'))
Rick Dean536ba022009-07-24 23:57:27 -05002842
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05002843 der = _runopenssl(crlData, "crl", "-outform", "DER")
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002844 crl = load_crl(FILETYPE_ASN1, der)
Rick Dean536ba022009-07-24 23:57:27 -05002845 revs = crl.get_revoked()
2846 self.assertEqual(len(revs), 2)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002847 self.assertEqual(revs[0].get_serial(), b('03AB'))
Rick Dean6385faf2009-07-26 00:07:47 -05002848 self.assertEqual(revs[0].get_reason(), None)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002849 self.assertEqual(revs[1].get_serial(), b('0100'))
2850 self.assertEqual(revs[1].get_reason(), b('Superseded'))
Rick Dean536ba022009-07-24 23:57:27 -05002851
2852
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05002853 def test_load_crl_wrong_args(self):
2854 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002855 Calling :py:obj:`OpenSSL.crypto.load_crl` with other than two
2856 arguments results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05002857 """
2858 self.assertRaises(TypeError, load_crl)
2859 self.assertRaises(TypeError, load_crl, FILETYPE_PEM)
2860 self.assertRaises(TypeError, load_crl, FILETYPE_PEM, crlData, None)
2861
2862
2863 def test_load_crl_bad_filetype(self):
2864 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002865 Calling :py:obj:`OpenSSL.crypto.load_crl` with an unknown file type
2866 raises a :py:obj:`ValueError`.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05002867 """
2868 self.assertRaises(ValueError, load_crl, 100, crlData)
2869
2870
2871 def test_load_crl_bad_data(self):
2872 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002873 Calling :py:obj:`OpenSSL.crypto.load_crl` with file data which can't
2874 be loaded raises a :py:obj:`OpenSSL.crypto.Error`.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05002875 """
2876 self.assertRaises(Error, load_crl, FILETYPE_PEM, "hello, world")
2877
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002878
James Yonan7c2e5d32010-02-27 05:45:50 -07002879class SignVerifyTests(TestCase):
2880 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002881 Tests for :py:obj:`OpenSSL.crypto.sign` and :py:obj:`OpenSSL.crypto.verify`.
James Yonan7c2e5d32010-02-27 05:45:50 -07002882 """
2883 def test_sign_verify(self):
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04002884 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002885 :py:obj:`sign` generates a cryptographic signature which :py:obj:`verify` can check.
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04002886 """
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04002887 content = b(
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04002888 "It was a bright cold day in April, and the clocks were striking "
2889 "thirteen. Winston Smith, his chin nuzzled into his breast in an "
2890 "effort to escape the vile wind, slipped quickly through the "
2891 "glass doors of Victory Mansions, though not quickly enough to "
2892 "prevent a swirl of gritty dust from entering along with him.")
2893
2894 # sign the content with this private key
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04002895 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04002896 # verify the content with this cert
2897 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
2898 # certificate unrelated to priv_key, used to trigger an error
2899 bad_cert = load_certificate(FILETYPE_PEM, server_cert_pem)
James Yonan7c2e5d32010-02-27 05:45:50 -07002900
Jean-Paul Calderoned08feb02010-10-12 21:53:24 -04002901 for digest in ['md5', 'sha1']:
James Yonan7c2e5d32010-02-27 05:45:50 -07002902 sig = sign(priv_key, content, digest)
2903
2904 # Verify the signature of content, will throw an exception if error.
2905 verify(good_cert, sig, content, digest)
2906
2907 # This should fail because the certificate doesn't match the
2908 # private key that was used to sign the content.
2909 self.assertRaises(Error, verify, bad_cert, sig, content, digest)
2910
2911 # This should fail because we've "tainted" the content after
2912 # signing it.
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04002913 self.assertRaises(
2914 Error, verify,
2915 good_cert, sig, content + b("tainted"), digest)
James Yonan7c2e5d32010-02-27 05:45:50 -07002916
2917 # test that unknown digest types fail
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04002918 self.assertRaises(
Jean-Paul Calderone9538f142010-10-13 22:13:40 -04002919 ValueError, sign, priv_key, content, "strange-digest")
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04002920 self.assertRaises(
Jean-Paul Calderone9538f142010-10-13 22:13:40 -04002921 ValueError, verify, good_cert, sig, content, "strange-digest")
James Yonan7c2e5d32010-02-27 05:45:50 -07002922
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04002923
Jean-Paul Calderone9828f662010-12-08 22:57:26 -05002924 def test_sign_nulls(self):
2925 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002926 :py:obj:`sign` produces a signature for a string with embedded nulls.
Jean-Paul Calderone9828f662010-12-08 22:57:26 -05002927 """
2928 content = b("Watch out! \0 Did you see it?")
2929 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
2930 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
2931 sig = sign(priv_key, content, "sha1")
2932 verify(good_cert, sig, content, "sha1")
2933
2934
Rick Dean5b7b6372009-04-01 11:34:06 -05002935if __name__ == '__main__':
2936 main()