blob: d461d8b8f3998a43a5b14d0aa457fe22b26ae889 [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 Calderone2aa2b332008-03-06 21:43:14 -050016from OpenSSL.crypto import 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.
700 self.assertRaises(TypeError, setattr, name, None, "hello")
701 self.assertRaises(TypeError, setattr, name, 30, "hello")
702 class evil(str):
703 pass
704 self.assertRaises(TypeError, setattr, name, evil(), "hello")
705
706
707 def test_setInvalidAttribute(self):
708 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900709 Attempting to set any attribute name on an :py:class:`X509NameType` instance for
710 which no corresponding NID is defined causes :py:exc:`AttributeError` to be
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400711 raised.
712 """
713 name = self._x509name()
714 self.assertRaises(AttributeError, setattr, name, "no such thing", None)
715
716
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500717 def test_attributes(self):
718 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900719 :py:class:`X509NameType` instances have attributes for each standard (?)
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500720 X509Name field.
721 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500722 name = self._x509name()
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500723 name.commonName = "foo"
724 self.assertEqual(name.commonName, "foo")
725 self.assertEqual(name.CN, "foo")
726 name.CN = "baz"
727 self.assertEqual(name.commonName, "baz")
728 self.assertEqual(name.CN, "baz")
729 name.commonName = "bar"
730 self.assertEqual(name.commonName, "bar")
731 self.assertEqual(name.CN, "bar")
732 name.CN = "quux"
733 self.assertEqual(name.commonName, "quux")
734 self.assertEqual(name.CN, "quux")
735
736
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500737 def test_copy(self):
738 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900739 :py:class:`X509Name` creates a new :py:class:`X509NameType` instance with all the same
740 attributes as an existing :py:class:`X509NameType` instance when called with
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500741 one.
742 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500743 name = self._x509name(commonName="foo", emailAddress="bar@example.com")
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500744
745 copy = X509Name(name)
746 self.assertEqual(copy.commonName, "foo")
747 self.assertEqual(copy.emailAddress, "bar@example.com")
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500748
749 # Mutate the copy and ensure the original is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500750 copy.commonName = "baz"
751 self.assertEqual(name.commonName, "foo")
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500752
753 # Mutate the original and ensure the copy is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500754 name.emailAddress = "quux@example.com"
755 self.assertEqual(copy.emailAddress, "bar@example.com")
756
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500757
758 def test_repr(self):
759 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900760 :py:func:`repr` passed an :py:class:`X509NameType` instance should return a string
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500761 containing a description of the type and the NIDs which have been set
762 on it.
763 """
764 name = self._x509name(commonName="foo", emailAddress="bar")
765 self.assertEqual(
766 repr(name),
767 "<X509Name object '/emailAddress=bar/CN=foo'>")
768
769
770 def test_comparison(self):
771 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900772 :py:class:`X509NameType` instances should compare based on their NIDs.
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500773 """
774 def _equality(a, b, assertTrue, assertFalse):
775 assertTrue(a == b, "(%r == %r) --> False" % (a, b))
776 assertFalse(a != b)
777 assertTrue(b == a)
778 assertFalse(b != a)
779
780 def assertEqual(a, b):
781 _equality(a, b, self.assertTrue, self.assertFalse)
782
783 # Instances compare equal to themselves.
784 name = self._x509name()
785 assertEqual(name, name)
786
787 # Empty instances should compare equal to each other.
788 assertEqual(self._x509name(), self._x509name())
789
790 # Instances with equal NIDs should compare equal to each other.
791 assertEqual(self._x509name(commonName="foo"),
792 self._x509name(commonName="foo"))
793
794 # Instance with equal NIDs set using different aliases should compare
795 # equal to each other.
796 assertEqual(self._x509name(commonName="foo"),
797 self._x509name(CN="foo"))
798
799 # Instances with more than one NID with the same values should compare
800 # equal to each other.
801 assertEqual(self._x509name(CN="foo", organizationalUnitName="bar"),
802 self._x509name(commonName="foo", OU="bar"))
803
804 def assertNotEqual(a, b):
805 _equality(a, b, self.assertFalse, self.assertTrue)
806
807 # Instances with different values for the same NID should not compare
808 # equal to each other.
809 assertNotEqual(self._x509name(CN="foo"),
810 self._x509name(CN="bar"))
811
812 # Instances with different NIDs should not compare equal to each other.
813 assertNotEqual(self._x509name(CN="foo"),
814 self._x509name(OU="foo"))
815
816 def _inequality(a, b, assertTrue, assertFalse):
817 assertTrue(a < b)
818 assertTrue(a <= b)
819 assertTrue(b > a)
820 assertTrue(b >= a)
821 assertFalse(a > b)
822 assertFalse(a >= b)
823 assertFalse(b < a)
824 assertFalse(b <= a)
825
826 def assertLessThan(a, b):
827 _inequality(a, b, self.assertTrue, self.assertFalse)
828
829 # An X509Name with a NID with a value which sorts less than the value
830 # of the same NID on another X509Name compares less than the other
831 # X509Name.
832 assertLessThan(self._x509name(CN="abc"),
833 self._x509name(CN="def"))
834
835 def assertGreaterThan(a, b):
836 _inequality(a, b, self.assertFalse, self.assertTrue)
837
838 # An X509Name with a NID with a value which sorts greater than the
839 # value of the same NID on another X509Name compares greater than the
840 # other X509Name.
841 assertGreaterThan(self._x509name(CN="def"),
842 self._x509name(CN="abc"))
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -0500843
844
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400845 def test_hash(self):
846 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900847 :py:meth:`X509Name.hash` returns an integer hash based on the value of the
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400848 name.
849 """
850 a = self._x509name(CN="foo")
851 b = self._x509name(CN="foo")
852 self.assertEqual(a.hash(), b.hash())
853 a.CN = "bar"
854 self.assertNotEqual(a.hash(), b.hash())
855
856
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400857 def test_der(self):
858 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900859 :py:meth:`X509Name.der` returns the DER encoded form of the name.
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400860 """
861 a = self._x509name(CN="foo", C="US")
862 self.assertEqual(
863 a.der(),
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -0400864 b('0\x1b1\x0b0\t\x06\x03U\x04\x06\x13\x02US'
865 '1\x0c0\n\x06\x03U\x04\x03\x13\x03foo'))
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400866
867
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400868 def test_get_components(self):
869 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900870 :py:meth:`X509Name.get_components` returns a :py:data:`list` of
871 two-tuples of :py:data:`str`
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400872 giving the NIDs and associated values which make up the name.
873 """
874 a = self._x509name()
875 self.assertEqual(a.get_components(), [])
876 a.CN = "foo"
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -0400877 self.assertEqual(a.get_components(), [(b("CN"), b("foo"))])
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400878 a.organizationalUnitName = "bar"
879 self.assertEqual(
880 a.get_components(),
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -0400881 [(b("CN"), b("foo")), (b("OU"), b("bar"))])
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400882
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400883
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400884class _PKeyInteractionTestsMixin:
885 """
886 Tests which involve another thing and a PKey.
887 """
888 def signable(self):
889 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900890 Return something with a :py:meth:`set_pubkey`, :py:meth:`set_pubkey`,
891 and :py:meth:`sign` method.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400892 """
893 raise NotImplementedError()
894
895
896 def test_signWithUngenerated(self):
897 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900898 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when pass a
899 :py:class:`PKey` with no parts.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400900 """
901 request = self.signable()
902 key = PKey()
903 self.assertRaises(ValueError, request.sign, key, 'MD5')
904
905
906 def test_signWithPublicKey(self):
907 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900908 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when pass a
909 :py:class:`PKey` with no private part as the signing key.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400910 """
911 request = self.signable()
912 key = PKey()
913 key.generate_key(TYPE_RSA, 512)
914 request.set_pubkey(key)
915 pub = request.get_pubkey()
916 self.assertRaises(ValueError, request.sign, pub, 'MD5')
917
918
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -0400919 def test_signWithUnknownDigest(self):
920 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900921 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when passed a digest name which is
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -0400922 not known.
923 """
924 request = self.signable()
925 key = PKey()
926 key.generate_key(TYPE_RSA, 512)
927 self.assertRaises(ValueError, request.sign, key, "monkeys")
928
929
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -0400930 def test_sign(self):
931 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900932 :py:meth:`X509Req.sign` succeeds when passed a private key object and a valid
933 digest function. :py:meth:`X509Req.verify` can be used to check the signature.
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -0400934 """
935 request = self.signable()
936 key = PKey()
937 key.generate_key(TYPE_RSA, 512)
938 request.set_pubkey(key)
939 request.sign(key, 'MD5')
940 # If the type has a verify method, cover that too.
941 if getattr(request, 'verify', None) is not None:
942 pub = request.get_pubkey()
943 self.assertTrue(request.verify(pub))
944 # Make another key that won't verify.
945 key = PKey()
946 key.generate_key(TYPE_RSA, 512)
947 self.assertRaises(Error, request.verify, key)
948
949
950
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400951
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400952class X509ReqTests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -0500953 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900954 Tests for :py:class:`OpenSSL.crypto.X509Req`.
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -0500955 """
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400956 def signable(self):
957 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900958 Create and return a new :py:class:`X509Req`.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400959 """
960 return X509Req()
961
962
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400963 def test_type(self):
964 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900965 :py:obj:`X509Req` and :py:obj:`X509ReqType` refer to the same type object and can be
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400966 used to create instances of that type.
967 """
968 self.assertIdentical(X509Req, X509ReqType)
969 self.assertConsistentType(X509Req, 'X509Req')
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -0500970
971
972 def test_construction(self):
973 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900974 :py:obj:`X509Req` takes no arguments and returns an :py:obj:`X509ReqType` instance.
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -0500975 """
976 request = X509Req()
977 self.assertTrue(
978 isinstance(request, X509ReqType),
979 "%r is of type %r, should be %r" % (request, type(request), X509ReqType))
980
981
Jean-Paul Calderone8dd19b82008-12-28 20:41:16 -0500982 def test_version(self):
983 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900984 :py:obj:`X509ReqType.set_version` sets the X.509 version of the certificate
985 request. :py:obj:`X509ReqType.get_version` returns the X.509 version of
Jean-Paul Calderone8dd19b82008-12-28 20:41:16 -0500986 the certificate request. The initial value of the version is 0.
987 """
988 request = X509Req()
989 self.assertEqual(request.get_version(), 0)
990 request.set_version(1)
991 self.assertEqual(request.get_version(), 1)
992 request.set_version(3)
993 self.assertEqual(request.get_version(), 3)
994
995
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -0400996 def test_version_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -0400997 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900998 :py:obj:`X509ReqType.set_version` raises :py:obj:`TypeError` if called with the wrong
999 number of arguments or with a non-:py:obj:`int` argument.
1000 :py:obj:`X509ReqType.get_version` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001001 arguments.
1002 """
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001003 request = X509Req()
1004 self.assertRaises(TypeError, request.set_version)
1005 self.assertRaises(TypeError, request.set_version, "foo")
1006 self.assertRaises(TypeError, request.set_version, 1, 2)
1007 self.assertRaises(TypeError, request.get_version, None)
1008
1009
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001010 def test_get_subject(self):
1011 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001012 :py:obj:`X509ReqType.get_subject` returns an :py:obj:`X509Name` for the subject of
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001013 the request and which is valid even after the request object is
1014 otherwise dead.
1015 """
1016 request = X509Req()
1017 subject = request.get_subject()
1018 self.assertTrue(
1019 isinstance(subject, X509NameType),
1020 "%r is of type %r, should be %r" % (subject, type(subject), X509NameType))
1021 subject.commonName = "foo"
1022 self.assertEqual(request.get_subject().commonName, "foo")
1023 del request
1024 subject.commonName = "bar"
1025 self.assertEqual(subject.commonName, "bar")
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001026
1027
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001028 def test_get_subject_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001029 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001030 :py:obj:`X509ReqType.get_subject` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001031 arguments.
1032 """
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001033 request = X509Req()
1034 self.assertRaises(TypeError, request.get_subject, None)
1035
1036
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001037 def test_add_extensions(self):
1038 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001039 :py:obj:`X509Req.add_extensions` accepts a :py:obj:`list` of :py:obj:`X509Extension`
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001040 instances and adds them to the X509 request.
1041 """
1042 request = X509Req()
1043 request.add_extensions([
Jean-Paul Calderonee16f9f32010-08-22 19:20:37 -04001044 X509Extension(b('basicConstraints'), True, b('CA:false'))])
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001045 # XXX Add get_extensions so the rest of this unit test can be written.
1046
1047
1048 def test_add_extensions_wrong_args(self):
1049 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001050 :py:obj:`X509Req.add_extensions` raises :py:obj:`TypeError` if called with the wrong
1051 number of arguments or with a non-:py:obj:`list`. Or it raises :py:obj:`ValueError`
1052 if called with a :py:obj:`list` containing objects other than :py:obj:`X509Extension`
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001053 instances.
1054 """
1055 request = X509Req()
1056 self.assertRaises(TypeError, request.add_extensions)
1057 self.assertRaises(TypeError, request.add_extensions, object())
1058 self.assertRaises(ValueError, request.add_extensions, [object()])
1059 self.assertRaises(TypeError, request.add_extensions, [], None)
1060
1061
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001062
Jean-Paul Calderone18808652009-07-05 12:54:05 -04001063class X509Tests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001064 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001065 Tests for :py:obj:`OpenSSL.crypto.X509`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001066 """
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001067 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
Jean-Paul Calderone8114b452008-03-25 15:27:59 -04001068
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001069 extpem = """
1070-----BEGIN CERTIFICATE-----
1071MIIC3jCCAkegAwIBAgIJAJHFjlcCgnQzMA0GCSqGSIb3DQEBBQUAMEcxCzAJBgNV
1072BAYTAlNFMRUwEwYDVQQIEwxXZXN0ZXJib3R0b20xEjAQBgNVBAoTCUNhdGFsb2dp
1073eDENMAsGA1UEAxMEUm9vdDAeFw0wODA0MjIxNDQ1MzhaFw0wOTA0MjIxNDQ1Mzha
1074MFQxCzAJBgNVBAYTAlNFMQswCQYDVQQIEwJXQjEUMBIGA1UEChMLT3Blbk1ldGFk
1075aXIxIjAgBgNVBAMTGW5vZGUxLm9tMi5vcGVubWV0YWRpci5vcmcwgZ8wDQYJKoZI
1076hvcNAQEBBQADgY0AMIGJAoGBAPIcQMrwbk2nESF/0JKibj9i1x95XYAOwP+LarwT
1077Op4EQbdlI9SY+uqYqlERhF19w7CS+S6oyqx0DRZSk4Y9dZ9j9/xgm2u/f136YS1u
1078zgYFPvfUs6PqYLPSM8Bw+SjJ+7+2+TN+Tkiof9WP1cMjodQwOmdsiRbR0/J7+b1B
1079hec1AgMBAAGjgcQwgcEwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNT
1080TCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFIdHsBcMVVMbAO7j6NCj
108103HgLnHaMB8GA1UdIwQYMBaAFL2h9Bf9Mre4vTdOiHTGAt7BRY/8MEYGA1UdEQQ/
1082MD2CDSouZXhhbXBsZS5vcmeCESoub20yLmV4bWFwbGUuY29thwSC7wgKgRNvbTJA
1083b3Blbm1ldGFkaXIub3JnMA0GCSqGSIb3DQEBBQUAA4GBALd7WdXkp2KvZ7/PuWZA
1084MPlIxyjS+Ly11+BNE0xGQRp9Wz+2lABtpgNqssvU156+HkKd02rGheb2tj7MX9hG
1085uZzbwDAZzJPjzDQDD7d3cWsrVcfIdqVU7epHqIadnOF+X0ghJ39pAm6VVadnSXCt
1086WpOdIpB8KksUTCzV591Nr1wd
1087-----END CERTIFICATE-----
1088 """
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001089 def signable(self):
1090 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001091 Create and return a new :py:obj:`X509`.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001092 """
1093 return X509()
1094
1095
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001096 def test_type(self):
1097 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001098 :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 -04001099 to create instances of that type.
1100 """
1101 self.assertIdentical(X509, X509Type)
1102 self.assertConsistentType(X509, 'X509')
1103
1104
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001105 def test_construction(self):
1106 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001107 :py:obj:`X509` takes no arguments and returns an instance of :py:obj:`X509Type`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001108 """
1109 certificate = X509()
1110 self.assertTrue(
1111 isinstance(certificate, X509Type),
1112 "%r is of type %r, should be %r" % (certificate,
1113 type(certificate),
1114 X509Type))
Rick Deane15b1472009-07-09 15:53:42 -05001115 self.assertEqual(type(X509Type).__name__, 'type')
1116 self.assertEqual(type(certificate).__name__, 'X509')
1117 self.assertEqual(type(certificate), X509Type)
Rick Dean04113e72009-07-16 12:06:35 -05001118 self.assertEqual(type(certificate), X509)
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001119
1120
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001121 def test_get_version_wrong_args(self):
1122 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001123 :py:obj:`X509.get_version` raises :py:obj:`TypeError` if invoked with any arguments.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001124 """
1125 cert = X509()
1126 self.assertRaises(TypeError, cert.get_version, None)
1127
1128
1129 def test_set_version_wrong_args(self):
1130 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001131 :py:obj:`X509.set_version` raises :py:obj:`TypeError` if invoked with the wrong number
1132 of arguments or an argument not of type :py:obj:`int`.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001133 """
1134 cert = X509()
1135 self.assertRaises(TypeError, cert.set_version)
1136 self.assertRaises(TypeError, cert.set_version, None)
1137 self.assertRaises(TypeError, cert.set_version, 1, None)
1138
1139
1140 def test_version(self):
1141 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001142 :py:obj:`X509.set_version` sets the certificate version number.
1143 :py:obj:`X509.get_version` retrieves it.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001144 """
1145 cert = X509()
1146 cert.set_version(1234)
1147 self.assertEquals(cert.get_version(), 1234)
1148
1149
1150 def test_get_serial_number_wrong_args(self):
1151 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001152 :py:obj:`X509.get_serial_number` raises :py:obj:`TypeError` if invoked with any
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001153 arguments.
1154 """
1155 cert = X509()
1156 self.assertRaises(TypeError, cert.get_serial_number, None)
1157
1158
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001159 def test_serial_number(self):
1160 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001161 The serial number of an :py:obj:`X509Type` can be retrieved and modified with
1162 :py:obj:`X509Type.get_serial_number` and :py:obj:`X509Type.set_serial_number`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001163 """
1164 certificate = X509()
1165 self.assertRaises(TypeError, certificate.set_serial_number)
1166 self.assertRaises(TypeError, certificate.set_serial_number, 1, 2)
1167 self.assertRaises(TypeError, certificate.set_serial_number, "1")
1168 self.assertRaises(TypeError, certificate.set_serial_number, 5.5)
1169 self.assertEqual(certificate.get_serial_number(), 0)
1170 certificate.set_serial_number(1)
1171 self.assertEqual(certificate.get_serial_number(), 1)
1172 certificate.set_serial_number(2 ** 32 + 1)
1173 self.assertEqual(certificate.get_serial_number(), 2 ** 32 + 1)
1174 certificate.set_serial_number(2 ** 64 + 1)
1175 self.assertEqual(certificate.get_serial_number(), 2 ** 64 + 1)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001176 certificate.set_serial_number(2 ** 128 + 1)
1177 self.assertEqual(certificate.get_serial_number(), 2 ** 128 + 1)
1178
1179
1180 def _setBoundTest(self, which):
1181 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001182 :py:obj:`X509Type.set_notBefore` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001183 GENERALIZEDTIME and sets the beginning of the certificate's validity
1184 period to it.
1185 """
1186 certificate = X509()
1187 set = getattr(certificate, 'set_not' + which)
1188 get = getattr(certificate, 'get_not' + which)
1189
Jean-Paul Calderonee0615b52008-03-09 21:44:46 -04001190 # Starts with no value.
1191 self.assertEqual(get(), None)
1192
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001193 # GMT (Or is it UTC?) -exarkun
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001194 when = b("20040203040506Z")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001195 set(when)
1196 self.assertEqual(get(), when)
1197
1198 # A plus two hours and thirty minutes offset
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001199 when = b("20040203040506+0530")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001200 set(when)
1201 self.assertEqual(get(), when)
1202
1203 # A minus one hour fifteen minutes offset
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001204 when = b("20040203040506-0115")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001205 set(when)
1206 self.assertEqual(get(), when)
1207
1208 # An invalid string results in a ValueError
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001209 self.assertRaises(ValueError, set, b("foo bar"))
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001210
Jean-Paul Calderone31ca2002010-01-30 15:14:43 -05001211 # The wrong number of arguments results in a TypeError.
1212 self.assertRaises(TypeError, set)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001213 self.assertRaises(TypeError, set, b("20040203040506Z"), b("20040203040506Z"))
1214 self.assertRaises(TypeError, get, b("foo bar"))
1215
Jean-Paul Calderone31ca2002010-01-30 15:14:43 -05001216
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001217 # XXX ASN1_TIME (not GENERALIZEDTIME)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001218
1219 def test_set_notBefore(self):
1220 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001221 :py:obj:`X509Type.set_notBefore` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001222 GENERALIZEDTIME and sets the beginning of the certificate's validity
1223 period to it.
1224 """
1225 self._setBoundTest("Before")
1226
1227
1228 def test_set_notAfter(self):
1229 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001230 :py:obj:`X509Type.set_notAfter` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001231 GENERALIZEDTIME and sets the end of the certificate's validity period
1232 to it.
1233 """
1234 self._setBoundTest("After")
Jean-Paul Calderone76576d52008-03-24 16:04:46 -04001235
1236
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001237 def test_get_notBefore(self):
1238 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001239 :py:obj:`X509Type.get_notBefore` returns a string in the format of an ASN1
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001240 GENERALIZEDTIME even for certificates which store it as UTCTIME
1241 internally.
1242 """
Jean-Paul Calderone8114b452008-03-25 15:27:59 -04001243 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001244 self.assertEqual(cert.get_notBefore(), b("20090325123658Z"))
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001245
Rick Dean38a05c82009-07-18 01:41:30 -05001246
1247 def test_get_notAfter(self):
1248 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001249 :py:obj:`X509Type.get_notAfter` returns a string in the format of an ASN1
Rick Dean38a05c82009-07-18 01:41:30 -05001250 GENERALIZEDTIME even for certificates which store it as UTCTIME
1251 internally.
1252 """
1253 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001254 self.assertEqual(cert.get_notAfter(), b("20170611123658Z"))
Rick Dean38a05c82009-07-18 01:41:30 -05001255
1256
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001257 def test_gmtime_adj_notBefore_wrong_args(self):
1258 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001259 :py:obj:`X509Type.gmtime_adj_notBefore` raises :py:obj:`TypeError` if called with the
1260 wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001261 """
1262 cert = X509()
1263 self.assertRaises(TypeError, cert.gmtime_adj_notBefore)
1264 self.assertRaises(TypeError, cert.gmtime_adj_notBefore, None)
1265 self.assertRaises(TypeError, cert.gmtime_adj_notBefore, 123, None)
1266
1267
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001268 def test_gmtime_adj_notBefore(self):
1269 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001270 :py:obj:`X509Type.gmtime_adj_notBefore` changes the not-before timestamp to be
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001271 the current time plus the number of seconds passed in.
1272 """
1273 cert = load_certificate(FILETYPE_PEM, self.pemData)
1274 now = datetime.utcnow() + timedelta(seconds=100)
1275 cert.gmtime_adj_notBefore(100)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001276 self.assertEqual(cert.get_notBefore(), b(now.strftime("%Y%m%d%H%M%SZ")))
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001277
1278
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001279 def test_gmtime_adj_notAfter_wrong_args(self):
1280 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001281 :py:obj:`X509Type.gmtime_adj_notAfter` raises :py:obj:`TypeError` if called with the
1282 wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001283 """
1284 cert = X509()
1285 self.assertRaises(TypeError, cert.gmtime_adj_notAfter)
1286 self.assertRaises(TypeError, cert.gmtime_adj_notAfter, None)
1287 self.assertRaises(TypeError, cert.gmtime_adj_notAfter, 123, None)
1288
1289
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001290 def test_gmtime_adj_notAfter(self):
1291 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001292 :py:obj:`X509Type.gmtime_adj_notAfter` changes the not-after timestamp to be
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001293 the current time plus the number of seconds passed in.
1294 """
1295 cert = load_certificate(FILETYPE_PEM, self.pemData)
1296 now = datetime.utcnow() + timedelta(seconds=100)
1297 cert.gmtime_adj_notAfter(100)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001298 self.assertEqual(cert.get_notAfter(), b(now.strftime("%Y%m%d%H%M%SZ")))
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001299
1300
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001301 def test_has_expired_wrong_args(self):
1302 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001303 :py:obj:`X509Type.has_expired` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001304 arguments.
1305 """
1306 cert = X509()
1307 self.assertRaises(TypeError, cert.has_expired, None)
1308
1309
1310 def test_has_expired(self):
1311 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001312 :py:obj:`X509Type.has_expired` returns :py:obj:`True` if the certificate's not-after
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001313 time is in the past.
1314 """
1315 cert = X509()
1316 cert.gmtime_adj_notAfter(-1)
1317 self.assertTrue(cert.has_expired())
1318
1319
1320 def test_has_not_expired(self):
1321 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001322 :py:obj:`X509Type.has_expired` returns :py:obj:`False` if the certificate's not-after
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001323 time is in the future.
1324 """
1325 cert = X509()
1326 cert.gmtime_adj_notAfter(2)
1327 self.assertFalse(cert.has_expired())
1328
1329
Rick Dean38a05c82009-07-18 01:41:30 -05001330 def test_digest(self):
1331 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001332 :py:obj:`X509.digest` returns a string giving ":"-separated hex-encoded words
Rick Dean38a05c82009-07-18 01:41:30 -05001333 of the digest of the certificate.
1334 """
1335 cert = X509()
1336 self.assertEqual(
1337 cert.digest("md5"),
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001338 b("A8:EB:07:F8:53:25:0A:F2:56:05:C5:A5:C4:C4:C7:15"))
Rick Dean38a05c82009-07-18 01:41:30 -05001339
1340
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001341 def _extcert(self, pkey, extensions):
1342 cert = X509()
1343 cert.set_pubkey(pkey)
1344 cert.get_subject().commonName = "Unit Tests"
1345 cert.get_issuer().commonName = "Unit Tests"
1346 when = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
1347 cert.set_notBefore(when)
1348 cert.set_notAfter(when)
1349
1350 cert.add_extensions(extensions)
1351 return load_certificate(
1352 FILETYPE_PEM, dump_certificate(FILETYPE_PEM, cert))
1353
1354
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001355 def test_extension_count(self):
1356 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001357 :py:obj:`X509.get_extension_count` returns the number of extensions that are
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001358 present in the certificate.
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001359 """
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001360 pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001361 ca = X509Extension(b('basicConstraints'), True, b('CA:FALSE'))
1362 key = X509Extension(b('keyUsage'), True, b('digitalSignature'))
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001363 subjectAltName = X509Extension(
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001364 b('subjectAltName'), True, b('DNS:example.com'))
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001365
1366 # Try a certificate with no extensions at all.
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001367 c = self._extcert(pkey, [])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001368 self.assertEqual(c.get_extension_count(), 0)
1369
1370 # And a certificate with one
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001371 c = self._extcert(pkey, [ca])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001372 self.assertEqual(c.get_extension_count(), 1)
1373
1374 # And a certificate with several
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001375 c = self._extcert(pkey, [ca, key, subjectAltName])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001376 self.assertEqual(c.get_extension_count(), 3)
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001377
1378
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001379 def test_get_extension(self):
1380 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001381 :py:obj:`X509.get_extension` takes an integer and returns an :py:obj:`X509Extension`
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001382 corresponding to the extension at that index.
1383 """
1384 pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001385 ca = X509Extension(b('basicConstraints'), True, b('CA:FALSE'))
1386 key = X509Extension(b('keyUsage'), True, b('digitalSignature'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001387 subjectAltName = X509Extension(
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001388 b('subjectAltName'), False, b('DNS:example.com'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001389
1390 cert = self._extcert(pkey, [ca, key, subjectAltName])
1391
1392 ext = cert.get_extension(0)
1393 self.assertTrue(isinstance(ext, X509Extension))
1394 self.assertTrue(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001395 self.assertEqual(ext.get_short_name(), b('basicConstraints'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001396
1397 ext = cert.get_extension(1)
1398 self.assertTrue(isinstance(ext, X509Extension))
1399 self.assertTrue(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001400 self.assertEqual(ext.get_short_name(), b('keyUsage'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001401
1402 ext = cert.get_extension(2)
1403 self.assertTrue(isinstance(ext, X509Extension))
1404 self.assertFalse(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001405 self.assertEqual(ext.get_short_name(), b('subjectAltName'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001406
1407 self.assertRaises(IndexError, cert.get_extension, -1)
1408 self.assertRaises(IndexError, cert.get_extension, 4)
1409 self.assertRaises(TypeError, cert.get_extension, "hello")
1410
1411
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001412 def test_invalid_digest_algorithm(self):
1413 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001414 :py:obj:`X509.digest` raises :py:obj:`ValueError` if called with an unrecognized hash
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001415 algorithm.
1416 """
1417 cert = X509()
1418 self.assertRaises(ValueError, cert.digest, "monkeys")
1419
1420
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001421 def test_get_subject_wrong_args(self):
1422 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001423 :py:obj:`X509.get_subject` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001424 """
1425 cert = X509()
1426 self.assertRaises(TypeError, cert.get_subject, None)
1427
1428
1429 def test_get_subject(self):
1430 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001431 :py:obj:`X509.get_subject` returns an :py:obj:`X509Name` instance.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001432 """
1433 cert = load_certificate(FILETYPE_PEM, self.pemData)
1434 subj = cert.get_subject()
1435 self.assertTrue(isinstance(subj, X509Name))
1436 self.assertEquals(
1437 subj.get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001438 [(b('C'), b('US')), (b('ST'), b('IL')), (b('L'), b('Chicago')),
1439 (b('O'), b('Testing')), (b('CN'), b('Testing Root CA'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001440
1441
1442 def test_set_subject_wrong_args(self):
1443 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001444 :py:obj:`X509.set_subject` raises a :py:obj:`TypeError` if called with the wrong
1445 number of arguments or an argument not of type :py:obj:`X509Name`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001446 """
1447 cert = X509()
1448 self.assertRaises(TypeError, cert.set_subject)
1449 self.assertRaises(TypeError, cert.set_subject, None)
1450 self.assertRaises(TypeError, cert.set_subject, cert.get_subject(), None)
1451
1452
1453 def test_set_subject(self):
1454 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001455 :py:obj:`X509.set_subject` changes the subject of the certificate to the one
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001456 passed in.
1457 """
1458 cert = X509()
1459 name = cert.get_subject()
1460 name.C = 'AU'
1461 name.O = 'Unit Tests'
1462 cert.set_subject(name)
1463 self.assertEquals(
1464 cert.get_subject().get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001465 [(b('C'), b('AU')), (b('O'), b('Unit Tests'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001466
1467
1468 def test_get_issuer_wrong_args(self):
1469 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001470 :py:obj:`X509.get_issuer` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001471 """
1472 cert = X509()
1473 self.assertRaises(TypeError, cert.get_issuer, None)
1474
1475
1476 def test_get_issuer(self):
1477 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001478 :py:obj:`X509.get_issuer` returns an :py:obj:`X509Name` instance.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001479 """
1480 cert = load_certificate(FILETYPE_PEM, self.pemData)
1481 subj = cert.get_issuer()
1482 self.assertTrue(isinstance(subj, X509Name))
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001483 comp = subj.get_components()
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001484 self.assertEquals(
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001485 comp,
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001486 [(b('C'), b('US')), (b('ST'), b('IL')), (b('L'), b('Chicago')),
1487 (b('O'), b('Testing')), (b('CN'), b('Testing Root CA'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001488
1489
1490 def test_set_issuer_wrong_args(self):
1491 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001492 :py:obj:`X509.set_issuer` raises a :py:obj:`TypeError` if called with the wrong
1493 number of arguments or an argument not of type :py:obj:`X509Name`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001494 """
1495 cert = X509()
1496 self.assertRaises(TypeError, cert.set_issuer)
1497 self.assertRaises(TypeError, cert.set_issuer, None)
1498 self.assertRaises(TypeError, cert.set_issuer, cert.get_issuer(), None)
1499
1500
1501 def test_set_issuer(self):
1502 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001503 :py:obj:`X509.set_issuer` changes the issuer of the certificate to the one
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001504 passed in.
1505 """
1506 cert = X509()
1507 name = cert.get_issuer()
1508 name.C = 'AU'
1509 name.O = 'Unit Tests'
1510 cert.set_issuer(name)
1511 self.assertEquals(
1512 cert.get_issuer().get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001513 [(b('C'), b('AU')), (b('O'), b('Unit Tests'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001514
1515
1516 def test_get_pubkey_uninitialized(self):
1517 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001518 When called on a certificate with no public key, :py:obj:`X509.get_pubkey`
1519 raises :py:obj:`OpenSSL.crypto.Error`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001520 """
1521 cert = X509()
1522 self.assertRaises(Error, cert.get_pubkey)
1523
1524
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001525 def test_subject_name_hash_wrong_args(self):
1526 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001527 :py:obj:`X509.subject_name_hash` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001528 arguments.
1529 """
1530 cert = X509()
1531 self.assertRaises(TypeError, cert.subject_name_hash, None)
1532
1533
1534 def test_subject_name_hash(self):
1535 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001536 :py:obj:`X509.subject_name_hash` returns the hash of the certificate's subject
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001537 name.
1538 """
1539 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -04001540 self.assertIn(
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001541 cert.subject_name_hash(),
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -04001542 [3350047874, # OpenSSL 0.9.8, MD5
1543 3278919224, # OpenSSL 1.0.0, SHA1
1544 ])
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001545
1546
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001547 def test_get_signature_algorithm(self):
1548 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001549 :py:obj:`X509Type.get_signature_algorithm` returns a string which means
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001550 the algorithm used to sign the certificate.
1551 """
1552 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001553 self.assertEqual(
1554 b("sha1WithRSAEncryption"), cert.get_signature_algorithm())
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001555
1556
1557 def test_get_undefined_signature_algorithm(self):
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001558 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001559 :py:obj:`X509Type.get_signature_algorithm` raises :py:obj:`ValueError` if the
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001560 signature algorithm is undefined or unknown.
1561 """
1562 # This certificate has been modified to indicate a bogus OID in the
1563 # signature algorithm field so that OpenSSL does not recognize it.
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001564 certPEM = """\
1565-----BEGIN CERTIFICATE-----
1566MIIC/zCCAmigAwIBAgIBATAGBgJ8BQUAMHsxCzAJBgNVBAYTAlNHMREwDwYDVQQK
1567EwhNMkNyeXB0bzEUMBIGA1UECxMLTTJDcnlwdG8gQ0ExJDAiBgNVBAMTG00yQ3J5
1568cHRvIENlcnRpZmljYXRlIE1hc3RlcjEdMBsGCSqGSIb3DQEJARYObmdwc0Bwb3N0
1569MS5jb20wHhcNMDAwOTEwMDk1MTMwWhcNMDIwOTEwMDk1MTMwWjBTMQswCQYDVQQG
1570EwJTRzERMA8GA1UEChMITTJDcnlwdG8xEjAQBgNVBAMTCWxvY2FsaG9zdDEdMBsG
1571CSqGSIb3DQEJARYObmdwc0Bwb3N0MS5jb20wXDANBgkqhkiG9w0BAQEFAANLADBI
1572AkEArL57d26W9fNXvOhNlZzlPOACmvwOZ5AdNgLzJ1/MfsQQJ7hHVeHmTAjM664V
1573+fXvwUGJLziCeBo1ysWLRnl8CQIDAQABo4IBBDCCAQAwCQYDVR0TBAIwADAsBglg
1574hkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0O
1575BBYEFM+EgpK+eyZiwFU1aOPSbczbPSpVMIGlBgNVHSMEgZ0wgZqAFPuHI2nrnDqT
1576FeXFvylRT/7tKDgBoX+kfTB7MQswCQYDVQQGEwJTRzERMA8GA1UEChMITTJDcnlw
1577dG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtNMkNyeXB0byBDZXJ0
1578aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tggEA
1579MA0GCSqGSIb3DQEBBAUAA4GBADv8KpPo+gfJxN2ERK1Y1l17sz/ZhzoGgm5XCdbx
1580jEY7xKfpQngV599k1xhl11IMqizDwu0855agrckg2MCTmOI9DZzDD77tAYb+Dk0O
1581PEVk0Mk/V0aIsDE9bolfCi/i/QWZ3N8s5nTWMNyBBBmoSliWCm4jkkRZRD0ejgTN
1582tgI5
1583-----END CERTIFICATE-----
1584"""
1585 cert = load_certificate(FILETYPE_PEM, certPEM)
1586 self.assertRaises(ValueError, cert.get_signature_algorithm)
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001587
1588
Rick Dean38a05c82009-07-18 01:41:30 -05001589
Rick Dean623ee362009-07-17 12:22:16 -05001590class PKCS12Tests(TestCase):
1591 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001592 Test for :py:obj:`OpenSSL.crypto.PKCS12` and :py:obj:`OpenSSL.crypto.load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001593 """
1594 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
1595
Jean-Paul Calderonec3a41f72009-07-25 12:36:02 -04001596 def test_type(self):
1597 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001598 :py:obj:`PKCS12Type` is a type object.
Jean-Paul Calderonec3a41f72009-07-25 12:36:02 -04001599 """
1600 self.assertIdentical(PKCS12, PKCS12Type)
1601 self.assertConsistentType(PKCS12, 'PKCS12')
1602
1603
Rick Deanf94096c2009-07-18 14:23:06 -05001604 def test_empty_construction(self):
Rick Dean38a05c82009-07-18 01:41:30 -05001605 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001606 :py:obj:`PKCS12` returns a new instance of :py:obj:`PKCS12` with no certificate,
Jean-Paul Calderonedc857b52009-07-25 12:25:07 -04001607 private key, CA certificates, or friendly name.
Rick Dean38a05c82009-07-18 01:41:30 -05001608 """
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001609 p12 = PKCS12()
Rick Dean623ee362009-07-17 12:22:16 -05001610 self.assertEqual(None, p12.get_certificate())
1611 self.assertEqual(None, p12.get_privatekey())
1612 self.assertEqual(None, p12.get_ca_certificates())
Rick Dean42d69e12009-07-20 11:36:08 -05001613 self.assertEqual(None, p12.get_friendlyname())
Rick Dean623ee362009-07-17 12:22:16 -05001614
Rick Dean38a05c82009-07-18 01:41:30 -05001615
Rick Dean623ee362009-07-17 12:22:16 -05001616 def test_type_errors(self):
Rick Dean38a05c82009-07-18 01:41:30 -05001617 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001618 The :py:obj:`PKCS12` setter functions (:py:obj:`set_certificate`, :py:obj:`set_privatekey`,
1619 :py:obj:`set_ca_certificates`, and :py:obj:`set_friendlyname`) raise :py:obj:`TypeError`
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001620 when passed objects of types other than those expected.
Rick Dean38a05c82009-07-18 01:41:30 -05001621 """
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001622 p12 = PKCS12()
Rick Dean623ee362009-07-17 12:22:16 -05001623 self.assertRaises(TypeError, p12.set_certificate, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05001624 self.assertRaises(TypeError, p12.set_certificate, PKey())
1625 self.assertRaises(TypeError, p12.set_certificate, X509)
Rick Dean623ee362009-07-17 12:22:16 -05001626 self.assertRaises(TypeError, p12.set_privatekey, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05001627 self.assertRaises(TypeError, p12.set_privatekey, 'legbone')
1628 self.assertRaises(TypeError, p12.set_privatekey, X509())
Rick Dean623ee362009-07-17 12:22:16 -05001629 self.assertRaises(TypeError, p12.set_ca_certificates, 3)
1630 self.assertRaises(TypeError, p12.set_ca_certificates, X509())
1631 self.assertRaises(TypeError, p12.set_ca_certificates, (3, 4))
Rick Deanf94096c2009-07-18 14:23:06 -05001632 self.assertRaises(TypeError, p12.set_ca_certificates, ( PKey(), ))
Rick Dean42d69e12009-07-20 11:36:08 -05001633 self.assertRaises(TypeError, p12.set_friendlyname, 6)
1634 self.assertRaises(TypeError, p12.set_friendlyname, ('foo', 'bar'))
Rick Dean623ee362009-07-17 12:22:16 -05001635
Rick Dean38a05c82009-07-18 01:41:30 -05001636
Rick Dean623ee362009-07-17 12:22:16 -05001637 def test_key_only(self):
1638 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001639 A :py:obj:`PKCS12` with only a private key can be exported using
1640 :py:obj:`PKCS12.export` and loaded again using :py:obj:`load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001641 """
1642 passwd = 'blah'
1643 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001644 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001645 p12.set_privatekey(pkey)
Rick Dean623ee362009-07-17 12:22:16 -05001646 self.assertEqual(None, p12.get_certificate())
1647 self.assertEqual(pkey, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05001648 try:
1649 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
1650 except Error:
1651 # Some versions of OpenSSL will throw an exception
1652 # for this nearly useless PKCS12 we tried to generate:
1653 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
1654 return
Rick Dean623ee362009-07-17 12:22:16 -05001655 p12 = load_pkcs12(dumped_p12, passwd)
1656 self.assertEqual(None, p12.get_ca_certificates())
1657 self.assertEqual(None, p12.get_certificate())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001658
1659 # OpenSSL fails to bring the key back to us. So sad. Perhaps in the
1660 # future this will be improved.
1661 self.assertTrue(isinstance(p12.get_privatekey(), (PKey, type(None))))
Rick Dean623ee362009-07-17 12:22:16 -05001662
Rick Dean38a05c82009-07-18 01:41:30 -05001663
Rick Dean623ee362009-07-17 12:22:16 -05001664 def test_cert_only(self):
1665 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001666 A :py:obj:`PKCS12` with only a certificate can be exported using
1667 :py:obj:`PKCS12.export` and loaded again using :py:obj:`load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001668 """
1669 passwd = 'blah'
1670 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001671 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001672 p12.set_certificate(cert)
Rick Dean623ee362009-07-17 12:22:16 -05001673 self.assertEqual(cert, p12.get_certificate())
1674 self.assertEqual(None, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05001675 try:
1676 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
1677 except Error:
1678 # Some versions of OpenSSL will throw an exception
1679 # for this nearly useless PKCS12 we tried to generate:
1680 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
1681 return
Rick Dean623ee362009-07-17 12:22:16 -05001682 p12 = load_pkcs12(dumped_p12, passwd)
1683 self.assertEqual(None, p12.get_privatekey())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001684
1685 # OpenSSL fails to bring the cert back to us. Groany mcgroan.
1686 self.assertTrue(isinstance(p12.get_certificate(), (X509, type(None))))
1687
1688 # Oh ho. It puts the certificate into the ca certificates list, in
1689 # fact. Totally bogus, I would think. Nevertheless, let's exploit
1690 # that to check to see if it reconstructed the certificate we expected
1691 # it to. At some point, hopefully this will change so that
1692 # p12.get_certificate() is actually what returns the loaded
1693 # certificate.
1694 self.assertEqual(
1695 cleartextCertificatePEM,
1696 dump_certificate(FILETYPE_PEM, p12.get_ca_certificates()[0]))
Rick Dean623ee362009-07-17 12:22:16 -05001697
1698
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001699 def gen_pkcs12(self, cert_pem=None, key_pem=None, ca_pem=None, friendly_name=None):
Rick Dean623ee362009-07-17 12:22:16 -05001700 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001701 Generate a PKCS12 object with components from PEM. Verify that the set
1702 functions return None.
Rick Dean623ee362009-07-17 12:22:16 -05001703 """
Rick Deanf94096c2009-07-18 14:23:06 -05001704 p12 = PKCS12()
1705 if cert_pem:
1706 ret = p12.set_certificate(load_certificate(FILETYPE_PEM, cert_pem))
1707 self.assertEqual(ret, None)
1708 if key_pem:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001709 ret = p12.set_privatekey(load_privatekey(FILETYPE_PEM, key_pem))
Rick Deanf94096c2009-07-18 14:23:06 -05001710 self.assertEqual(ret, None)
1711 if ca_pem:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001712 ret = p12.set_ca_certificates((load_certificate(FILETYPE_PEM, ca_pem),))
Rick Deanf94096c2009-07-18 14:23:06 -05001713 self.assertEqual(ret, None)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001714 if friendly_name:
1715 ret = p12.set_friendlyname(friendly_name)
Rick Dean42d69e12009-07-20 11:36:08 -05001716 self.assertEqual(ret, None)
Rick Deanf94096c2009-07-18 14:23:06 -05001717 return p12
1718
1719
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001720 def check_recovery(self, p12_str, key=None, cert=None, ca=None, passwd='',
1721 extra=()):
Rick Deanf94096c2009-07-18 14:23:06 -05001722 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001723 Use openssl program to confirm three components are recoverable from a
1724 PKCS12 string.
Rick Deanf94096c2009-07-18 14:23:06 -05001725 """
1726 if key:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001727 recovered_key = _runopenssl(
1728 p12_str, "pkcs12", '-nocerts', '-nodes', '-passin',
1729 'pass:' + passwd, *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001730 self.assertEqual(recovered_key[-len(key):], key)
1731 if cert:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001732 recovered_cert = _runopenssl(
1733 p12_str, "pkcs12", '-clcerts', '-nodes', '-passin',
1734 'pass:' + passwd, '-nokeys', *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001735 self.assertEqual(recovered_cert[-len(cert):], cert)
1736 if ca:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001737 recovered_cert = _runopenssl(
1738 p12_str, "pkcs12", '-cacerts', '-nodes', '-passin',
1739 'pass:' + passwd, '-nokeys', *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001740 self.assertEqual(recovered_cert[-len(ca):], ca)
1741
1742
1743 def test_load_pkcs12(self):
1744 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001745 A PKCS12 string generated using the openssl command line can be loaded
Jonathan Ballet648875f2011-07-16 14:14:58 +09001746 with :py:obj:`load_pkcs12` and its components extracted and examined.
Rick Deanf94096c2009-07-18 14:23:06 -05001747 """
Rick Dean623ee362009-07-17 12:22:16 -05001748 passwd = 'whatever'
1749 pem = client_key_pem + client_cert_pem
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001750 p12_str = _runopenssl(
1751 pem, "pkcs12", '-export', '-clcerts', '-passout', 'pass:' + passwd)
Rick Dean623ee362009-07-17 12:22:16 -05001752 p12 = load_pkcs12(p12_str, passwd)
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001753 # verify
Rick Deanf94096c2009-07-18 14:23:06 -05001754 self.assertTrue(isinstance(p12, PKCS12))
Rick Dean623ee362009-07-17 12:22:16 -05001755 cert_pem = dump_certificate(FILETYPE_PEM, p12.get_certificate())
1756 self.assertEqual(cert_pem, client_cert_pem)
1757 key_pem = dump_privatekey(FILETYPE_PEM, p12.get_privatekey())
1758 self.assertEqual(key_pem, client_key_pem)
1759 self.assertEqual(None, p12.get_ca_certificates())
Rick Deanf94096c2009-07-18 14:23:06 -05001760
Rick Deanee568302009-07-24 09:56:29 -05001761
1762 def test_load_pkcs12_garbage(self):
1763 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001764 :py:obj:`load_pkcs12` raises :py:obj:`OpenSSL.crypto.Error` when passed a string
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001765 which is not a PKCS12 dump.
Rick Deanee568302009-07-24 09:56:29 -05001766 """
1767 passwd = 'whatever'
1768 e = self.assertRaises(Error, load_pkcs12, 'fruit loops', passwd)
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -04001769 self.assertEqual( e.args[0][0][0], 'asn1 encoding routines')
1770 self.assertEqual( len(e.args[0][0]), 3)
Rick Deanee568302009-07-24 09:56:29 -05001771
1772
Rick Deanf94096c2009-07-18 14:23:06 -05001773 def test_replace(self):
1774 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001775 :py:obj:`PKCS12.set_certificate` replaces the certificate in a PKCS12 cluster.
1776 :py:obj:`PKCS12.set_privatekey` replaces the private key.
1777 :py:obj:`PKCS12.set_ca_certificates` replaces the CA certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05001778 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001779 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
1780 p12.set_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1781 p12.set_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001782 root_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05001783 client_cert = load_certificate(FILETYPE_PEM, client_cert_pem)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001784 p12.set_ca_certificates([root_cert]) # not a tuple
Rick Dean623ee362009-07-17 12:22:16 -05001785 self.assertEqual(1, len(p12.get_ca_certificates()))
1786 self.assertEqual(root_cert, p12.get_ca_certificates()[0])
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001787 p12.set_ca_certificates([client_cert, root_cert])
Rick Deanf94096c2009-07-18 14:23:06 -05001788 self.assertEqual(2, len(p12.get_ca_certificates()))
1789 self.assertEqual(client_cert, p12.get_ca_certificates()[0])
1790 self.assertEqual(root_cert, p12.get_ca_certificates()[1])
1791
1792
1793 def test_friendly_name(self):
1794 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04001795 The *friendlyName* of a PKCS12 can be set and retrieved via
Jonathan Ballet648875f2011-07-16 14:14:58 +09001796 :py:obj:`PKCS12.get_friendlyname` and :py:obj:`PKCS12_set_friendlyname`, and a
1797 :py:obj:`PKCS12` with a friendly name set can be dumped with :py:obj:`PKCS12.export`.
Rick Deanf94096c2009-07-18 14:23:06 -05001798 """
Rick Deanf94096c2009-07-18 14:23:06 -05001799 passwd = 'Dogmeat[]{}!@#$%^&*()~`?/.,<>-_+=";:'
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001800 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -04001801 for friendly_name in [b('Serverlicious'), None, b('###')]:
Rick Dean42d69e12009-07-20 11:36:08 -05001802 p12.set_friendlyname(friendly_name)
1803 self.assertEqual(p12.get_friendlyname(), friendly_name)
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001804 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
Rick Dean42d69e12009-07-20 11:36:08 -05001805 reloaded_p12 = load_pkcs12(dumped_p12, passwd)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001806 self.assertEqual(
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -04001807 p12.get_friendlyname(), reloaded_p12.get_friendlyname())
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001808 # We would use the openssl program to confirm the friendly
1809 # name, but it is not possible. The pkcs12 command
1810 # does not store the friendly name in the cert's
Rick Dean42d69e12009-07-20 11:36:08 -05001811 # alias, which we could then extract.
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001812 self.check_recovery(
1813 dumped_p12, key=server_key_pem, cert=server_cert_pem,
1814 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05001815
1816
1817 def test_various_empty_passphrases(self):
1818 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001819 Test that missing, None, and '' passphrases are identical for PKCS12
1820 export.
Rick Deanf94096c2009-07-18 14:23:06 -05001821 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001822 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
Rick Dean623ee362009-07-17 12:22:16 -05001823 passwd = ''
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001824 dumped_p12_empty = p12.export(iter=2, maciter=0, passphrase=passwd)
1825 dumped_p12_none = p12.export(iter=3, maciter=2, passphrase=None)
1826 dumped_p12_nopw = p12.export(iter=9, maciter=4)
1827 for dumped_p12 in [dumped_p12_empty, dumped_p12_none, dumped_p12_nopw]:
1828 self.check_recovery(
1829 dumped_p12, key=client_key_pem, cert=client_cert_pem,
1830 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05001831
1832
1833 def test_removing_ca_cert(self):
1834 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001835 Passing :py:obj:`None` to :py:obj:`PKCS12.set_ca_certificates` removes all CA
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001836 certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05001837 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001838 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
1839 p12.set_ca_certificates(None)
Rick Dean623ee362009-07-17 12:22:16 -05001840 self.assertEqual(None, p12.get_ca_certificates())
Rick Deanf94096c2009-07-18 14:23:06 -05001841
1842
1843 def test_export_without_mac(self):
1844 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04001845 Exporting a PKCS12 with a :py:obj:`maciter` of ``-1`` excludes the MAC
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001846 entirely.
Rick Deanf94096c2009-07-18 14:23:06 -05001847 """
1848 passwd = 'Lake Michigan'
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001849 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Dean623ee362009-07-17 12:22:16 -05001850 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001851 self.check_recovery(
1852 dumped_p12, key=server_key_pem, cert=server_cert_pem,
1853 passwd=passwd, extra=('-nomacver',))
1854
1855
1856 def test_load_without_mac(self):
1857 """
1858 Loading a PKCS12 without a MAC does something other than crash.
1859 """
1860 passwd = 'Lake Michigan'
1861 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
1862 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Rick Dean321a0512009-08-13 17:21:29 -05001863 try:
1864 recovered_p12 = load_pkcs12(dumped_p12, passwd)
1865 # The person who generated this PCKS12 should be flogged,
1866 # or better yet we should have a means to determine
1867 # whether a PCKS12 had a MAC that was verified.
1868 # Anyway, libopenssl chooses to allow it, so the
1869 # pyopenssl binding does as well.
1870 self.assertTrue(isinstance(recovered_p12, PKCS12))
1871 except Error:
1872 # Failing here with an exception is preferred as some openssl
1873 # versions do.
1874 pass
Rick Dean623ee362009-07-17 12:22:16 -05001875
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001876
Rick Dean25bcc1f2009-07-20 11:53:13 -05001877 def test_zero_len_list_for_ca(self):
1878 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04001879 A PKCS12 with an empty CA certificates list can be exported.
Rick Dean25bcc1f2009-07-20 11:53:13 -05001880 """
1881 passwd = 'Hobie 18'
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04001882 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001883 # p12.set_ca_certificates([])
1884 # self.assertEqual((), p12.get_ca_certificates())
1885 # dumped_p12 = p12.export(passphrase=passwd, iter=3)
1886 # self.check_recovery(
1887 # dumped_p12, key=server_key_pem, cert=server_cert_pem,
1888 # passwd=passwd)
Rick Dean25bcc1f2009-07-20 11:53:13 -05001889
1890
Rick Deanf94096c2009-07-18 14:23:06 -05001891 def test_export_without_args(self):
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001892 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001893 All the arguments to :py:obj:`PKCS12.export` are optional.
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001894 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04001895 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05001896 dumped_p12 = p12.export() # no args
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04001897 self.check_recovery(
1898 dumped_p12, key=server_key_pem, cert=server_cert_pem, passwd='')
Rick Deanf94096c2009-07-18 14:23:06 -05001899
1900
1901 def test_key_cert_mismatch(self):
1902 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001903 :py:obj:`PKCS12.export` raises an exception when a key and certificate
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04001904 mismatch.
Rick Deanf94096c2009-07-18 14:23:06 -05001905 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04001906 p12 = self.gen_pkcs12(server_cert_pem, client_key_pem, root_cert_pem)
1907 self.assertRaises(Error, p12.export)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04001908
1909
1910
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04001911# These quoting functions taken directly from Twisted's twisted.python.win32.
1912_cmdLineQuoteRe = re.compile(r'(\\*)"')
1913_cmdLineQuoteRe2 = re.compile(r'(\\+)\Z')
1914def cmdLineQuote(s):
1915 """
1916 Internal method for quoting a single command-line argument.
1917
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04001918 See http://www.perlmonks.org/?node_id=764004
1919
Jonathan Ballet648875f2011-07-16 14:14:58 +09001920 :type: :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09001921 :param s: A single unquoted string to quote for something that is expecting
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04001922 cmd.exe-style quoting
1923
Jonathan Ballet648875f2011-07-16 14:14:58 +09001924 :rtype: :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09001925 :return: A cmd.exe-style quoted string
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04001926 """
1927 s = _cmdLineQuoteRe2.sub(r"\1\1", _cmdLineQuoteRe.sub(r'\1\1\\"', s))
1928 return '"%s"' % s
1929
1930
1931
1932def quoteArguments(arguments):
1933 """
1934 Quote an iterable of command-line arguments for passing to CreateProcess or
Jonathan Ballet648875f2011-07-16 14:14:58 +09001935 a similar API. This allows the list passed to :py:obj:`reactor.spawnProcess` to
1936 match the child process's :py:obj:`sys.argv` properly.
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04001937
Jonathan Ballet648875f2011-07-16 14:14:58 +09001938 :type arguments: :py:obj:`iterable` of :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09001939 :param arguments: An iterable of unquoted arguments to quote
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04001940
Jonathan Ballet648875f2011-07-16 14:14:58 +09001941 :rtype: :py:obj:`str`
1942 :return: A space-delimited string containing quoted versions of :py:obj:`arguments`
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04001943 """
1944 return ' '.join(map(cmdLineQuote, arguments))
1945
1946
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05001947
Rick Dean4c9ad612009-07-17 15:05:22 -05001948def _runopenssl(pem, *args):
1949 """
1950 Run the command line openssl tool with the given arguments and write
Rick Dean55d1ce62009-08-13 17:40:24 -05001951 the given PEM to its stdin. Not safe for quotes.
Rick Dean4c9ad612009-07-17 15:05:22 -05001952 """
Jean-Paul Calderone038de952009-08-21 12:16:06 -04001953 if os.name == 'posix':
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001954 command = "openssl " + " ".join([
1955 "'%s'" % (arg.replace("'", "'\\''"),) for arg in args])
Rick Dean55d1ce62009-08-13 17:40:24 -05001956 else:
Jean-Paul Calderone50924502009-08-27 12:47:55 -04001957 command = "openssl " + quoteArguments(args)
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001958 proc = Popen(command, shell=True, stdin=PIPE, stdout=PIPE)
Jean-Paul Calderone62ca8da2010-08-11 19:58:08 -04001959 proc.stdin.write(pem)
1960 proc.stdin.close()
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08001961 output = proc.stdout.read()
1962 proc.stdout.close()
1963 proc.wait()
1964 return output
Rick Dean4c9ad612009-07-17 15:05:22 -05001965
1966
1967
Jean-Paul Calderone18808652009-07-05 12:54:05 -04001968class FunctionTests(TestCase):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04001969 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001970 Tests for free-functions in the :py:obj:`OpenSSL.crypto` module.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04001971 """
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001972
1973 def test_load_privatekey_invalid_format(self):
1974 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001975 :py:obj:`load_privatekey` raises :py:obj:`ValueError` if passed an unknown filetype.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001976 """
1977 self.assertRaises(ValueError, load_privatekey, 100, root_key_pem)
1978
1979
1980 def test_load_privatekey_invalid_passphrase_type(self):
1981 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001982 :py:obj:`load_privatekey` raises :py:obj:`TypeError` if passed a passphrase that is
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04001983 neither a :py:obj:`str` nor a callable.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001984 """
1985 self.assertRaises(
1986 TypeError,
1987 load_privatekey,
1988 FILETYPE_PEM, encryptedPrivateKeyPEMPassphrase, object())
1989
1990
1991 def test_load_privatekey_wrong_args(self):
1992 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001993 :py:obj:`load_privatekey` raises :py:obj:`TypeError` if called with the wrong number
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001994 of arguments.
1995 """
1996 self.assertRaises(TypeError, load_privatekey)
1997
1998
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04001999 def test_load_privatekey_wrongPassphrase(self):
2000 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002001 :py:obj:`load_privatekey` raises :py:obj:`OpenSSL.crypto.Error` when it is passed an
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002002 encrypted PEM and an incorrect passphrase.
2003 """
2004 self.assertRaises(
2005 Error,
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002006 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, b("quack"))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002007
2008
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002009 def test_load_privatekey_passphraseWrongType(self):
2010 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002011 :py:obj:`load_privatekey` raises :py:obj:`ValueError` when it is passed a passphrase
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002012 with a private key encoded in a format, that doesn't support
2013 encryption.
2014 """
2015 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2016 blob = dump_privatekey(FILETYPE_ASN1, key)
2017 self.assertRaises(ValueError,
2018 load_privatekey, FILETYPE_ASN1, blob, "secret")
2019
2020
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002021 def test_load_privatekey_passphrase(self):
2022 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002023 :py:obj:`load_privatekey` can create a :py:obj:`PKey` object from an encrypted PEM
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002024 string if given the passphrase.
2025 """
2026 key = load_privatekey(
2027 FILETYPE_PEM, encryptedPrivateKeyPEM,
2028 encryptedPrivateKeyPEMPassphrase)
2029 self.assertTrue(isinstance(key, PKeyType))
2030
2031
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002032 def test_load_privatekey_passphrase_exception(self):
2033 """
2034 If the passphrase callback raises an exception, that exception is raised
2035 by :py:obj:`load_privatekey`.
2036 """
2037 def cb(ignored):
2038 raise ArithmeticError
2039
2040 self.assertRaises(ArithmeticError,
2041 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2042
2043
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002044 def test_load_privatekey_wrongPassphraseCallback(self):
2045 """
Jean-Paul Calderoned440a082011-09-14 11:02:05 -04002046 :py:obj:`load_privatekey` raises :py:obj:`OpenSSL.crypto.Error` when it
2047 is passed an encrypted PEM and a passphrase callback which returns an
2048 incorrect passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002049 """
2050 called = []
2051 def cb(*a):
2052 called.append(None)
Jean-Paul Calderoned440a082011-09-14 11:02:05 -04002053 return b("quack")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002054 self.assertRaises(
2055 Error,
2056 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2057 self.assertTrue(called)
2058
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002059
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002060 def test_load_privatekey_passphraseCallback(self):
2061 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002062 :py:obj:`load_privatekey` can create a :py:obj:`PKey` object from an encrypted PEM
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002063 string if given a passphrase callback which returns the correct
2064 password.
2065 """
2066 called = []
2067 def cb(writing):
2068 called.append(writing)
2069 return encryptedPrivateKeyPEMPassphrase
2070 key = load_privatekey(FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2071 self.assertTrue(isinstance(key, PKeyType))
2072 self.assertEqual(called, [False])
2073
2074
Jean-Paul Calderone105cb952011-09-14 10:16:46 -04002075 def test_load_privatekey_passphrase_wrong_return_type(self):
2076 """
2077 :py:obj:`load_privatekey` raises :py:obj:`ValueError` if the passphrase
2078 callback returns something other than a byte string.
2079 """
2080 self.assertRaises(
2081 ValueError,
2082 load_privatekey,
2083 FILETYPE_PEM, encryptedPrivateKeyPEM, lambda *args: 3)
2084
2085
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002086 def test_dump_privatekey_wrong_args(self):
2087 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002088 :py:obj:`dump_privatekey` raises :py:obj:`TypeError` if called with the wrong number
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002089 of arguments.
2090 """
2091 self.assertRaises(TypeError, dump_privatekey)
Jean-Paul Calderone1eeccd82011-09-14 10:18:52 -04002092 # If cipher name is given, password is required.
2093 self.assertRaises(
2094 ValueError, dump_privatekey, FILETYPE_PEM, PKey(), "foo")
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002095
2096
2097 def test_dump_privatekey_unknown_cipher(self):
2098 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002099 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` if called with an unrecognized
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002100 cipher name.
2101 """
2102 key = PKey()
2103 key.generate_key(TYPE_RSA, 512)
2104 self.assertRaises(
2105 ValueError, dump_privatekey,
2106 FILETYPE_PEM, key, "zippers", "passphrase")
2107
2108
2109 def test_dump_privatekey_invalid_passphrase_type(self):
2110 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002111 :py:obj:`dump_privatekey` raises :py:obj:`TypeError` if called with a passphrase which
2112 is neither a :py:obj:`str` nor a callable.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002113 """
2114 key = PKey()
2115 key.generate_key(TYPE_RSA, 512)
2116 self.assertRaises(
2117 TypeError,
2118 dump_privatekey, FILETYPE_PEM, key, "blowfish", object())
2119
2120
2121 def test_dump_privatekey_invalid_filetype(self):
2122 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002123 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` if called with an unrecognized
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002124 filetype.
2125 """
2126 key = PKey()
2127 key.generate_key(TYPE_RSA, 512)
2128 self.assertRaises(ValueError, dump_privatekey, 100, key)
2129
2130
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002131 def test_load_privatekey_passphraseCallbackLength(self):
2132 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002133 :py:obj:`crypto.load_privatekey` should raise an error when the passphrase
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002134 provided by the callback is too long, not silently truncate it.
2135 """
2136 def cb(ignored):
2137 return "a" * 1025
2138
2139 self.assertRaises(ValueError,
2140 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2141
2142
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002143 def test_dump_privatekey_passphrase(self):
2144 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002145 :py:obj:`dump_privatekey` writes an encrypted PEM when given a passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002146 """
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002147 passphrase = b("foo")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002148 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2149 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002150 self.assertTrue(isinstance(pem, bytes))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002151 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
2152 self.assertTrue(isinstance(loadedKey, PKeyType))
2153 self.assertEqual(loadedKey.type(), key.type())
2154 self.assertEqual(loadedKey.bits(), key.bits())
2155
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002156
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002157 def test_dump_privatekey_passphraseWrongType(self):
2158 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002159 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` when it is passed a passphrase
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002160 with a private key encoded in a format, that doesn't support
2161 encryption.
2162 """
2163 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2164 self.assertRaises(ValueError,
2165 dump_privatekey, FILETYPE_ASN1, key, "blowfish", "secret")
2166
2167
Rick Dean5b7b6372009-04-01 11:34:06 -05002168 def test_dump_certificate(self):
2169 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002170 :py:obj:`dump_certificate` writes PEM, DER, and text.
Rick Dean5b7b6372009-04-01 11:34:06 -05002171 """
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002172 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
Rick Dean5b7b6372009-04-01 11:34:06 -05002173 cert = load_certificate(FILETYPE_PEM, pemData)
2174 dumped_pem = dump_certificate(FILETYPE_PEM, cert)
2175 self.assertEqual(dumped_pem, cleartextCertificatePEM)
2176 dumped_der = dump_certificate(FILETYPE_ASN1, cert)
Rick Dean4c9ad612009-07-17 15:05:22 -05002177 good_der = _runopenssl(dumped_pem, "x509", "-outform", "DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002178 self.assertEqual(dumped_der, good_der)
2179 cert2 = load_certificate(FILETYPE_ASN1, dumped_der)
2180 dumped_pem2 = dump_certificate(FILETYPE_PEM, cert2)
2181 self.assertEqual(dumped_pem2, cleartextCertificatePEM)
2182 dumped_text = dump_certificate(FILETYPE_TEXT, cert)
Rick Dean4c9ad612009-07-17 15:05:22 -05002183 good_text = _runopenssl(dumped_pem, "x509", "-noout", "-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002184 self.assertEqual(dumped_text, good_text)
2185
2186
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002187 def test_dump_privatekey_pem(self):
Rick Dean5b7b6372009-04-01 11:34:06 -05002188 """
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002189 :py:obj:`dump_privatekey` writes a PEM
Rick Dean5b7b6372009-04-01 11:34:06 -05002190 """
2191 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -04002192 self.assertTrue(key.check())
Rick Dean5b7b6372009-04-01 11:34:06 -05002193 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2194 self.assertEqual(dumped_pem, cleartextPrivateKeyPEM)
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002195
2196
2197 def test_dump_privatekey_asn1(self):
2198 """
2199 :py:obj:`dump_privatekey` writes a DER
2200 """
2201 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2202 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2203
Rick Dean5b7b6372009-04-01 11:34:06 -05002204 dumped_der = dump_privatekey(FILETYPE_ASN1, key)
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002205 # XXX This OpenSSL call writes "writing RSA key" to standard out. Sad.
Rick Dean4c9ad612009-07-17 15:05:22 -05002206 good_der = _runopenssl(dumped_pem, "rsa", "-outform", "DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002207 self.assertEqual(dumped_der, good_der)
2208 key2 = load_privatekey(FILETYPE_ASN1, dumped_der)
2209 dumped_pem2 = dump_privatekey(FILETYPE_PEM, key2)
2210 self.assertEqual(dumped_pem2, cleartextPrivateKeyPEM)
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002211
2212
2213 def test_dump_privatekey_text(self):
2214 """
2215 :py:obj:`dump_privatekey` writes a text
2216 """
2217 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2218 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2219
Rick Dean5b7b6372009-04-01 11:34:06 -05002220 dumped_text = dump_privatekey(FILETYPE_TEXT, key)
Rick Dean4c9ad612009-07-17 15:05:22 -05002221 good_text = _runopenssl(dumped_pem, "rsa", "-noout", "-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002222 self.assertEqual(dumped_text, good_text)
2223
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002224
Rick Dean5b7b6372009-04-01 11:34:06 -05002225 def test_dump_certificate_request(self):
2226 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002227 :py:obj:`dump_certificate_request` writes a PEM, DER, and text.
Rick Dean5b7b6372009-04-01 11:34:06 -05002228 """
2229 req = load_certificate_request(FILETYPE_PEM, cleartextCertificateRequestPEM)
2230 dumped_pem = dump_certificate_request(FILETYPE_PEM, req)
2231 self.assertEqual(dumped_pem, cleartextCertificateRequestPEM)
2232 dumped_der = dump_certificate_request(FILETYPE_ASN1, req)
Rick Dean4c9ad612009-07-17 15:05:22 -05002233 good_der = _runopenssl(dumped_pem, "req", "-outform", "DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002234 self.assertEqual(dumped_der, good_der)
2235 req2 = load_certificate_request(FILETYPE_ASN1, dumped_der)
2236 dumped_pem2 = dump_certificate_request(FILETYPE_PEM, req2)
2237 self.assertEqual(dumped_pem2, cleartextCertificateRequestPEM)
2238 dumped_text = dump_certificate_request(FILETYPE_TEXT, req)
Rick Dean4c9ad612009-07-17 15:05:22 -05002239 good_text = _runopenssl(dumped_pem, "req", "-noout", "-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002240 self.assertEqual(dumped_text, good_text)
Jean-Paul Calderoneaf43cdf2010-08-03 18:40:52 -04002241 self.assertRaises(ValueError, dump_certificate_request, 100, req)
Rick Dean5b7b6372009-04-01 11:34:06 -05002242
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002243
2244 def test_dump_privatekey_passphraseCallback(self):
2245 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002246 :py:obj:`dump_privatekey` writes an encrypted PEM when given a callback which
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002247 returns the correct passphrase.
2248 """
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002249 passphrase = b("foo")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002250 called = []
2251 def cb(writing):
2252 called.append(writing)
2253 return passphrase
2254 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2255 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", cb)
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002256 self.assertTrue(isinstance(pem, bytes))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002257 self.assertEqual(called, [True])
2258 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
2259 self.assertTrue(isinstance(loadedKey, PKeyType))
2260 self.assertEqual(loadedKey.type(), key.type())
2261 self.assertEqual(loadedKey.bits(), key.bits())
Rick Dean5b7b6372009-04-01 11:34:06 -05002262
2263
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002264 def test_dump_privatekey_passphrase_exception(self):
2265 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002266 :py:obj:`dump_privatekey` should not overwrite the exception raised
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002267 by the passphrase callback.
2268 """
2269 def cb(ignored):
2270 raise ArithmeticError
2271
2272 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2273 self.assertRaises(ArithmeticError,
2274 dump_privatekey, FILETYPE_PEM, key, "blowfish", cb)
2275
2276
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002277 def test_dump_privatekey_passphraseCallbackLength(self):
2278 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002279 :py:obj:`crypto.dump_privatekey` should raise an error when the passphrase
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002280 provided by the callback is too long, not silently truncate it.
2281 """
2282 def cb(ignored):
2283 return "a" * 1025
2284
2285 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2286 self.assertRaises(ValueError,
2287 dump_privatekey, FILETYPE_PEM, key, "blowfish", cb)
2288
2289
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002290 def test_load_pkcs7_data(self):
2291 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002292 :py:obj:`load_pkcs7_data` accepts a PKCS#7 string and returns an instance of
2293 :py:obj:`PKCS7Type`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002294 """
2295 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2296 self.assertTrue(isinstance(pkcs7, PKCS7Type))
2297
2298
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002299 def test_load_pkcs7_data_invalid(self):
2300 """
2301 If the data passed to :py:obj:`load_pkcs7_data` is invalid,
2302 :py:obj:`Error` is raised.
2303 """
2304 self.assertRaises(Error, load_pkcs7_data, FILETYPE_PEM, "foo")
2305
2306
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002307
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002308class PKCS7Tests(TestCase):
2309 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002310 Tests for :py:obj:`PKCS7Type`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002311 """
2312 def test_type(self):
2313 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002314 :py:obj:`PKCS7Type` is a type object.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002315 """
2316 self.assertTrue(isinstance(PKCS7Type, type))
2317 self.assertEqual(PKCS7Type.__name__, 'PKCS7')
2318
2319 # XXX This doesn't currently work.
2320 # self.assertIdentical(PKCS7, PKCS7Type)
2321
2322
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002323 # XXX Opposite results for all these following methods
2324
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002325 def test_type_is_signed_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002326 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002327 :py:obj:`PKCS7Type.type_is_signed` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002328 arguments.
2329 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002330 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2331 self.assertRaises(TypeError, pkcs7.type_is_signed, None)
2332
2333
2334 def test_type_is_signed(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002335 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002336 :py:obj:`PKCS7Type.type_is_signed` returns :py:obj:`True` if the PKCS7 object is of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002337 the type *signed*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002338 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002339 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2340 self.assertTrue(pkcs7.type_is_signed())
2341
2342
2343 def test_type_is_enveloped_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002344 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002345 :py:obj:`PKCS7Type.type_is_enveloped` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002346 arguments.
2347 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002348 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2349 self.assertRaises(TypeError, pkcs7.type_is_enveloped, None)
2350
2351
2352 def test_type_is_enveloped(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002353 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002354 :py:obj:`PKCS7Type.type_is_enveloped` returns :py:obj:`False` if the PKCS7 object is
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002355 not of the type *enveloped*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002356 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002357 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2358 self.assertFalse(pkcs7.type_is_enveloped())
2359
2360
2361 def test_type_is_signedAndEnveloped_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002362 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002363 :py:obj:`PKCS7Type.type_is_signedAndEnveloped` raises :py:obj:`TypeError` if called
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002364 with any arguments.
2365 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002366 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2367 self.assertRaises(TypeError, pkcs7.type_is_signedAndEnveloped, None)
2368
2369
2370 def test_type_is_signedAndEnveloped(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002371 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002372 :py:obj:`PKCS7Type.type_is_signedAndEnveloped` returns :py:obj:`False` if the PKCS7
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002373 object is not of the type *signed and enveloped*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002374 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002375 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2376 self.assertFalse(pkcs7.type_is_signedAndEnveloped())
2377
2378
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002379 def test_type_is_data(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002380 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002381 :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 -04002382 the type data.
2383 """
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002384 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2385 self.assertFalse(pkcs7.type_is_data())
2386
2387
2388 def test_type_is_data_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002389 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002390 :py:obj:`PKCS7Type.type_is_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002391 arguments.
2392 """
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002393 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2394 self.assertRaises(TypeError, pkcs7.type_is_data, None)
2395
2396
Jean-Paul Calderone97b28ca2010-07-30 10:56:07 -04002397 def test_get_type_name_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002398 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002399 :py:obj:`PKCS7Type.get_type_name` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002400 arguments.
2401 """
Jean-Paul Calderone97b28ca2010-07-30 10:56:07 -04002402 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2403 self.assertRaises(TypeError, pkcs7.get_type_name, None)
2404
2405
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002406 def test_get_type_name(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002407 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002408 :py:obj:`PKCS7Type.get_type_name` returns a :py:obj:`str` giving the type name.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002409 """
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002410 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
Jean-Paul Calderone07640f12010-08-22 17:14:43 -04002411 self.assertEquals(pkcs7.get_type_name(), b('pkcs7-signedData'))
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002412
2413
2414 def test_attribute(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002415 """
2416 If an attribute other than one of the methods tested here is accessed on
Jonathan Ballet648875f2011-07-16 14:14:58 +09002417 an instance of :py:obj:`PKCS7Type`, :py:obj:`AttributeError` is raised.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002418 """
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002419 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2420 self.assertRaises(AttributeError, getattr, pkcs7, "foo")
2421
2422
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002423
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002424class NetscapeSPKITests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002425 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002426 Tests for :py:obj:`OpenSSL.crypto.NetscapeSPKI`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002427 """
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002428 def signable(self):
2429 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002430 Return a new :py:obj:`NetscapeSPKI` for use with signing tests.
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002431 """
2432 return NetscapeSPKI()
2433
2434
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002435 def test_type(self):
2436 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002437 :py:obj:`NetscapeSPKI` and :py:obj:`NetscapeSPKIType` refer to the same type object
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002438 and can be used to create instances of that type.
2439 """
2440 self.assertIdentical(NetscapeSPKI, NetscapeSPKIType)
2441 self.assertConsistentType(NetscapeSPKI, 'NetscapeSPKI')
2442
2443
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002444 def test_construction(self):
2445 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002446 :py:obj:`NetscapeSPKI` returns an instance of :py:obj:`NetscapeSPKIType`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002447 """
2448 nspki = NetscapeSPKI()
2449 self.assertTrue(isinstance(nspki, NetscapeSPKIType))
2450
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002451
Jean-Paul Calderone969efaa2010-08-03 18:19:19 -04002452 def test_invalid_attribute(self):
2453 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002454 Accessing a non-existent attribute of a :py:obj:`NetscapeSPKI` instance causes
2455 an :py:obj:`AttributeError` to be raised.
Jean-Paul Calderone969efaa2010-08-03 18:19:19 -04002456 """
2457 nspki = NetscapeSPKI()
2458 self.assertRaises(AttributeError, lambda: nspki.foo)
2459
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002460
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002461 def test_b64_encode(self):
2462 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002463 :py:obj:`NetscapeSPKI.b64_encode` encodes the certificate to a base64 blob.
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002464 """
2465 nspki = NetscapeSPKI()
2466 blob = nspki.b64_encode()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002467 self.assertTrue(isinstance(blob, bytes))
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002468
2469
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002470
Rick Dean536ba022009-07-24 23:57:27 -05002471class RevokedTests(TestCase):
2472 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002473 Tests for :py:obj:`OpenSSL.crypto.Revoked`
Rick Dean536ba022009-07-24 23:57:27 -05002474 """
2475 def test_construction(self):
2476 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002477 Confirm we can create :py:obj:`OpenSSL.crypto.Revoked`. Check
Rick Dean536ba022009-07-24 23:57:27 -05002478 that it is empty.
2479 """
2480 revoked = Revoked()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002481 self.assertTrue(isinstance(revoked, Revoked))
2482 self.assertEquals(type(revoked), Revoked)
2483 self.assertEquals(revoked.get_serial(), b('00'))
2484 self.assertEquals(revoked.get_rev_date(), None)
2485 self.assertEquals(revoked.get_reason(), None)
Rick Dean536ba022009-07-24 23:57:27 -05002486
2487
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002488 def test_construction_wrong_args(self):
2489 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002490 Calling :py:obj:`OpenSSL.crypto.Revoked` with any arguments results
2491 in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002492 """
2493 self.assertRaises(TypeError, Revoked, None)
2494 self.assertRaises(TypeError, Revoked, 1)
2495 self.assertRaises(TypeError, Revoked, "foo")
2496
2497
Rick Dean536ba022009-07-24 23:57:27 -05002498 def test_serial(self):
2499 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002500 Confirm we can set and get serial numbers from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002501 :py:obj:`OpenSSL.crypto.Revoked`. Confirm errors are handled
Rick Dean536ba022009-07-24 23:57:27 -05002502 with grace.
2503 """
2504 revoked = Revoked()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002505 ret = revoked.set_serial(b('10b'))
2506 self.assertEquals(ret, None)
Rick Dean536ba022009-07-24 23:57:27 -05002507 ser = revoked.get_serial()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002508 self.assertEquals(ser, b('010B'))
Rick Dean536ba022009-07-24 23:57:27 -05002509
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002510 revoked.set_serial(b('31ppp')) # a type error would be nice
Rick Dean536ba022009-07-24 23:57:27 -05002511 ser = revoked.get_serial()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002512 self.assertEquals(ser, b('31'))
Rick Dean536ba022009-07-24 23:57:27 -05002513
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002514 self.assertRaises(ValueError, revoked.set_serial, b('pqrst'))
Rick Dean536ba022009-07-24 23:57:27 -05002515 self.assertRaises(TypeError, revoked.set_serial, 100)
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002516 self.assertRaises(TypeError, revoked.get_serial, 1)
2517 self.assertRaises(TypeError, revoked.get_serial, None)
2518 self.assertRaises(TypeError, revoked.get_serial, "")
Rick Dean536ba022009-07-24 23:57:27 -05002519
2520
2521 def test_date(self):
2522 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002523 Confirm we can set and get revocation dates from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002524 :py:obj:`OpenSSL.crypto.Revoked`. Confirm errors are handled
Rick Dean536ba022009-07-24 23:57:27 -05002525 with grace.
2526 """
2527 revoked = Revoked()
2528 date = revoked.get_rev_date()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002529 self.assertEquals(date, None)
Rick Dean536ba022009-07-24 23:57:27 -05002530
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002531 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05002532 ret = revoked.set_rev_date(now)
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002533 self.assertEqual(ret, None)
Rick Dean536ba022009-07-24 23:57:27 -05002534 date = revoked.get_rev_date()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002535 self.assertEqual(date, now)
Rick Dean536ba022009-07-24 23:57:27 -05002536
2537
Rick Dean6385faf2009-07-26 00:07:47 -05002538 def test_reason(self):
2539 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002540 Confirm we can set and get revocation reasons from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002541 :py:obj:`OpenSSL.crypto.Revoked`. The "get" need to work
Rick Dean6385faf2009-07-26 00:07:47 -05002542 as "set". Likewise, each reason of all_reasons() must work.
2543 """
2544 revoked = Revoked()
2545 for r in revoked.all_reasons():
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002546 for x in range(2):
Rick Dean6385faf2009-07-26 00:07:47 -05002547 ret = revoked.set_reason(r)
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002548 self.assertEquals(ret, None)
Rick Dean6385faf2009-07-26 00:07:47 -05002549 reason = revoked.get_reason()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002550 self.assertEquals(
2551 reason.lower().replace(b(' '), b('')),
2552 r.lower().replace(b(' '), b('')))
Rick Dean6385faf2009-07-26 00:07:47 -05002553 r = reason # again with the resp of get
2554
2555 revoked.set_reason(None)
2556 self.assertEqual(revoked.get_reason(), None)
2557
2558
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002559 def test_set_reason_wrong_arguments(self):
Rick Dean6385faf2009-07-26 00:07:47 -05002560 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002561 Calling :py:obj:`OpenSSL.crypto.Revoked.set_reason` with other than
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002562 one argument, or an argument which isn't a valid reason,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002563 results in :py:obj:`TypeError` or :py:obj:`ValueError` being raised.
Rick Dean6385faf2009-07-26 00:07:47 -05002564 """
2565 revoked = Revoked()
2566 self.assertRaises(TypeError, revoked.set_reason, 100)
Jean-Paul Calderone281b62b2010-08-28 14:22:29 -04002567 self.assertRaises(ValueError, revoked.set_reason, b('blue'))
Rick Dean6385faf2009-07-26 00:07:47 -05002568
Rick Dean536ba022009-07-24 23:57:27 -05002569
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002570 def test_get_reason_wrong_arguments(self):
2571 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002572 Calling :py:obj:`OpenSSL.crypto.Revoked.get_reason` with any
2573 arguments results in :py:obj:`TypeError` being raised.
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002574 """
2575 revoked = Revoked()
2576 self.assertRaises(TypeError, revoked.get_reason, None)
2577 self.assertRaises(TypeError, revoked.get_reason, 1)
2578 self.assertRaises(TypeError, revoked.get_reason, "foo")
2579
2580
2581
Rick Dean536ba022009-07-24 23:57:27 -05002582class CRLTests(TestCase):
2583 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002584 Tests for :py:obj:`OpenSSL.crypto.CRL`
Rick Dean536ba022009-07-24 23:57:27 -05002585 """
2586 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
2587 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2588
2589 def test_construction(self):
2590 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002591 Confirm we can create :py:obj:`OpenSSL.crypto.CRL`. Check
Rick Dean536ba022009-07-24 23:57:27 -05002592 that it is empty
2593 """
2594 crl = CRL()
2595 self.assertTrue( isinstance(crl, CRL) )
2596 self.assertEqual(crl.get_revoked(), None)
2597
2598
Jean-Paul Calderone2efd03e2010-01-30 13:59:55 -05002599 def test_construction_wrong_args(self):
2600 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002601 Calling :py:obj:`OpenSSL.crypto.CRL` with any number of arguments
2602 results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone2efd03e2010-01-30 13:59:55 -05002603 """
2604 self.assertRaises(TypeError, CRL, 1)
2605 self.assertRaises(TypeError, CRL, "")
2606 self.assertRaises(TypeError, CRL, None)
2607
2608
Rick Dean536ba022009-07-24 23:57:27 -05002609 def test_export(self):
2610 """
2611 Use python to create a simple CRL with a revocation, and export
2612 the CRL in formats of PEM, DER and text. Those outputs are verified
2613 with the openssl program.
2614 """
2615 crl = CRL()
2616 revoked = Revoked()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002617 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05002618 revoked.set_rev_date(now)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002619 revoked.set_serial(b('3ab'))
2620 revoked.set_reason(b('sUpErSeDEd'))
Rick Dean536ba022009-07-24 23:57:27 -05002621 crl.add_revoked(revoked)
2622
2623 # PEM format
2624 dumped_crl = crl.export(self.cert, self.pkey, days=20)
2625 text = _runopenssl(dumped_crl, "crl", "-noout", "-text")
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002626 text.index(b('Serial Number: 03AB'))
2627 text.index(b('Superseded'))
2628 text.index(b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA'))
Rick Dean536ba022009-07-24 23:57:27 -05002629
2630 # DER format
2631 dumped_crl = crl.export(self.cert, self.pkey, FILETYPE_ASN1)
2632 text = _runopenssl(dumped_crl, "crl", "-noout", "-text", "-inform", "DER")
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002633 text.index(b('Serial Number: 03AB'))
2634 text.index(b('Superseded'))
2635 text.index(b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA'))
Rick Dean536ba022009-07-24 23:57:27 -05002636
2637 # text format
2638 dumped_text = crl.export(self.cert, self.pkey, type=FILETYPE_TEXT)
2639 self.assertEqual(text, dumped_text)
2640
2641
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -04002642 def test_export_invalid(self):
2643 """
2644 If :py:obj:`CRL.export` is used with an uninitialized :py:obj:`X509`
Jean-Paul Calderoneb5871072012-03-09 14:58:00 -08002645 instance, :py:obj:`OpenSSL.crypto.Error` is raised.
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -04002646 """
2647 crl = CRL()
2648 self.assertRaises(Error, crl.export, X509(), PKey())
2649
2650
Jean-Paul Calderone56515342010-01-30 13:49:38 -05002651 def test_add_revoked_keyword(self):
2652 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002653 :py:obj:`OpenSSL.CRL.add_revoked` accepts its single argument as the
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002654 ``revoked`` keyword argument.
Jean-Paul Calderone56515342010-01-30 13:49:38 -05002655 """
2656 crl = CRL()
2657 revoked = Revoked()
2658 crl.add_revoked(revoked=revoked)
2659 self.assertTrue(isinstance(crl.get_revoked()[0], Revoked))
2660
Rick Dean6385faf2009-07-26 00:07:47 -05002661
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05002662 def test_export_wrong_args(self):
2663 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002664 Calling :py:obj:`OpenSSL.CRL.export` with fewer than two or more than
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05002665 four arguments, or with arguments other than the certificate,
2666 private key, integer file type, and integer number of days it
Jonathan Ballet648875f2011-07-16 14:14:58 +09002667 expects, results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05002668 """
2669 crl = CRL()
2670 self.assertRaises(TypeError, crl.export)
2671 self.assertRaises(TypeError, crl.export, self.cert)
2672 self.assertRaises(TypeError, crl.export, self.cert, self.pkey, FILETYPE_PEM, 10, "foo")
2673
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05002674 self.assertRaises(TypeError, crl.export, None, self.pkey, FILETYPE_PEM, 10)
2675 self.assertRaises(TypeError, crl.export, self.cert, None, FILETYPE_PEM, 10)
2676 self.assertRaises(TypeError, crl.export, self.cert, self.pkey, None, 10)
2677 self.assertRaises(TypeError, crl.export, self.cert, FILETYPE_PEM, None)
2678
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05002679
Jean-Paul Calderoneea198422010-01-30 13:58:23 -05002680 def test_export_unknown_filetype(self):
2681 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002682 Calling :py:obj:`OpenSSL.CRL.export` with a file type other than
2683 :py:obj:`FILETYPE_PEM`, :py:obj:`FILETYPE_ASN1`, or :py:obj:`FILETYPE_TEXT` results
2684 in a :py:obj:`ValueError` being raised.
Jean-Paul Calderoneea198422010-01-30 13:58:23 -05002685 """
2686 crl = CRL()
2687 self.assertRaises(ValueError, crl.export, self.cert, self.pkey, 100, 10)
2688
2689
Rick Dean536ba022009-07-24 23:57:27 -05002690 def test_get_revoked(self):
2691 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002692 Use python to create a simple CRL with two revocations.
Jonathan Ballet648875f2011-07-16 14:14:58 +09002693 Get back the :py:obj:`Revoked` using :py:obj:`OpenSSL.CRL.get_revoked` and
Rick Dean536ba022009-07-24 23:57:27 -05002694 verify them.
2695 """
2696 crl = CRL()
2697
2698 revoked = Revoked()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002699 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05002700 revoked.set_rev_date(now)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002701 revoked.set_serial(b('3ab'))
Rick Dean536ba022009-07-24 23:57:27 -05002702 crl.add_revoked(revoked)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002703 revoked.set_serial(b('100'))
2704 revoked.set_reason(b('sUpErSeDEd'))
Rick Dean536ba022009-07-24 23:57:27 -05002705 crl.add_revoked(revoked)
2706
2707 revs = crl.get_revoked()
2708 self.assertEqual(len(revs), 2)
2709 self.assertEqual(type(revs[0]), Revoked)
2710 self.assertEqual(type(revs[1]), Revoked)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002711 self.assertEqual(revs[0].get_serial(), b('03AB'))
2712 self.assertEqual(revs[1].get_serial(), b('0100'))
Rick Dean536ba022009-07-24 23:57:27 -05002713 self.assertEqual(revs[0].get_rev_date(), now)
2714 self.assertEqual(revs[1].get_rev_date(), now)
2715
2716
Jean-Paul Calderone46bdce42010-01-30 13:44:16 -05002717 def test_get_revoked_wrong_args(self):
2718 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002719 Calling :py:obj:`OpenSSL.CRL.get_revoked` with any arguments results
2720 in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone46bdce42010-01-30 13:44:16 -05002721 """
2722 crl = CRL()
2723 self.assertRaises(TypeError, crl.get_revoked, None)
2724 self.assertRaises(TypeError, crl.get_revoked, 1)
2725 self.assertRaises(TypeError, crl.get_revoked, "")
2726 self.assertRaises(TypeError, crl.get_revoked, "", 1, None)
2727
2728
Jean-Paul Calderoneecef6fa2010-01-30 13:47:18 -05002729 def test_add_revoked_wrong_args(self):
2730 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002731 Calling :py:obj:`OpenSSL.CRL.add_revoked` with other than one
2732 argument results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderoneecef6fa2010-01-30 13:47:18 -05002733 """
2734 crl = CRL()
2735 self.assertRaises(TypeError, crl.add_revoked)
2736 self.assertRaises(TypeError, crl.add_revoked, 1, 2)
2737 self.assertRaises(TypeError, crl.add_revoked, "foo", "bar")
2738
2739
Rick Dean536ba022009-07-24 23:57:27 -05002740 def test_load_crl(self):
2741 """
2742 Load a known CRL and inspect its revocations. Both
2743 PEM and DER formats are loaded.
2744 """
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05002745 crl = load_crl(FILETYPE_PEM, crlData)
Rick Dean536ba022009-07-24 23:57:27 -05002746 revs = crl.get_revoked()
2747 self.assertEqual(len(revs), 2)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002748 self.assertEqual(revs[0].get_serial(), b('03AB'))
Rick Dean6385faf2009-07-26 00:07:47 -05002749 self.assertEqual(revs[0].get_reason(), None)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002750 self.assertEqual(revs[1].get_serial(), b('0100'))
2751 self.assertEqual(revs[1].get_reason(), b('Superseded'))
Rick Dean536ba022009-07-24 23:57:27 -05002752
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05002753 der = _runopenssl(crlData, "crl", "-outform", "DER")
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002754 crl = load_crl(FILETYPE_ASN1, der)
Rick Dean536ba022009-07-24 23:57:27 -05002755 revs = crl.get_revoked()
2756 self.assertEqual(len(revs), 2)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002757 self.assertEqual(revs[0].get_serial(), b('03AB'))
Rick Dean6385faf2009-07-26 00:07:47 -05002758 self.assertEqual(revs[0].get_reason(), None)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002759 self.assertEqual(revs[1].get_serial(), b('0100'))
2760 self.assertEqual(revs[1].get_reason(), b('Superseded'))
Rick Dean536ba022009-07-24 23:57:27 -05002761
2762
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05002763 def test_load_crl_wrong_args(self):
2764 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002765 Calling :py:obj:`OpenSSL.crypto.load_crl` with other than two
2766 arguments results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05002767 """
2768 self.assertRaises(TypeError, load_crl)
2769 self.assertRaises(TypeError, load_crl, FILETYPE_PEM)
2770 self.assertRaises(TypeError, load_crl, FILETYPE_PEM, crlData, None)
2771
2772
2773 def test_load_crl_bad_filetype(self):
2774 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002775 Calling :py:obj:`OpenSSL.crypto.load_crl` with an unknown file type
2776 raises a :py:obj:`ValueError`.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05002777 """
2778 self.assertRaises(ValueError, load_crl, 100, crlData)
2779
2780
2781 def test_load_crl_bad_data(self):
2782 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002783 Calling :py:obj:`OpenSSL.crypto.load_crl` with file data which can't
2784 be loaded raises a :py:obj:`OpenSSL.crypto.Error`.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05002785 """
2786 self.assertRaises(Error, load_crl, FILETYPE_PEM, "hello, world")
2787
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002788
James Yonan7c2e5d32010-02-27 05:45:50 -07002789class SignVerifyTests(TestCase):
2790 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002791 Tests for :py:obj:`OpenSSL.crypto.sign` and :py:obj:`OpenSSL.crypto.verify`.
James Yonan7c2e5d32010-02-27 05:45:50 -07002792 """
2793 def test_sign_verify(self):
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04002794 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002795 :py:obj:`sign` generates a cryptographic signature which :py:obj:`verify` can check.
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04002796 """
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04002797 content = b(
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04002798 "It was a bright cold day in April, and the clocks were striking "
2799 "thirteen. Winston Smith, his chin nuzzled into his breast in an "
2800 "effort to escape the vile wind, slipped quickly through the "
2801 "glass doors of Victory Mansions, though not quickly enough to "
2802 "prevent a swirl of gritty dust from entering along with him.")
2803
2804 # sign the content with this private key
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04002805 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04002806 # verify the content with this cert
2807 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
2808 # certificate unrelated to priv_key, used to trigger an error
2809 bad_cert = load_certificate(FILETYPE_PEM, server_cert_pem)
James Yonan7c2e5d32010-02-27 05:45:50 -07002810
Jean-Paul Calderoned08feb02010-10-12 21:53:24 -04002811 for digest in ['md5', 'sha1']:
James Yonan7c2e5d32010-02-27 05:45:50 -07002812 sig = sign(priv_key, content, digest)
2813
2814 # Verify the signature of content, will throw an exception if error.
2815 verify(good_cert, sig, content, digest)
2816
2817 # This should fail because the certificate doesn't match the
2818 # private key that was used to sign the content.
2819 self.assertRaises(Error, verify, bad_cert, sig, content, digest)
2820
2821 # This should fail because we've "tainted" the content after
2822 # signing it.
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04002823 self.assertRaises(
2824 Error, verify,
2825 good_cert, sig, content + b("tainted"), digest)
James Yonan7c2e5d32010-02-27 05:45:50 -07002826
2827 # test that unknown digest types fail
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04002828 self.assertRaises(
Jean-Paul Calderone9538f142010-10-13 22:13:40 -04002829 ValueError, sign, priv_key, content, "strange-digest")
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04002830 self.assertRaises(
Jean-Paul Calderone9538f142010-10-13 22:13:40 -04002831 ValueError, verify, good_cert, sig, content, "strange-digest")
James Yonan7c2e5d32010-02-27 05:45:50 -07002832
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04002833
Jean-Paul Calderone9828f662010-12-08 22:57:26 -05002834 def test_sign_nulls(self):
2835 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002836 :py:obj:`sign` produces a signature for a string with embedded nulls.
Jean-Paul Calderone9828f662010-12-08 22:57:26 -05002837 """
2838 content = b("Watch out! \0 Did you see it?")
2839 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
2840 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
2841 sig = sign(priv_key, content, "sha1")
2842 verify(good_cert, sig, content, "sha1")
2843
2844
Rick Dean5b7b6372009-04-01 11:34:06 -05002845if __name__ == '__main__':
2846 main()