blob: b0940d89b9d3ac8bb76ee229fcd37689ee1b3c2c [file] [log] [blame]
Jean-Paul Calderone8671c852011-03-02 19:26:20 -05001# Copyright (c) Jean-Paul Calderone
2# See LICENSE file for details.
Jean-Paul Calderone8b63d452008-03-21 18:31:12 -04003
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -05004"""
Jonathan Ballet648875f2011-07-16 14:14:58 +09005Unit tests for :py:mod:`OpenSSL.crypto`.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -05006"""
7
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04008from unittest import main
9
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -040010import os, re
Jean-Paul Calderone62ca8da2010-08-11 19:58:08 -040011from subprocess import PIPE, Popen
Rick Dean47262da2009-07-08 16:17:17 -050012from datetime import datetime, timedelta
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -050013
14from OpenSSL.crypto import TYPE_RSA, TYPE_DSA, Error, PKey, PKeyType
Jean-Paul Calderone78381d22008-03-06 23:35:22 -050015from OpenSSL.crypto import X509, X509Type, X509Name, X509NameType
Jean-Paul 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
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -0400268# certificate with NULL bytes in subjectAltName and common name
269
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400270nulbyteSubjectAltNamePEM = b("""-----BEGIN CERTIFICATE-----
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -0400271MIIE2DCCA8CgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBxTELMAkGA1UEBhMCVVMx
272DzANBgNVBAgMBk9yZWdvbjESMBAGA1UEBwwJQmVhdmVydG9uMSMwIQYDVQQKDBpQ
273eXRob24gU29mdHdhcmUgRm91bmRhdGlvbjEgMB4GA1UECwwXUHl0aG9uIENvcmUg
274RGV2ZWxvcG1lbnQxJDAiBgNVBAMMG251bGwucHl0aG9uLm9yZwBleGFtcGxlLm9y
275ZzEkMCIGCSqGSIb3DQEJARYVcHl0aG9uLWRldkBweXRob24ub3JnMB4XDTEzMDgw
276NzEzMTE1MloXDTEzMDgwNzEzMTI1MlowgcUxCzAJBgNVBAYTAlVTMQ8wDQYDVQQI
277DAZPcmVnb24xEjAQBgNVBAcMCUJlYXZlcnRvbjEjMCEGA1UECgwaUHl0aG9uIFNv
278ZnR3YXJlIEZvdW5kYXRpb24xIDAeBgNVBAsMF1B5dGhvbiBDb3JlIERldmVsb3Bt
279ZW50MSQwIgYDVQQDDBtudWxsLnB5dGhvbi5vcmcAZXhhbXBsZS5vcmcxJDAiBgkq
280hkiG9w0BCQEWFXB5dGhvbi1kZXZAcHl0aG9uLm9yZzCCASIwDQYJKoZIhvcNAQEB
281BQADggEPADCCAQoCggEBALXq7cn7Rn1vO3aA3TrzA5QLp6bb7B3f/yN0CJ2XFj+j
282pHs+Gw6WWSUDpybiiKnPec33BFawq3kyblnBMjBU61ioy5HwQqVkJ8vUVjGIUq3P
283vX/wBmQfzCe4o4uM89gpHyUL9UYGG8oCRa17dgqcv7u5rg0Wq2B1rgY+nHwx3JIv
284KRrgSwyRkGzpN8WQ1yrXlxWjgI9de0mPVDDUlywcWze1q2kwaEPTM3hLAmD1PESA
285oY/n8A/RXoeeRs9i/Pm/DGUS8ZPINXk/yOzsR/XvvkTVroIeLZqfmFpnZeF0cHzL
28608LODkVJJ9zjLdT7SA4vnne4FEbAxDbKAq5qkYzaL4UCAwEAAaOB0DCBzTAMBgNV
287HRMBAf8EAjAAMB0GA1UdDgQWBBSIWlXAUv9hzVKjNQ/qWpwkOCL3XDALBgNVHQ8E
288BAMCBeAwgZAGA1UdEQSBiDCBhYIeYWx0bnVsbC5weXRob24ub3JnAGV4YW1wbGUu
289Y29tgSBudWxsQHB5dGhvbi5vcmcAdXNlckBleGFtcGxlLm9yZ4YpaHR0cDovL251
290bGwucHl0aG9uLm9yZwBodHRwOi8vZXhhbXBsZS5vcmeHBMAAAgGHECABDbgAAAAA
291AAAAAAAAAAEwDQYJKoZIhvcNAQEFBQADggEBAKxPRe99SaghcI6IWT7UNkJw9aO9
292i9eo0Fj2MUqxpKbdb9noRDy2CnHWf7EIYZ1gznXPdwzSN4YCjV5d+Q9xtBaowT0j
293HPERs1ZuytCNNJTmhyqZ8q6uzMLoht4IqH/FBfpvgaeC5tBTnTT0rD5A/olXeimk
294kX4LxlEx5RAvpGB2zZVRGr6LobD9rVK91xuHYNIxxxfEGE8tCCWjp0+3ksri9SXx
295VHWBnbM9YaL32u3hxm8sYB/Yb8WSBavJCWJJqRStVRHM1koZlJmXNx2BX4vPo6iW
296RFEIPQsFZRLrtnCAiEhyT8bC2s/Njlu6ly9gtJZWSV46Q3ZjBL4q9sHKqZQ=
297-----END CERTIFICATE-----""")
298
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400299
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400300class X509ExtTests(TestCase):
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400301 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900302 Tests for :py:class:`OpenSSL.crypto.X509Extension`.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400303 """
304
305 def setUp(self):
306 """
307 Create a new private key and start a certificate request (for a test
308 method to finish in one way or another).
309 """
310 # Basic setup stuff to generate a certificate
311 self.pkey = PKey()
312 self.pkey.generate_key(TYPE_RSA, 384)
313 self.req = X509Req()
314 self.req.set_pubkey(self.pkey)
315 # Authority good you have.
316 self.req.get_subject().commonName = "Yoda root CA"
317 self.x509 = X509()
318 self.subject = self.x509.get_subject()
319 self.subject.commonName = self.req.get_subject().commonName
320 self.x509.set_issuer(self.subject)
321 self.x509.set_pubkey(self.pkey)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400322 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
323 expire = b((datetime.now() + timedelta(days=100)).strftime("%Y%m%d%H%M%SZ"))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400324 self.x509.set_notBefore(now)
325 self.x509.set_notAfter(expire)
326
327
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400328 def test_str(self):
329 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900330 The string representation of :py:class:`X509Extension` instances as returned by
331 :py:data:`str` includes stuff.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400332 """
333 # This isn't necessarily the best string representation. Perhaps it
334 # will be changed/improved in the future.
335 self.assertEquals(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400336 str(X509Extension(b('basicConstraints'), True, b('CA:false'))),
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400337 'CA:FALSE')
338
339
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400340 def test_type(self):
341 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900342 :py:class:`X509Extension` and :py:class:`X509ExtensionType` refer to the same type object
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400343 and can be used to create instances of that type.
344 """
345 self.assertIdentical(X509Extension, X509ExtensionType)
346 self.assertConsistentType(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400347 X509Extension,
348 'X509Extension', b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400349
350
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500351 def test_construction(self):
352 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900353 :py:class:`X509Extension` accepts an extension type name, a critical flag,
354 and an extension value and returns an :py:class:`X509ExtensionType` instance.
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500355 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400356 basic = X509Extension(b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500357 self.assertTrue(
358 isinstance(basic, X509ExtensionType),
359 "%r is of type %r, should be %r" % (
360 basic, type(basic), X509ExtensionType))
361
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400362 comment = X509Extension(
363 b('nsComment'), False, b('pyOpenSSL unit test'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500364 self.assertTrue(
365 isinstance(comment, X509ExtensionType),
366 "%r is of type %r, should be %r" % (
367 comment, type(comment), X509ExtensionType))
368
369
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500370 def test_invalid_extension(self):
371 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900372 :py:class:`X509Extension` raises something if it is passed a bad extension
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500373 name or value.
374 """
375 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400376 Error, X509Extension, b('thisIsMadeUp'), False, b('hi'))
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500377 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400378 Error, X509Extension, b('basicConstraints'), False, b('blah blah'))
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500379
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500380 # Exercise a weird one (an extension which uses the r2i method). This
381 # exercises the codepath that requires a non-NULL ctx to be passed to
382 # X509V3_EXT_nconf. It can't work now because we provide no
383 # configuration database. It might be made to work in the future.
384 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400385 Error, X509Extension, b('proxyCertInfo'), True,
386 b('language:id-ppl-anyLanguage,pathlen:1,policy:text:AB'))
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500387
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500388
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500389 def test_get_critical(self):
390 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900391 :py:meth:`X509ExtensionType.get_critical` returns the value of the
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500392 extension's critical flag.
393 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400394 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500395 self.assertTrue(ext.get_critical())
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400396 ext = X509Extension(b('basicConstraints'), False, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500397 self.assertFalse(ext.get_critical())
398
Jean-Paul Calderone7535dab2008-03-06 18:53:11 -0500399
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500400 def test_get_short_name(self):
401 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900402 :py:meth:`X509ExtensionType.get_short_name` returns a string giving the short
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500403 type name of the extension.
404 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400405 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
406 self.assertEqual(ext.get_short_name(), b('basicConstraints'))
407 ext = X509Extension(b('nsComment'), True, b('foo bar'))
408 self.assertEqual(ext.get_short_name(), b('nsComment'))
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500409
410
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400411 def test_get_data(self):
412 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900413 :py:meth:`X509Extension.get_data` returns a string giving the data of the
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400414 extension.
415 """
416 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
417 # Expect to get back the DER encoded form of CA:true.
418 self.assertEqual(ext.get_data(), b('0\x03\x01\x01\xff'))
419
420
421 def test_get_data_wrong_args(self):
422 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900423 :py:meth:`X509Extension.get_data` raises :py:exc:`TypeError` if passed any arguments.
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400424 """
425 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
426 self.assertRaises(TypeError, ext.get_data, None)
427 self.assertRaises(TypeError, ext.get_data, "foo")
428 self.assertRaises(TypeError, ext.get_data, 7)
429
430
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400431 def test_unused_subject(self):
Rick Dean47262da2009-07-08 16:17:17 -0500432 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900433 The :py:data:`subject` parameter to :py:class:`X509Extension` may be provided for an
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400434 extension which does not use it and is ignored in this case.
Rick Dean47262da2009-07-08 16:17:17 -0500435 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400436 ext1 = X509Extension(
437 b('basicConstraints'), False, b('CA:TRUE'), subject=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400438 self.x509.add_extensions([ext1])
439 self.x509.sign(self.pkey, 'sha1')
440 # This is a little lame. Can we think of a better way?
441 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400442 self.assertTrue(b('X509v3 Basic Constraints:') in text)
443 self.assertTrue(b('CA:TRUE') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400444
445
446 def test_subject(self):
447 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900448 If an extension requires a subject, the :py:data:`subject` parameter to
449 :py:class:`X509Extension` provides its value.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400450 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400451 ext3 = X509Extension(
452 b('subjectKeyIdentifier'), False, b('hash'), subject=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400453 self.x509.add_extensions([ext3])
454 self.x509.sign(self.pkey, 'sha1')
455 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400456 self.assertTrue(b('X509v3 Subject Key Identifier:') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400457
458
459 def test_missing_subject(self):
460 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900461 If an extension requires a subject and the :py:data:`subject` parameter is
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400462 given no value, something happens.
463 """
464 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400465 Error, X509Extension, b('subjectKeyIdentifier'), False, b('hash'))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400466
467
468 def test_invalid_subject(self):
469 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900470 If the :py:data:`subject` parameter is given a value which is not an
471 :py:class:`X509` instance, :py:exc:`TypeError` is raised.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400472 """
473 for badObj in [True, object(), "hello", [], self]:
474 self.assertRaises(
475 TypeError,
476 X509Extension,
477 'basicConstraints', False, 'CA:TRUE', subject=badObj)
478
479
480 def test_unused_issuer(self):
481 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900482 The :py:data:`issuer` parameter to :py:class:`X509Extension` may be provided for an
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400483 extension which does not use it and is ignored in this case.
484 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400485 ext1 = X509Extension(
486 b('basicConstraints'), False, b('CA:TRUE'), issuer=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400487 self.x509.add_extensions([ext1])
488 self.x509.sign(self.pkey, 'sha1')
489 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400490 self.assertTrue(b('X509v3 Basic Constraints:') in text)
491 self.assertTrue(b('CA:TRUE') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400492
493
494 def test_issuer(self):
495 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900496 If an extension requires a issuer, the :py:data:`issuer` parameter to
497 :py:class:`X509Extension` provides its value.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400498 """
499 ext2 = X509Extension(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400500 b('authorityKeyIdentifier'), False, b('issuer:always'),
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400501 issuer=self.x509)
502 self.x509.add_extensions([ext2])
503 self.x509.sign(self.pkey, 'sha1')
504 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400505 self.assertTrue(b('X509v3 Authority Key Identifier:') in text)
506 self.assertTrue(b('DirName:/CN=Yoda root CA') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400507
508
509 def test_missing_issuer(self):
510 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900511 If an extension requires an issue and the :py:data:`issuer` parameter is given
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400512 no value, something happens.
513 """
514 self.assertRaises(
515 Error,
516 X509Extension,
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400517 b('authorityKeyIdentifier'), False,
518 b('keyid:always,issuer:always'))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400519
520
521 def test_invalid_issuer(self):
522 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900523 If the :py:data:`issuer` parameter is given a value which is not an
524 :py:class:`X509` instance, :py:exc:`TypeError` is raised.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400525 """
526 for badObj in [True, object(), "hello", [], self]:
527 self.assertRaises(
528 TypeError,
529 X509Extension,
530 'authorityKeyIdentifier', False, 'keyid:always,issuer:always',
531 issuer=badObj)
Rick Dean47262da2009-07-08 16:17:17 -0500532
533
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500534
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400535class PKeyTests(TestCase):
Jean-Paul Calderoneac930e12008-03-06 18:50:51 -0500536 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900537 Unit tests for :py:class:`OpenSSL.crypto.PKey`.
Jean-Paul Calderoneac930e12008-03-06 18:50:51 -0500538 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400539 def test_type(self):
540 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900541 :py:class:`PKey` and :py:class:`PKeyType` refer to the same type object
542 and can be used to create instances of that type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400543 """
544 self.assertIdentical(PKey, PKeyType)
545 self.assertConsistentType(PKey, 'PKey')
546
547
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500548 def test_construction(self):
549 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900550 :py:class:`PKey` takes no arguments and returns a new :py:class:`PKey` instance.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500551 """
552 self.assertRaises(TypeError, PKey, None)
553 key = PKey()
554 self.assertTrue(
555 isinstance(key, PKeyType),
556 "%r is of type %r, should be %r" % (key, type(key), PKeyType))
557
558
559 def test_pregeneration(self):
560 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900561 :py:attr:`PKeyType.bits` and :py:attr:`PKeyType.type` return :py:data:`0` before the key is
562 generated. :py:attr:`PKeyType.check` raises :py:exc:`TypeError` before the key is
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500563 generated.
564 """
565 key = PKey()
566 self.assertEqual(key.type(), 0)
567 self.assertEqual(key.bits(), 0)
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400568 self.assertRaises(TypeError, key.check)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500569
570
571 def test_failedGeneration(self):
572 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900573 :py:meth:`PKeyType.generate_key` takes two arguments, the first giving the key
574 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 -0500575 number of bits to generate. If an invalid type is specified or
Jonathan Ballet648875f2011-07-16 14:14:58 +0900576 generation fails, :py:exc:`Error` is raised. If an invalid number of bits is
577 specified, :py:exc:`ValueError` or :py:exc:`Error` is raised.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500578 """
579 key = PKey()
580 self.assertRaises(TypeError, key.generate_key)
581 self.assertRaises(TypeError, key.generate_key, 1, 2, 3)
582 self.assertRaises(TypeError, key.generate_key, "foo", "bar")
583 self.assertRaises(Error, key.generate_key, -1, 0)
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500584
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500585 self.assertRaises(ValueError, key.generate_key, TYPE_RSA, -1)
586 self.assertRaises(ValueError, key.generate_key, TYPE_RSA, 0)
Jean-Paul Calderoned71fe982008-03-06 00:31:50 -0500587
588 # XXX RSA generation for small values of bits is fairly buggy in a wide
589 # range of OpenSSL versions. I need to figure out what the safe lower
590 # bound for a reasonable number of OpenSSL versions is and explicitly
591 # check for that in the wrapper. The failure behavior is typically an
592 # infinite loop inside OpenSSL.
593
594 # self.assertRaises(Error, key.generate_key, TYPE_RSA, 2)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500595
596 # XXX DSA generation seems happy with any number of bits. The DSS
597 # says bits must be between 512 and 1024 inclusive. OpenSSL's DSA
598 # generator doesn't seem to care about the upper limit at all. For
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500599 # the lower limit, it uses 512 if anything smaller is specified.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500600 # So, it doesn't seem possible to make generate_key fail for
601 # TYPE_DSA with a bits argument which is at least an int.
602
603 # self.assertRaises(Error, key.generate_key, TYPE_DSA, -7)
604
605
606 def test_rsaGeneration(self):
607 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900608 :py:meth:`PKeyType.generate_key` generates an RSA key when passed
609 :py:data:`TYPE_RSA` as a type and a reasonable number of bits.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500610 """
611 bits = 128
612 key = PKey()
613 key.generate_key(TYPE_RSA, bits)
614 self.assertEqual(key.type(), TYPE_RSA)
615 self.assertEqual(key.bits(), bits)
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -0400616 self.assertTrue(key.check())
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500617
618
619 def test_dsaGeneration(self):
620 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900621 :py:meth:`PKeyType.generate_key` generates a DSA key when passed
622 :py:data:`TYPE_DSA` as a type and a reasonable number of bits.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500623 """
624 # 512 is a magic number. The DSS (Digital Signature Standard)
625 # allows a minimum of 512 bits for DSA. DSA_generate_parameters
626 # will silently promote any value below 512 to 512.
627 bits = 512
628 key = PKey()
629 key.generate_key(TYPE_DSA, bits)
630 self.assertEqual(key.type(), TYPE_DSA)
631 self.assertEqual(key.bits(), bits)
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -0400632 self.assertRaises(TypeError, key.check)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500633
634
635 def test_regeneration(self):
636 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900637 :py:meth:`PKeyType.generate_key` can be called multiple times on the same
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500638 key to generate new keys.
639 """
640 key = PKey()
641 for type, bits in [(TYPE_RSA, 512), (TYPE_DSA, 576)]:
642 key.generate_key(type, bits)
643 self.assertEqual(key.type(), type)
644 self.assertEqual(key.bits(), bits)
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500645
646
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400647 def test_inconsistentKey(self):
648 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900649 :py:`PKeyType.check` returns :py:exc:`Error` if the key is not consistent.
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400650 """
651 key = load_privatekey(FILETYPE_PEM, inconsistentPrivateKeyPEM)
Jean-Paul Calderoned338e4e2009-05-13 15:45:07 -0400652 self.assertRaises(Error, key.check)
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400653
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500654
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400655 def test_check_wrong_args(self):
656 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900657 :py:meth:`PKeyType.check` raises :py:exc:`TypeError` if called with any arguments.
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400658 """
659 self.assertRaises(TypeError, PKey().check, None)
660 self.assertRaises(TypeError, PKey().check, object())
661 self.assertRaises(TypeError, PKey().check, 1)
662
663
Jean-Paul Calderone02d01972011-10-31 10:39:29 -0400664 def test_check_public_key(self):
665 """
666 :py:meth:`PKeyType.check` raises :py:exc:`TypeError` if only the public
667 part of the key is available.
668 """
669 # A trick to get a public-only key
670 key = PKey()
671 key.generate_key(TYPE_RSA, 512)
672 cert = X509()
673 cert.set_pubkey(key)
674 pub = cert.get_pubkey()
675 self.assertRaises(TypeError, pub.check)
676
677
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400678
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400679class X509NameTests(TestCase):
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500680 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900681 Unit tests for :py:class:`OpenSSL.crypto.X509Name`.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500682 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500683 def _x509name(self, **attrs):
684 # XXX There's no other way to get a new X509Name yet.
685 name = X509().get_subject()
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400686 attrs = list(attrs.items())
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500687 # Make the order stable - order matters!
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400688 def key(attr):
689 return attr[1]
690 attrs.sort(key=key)
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500691 for k, v in attrs:
692 setattr(name, k, v)
693 return name
694
695
Rick Deane15b1472009-07-09 15:53:42 -0500696 def test_type(self):
697 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900698 The type of X509Name objects is :py:class:`X509NameType`.
Rick Deane15b1472009-07-09 15:53:42 -0500699 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400700 self.assertIdentical(X509Name, X509NameType)
701 self.assertEqual(X509NameType.__name__, 'X509Name')
702 self.assertTrue(isinstance(X509NameType, type))
703
Rick Deane15b1472009-07-09 15:53:42 -0500704 name = self._x509name()
705 self.assertTrue(
706 isinstance(name, X509NameType),
707 "%r is of type %r, should be %r" % (
708 name, type(name), X509NameType))
Rick Deane15b1472009-07-09 15:53:42 -0500709
710
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400711 def test_onlyStringAttributes(self):
712 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900713 Attempting to set a non-:py:data:`str` attribute name on an :py:class:`X509NameType`
714 instance causes :py:exc:`TypeError` to be raised.
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400715 """
716 name = self._x509name()
717 # Beyond these cases, you may also think that unicode should be
718 # rejected. Sorry, you're wrong. unicode is automatically converted to
719 # str outside of the control of X509Name, so there's no way to reject
720 # it.
721 self.assertRaises(TypeError, setattr, name, None, "hello")
722 self.assertRaises(TypeError, setattr, name, 30, "hello")
723 class evil(str):
724 pass
725 self.assertRaises(TypeError, setattr, name, evil(), "hello")
726
727
728 def test_setInvalidAttribute(self):
729 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900730 Attempting to set any attribute name on an :py:class:`X509NameType` instance for
731 which no corresponding NID is defined causes :py:exc:`AttributeError` to be
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400732 raised.
733 """
734 name = self._x509name()
735 self.assertRaises(AttributeError, setattr, name, "no such thing", None)
736
737
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500738 def test_attributes(self):
739 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900740 :py:class:`X509NameType` instances have attributes for each standard (?)
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500741 X509Name field.
742 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500743 name = self._x509name()
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500744 name.commonName = "foo"
745 self.assertEqual(name.commonName, "foo")
746 self.assertEqual(name.CN, "foo")
747 name.CN = "baz"
748 self.assertEqual(name.commonName, "baz")
749 self.assertEqual(name.CN, "baz")
750 name.commonName = "bar"
751 self.assertEqual(name.commonName, "bar")
752 self.assertEqual(name.CN, "bar")
753 name.CN = "quux"
754 self.assertEqual(name.commonName, "quux")
755 self.assertEqual(name.CN, "quux")
756
757
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500758 def test_copy(self):
759 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900760 :py:class:`X509Name` creates a new :py:class:`X509NameType` instance with all the same
761 attributes as an existing :py:class:`X509NameType` instance when called with
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500762 one.
763 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500764 name = self._x509name(commonName="foo", emailAddress="bar@example.com")
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500765
766 copy = X509Name(name)
767 self.assertEqual(copy.commonName, "foo")
768 self.assertEqual(copy.emailAddress, "bar@example.com")
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500769
770 # Mutate the copy and ensure the original is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500771 copy.commonName = "baz"
772 self.assertEqual(name.commonName, "foo")
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500773
774 # Mutate the original and ensure the copy is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500775 name.emailAddress = "quux@example.com"
776 self.assertEqual(copy.emailAddress, "bar@example.com")
777
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500778
779 def test_repr(self):
780 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900781 :py:func:`repr` passed an :py:class:`X509NameType` instance should return a string
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500782 containing a description of the type and the NIDs which have been set
783 on it.
784 """
785 name = self._x509name(commonName="foo", emailAddress="bar")
786 self.assertEqual(
787 repr(name),
788 "<X509Name object '/emailAddress=bar/CN=foo'>")
789
790
791 def test_comparison(self):
792 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900793 :py:class:`X509NameType` instances should compare based on their NIDs.
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500794 """
795 def _equality(a, b, assertTrue, assertFalse):
796 assertTrue(a == b, "(%r == %r) --> False" % (a, b))
797 assertFalse(a != b)
798 assertTrue(b == a)
799 assertFalse(b != a)
800
801 def assertEqual(a, b):
802 _equality(a, b, self.assertTrue, self.assertFalse)
803
804 # Instances compare equal to themselves.
805 name = self._x509name()
806 assertEqual(name, name)
807
808 # Empty instances should compare equal to each other.
809 assertEqual(self._x509name(), self._x509name())
810
811 # Instances with equal NIDs should compare equal to each other.
812 assertEqual(self._x509name(commonName="foo"),
813 self._x509name(commonName="foo"))
814
815 # Instance with equal NIDs set using different aliases should compare
816 # equal to each other.
817 assertEqual(self._x509name(commonName="foo"),
818 self._x509name(CN="foo"))
819
820 # Instances with more than one NID with the same values should compare
821 # equal to each other.
822 assertEqual(self._x509name(CN="foo", organizationalUnitName="bar"),
823 self._x509name(commonName="foo", OU="bar"))
824
825 def assertNotEqual(a, b):
826 _equality(a, b, self.assertFalse, self.assertTrue)
827
828 # Instances with different values for the same NID should not compare
829 # equal to each other.
830 assertNotEqual(self._x509name(CN="foo"),
831 self._x509name(CN="bar"))
832
833 # Instances with different NIDs should not compare equal to each other.
834 assertNotEqual(self._x509name(CN="foo"),
835 self._x509name(OU="foo"))
836
837 def _inequality(a, b, assertTrue, assertFalse):
838 assertTrue(a < b)
839 assertTrue(a <= b)
840 assertTrue(b > a)
841 assertTrue(b >= a)
842 assertFalse(a > b)
843 assertFalse(a >= b)
844 assertFalse(b < a)
845 assertFalse(b <= a)
846
847 def assertLessThan(a, b):
848 _inequality(a, b, self.assertTrue, self.assertFalse)
849
850 # An X509Name with a NID with a value which sorts less than the value
851 # of the same NID on another X509Name compares less than the other
852 # X509Name.
853 assertLessThan(self._x509name(CN="abc"),
854 self._x509name(CN="def"))
855
856 def assertGreaterThan(a, b):
857 _inequality(a, b, self.assertFalse, self.assertTrue)
858
859 # An X509Name with a NID with a value which sorts greater than the
860 # value of the same NID on another X509Name compares greater than the
861 # other X509Name.
862 assertGreaterThan(self._x509name(CN="def"),
863 self._x509name(CN="abc"))
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -0500864
865
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400866 def test_hash(self):
867 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900868 :py:meth:`X509Name.hash` returns an integer hash based on the value of the
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400869 name.
870 """
871 a = self._x509name(CN="foo")
872 b = self._x509name(CN="foo")
873 self.assertEqual(a.hash(), b.hash())
874 a.CN = "bar"
875 self.assertNotEqual(a.hash(), b.hash())
876
877
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400878 def test_der(self):
879 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900880 :py:meth:`X509Name.der` returns the DER encoded form of the name.
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400881 """
882 a = self._x509name(CN="foo", C="US")
883 self.assertEqual(
884 a.der(),
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -0400885 b('0\x1b1\x0b0\t\x06\x03U\x04\x06\x13\x02US'
886 '1\x0c0\n\x06\x03U\x04\x03\x13\x03foo'))
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400887
888
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400889 def test_get_components(self):
890 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900891 :py:meth:`X509Name.get_components` returns a :py:data:`list` of
892 two-tuples of :py:data:`str`
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400893 giving the NIDs and associated values which make up the name.
894 """
895 a = self._x509name()
896 self.assertEqual(a.get_components(), [])
897 a.CN = "foo"
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -0400898 self.assertEqual(a.get_components(), [(b("CN"), b("foo"))])
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400899 a.organizationalUnitName = "bar"
900 self.assertEqual(
901 a.get_components(),
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -0400902 [(b("CN"), b("foo")), (b("OU"), b("bar"))])
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400903
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400904
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400905 def test_load_nul_byte_attribute(self):
906 """
Jean-Paul Calderone9af07b02013-08-23 16:07:31 -0400907 An :py:class:`OpenSSL.crypto.X509Name` from an
908 :py:class:`OpenSSL.crypto.X509` instance loaded from a file can have a
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400909 NUL byte in the value of one of its attributes.
910 """
911 cert = load_certificate(FILETYPE_PEM, nulbyteSubjectAltNamePEM)
912 subject = cert.get_subject()
913 self.assertEqual(
Jean-Paul Calderone06754fc2013-08-23 15:47:47 -0400914 "null.python.org\x00example.org", subject.commonName)
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400915
916
917
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400918class _PKeyInteractionTestsMixin:
919 """
920 Tests which involve another thing and a PKey.
921 """
922 def signable(self):
923 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900924 Return something with a :py:meth:`set_pubkey`, :py:meth:`set_pubkey`,
925 and :py:meth:`sign` method.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400926 """
927 raise NotImplementedError()
928
929
930 def test_signWithUngenerated(self):
931 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900932 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when pass a
933 :py:class:`PKey` with no parts.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400934 """
935 request = self.signable()
936 key = PKey()
937 self.assertRaises(ValueError, request.sign, key, 'MD5')
938
939
940 def test_signWithPublicKey(self):
941 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900942 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when pass a
943 :py:class:`PKey` with no private part as the signing key.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400944 """
945 request = self.signable()
946 key = PKey()
947 key.generate_key(TYPE_RSA, 512)
948 request.set_pubkey(key)
949 pub = request.get_pubkey()
950 self.assertRaises(ValueError, request.sign, pub, 'MD5')
951
952
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -0400953 def test_signWithUnknownDigest(self):
954 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900955 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when passed a digest name which is
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -0400956 not known.
957 """
958 request = self.signable()
959 key = PKey()
960 key.generate_key(TYPE_RSA, 512)
961 self.assertRaises(ValueError, request.sign, key, "monkeys")
962
963
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -0400964 def test_sign(self):
965 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900966 :py:meth:`X509Req.sign` succeeds when passed a private key object and a valid
967 digest function. :py:meth:`X509Req.verify` can be used to check the signature.
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -0400968 """
969 request = self.signable()
970 key = PKey()
971 key.generate_key(TYPE_RSA, 512)
972 request.set_pubkey(key)
973 request.sign(key, 'MD5')
974 # If the type has a verify method, cover that too.
975 if getattr(request, 'verify', None) is not None:
976 pub = request.get_pubkey()
977 self.assertTrue(request.verify(pub))
978 # Make another key that won't verify.
979 key = PKey()
980 key.generate_key(TYPE_RSA, 512)
981 self.assertRaises(Error, request.verify, key)
982
983
984
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400985
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400986class X509ReqTests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -0500987 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900988 Tests for :py:class:`OpenSSL.crypto.X509Req`.
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -0500989 """
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400990 def signable(self):
991 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900992 Create and return a new :py:class:`X509Req`.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400993 """
994 return X509Req()
995
996
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400997 def test_type(self):
998 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900999 :py:obj:`X509Req` and :py:obj:`X509ReqType` refer to the same type object and can be
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001000 used to create instances of that type.
1001 """
1002 self.assertIdentical(X509Req, X509ReqType)
1003 self.assertConsistentType(X509Req, 'X509Req')
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001004
1005
1006 def test_construction(self):
1007 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001008 :py:obj:`X509Req` takes no arguments and returns an :py:obj:`X509ReqType` instance.
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001009 """
1010 request = X509Req()
1011 self.assertTrue(
1012 isinstance(request, X509ReqType),
1013 "%r is of type %r, should be %r" % (request, type(request), X509ReqType))
1014
1015
Jean-Paul Calderone8dd19b82008-12-28 20:41:16 -05001016 def test_version(self):
1017 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001018 :py:obj:`X509ReqType.set_version` sets the X.509 version of the certificate
1019 request. :py:obj:`X509ReqType.get_version` returns the X.509 version of
Jean-Paul Calderone8dd19b82008-12-28 20:41:16 -05001020 the certificate request. The initial value of the version is 0.
1021 """
1022 request = X509Req()
1023 self.assertEqual(request.get_version(), 0)
1024 request.set_version(1)
1025 self.assertEqual(request.get_version(), 1)
1026 request.set_version(3)
1027 self.assertEqual(request.get_version(), 3)
1028
1029
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001030 def test_version_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001031 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001032 :py:obj:`X509ReqType.set_version` raises :py:obj:`TypeError` if called with the wrong
1033 number of arguments or with a non-:py:obj:`int` argument.
1034 :py:obj:`X509ReqType.get_version` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001035 arguments.
1036 """
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001037 request = X509Req()
1038 self.assertRaises(TypeError, request.set_version)
1039 self.assertRaises(TypeError, request.set_version, "foo")
1040 self.assertRaises(TypeError, request.set_version, 1, 2)
1041 self.assertRaises(TypeError, request.get_version, None)
1042
1043
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001044 def test_get_subject(self):
1045 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001046 :py:obj:`X509ReqType.get_subject` returns an :py:obj:`X509Name` for the subject of
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001047 the request and which is valid even after the request object is
1048 otherwise dead.
1049 """
1050 request = X509Req()
1051 subject = request.get_subject()
1052 self.assertTrue(
1053 isinstance(subject, X509NameType),
1054 "%r is of type %r, should be %r" % (subject, type(subject), X509NameType))
1055 subject.commonName = "foo"
1056 self.assertEqual(request.get_subject().commonName, "foo")
1057 del request
1058 subject.commonName = "bar"
1059 self.assertEqual(subject.commonName, "bar")
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001060
1061
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001062 def test_get_subject_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001063 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001064 :py:obj:`X509ReqType.get_subject` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001065 arguments.
1066 """
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001067 request = X509Req()
1068 self.assertRaises(TypeError, request.get_subject, None)
1069
1070
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001071 def test_add_extensions(self):
1072 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001073 :py:obj:`X509Req.add_extensions` accepts a :py:obj:`list` of :py:obj:`X509Extension`
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001074 instances and adds them to the X509 request.
1075 """
1076 request = X509Req()
1077 request.add_extensions([
Jean-Paul Calderonee16f9f32010-08-22 19:20:37 -04001078 X509Extension(b('basicConstraints'), True, b('CA:false'))])
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001079 # XXX Add get_extensions so the rest of this unit test can be written.
1080
1081
1082 def test_add_extensions_wrong_args(self):
1083 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001084 :py:obj:`X509Req.add_extensions` raises :py:obj:`TypeError` if called with the wrong
1085 number of arguments or with a non-:py:obj:`list`. Or it raises :py:obj:`ValueError`
1086 if called with a :py:obj:`list` containing objects other than :py:obj:`X509Extension`
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001087 instances.
1088 """
1089 request = X509Req()
1090 self.assertRaises(TypeError, request.add_extensions)
1091 self.assertRaises(TypeError, request.add_extensions, object())
1092 self.assertRaises(ValueError, request.add_extensions, [object()])
1093 self.assertRaises(TypeError, request.add_extensions, [], None)
1094
1095
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001096
Jean-Paul Calderone18808652009-07-05 12:54:05 -04001097class X509Tests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001098 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001099 Tests for :py:obj:`OpenSSL.crypto.X509`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001100 """
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001101 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
Jean-Paul Calderone8114b452008-03-25 15:27:59 -04001102
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001103 extpem = """
1104-----BEGIN CERTIFICATE-----
1105MIIC3jCCAkegAwIBAgIJAJHFjlcCgnQzMA0GCSqGSIb3DQEBBQUAMEcxCzAJBgNV
1106BAYTAlNFMRUwEwYDVQQIEwxXZXN0ZXJib3R0b20xEjAQBgNVBAoTCUNhdGFsb2dp
1107eDENMAsGA1UEAxMEUm9vdDAeFw0wODA0MjIxNDQ1MzhaFw0wOTA0MjIxNDQ1Mzha
1108MFQxCzAJBgNVBAYTAlNFMQswCQYDVQQIEwJXQjEUMBIGA1UEChMLT3Blbk1ldGFk
1109aXIxIjAgBgNVBAMTGW5vZGUxLm9tMi5vcGVubWV0YWRpci5vcmcwgZ8wDQYJKoZI
1110hvcNAQEBBQADgY0AMIGJAoGBAPIcQMrwbk2nESF/0JKibj9i1x95XYAOwP+LarwT
1111Op4EQbdlI9SY+uqYqlERhF19w7CS+S6oyqx0DRZSk4Y9dZ9j9/xgm2u/f136YS1u
1112zgYFPvfUs6PqYLPSM8Bw+SjJ+7+2+TN+Tkiof9WP1cMjodQwOmdsiRbR0/J7+b1B
1113hec1AgMBAAGjgcQwgcEwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNT
1114TCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFIdHsBcMVVMbAO7j6NCj
111503HgLnHaMB8GA1UdIwQYMBaAFL2h9Bf9Mre4vTdOiHTGAt7BRY/8MEYGA1UdEQQ/
1116MD2CDSouZXhhbXBsZS5vcmeCESoub20yLmV4bWFwbGUuY29thwSC7wgKgRNvbTJA
1117b3Blbm1ldGFkaXIub3JnMA0GCSqGSIb3DQEBBQUAA4GBALd7WdXkp2KvZ7/PuWZA
1118MPlIxyjS+Ly11+BNE0xGQRp9Wz+2lABtpgNqssvU156+HkKd02rGheb2tj7MX9hG
1119uZzbwDAZzJPjzDQDD7d3cWsrVcfIdqVU7epHqIadnOF+X0ghJ39pAm6VVadnSXCt
1120WpOdIpB8KksUTCzV591Nr1wd
1121-----END CERTIFICATE-----
1122 """
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001123 def signable(self):
1124 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001125 Create and return a new :py:obj:`X509`.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001126 """
1127 return X509()
1128
1129
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001130 def test_type(self):
1131 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001132 :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 -04001133 to create instances of that type.
1134 """
1135 self.assertIdentical(X509, X509Type)
1136 self.assertConsistentType(X509, 'X509')
1137
1138
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001139 def test_construction(self):
1140 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001141 :py:obj:`X509` takes no arguments and returns an instance of :py:obj:`X509Type`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001142 """
1143 certificate = X509()
1144 self.assertTrue(
1145 isinstance(certificate, X509Type),
1146 "%r is of type %r, should be %r" % (certificate,
1147 type(certificate),
1148 X509Type))
Rick Deane15b1472009-07-09 15:53:42 -05001149 self.assertEqual(type(X509Type).__name__, 'type')
1150 self.assertEqual(type(certificate).__name__, 'X509')
1151 self.assertEqual(type(certificate), X509Type)
Rick Dean04113e72009-07-16 12:06:35 -05001152 self.assertEqual(type(certificate), X509)
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001153
1154
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001155 def test_get_version_wrong_args(self):
1156 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001157 :py:obj:`X509.get_version` raises :py:obj:`TypeError` if invoked with any arguments.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001158 """
1159 cert = X509()
1160 self.assertRaises(TypeError, cert.get_version, None)
1161
1162
1163 def test_set_version_wrong_args(self):
1164 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001165 :py:obj:`X509.set_version` raises :py:obj:`TypeError` if invoked with the wrong number
1166 of arguments or an argument not of type :py:obj:`int`.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001167 """
1168 cert = X509()
1169 self.assertRaises(TypeError, cert.set_version)
1170 self.assertRaises(TypeError, cert.set_version, None)
1171 self.assertRaises(TypeError, cert.set_version, 1, None)
1172
1173
1174 def test_version(self):
1175 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001176 :py:obj:`X509.set_version` sets the certificate version number.
1177 :py:obj:`X509.get_version` retrieves it.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001178 """
1179 cert = X509()
1180 cert.set_version(1234)
1181 self.assertEquals(cert.get_version(), 1234)
1182
1183
1184 def test_get_serial_number_wrong_args(self):
1185 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001186 :py:obj:`X509.get_serial_number` raises :py:obj:`TypeError` if invoked with any
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001187 arguments.
1188 """
1189 cert = X509()
1190 self.assertRaises(TypeError, cert.get_serial_number, None)
1191
1192
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001193 def test_serial_number(self):
1194 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001195 The serial number of an :py:obj:`X509Type` can be retrieved and modified with
1196 :py:obj:`X509Type.get_serial_number` and :py:obj:`X509Type.set_serial_number`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001197 """
1198 certificate = X509()
1199 self.assertRaises(TypeError, certificate.set_serial_number)
1200 self.assertRaises(TypeError, certificate.set_serial_number, 1, 2)
1201 self.assertRaises(TypeError, certificate.set_serial_number, "1")
1202 self.assertRaises(TypeError, certificate.set_serial_number, 5.5)
1203 self.assertEqual(certificate.get_serial_number(), 0)
1204 certificate.set_serial_number(1)
1205 self.assertEqual(certificate.get_serial_number(), 1)
1206 certificate.set_serial_number(2 ** 32 + 1)
1207 self.assertEqual(certificate.get_serial_number(), 2 ** 32 + 1)
1208 certificate.set_serial_number(2 ** 64 + 1)
1209 self.assertEqual(certificate.get_serial_number(), 2 ** 64 + 1)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001210 certificate.set_serial_number(2 ** 128 + 1)
1211 self.assertEqual(certificate.get_serial_number(), 2 ** 128 + 1)
1212
1213
1214 def _setBoundTest(self, which):
1215 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001216 :py:obj:`X509Type.set_notBefore` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001217 GENERALIZEDTIME and sets the beginning of the certificate's validity
1218 period to it.
1219 """
1220 certificate = X509()
1221 set = getattr(certificate, 'set_not' + which)
1222 get = getattr(certificate, 'get_not' + which)
1223
Jean-Paul Calderonee0615b52008-03-09 21:44:46 -04001224 # Starts with no value.
1225 self.assertEqual(get(), None)
1226
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001227 # GMT (Or is it UTC?) -exarkun
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001228 when = b("20040203040506Z")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001229 set(when)
1230 self.assertEqual(get(), when)
1231
1232 # A plus two hours and thirty minutes offset
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001233 when = b("20040203040506+0530")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001234 set(when)
1235 self.assertEqual(get(), when)
1236
1237 # A minus one hour fifteen minutes offset
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001238 when = b("20040203040506-0115")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001239 set(when)
1240 self.assertEqual(get(), when)
1241
1242 # An invalid string results in a ValueError
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001243 self.assertRaises(ValueError, set, b("foo bar"))
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001244
Jean-Paul Calderone31ca2002010-01-30 15:14:43 -05001245 # The wrong number of arguments results in a TypeError.
1246 self.assertRaises(TypeError, set)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001247 self.assertRaises(TypeError, set, b("20040203040506Z"), b("20040203040506Z"))
1248 self.assertRaises(TypeError, get, b("foo bar"))
1249
Jean-Paul Calderone31ca2002010-01-30 15:14:43 -05001250
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001251 # XXX ASN1_TIME (not GENERALIZEDTIME)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001252
1253 def test_set_notBefore(self):
1254 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001255 :py:obj:`X509Type.set_notBefore` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001256 GENERALIZEDTIME and sets the beginning of the certificate's validity
1257 period to it.
1258 """
1259 self._setBoundTest("Before")
1260
1261
1262 def test_set_notAfter(self):
1263 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001264 :py:obj:`X509Type.set_notAfter` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001265 GENERALIZEDTIME and sets the end of the certificate's validity period
1266 to it.
1267 """
1268 self._setBoundTest("After")
Jean-Paul Calderone76576d52008-03-24 16:04:46 -04001269
1270
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001271 def test_get_notBefore(self):
1272 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001273 :py:obj:`X509Type.get_notBefore` returns a string in the format of an ASN1
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001274 GENERALIZEDTIME even for certificates which store it as UTCTIME
1275 internally.
1276 """
Jean-Paul Calderone8114b452008-03-25 15:27:59 -04001277 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001278 self.assertEqual(cert.get_notBefore(), b("20090325123658Z"))
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001279
Rick Dean38a05c82009-07-18 01:41:30 -05001280
1281 def test_get_notAfter(self):
1282 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001283 :py:obj:`X509Type.get_notAfter` returns a string in the format of an ASN1
Rick Dean38a05c82009-07-18 01:41:30 -05001284 GENERALIZEDTIME even for certificates which store it as UTCTIME
1285 internally.
1286 """
1287 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001288 self.assertEqual(cert.get_notAfter(), b("20170611123658Z"))
Rick Dean38a05c82009-07-18 01:41:30 -05001289
1290
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001291 def test_gmtime_adj_notBefore_wrong_args(self):
1292 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001293 :py:obj:`X509Type.gmtime_adj_notBefore` raises :py:obj:`TypeError` if called with the
1294 wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001295 """
1296 cert = X509()
1297 self.assertRaises(TypeError, cert.gmtime_adj_notBefore)
1298 self.assertRaises(TypeError, cert.gmtime_adj_notBefore, None)
1299 self.assertRaises(TypeError, cert.gmtime_adj_notBefore, 123, None)
1300
1301
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001302 def test_gmtime_adj_notBefore(self):
1303 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001304 :py:obj:`X509Type.gmtime_adj_notBefore` changes the not-before timestamp to be
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001305 the current time plus the number of seconds passed in.
1306 """
1307 cert = load_certificate(FILETYPE_PEM, self.pemData)
1308 now = datetime.utcnow() + timedelta(seconds=100)
1309 cert.gmtime_adj_notBefore(100)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001310 self.assertEqual(cert.get_notBefore(), b(now.strftime("%Y%m%d%H%M%SZ")))
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001311
1312
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001313 def test_gmtime_adj_notAfter_wrong_args(self):
1314 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001315 :py:obj:`X509Type.gmtime_adj_notAfter` raises :py:obj:`TypeError` if called with the
1316 wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001317 """
1318 cert = X509()
1319 self.assertRaises(TypeError, cert.gmtime_adj_notAfter)
1320 self.assertRaises(TypeError, cert.gmtime_adj_notAfter, None)
1321 self.assertRaises(TypeError, cert.gmtime_adj_notAfter, 123, None)
1322
1323
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001324 def test_gmtime_adj_notAfter(self):
1325 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001326 :py:obj:`X509Type.gmtime_adj_notAfter` changes the not-after timestamp to be
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001327 the current time plus the number of seconds passed in.
1328 """
1329 cert = load_certificate(FILETYPE_PEM, self.pemData)
1330 now = datetime.utcnow() + timedelta(seconds=100)
1331 cert.gmtime_adj_notAfter(100)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001332 self.assertEqual(cert.get_notAfter(), b(now.strftime("%Y%m%d%H%M%SZ")))
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001333
1334
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001335 def test_has_expired_wrong_args(self):
1336 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001337 :py:obj:`X509Type.has_expired` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001338 arguments.
1339 """
1340 cert = X509()
1341 self.assertRaises(TypeError, cert.has_expired, None)
1342
1343
1344 def test_has_expired(self):
1345 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001346 :py:obj:`X509Type.has_expired` returns :py:obj:`True` if the certificate's not-after
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001347 time is in the past.
1348 """
1349 cert = X509()
1350 cert.gmtime_adj_notAfter(-1)
1351 self.assertTrue(cert.has_expired())
1352
1353
1354 def test_has_not_expired(self):
1355 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001356 :py:obj:`X509Type.has_expired` returns :py:obj:`False` if the certificate's not-after
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001357 time is in the future.
1358 """
1359 cert = X509()
1360 cert.gmtime_adj_notAfter(2)
1361 self.assertFalse(cert.has_expired())
1362
1363
Rick Dean38a05c82009-07-18 01:41:30 -05001364 def test_digest(self):
1365 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001366 :py:obj:`X509.digest` returns a string giving ":"-separated hex-encoded words
Rick Dean38a05c82009-07-18 01:41:30 -05001367 of the digest of the certificate.
1368 """
1369 cert = X509()
1370 self.assertEqual(
1371 cert.digest("md5"),
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001372 b("A8:EB:07:F8:53:25:0A:F2:56:05:C5:A5:C4:C4:C7:15"))
Rick Dean38a05c82009-07-18 01:41:30 -05001373
1374
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001375 def _extcert(self, pkey, extensions):
1376 cert = X509()
1377 cert.set_pubkey(pkey)
1378 cert.get_subject().commonName = "Unit Tests"
1379 cert.get_issuer().commonName = "Unit Tests"
1380 when = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
1381 cert.set_notBefore(when)
1382 cert.set_notAfter(when)
1383
1384 cert.add_extensions(extensions)
1385 return load_certificate(
1386 FILETYPE_PEM, dump_certificate(FILETYPE_PEM, cert))
1387
1388
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001389 def test_extension_count(self):
1390 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001391 :py:obj:`X509.get_extension_count` returns the number of extensions that are
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001392 present in the certificate.
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001393 """
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001394 pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001395 ca = X509Extension(b('basicConstraints'), True, b('CA:FALSE'))
1396 key = X509Extension(b('keyUsage'), True, b('digitalSignature'))
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001397 subjectAltName = X509Extension(
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001398 b('subjectAltName'), True, b('DNS:example.com'))
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001399
1400 # Try a certificate with no extensions at all.
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001401 c = self._extcert(pkey, [])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001402 self.assertEqual(c.get_extension_count(), 0)
1403
1404 # And a certificate with one
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001405 c = self._extcert(pkey, [ca])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001406 self.assertEqual(c.get_extension_count(), 1)
1407
1408 # And a certificate with several
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001409 c = self._extcert(pkey, [ca, key, subjectAltName])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001410 self.assertEqual(c.get_extension_count(), 3)
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001411
1412
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001413 def test_get_extension(self):
1414 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001415 :py:obj:`X509.get_extension` takes an integer and returns an :py:obj:`X509Extension`
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001416 corresponding to the extension at that index.
1417 """
1418 pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001419 ca = X509Extension(b('basicConstraints'), True, b('CA:FALSE'))
1420 key = X509Extension(b('keyUsage'), True, b('digitalSignature'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001421 subjectAltName = X509Extension(
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001422 b('subjectAltName'), False, b('DNS:example.com'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001423
1424 cert = self._extcert(pkey, [ca, key, subjectAltName])
1425
1426 ext = cert.get_extension(0)
1427 self.assertTrue(isinstance(ext, X509Extension))
1428 self.assertTrue(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001429 self.assertEqual(ext.get_short_name(), b('basicConstraints'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001430
1431 ext = cert.get_extension(1)
1432 self.assertTrue(isinstance(ext, X509Extension))
1433 self.assertTrue(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001434 self.assertEqual(ext.get_short_name(), b('keyUsage'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001435
1436 ext = cert.get_extension(2)
1437 self.assertTrue(isinstance(ext, X509Extension))
1438 self.assertFalse(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001439 self.assertEqual(ext.get_short_name(), b('subjectAltName'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001440
1441 self.assertRaises(IndexError, cert.get_extension, -1)
1442 self.assertRaises(IndexError, cert.get_extension, 4)
1443 self.assertRaises(TypeError, cert.get_extension, "hello")
1444
1445
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001446 def test_nullbyte_subjectAltName(self):
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001447 """
Jean-Paul Calderone9af07b02013-08-23 16:07:31 -04001448 The fields of a `subjectAltName` extension on an X509 may contain NUL
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001449 bytes and this value is reflected in the string representation of the
1450 extension object.
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001451 """
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001452 cert = load_certificate(FILETYPE_PEM, nulbyteSubjectAltNamePEM)
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001453
1454 ext = cert.get_extension(3)
1455 self.assertEqual(ext.get_short_name(), b('subjectAltName'))
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001456 self.assertEqual(
1457 b("DNS:altnull.python.org\x00example.com, "
1458 "email:null@python.org\x00user@example.org, "
1459 "URI:http://null.python.org\x00http://example.org, "
1460 "IP Address:192.0.2.1, IP Address:2001:DB8:0:0:0:0:0:1\n"),
1461 b(str(ext)))
1462
Rick Dean38a05c82009-07-18 01:41:30 -05001463
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001464 def test_invalid_digest_algorithm(self):
1465 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001466 :py:obj:`X509.digest` raises :py:obj:`ValueError` if called with an unrecognized hash
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001467 algorithm.
1468 """
1469 cert = X509()
1470 self.assertRaises(ValueError, cert.digest, "monkeys")
1471
1472
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001473 def test_get_subject_wrong_args(self):
1474 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001475 :py:obj:`X509.get_subject` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001476 """
1477 cert = X509()
1478 self.assertRaises(TypeError, cert.get_subject, None)
1479
1480
1481 def test_get_subject(self):
1482 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001483 :py:obj:`X509.get_subject` returns an :py:obj:`X509Name` instance.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001484 """
1485 cert = load_certificate(FILETYPE_PEM, self.pemData)
1486 subj = cert.get_subject()
1487 self.assertTrue(isinstance(subj, X509Name))
1488 self.assertEquals(
1489 subj.get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001490 [(b('C'), b('US')), (b('ST'), b('IL')), (b('L'), b('Chicago')),
1491 (b('O'), b('Testing')), (b('CN'), b('Testing Root CA'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001492
1493
1494 def test_set_subject_wrong_args(self):
1495 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001496 :py:obj:`X509.set_subject` raises a :py:obj:`TypeError` if called with the wrong
1497 number of arguments or an argument not of type :py:obj:`X509Name`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001498 """
1499 cert = X509()
1500 self.assertRaises(TypeError, cert.set_subject)
1501 self.assertRaises(TypeError, cert.set_subject, None)
1502 self.assertRaises(TypeError, cert.set_subject, cert.get_subject(), None)
1503
1504
1505 def test_set_subject(self):
1506 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001507 :py:obj:`X509.set_subject` changes the subject of the certificate to the one
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001508 passed in.
1509 """
1510 cert = X509()
1511 name = cert.get_subject()
1512 name.C = 'AU'
1513 name.O = 'Unit Tests'
1514 cert.set_subject(name)
1515 self.assertEquals(
1516 cert.get_subject().get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001517 [(b('C'), b('AU')), (b('O'), b('Unit Tests'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001518
1519
1520 def test_get_issuer_wrong_args(self):
1521 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001522 :py:obj:`X509.get_issuer` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001523 """
1524 cert = X509()
1525 self.assertRaises(TypeError, cert.get_issuer, None)
1526
1527
1528 def test_get_issuer(self):
1529 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001530 :py:obj:`X509.get_issuer` returns an :py:obj:`X509Name` instance.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001531 """
1532 cert = load_certificate(FILETYPE_PEM, self.pemData)
1533 subj = cert.get_issuer()
1534 self.assertTrue(isinstance(subj, X509Name))
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001535 comp = subj.get_components()
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001536 self.assertEquals(
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001537 comp,
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001538 [(b('C'), b('US')), (b('ST'), b('IL')), (b('L'), b('Chicago')),
1539 (b('O'), b('Testing')), (b('CN'), b('Testing Root CA'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001540
1541
1542 def test_set_issuer_wrong_args(self):
1543 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001544 :py:obj:`X509.set_issuer` raises a :py:obj:`TypeError` if called with the wrong
1545 number of arguments or an argument not of type :py:obj:`X509Name`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001546 """
1547 cert = X509()
1548 self.assertRaises(TypeError, cert.set_issuer)
1549 self.assertRaises(TypeError, cert.set_issuer, None)
1550 self.assertRaises(TypeError, cert.set_issuer, cert.get_issuer(), None)
1551
1552
1553 def test_set_issuer(self):
1554 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001555 :py:obj:`X509.set_issuer` changes the issuer of the certificate to the one
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001556 passed in.
1557 """
1558 cert = X509()
1559 name = cert.get_issuer()
1560 name.C = 'AU'
1561 name.O = 'Unit Tests'
1562 cert.set_issuer(name)
1563 self.assertEquals(
1564 cert.get_issuer().get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001565 [(b('C'), b('AU')), (b('O'), b('Unit Tests'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001566
1567
1568 def test_get_pubkey_uninitialized(self):
1569 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001570 When called on a certificate with no public key, :py:obj:`X509.get_pubkey`
1571 raises :py:obj:`OpenSSL.crypto.Error`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001572 """
1573 cert = X509()
1574 self.assertRaises(Error, cert.get_pubkey)
1575
1576
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001577 def test_subject_name_hash_wrong_args(self):
1578 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001579 :py:obj:`X509.subject_name_hash` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001580 arguments.
1581 """
1582 cert = X509()
1583 self.assertRaises(TypeError, cert.subject_name_hash, None)
1584
1585
1586 def test_subject_name_hash(self):
1587 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001588 :py:obj:`X509.subject_name_hash` returns the hash of the certificate's subject
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001589 name.
1590 """
1591 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -04001592 self.assertIn(
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001593 cert.subject_name_hash(),
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -04001594 [3350047874, # OpenSSL 0.9.8, MD5
1595 3278919224, # OpenSSL 1.0.0, SHA1
1596 ])
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001597
1598
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001599 def test_get_signature_algorithm(self):
1600 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001601 :py:obj:`X509Type.get_signature_algorithm` returns a string which means
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001602 the algorithm used to sign the certificate.
1603 """
1604 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001605 self.assertEqual(
1606 b("sha1WithRSAEncryption"), cert.get_signature_algorithm())
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001607
1608
1609 def test_get_undefined_signature_algorithm(self):
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001610 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001611 :py:obj:`X509Type.get_signature_algorithm` raises :py:obj:`ValueError` if the
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001612 signature algorithm is undefined or unknown.
1613 """
1614 # This certificate has been modified to indicate a bogus OID in the
1615 # signature algorithm field so that OpenSSL does not recognize it.
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001616 certPEM = """\
1617-----BEGIN CERTIFICATE-----
1618MIIC/zCCAmigAwIBAgIBATAGBgJ8BQUAMHsxCzAJBgNVBAYTAlNHMREwDwYDVQQK
1619EwhNMkNyeXB0bzEUMBIGA1UECxMLTTJDcnlwdG8gQ0ExJDAiBgNVBAMTG00yQ3J5
1620cHRvIENlcnRpZmljYXRlIE1hc3RlcjEdMBsGCSqGSIb3DQEJARYObmdwc0Bwb3N0
1621MS5jb20wHhcNMDAwOTEwMDk1MTMwWhcNMDIwOTEwMDk1MTMwWjBTMQswCQYDVQQG
1622EwJTRzERMA8GA1UEChMITTJDcnlwdG8xEjAQBgNVBAMTCWxvY2FsaG9zdDEdMBsG
1623CSqGSIb3DQEJARYObmdwc0Bwb3N0MS5jb20wXDANBgkqhkiG9w0BAQEFAANLADBI
1624AkEArL57d26W9fNXvOhNlZzlPOACmvwOZ5AdNgLzJ1/MfsQQJ7hHVeHmTAjM664V
1625+fXvwUGJLziCeBo1ysWLRnl8CQIDAQABo4IBBDCCAQAwCQYDVR0TBAIwADAsBglg
1626hkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0O
1627BBYEFM+EgpK+eyZiwFU1aOPSbczbPSpVMIGlBgNVHSMEgZ0wgZqAFPuHI2nrnDqT
1628FeXFvylRT/7tKDgBoX+kfTB7MQswCQYDVQQGEwJTRzERMA8GA1UEChMITTJDcnlw
1629dG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtNMkNyeXB0byBDZXJ0
1630aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tggEA
1631MA0GCSqGSIb3DQEBBAUAA4GBADv8KpPo+gfJxN2ERK1Y1l17sz/ZhzoGgm5XCdbx
1632jEY7xKfpQngV599k1xhl11IMqizDwu0855agrckg2MCTmOI9DZzDD77tAYb+Dk0O
1633PEVk0Mk/V0aIsDE9bolfCi/i/QWZ3N8s5nTWMNyBBBmoSliWCm4jkkRZRD0ejgTN
1634tgI5
1635-----END CERTIFICATE-----
1636"""
1637 cert = load_certificate(FILETYPE_PEM, certPEM)
1638 self.assertRaises(ValueError, cert.get_signature_algorithm)
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001639
1640
Rick Dean38a05c82009-07-18 01:41:30 -05001641
Rick Dean623ee362009-07-17 12:22:16 -05001642class PKCS12Tests(TestCase):
1643 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001644 Test for :py:obj:`OpenSSL.crypto.PKCS12` and :py:obj:`OpenSSL.crypto.load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001645 """
1646 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
1647
Jean-Paul Calderonec3a41f72009-07-25 12:36:02 -04001648 def test_type(self):
1649 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001650 :py:obj:`PKCS12Type` is a type object.
Jean-Paul Calderonec3a41f72009-07-25 12:36:02 -04001651 """
1652 self.assertIdentical(PKCS12, PKCS12Type)
1653 self.assertConsistentType(PKCS12, 'PKCS12')
1654
1655
Rick Deanf94096c2009-07-18 14:23:06 -05001656 def test_empty_construction(self):
Rick Dean38a05c82009-07-18 01:41:30 -05001657 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001658 :py:obj:`PKCS12` returns a new instance of :py:obj:`PKCS12` with no certificate,
Jean-Paul Calderonedc857b52009-07-25 12:25:07 -04001659 private key, CA certificates, or friendly name.
Rick Dean38a05c82009-07-18 01:41:30 -05001660 """
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001661 p12 = PKCS12()
Rick Dean623ee362009-07-17 12:22:16 -05001662 self.assertEqual(None, p12.get_certificate())
1663 self.assertEqual(None, p12.get_privatekey())
1664 self.assertEqual(None, p12.get_ca_certificates())
Rick Dean42d69e12009-07-20 11:36:08 -05001665 self.assertEqual(None, p12.get_friendlyname())
Rick Dean623ee362009-07-17 12:22:16 -05001666
Rick Dean38a05c82009-07-18 01:41:30 -05001667
Rick Dean623ee362009-07-17 12:22:16 -05001668 def test_type_errors(self):
Rick Dean38a05c82009-07-18 01:41:30 -05001669 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001670 The :py:obj:`PKCS12` setter functions (:py:obj:`set_certificate`, :py:obj:`set_privatekey`,
1671 :py:obj:`set_ca_certificates`, and :py:obj:`set_friendlyname`) raise :py:obj:`TypeError`
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001672 when passed objects of types other than those expected.
Rick Dean38a05c82009-07-18 01:41:30 -05001673 """
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001674 p12 = PKCS12()
Rick Dean623ee362009-07-17 12:22:16 -05001675 self.assertRaises(TypeError, p12.set_certificate, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05001676 self.assertRaises(TypeError, p12.set_certificate, PKey())
1677 self.assertRaises(TypeError, p12.set_certificate, X509)
Rick Dean623ee362009-07-17 12:22:16 -05001678 self.assertRaises(TypeError, p12.set_privatekey, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05001679 self.assertRaises(TypeError, p12.set_privatekey, 'legbone')
1680 self.assertRaises(TypeError, p12.set_privatekey, X509())
Rick Dean623ee362009-07-17 12:22:16 -05001681 self.assertRaises(TypeError, p12.set_ca_certificates, 3)
1682 self.assertRaises(TypeError, p12.set_ca_certificates, X509())
1683 self.assertRaises(TypeError, p12.set_ca_certificates, (3, 4))
Rick Deanf94096c2009-07-18 14:23:06 -05001684 self.assertRaises(TypeError, p12.set_ca_certificates, ( PKey(), ))
Rick Dean42d69e12009-07-20 11:36:08 -05001685 self.assertRaises(TypeError, p12.set_friendlyname, 6)
1686 self.assertRaises(TypeError, p12.set_friendlyname, ('foo', 'bar'))
Rick Dean623ee362009-07-17 12:22:16 -05001687
Rick Dean38a05c82009-07-18 01:41:30 -05001688
Rick Dean623ee362009-07-17 12:22:16 -05001689 def test_key_only(self):
1690 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001691 A :py:obj:`PKCS12` with only a private key can be exported using
1692 :py:obj:`PKCS12.export` and loaded again using :py:obj:`load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001693 """
1694 passwd = 'blah'
1695 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001696 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001697 p12.set_privatekey(pkey)
Rick Dean623ee362009-07-17 12:22:16 -05001698 self.assertEqual(None, p12.get_certificate())
1699 self.assertEqual(pkey, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05001700 try:
1701 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
1702 except Error:
1703 # Some versions of OpenSSL will throw an exception
1704 # for this nearly useless PKCS12 we tried to generate:
1705 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
1706 return
Rick Dean623ee362009-07-17 12:22:16 -05001707 p12 = load_pkcs12(dumped_p12, passwd)
1708 self.assertEqual(None, p12.get_ca_certificates())
1709 self.assertEqual(None, p12.get_certificate())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001710
1711 # OpenSSL fails to bring the key back to us. So sad. Perhaps in the
1712 # future this will be improved.
1713 self.assertTrue(isinstance(p12.get_privatekey(), (PKey, type(None))))
Rick Dean623ee362009-07-17 12:22:16 -05001714
Rick Dean38a05c82009-07-18 01:41:30 -05001715
Rick Dean623ee362009-07-17 12:22:16 -05001716 def test_cert_only(self):
1717 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001718 A :py:obj:`PKCS12` with only a certificate can be exported using
1719 :py:obj:`PKCS12.export` and loaded again using :py:obj:`load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001720 """
1721 passwd = 'blah'
1722 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001723 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001724 p12.set_certificate(cert)
Rick Dean623ee362009-07-17 12:22:16 -05001725 self.assertEqual(cert, p12.get_certificate())
1726 self.assertEqual(None, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05001727 try:
1728 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
1729 except Error:
1730 # Some versions of OpenSSL will throw an exception
1731 # for this nearly useless PKCS12 we tried to generate:
1732 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
1733 return
Rick Dean623ee362009-07-17 12:22:16 -05001734 p12 = load_pkcs12(dumped_p12, passwd)
1735 self.assertEqual(None, p12.get_privatekey())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001736
1737 # OpenSSL fails to bring the cert back to us. Groany mcgroan.
1738 self.assertTrue(isinstance(p12.get_certificate(), (X509, type(None))))
1739
1740 # Oh ho. It puts the certificate into the ca certificates list, in
1741 # fact. Totally bogus, I would think. Nevertheless, let's exploit
1742 # that to check to see if it reconstructed the certificate we expected
1743 # it to. At some point, hopefully this will change so that
1744 # p12.get_certificate() is actually what returns the loaded
1745 # certificate.
1746 self.assertEqual(
1747 cleartextCertificatePEM,
1748 dump_certificate(FILETYPE_PEM, p12.get_ca_certificates()[0]))
Rick Dean623ee362009-07-17 12:22:16 -05001749
1750
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001751 def gen_pkcs12(self, cert_pem=None, key_pem=None, ca_pem=None, friendly_name=None):
Rick Dean623ee362009-07-17 12:22:16 -05001752 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001753 Generate a PKCS12 object with components from PEM. Verify that the set
1754 functions return None.
Rick Dean623ee362009-07-17 12:22:16 -05001755 """
Rick Deanf94096c2009-07-18 14:23:06 -05001756 p12 = PKCS12()
1757 if cert_pem:
1758 ret = p12.set_certificate(load_certificate(FILETYPE_PEM, cert_pem))
1759 self.assertEqual(ret, None)
1760 if key_pem:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001761 ret = p12.set_privatekey(load_privatekey(FILETYPE_PEM, key_pem))
Rick Deanf94096c2009-07-18 14:23:06 -05001762 self.assertEqual(ret, None)
1763 if ca_pem:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001764 ret = p12.set_ca_certificates((load_certificate(FILETYPE_PEM, ca_pem),))
Rick Deanf94096c2009-07-18 14:23:06 -05001765 self.assertEqual(ret, None)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001766 if friendly_name:
1767 ret = p12.set_friendlyname(friendly_name)
Rick Dean42d69e12009-07-20 11:36:08 -05001768 self.assertEqual(ret, None)
Rick Deanf94096c2009-07-18 14:23:06 -05001769 return p12
1770
1771
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001772 def check_recovery(self, p12_str, key=None, cert=None, ca=None, passwd='',
1773 extra=()):
Rick Deanf94096c2009-07-18 14:23:06 -05001774 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001775 Use openssl program to confirm three components are recoverable from a
1776 PKCS12 string.
Rick Deanf94096c2009-07-18 14:23:06 -05001777 """
1778 if key:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001779 recovered_key = _runopenssl(
1780 p12_str, "pkcs12", '-nocerts', '-nodes', '-passin',
1781 'pass:' + passwd, *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001782 self.assertEqual(recovered_key[-len(key):], key)
1783 if cert:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001784 recovered_cert = _runopenssl(
1785 p12_str, "pkcs12", '-clcerts', '-nodes', '-passin',
1786 'pass:' + passwd, '-nokeys', *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001787 self.assertEqual(recovered_cert[-len(cert):], cert)
1788 if ca:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001789 recovered_cert = _runopenssl(
1790 p12_str, "pkcs12", '-cacerts', '-nodes', '-passin',
1791 'pass:' + passwd, '-nokeys', *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001792 self.assertEqual(recovered_cert[-len(ca):], ca)
1793
1794
1795 def test_load_pkcs12(self):
1796 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001797 A PKCS12 string generated using the openssl command line can be loaded
Jonathan Ballet648875f2011-07-16 14:14:58 +09001798 with :py:obj:`load_pkcs12` and its components extracted and examined.
Rick Deanf94096c2009-07-18 14:23:06 -05001799 """
Rick Dean623ee362009-07-17 12:22:16 -05001800 passwd = 'whatever'
1801 pem = client_key_pem + client_cert_pem
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001802 p12_str = _runopenssl(
1803 pem, "pkcs12", '-export', '-clcerts', '-passout', 'pass:' + passwd)
Rick Dean623ee362009-07-17 12:22:16 -05001804 p12 = load_pkcs12(p12_str, passwd)
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001805 # verify
Rick Deanf94096c2009-07-18 14:23:06 -05001806 self.assertTrue(isinstance(p12, PKCS12))
Rick Dean623ee362009-07-17 12:22:16 -05001807 cert_pem = dump_certificate(FILETYPE_PEM, p12.get_certificate())
1808 self.assertEqual(cert_pem, client_cert_pem)
1809 key_pem = dump_privatekey(FILETYPE_PEM, p12.get_privatekey())
1810 self.assertEqual(key_pem, client_key_pem)
1811 self.assertEqual(None, p12.get_ca_certificates())
Rick Deanf94096c2009-07-18 14:23:06 -05001812
Rick Deanee568302009-07-24 09:56:29 -05001813
1814 def test_load_pkcs12_garbage(self):
1815 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001816 :py:obj:`load_pkcs12` raises :py:obj:`OpenSSL.crypto.Error` when passed a string
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001817 which is not a PKCS12 dump.
Rick Deanee568302009-07-24 09:56:29 -05001818 """
1819 passwd = 'whatever'
1820 e = self.assertRaises(Error, load_pkcs12, 'fruit loops', passwd)
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -04001821 self.assertEqual( e.args[0][0][0], 'asn1 encoding routines')
1822 self.assertEqual( len(e.args[0][0]), 3)
Rick Deanee568302009-07-24 09:56:29 -05001823
1824
Rick Deanf94096c2009-07-18 14:23:06 -05001825 def test_replace(self):
1826 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001827 :py:obj:`PKCS12.set_certificate` replaces the certificate in a PKCS12 cluster.
1828 :py:obj:`PKCS12.set_privatekey` replaces the private key.
1829 :py:obj:`PKCS12.set_ca_certificates` replaces the CA certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05001830 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001831 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
1832 p12.set_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1833 p12.set_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001834 root_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05001835 client_cert = load_certificate(FILETYPE_PEM, client_cert_pem)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001836 p12.set_ca_certificates([root_cert]) # not a tuple
Rick Dean623ee362009-07-17 12:22:16 -05001837 self.assertEqual(1, len(p12.get_ca_certificates()))
1838 self.assertEqual(root_cert, p12.get_ca_certificates()[0])
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001839 p12.set_ca_certificates([client_cert, root_cert])
Rick Deanf94096c2009-07-18 14:23:06 -05001840 self.assertEqual(2, len(p12.get_ca_certificates()))
1841 self.assertEqual(client_cert, p12.get_ca_certificates()[0])
1842 self.assertEqual(root_cert, p12.get_ca_certificates()[1])
1843
1844
1845 def test_friendly_name(self):
1846 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04001847 The *friendlyName* of a PKCS12 can be set and retrieved via
Jonathan Ballet648875f2011-07-16 14:14:58 +09001848 :py:obj:`PKCS12.get_friendlyname` and :py:obj:`PKCS12_set_friendlyname`, and a
1849 :py:obj:`PKCS12` with a friendly name set can be dumped with :py:obj:`PKCS12.export`.
Rick Deanf94096c2009-07-18 14:23:06 -05001850 """
Rick Deanf94096c2009-07-18 14:23:06 -05001851 passwd = 'Dogmeat[]{}!@#$%^&*()~`?/.,<>-_+=";:'
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001852 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -04001853 for friendly_name in [b('Serverlicious'), None, b('###')]:
Rick Dean42d69e12009-07-20 11:36:08 -05001854 p12.set_friendlyname(friendly_name)
1855 self.assertEqual(p12.get_friendlyname(), friendly_name)
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001856 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
Rick Dean42d69e12009-07-20 11:36:08 -05001857 reloaded_p12 = load_pkcs12(dumped_p12, passwd)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001858 self.assertEqual(
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -04001859 p12.get_friendlyname(), reloaded_p12.get_friendlyname())
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001860 # We would use the openssl program to confirm the friendly
1861 # name, but it is not possible. The pkcs12 command
1862 # does not store the friendly name in the cert's
Rick Dean42d69e12009-07-20 11:36:08 -05001863 # alias, which we could then extract.
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001864 self.check_recovery(
1865 dumped_p12, key=server_key_pem, cert=server_cert_pem,
1866 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05001867
1868
1869 def test_various_empty_passphrases(self):
1870 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001871 Test that missing, None, and '' passphrases are identical for PKCS12
1872 export.
Rick Deanf94096c2009-07-18 14:23:06 -05001873 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001874 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
Rick Dean623ee362009-07-17 12:22:16 -05001875 passwd = ''
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001876 dumped_p12_empty = p12.export(iter=2, maciter=0, passphrase=passwd)
1877 dumped_p12_none = p12.export(iter=3, maciter=2, passphrase=None)
1878 dumped_p12_nopw = p12.export(iter=9, maciter=4)
1879 for dumped_p12 in [dumped_p12_empty, dumped_p12_none, dumped_p12_nopw]:
1880 self.check_recovery(
1881 dumped_p12, key=client_key_pem, cert=client_cert_pem,
1882 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05001883
1884
1885 def test_removing_ca_cert(self):
1886 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001887 Passing :py:obj:`None` to :py:obj:`PKCS12.set_ca_certificates` removes all CA
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001888 certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05001889 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001890 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
1891 p12.set_ca_certificates(None)
Rick Dean623ee362009-07-17 12:22:16 -05001892 self.assertEqual(None, p12.get_ca_certificates())
Rick Deanf94096c2009-07-18 14:23:06 -05001893
1894
1895 def test_export_without_mac(self):
1896 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04001897 Exporting a PKCS12 with a :py:obj:`maciter` of ``-1`` excludes the MAC
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001898 entirely.
Rick Deanf94096c2009-07-18 14:23:06 -05001899 """
1900 passwd = 'Lake Michigan'
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001901 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Dean623ee362009-07-17 12:22:16 -05001902 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001903 self.check_recovery(
1904 dumped_p12, key=server_key_pem, cert=server_cert_pem,
1905 passwd=passwd, extra=('-nomacver',))
1906
1907
1908 def test_load_without_mac(self):
1909 """
1910 Loading a PKCS12 without a MAC does something other than crash.
1911 """
1912 passwd = 'Lake Michigan'
1913 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
1914 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Rick Dean321a0512009-08-13 17:21:29 -05001915 try:
1916 recovered_p12 = load_pkcs12(dumped_p12, passwd)
1917 # The person who generated this PCKS12 should be flogged,
1918 # or better yet we should have a means to determine
1919 # whether a PCKS12 had a MAC that was verified.
1920 # Anyway, libopenssl chooses to allow it, so the
1921 # pyopenssl binding does as well.
1922 self.assertTrue(isinstance(recovered_p12, PKCS12))
1923 except Error:
1924 # Failing here with an exception is preferred as some openssl
1925 # versions do.
1926 pass
Rick Dean623ee362009-07-17 12:22:16 -05001927
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001928
Rick Dean25bcc1f2009-07-20 11:53:13 -05001929 def test_zero_len_list_for_ca(self):
1930 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04001931 A PKCS12 with an empty CA certificates list can be exported.
Rick Dean25bcc1f2009-07-20 11:53:13 -05001932 """
1933 passwd = 'Hobie 18'
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04001934 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem)
1935 p12.set_ca_certificates([])
Rick Dean25bcc1f2009-07-20 11:53:13 -05001936 self.assertEqual((), p12.get_ca_certificates())
1937 dumped_p12 = p12.export(passphrase=passwd, iter=3)
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04001938 self.check_recovery(
1939 dumped_p12, key=server_key_pem, cert=server_cert_pem,
1940 passwd=passwd)
Rick Dean25bcc1f2009-07-20 11:53:13 -05001941
1942
Rick Deanf94096c2009-07-18 14:23:06 -05001943 def test_export_without_args(self):
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001944 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001945 All the arguments to :py:obj:`PKCS12.export` are optional.
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001946 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04001947 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05001948 dumped_p12 = p12.export() # no args
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04001949 self.check_recovery(
1950 dumped_p12, key=server_key_pem, cert=server_cert_pem, passwd='')
Rick Deanf94096c2009-07-18 14:23:06 -05001951
1952
1953 def test_key_cert_mismatch(self):
1954 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001955 :py:obj:`PKCS12.export` raises an exception when a key and certificate
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04001956 mismatch.
Rick Deanf94096c2009-07-18 14:23:06 -05001957 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04001958 p12 = self.gen_pkcs12(server_cert_pem, client_key_pem, root_cert_pem)
1959 self.assertRaises(Error, p12.export)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04001960
1961
1962
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04001963# These quoting functions taken directly from Twisted's twisted.python.win32.
1964_cmdLineQuoteRe = re.compile(r'(\\*)"')
1965_cmdLineQuoteRe2 = re.compile(r'(\\+)\Z')
1966def cmdLineQuote(s):
1967 """
1968 Internal method for quoting a single command-line argument.
1969
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04001970 See http://www.perlmonks.org/?node_id=764004
1971
Jonathan Ballet648875f2011-07-16 14:14:58 +09001972 :type: :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09001973 :param s: A single unquoted string to quote for something that is expecting
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04001974 cmd.exe-style quoting
1975
Jonathan Ballet648875f2011-07-16 14:14:58 +09001976 :rtype: :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09001977 :return: A cmd.exe-style quoted string
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04001978 """
1979 s = _cmdLineQuoteRe2.sub(r"\1\1", _cmdLineQuoteRe.sub(r'\1\1\\"', s))
1980 return '"%s"' % s
1981
1982
1983
1984def quoteArguments(arguments):
1985 """
1986 Quote an iterable of command-line arguments for passing to CreateProcess or
Jonathan Ballet648875f2011-07-16 14:14:58 +09001987 a similar API. This allows the list passed to :py:obj:`reactor.spawnProcess` to
1988 match the child process's :py:obj:`sys.argv` properly.
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04001989
Jonathan Ballet648875f2011-07-16 14:14:58 +09001990 :type arguments: :py:obj:`iterable` of :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09001991 :param arguments: An iterable of unquoted arguments to quote
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04001992
Jonathan Ballet648875f2011-07-16 14:14:58 +09001993 :rtype: :py:obj:`str`
1994 :return: A space-delimited string containing quoted versions of :py:obj:`arguments`
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04001995 """
1996 return ' '.join(map(cmdLineQuote, arguments))
1997
1998
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05001999
Rick Dean4c9ad612009-07-17 15:05:22 -05002000def _runopenssl(pem, *args):
2001 """
2002 Run the command line openssl tool with the given arguments and write
Rick Dean55d1ce62009-08-13 17:40:24 -05002003 the given PEM to its stdin. Not safe for quotes.
Rick Dean4c9ad612009-07-17 15:05:22 -05002004 """
Jean-Paul Calderone038de952009-08-21 12:16:06 -04002005 if os.name == 'posix':
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04002006 command = "openssl " + " ".join([
2007 "'%s'" % (arg.replace("'", "'\\''"),) for arg in args])
Rick Dean55d1ce62009-08-13 17:40:24 -05002008 else:
Jean-Paul Calderone50924502009-08-27 12:47:55 -04002009 command = "openssl " + quoteArguments(args)
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04002010 proc = Popen(command, shell=True, stdin=PIPE, stdout=PIPE)
Jean-Paul Calderone62ca8da2010-08-11 19:58:08 -04002011 proc.stdin.write(pem)
2012 proc.stdin.close()
2013 return proc.stdout.read()
Rick Dean4c9ad612009-07-17 15:05:22 -05002014
2015
2016
Jean-Paul Calderone18808652009-07-05 12:54:05 -04002017class FunctionTests(TestCase):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002018 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002019 Tests for free-functions in the :py:obj:`OpenSSL.crypto` module.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002020 """
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002021
2022 def test_load_privatekey_invalid_format(self):
2023 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002024 :py:obj:`load_privatekey` raises :py:obj:`ValueError` if passed an unknown filetype.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002025 """
2026 self.assertRaises(ValueError, load_privatekey, 100, root_key_pem)
2027
2028
2029 def test_load_privatekey_invalid_passphrase_type(self):
2030 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002031 :py:obj:`load_privatekey` raises :py:obj:`TypeError` if passed a passphrase that is
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002032 neither a :py:obj:`str` nor a callable.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002033 """
2034 self.assertRaises(
2035 TypeError,
2036 load_privatekey,
2037 FILETYPE_PEM, encryptedPrivateKeyPEMPassphrase, object())
2038
2039
2040 def test_load_privatekey_wrong_args(self):
2041 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002042 :py:obj:`load_privatekey` raises :py:obj:`TypeError` if called with the wrong number
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002043 of arguments.
2044 """
2045 self.assertRaises(TypeError, load_privatekey)
2046
2047
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002048 def test_load_privatekey_wrongPassphrase(self):
2049 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002050 :py:obj:`load_privatekey` raises :py:obj:`OpenSSL.crypto.Error` when it is passed an
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002051 encrypted PEM and an incorrect passphrase.
2052 """
2053 self.assertRaises(
2054 Error,
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002055 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, b("quack"))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002056
2057
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002058 def test_load_privatekey_passphraseWrongType(self):
2059 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002060 :py:obj:`load_privatekey` raises :py:obj:`ValueError` when it is passed a passphrase
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002061 with a private key encoded in a format, that doesn't support
2062 encryption.
2063 """
2064 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2065 blob = dump_privatekey(FILETYPE_ASN1, key)
2066 self.assertRaises(ValueError,
2067 load_privatekey, FILETYPE_ASN1, blob, "secret")
2068
2069
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002070 def test_load_privatekey_passphrase(self):
2071 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002072 :py:obj:`load_privatekey` can create a :py:obj:`PKey` object from an encrypted PEM
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002073 string if given the passphrase.
2074 """
2075 key = load_privatekey(
2076 FILETYPE_PEM, encryptedPrivateKeyPEM,
2077 encryptedPrivateKeyPEMPassphrase)
2078 self.assertTrue(isinstance(key, PKeyType))
2079
2080
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002081 def test_load_privatekey_passphrase_exception(self):
2082 """
2083 If the passphrase callback raises an exception, that exception is raised
2084 by :py:obj:`load_privatekey`.
2085 """
2086 def cb(ignored):
2087 raise ArithmeticError
2088
2089 self.assertRaises(ArithmeticError,
2090 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2091
2092
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002093 def test_load_privatekey_wrongPassphraseCallback(self):
2094 """
Jean-Paul Calderoned440a082011-09-14 11:02:05 -04002095 :py:obj:`load_privatekey` raises :py:obj:`OpenSSL.crypto.Error` when it
2096 is passed an encrypted PEM and a passphrase callback which returns an
2097 incorrect passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002098 """
2099 called = []
2100 def cb(*a):
2101 called.append(None)
Jean-Paul Calderoned440a082011-09-14 11:02:05 -04002102 return b("quack")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002103 self.assertRaises(
2104 Error,
2105 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2106 self.assertTrue(called)
2107
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002108
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002109 def test_load_privatekey_passphraseCallback(self):
2110 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002111 :py:obj:`load_privatekey` can create a :py:obj:`PKey` object from an encrypted PEM
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002112 string if given a passphrase callback which returns the correct
2113 password.
2114 """
2115 called = []
2116 def cb(writing):
2117 called.append(writing)
2118 return encryptedPrivateKeyPEMPassphrase
2119 key = load_privatekey(FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2120 self.assertTrue(isinstance(key, PKeyType))
2121 self.assertEqual(called, [False])
2122
2123
Jean-Paul Calderone105cb952011-09-14 10:16:46 -04002124 def test_load_privatekey_passphrase_wrong_return_type(self):
2125 """
2126 :py:obj:`load_privatekey` raises :py:obj:`ValueError` if the passphrase
2127 callback returns something other than a byte string.
2128 """
2129 self.assertRaises(
2130 ValueError,
2131 load_privatekey,
2132 FILETYPE_PEM, encryptedPrivateKeyPEM, lambda *args: 3)
2133
2134
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002135 def test_dump_privatekey_wrong_args(self):
2136 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002137 :py:obj:`dump_privatekey` raises :py:obj:`TypeError` if called with the wrong number
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002138 of arguments.
2139 """
2140 self.assertRaises(TypeError, dump_privatekey)
Jean-Paul Calderone1eeccd82011-09-14 10:18:52 -04002141 # If cipher name is given, password is required.
2142 self.assertRaises(
2143 ValueError, dump_privatekey, FILETYPE_PEM, PKey(), "foo")
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002144
2145
2146 def test_dump_privatekey_unknown_cipher(self):
2147 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002148 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` if called with an unrecognized
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002149 cipher name.
2150 """
2151 key = PKey()
2152 key.generate_key(TYPE_RSA, 512)
2153 self.assertRaises(
2154 ValueError, dump_privatekey,
2155 FILETYPE_PEM, key, "zippers", "passphrase")
2156
2157
2158 def test_dump_privatekey_invalid_passphrase_type(self):
2159 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002160 :py:obj:`dump_privatekey` raises :py:obj:`TypeError` if called with a passphrase which
2161 is neither a :py:obj:`str` nor a callable.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002162 """
2163 key = PKey()
2164 key.generate_key(TYPE_RSA, 512)
2165 self.assertRaises(
2166 TypeError,
2167 dump_privatekey, FILETYPE_PEM, key, "blowfish", object())
2168
2169
2170 def test_dump_privatekey_invalid_filetype(self):
2171 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002172 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` if called with an unrecognized
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002173 filetype.
2174 """
2175 key = PKey()
2176 key.generate_key(TYPE_RSA, 512)
2177 self.assertRaises(ValueError, dump_privatekey, 100, key)
2178
2179
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002180 def test_load_privatekey_passphraseCallbackLength(self):
2181 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002182 :py:obj:`crypto.load_privatekey` should raise an error when the passphrase
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002183 provided by the callback is too long, not silently truncate it.
2184 """
2185 def cb(ignored):
2186 return "a" * 1025
2187
2188 self.assertRaises(ValueError,
2189 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2190
2191
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002192 def test_dump_privatekey_passphrase(self):
2193 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002194 :py:obj:`dump_privatekey` writes an encrypted PEM when given a passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002195 """
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002196 passphrase = b("foo")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002197 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2198 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002199 self.assertTrue(isinstance(pem, bytes))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002200 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
2201 self.assertTrue(isinstance(loadedKey, PKeyType))
2202 self.assertEqual(loadedKey.type(), key.type())
2203 self.assertEqual(loadedKey.bits(), key.bits())
2204
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002205
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002206 def test_dump_privatekey_passphraseWrongType(self):
2207 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002208 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` when it is passed a passphrase
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002209 with a private key encoded in a format, that doesn't support
2210 encryption.
2211 """
2212 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2213 self.assertRaises(ValueError,
2214 dump_privatekey, FILETYPE_ASN1, key, "blowfish", "secret")
2215
2216
Rick Dean5b7b6372009-04-01 11:34:06 -05002217 def test_dump_certificate(self):
2218 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002219 :py:obj:`dump_certificate` writes PEM, DER, and text.
Rick Dean5b7b6372009-04-01 11:34:06 -05002220 """
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002221 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
Rick Dean5b7b6372009-04-01 11:34:06 -05002222 cert = load_certificate(FILETYPE_PEM, pemData)
2223 dumped_pem = dump_certificate(FILETYPE_PEM, cert)
2224 self.assertEqual(dumped_pem, cleartextCertificatePEM)
2225 dumped_der = dump_certificate(FILETYPE_ASN1, cert)
Rick Dean4c9ad612009-07-17 15:05:22 -05002226 good_der = _runopenssl(dumped_pem, "x509", "-outform", "DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002227 self.assertEqual(dumped_der, good_der)
2228 cert2 = load_certificate(FILETYPE_ASN1, dumped_der)
2229 dumped_pem2 = dump_certificate(FILETYPE_PEM, cert2)
2230 self.assertEqual(dumped_pem2, cleartextCertificatePEM)
2231 dumped_text = dump_certificate(FILETYPE_TEXT, cert)
Rick Dean4c9ad612009-07-17 15:05:22 -05002232 good_text = _runopenssl(dumped_pem, "x509", "-noout", "-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002233 self.assertEqual(dumped_text, good_text)
2234
2235
2236 def test_dump_privatekey(self):
2237 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002238 :py:obj:`dump_privatekey` writes a PEM, DER, and text.
Rick Dean5b7b6372009-04-01 11:34:06 -05002239 """
2240 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -04002241 self.assertTrue(key.check())
Rick Dean5b7b6372009-04-01 11:34:06 -05002242 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2243 self.assertEqual(dumped_pem, cleartextPrivateKeyPEM)
2244 dumped_der = dump_privatekey(FILETYPE_ASN1, key)
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002245 # XXX This OpenSSL call writes "writing RSA key" to standard out. Sad.
Rick Dean4c9ad612009-07-17 15:05:22 -05002246 good_der = _runopenssl(dumped_pem, "rsa", "-outform", "DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002247 self.assertEqual(dumped_der, good_der)
2248 key2 = load_privatekey(FILETYPE_ASN1, dumped_der)
2249 dumped_pem2 = dump_privatekey(FILETYPE_PEM, key2)
2250 self.assertEqual(dumped_pem2, cleartextPrivateKeyPEM)
2251 dumped_text = dump_privatekey(FILETYPE_TEXT, key)
Rick Dean4c9ad612009-07-17 15:05:22 -05002252 good_text = _runopenssl(dumped_pem, "rsa", "-noout", "-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002253 self.assertEqual(dumped_text, good_text)
2254
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002255
Rick Dean5b7b6372009-04-01 11:34:06 -05002256 def test_dump_certificate_request(self):
2257 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002258 :py:obj:`dump_certificate_request` writes a PEM, DER, and text.
Rick Dean5b7b6372009-04-01 11:34:06 -05002259 """
2260 req = load_certificate_request(FILETYPE_PEM, cleartextCertificateRequestPEM)
2261 dumped_pem = dump_certificate_request(FILETYPE_PEM, req)
2262 self.assertEqual(dumped_pem, cleartextCertificateRequestPEM)
2263 dumped_der = dump_certificate_request(FILETYPE_ASN1, req)
Rick Dean4c9ad612009-07-17 15:05:22 -05002264 good_der = _runopenssl(dumped_pem, "req", "-outform", "DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002265 self.assertEqual(dumped_der, good_der)
2266 req2 = load_certificate_request(FILETYPE_ASN1, dumped_der)
2267 dumped_pem2 = dump_certificate_request(FILETYPE_PEM, req2)
2268 self.assertEqual(dumped_pem2, cleartextCertificateRequestPEM)
2269 dumped_text = dump_certificate_request(FILETYPE_TEXT, req)
Rick Dean4c9ad612009-07-17 15:05:22 -05002270 good_text = _runopenssl(dumped_pem, "req", "-noout", "-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002271 self.assertEqual(dumped_text, good_text)
Jean-Paul Calderoneaf43cdf2010-08-03 18:40:52 -04002272 self.assertRaises(ValueError, dump_certificate_request, 100, req)
Rick Dean5b7b6372009-04-01 11:34:06 -05002273
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002274
2275 def test_dump_privatekey_passphraseCallback(self):
2276 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002277 :py:obj:`dump_privatekey` writes an encrypted PEM when given a callback which
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002278 returns the correct passphrase.
2279 """
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002280 passphrase = b("foo")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002281 called = []
2282 def cb(writing):
2283 called.append(writing)
2284 return passphrase
2285 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2286 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", cb)
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002287 self.assertTrue(isinstance(pem, bytes))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002288 self.assertEqual(called, [True])
2289 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
2290 self.assertTrue(isinstance(loadedKey, PKeyType))
2291 self.assertEqual(loadedKey.type(), key.type())
2292 self.assertEqual(loadedKey.bits(), key.bits())
Rick Dean5b7b6372009-04-01 11:34:06 -05002293
2294
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002295 def test_dump_privatekey_passphrase_exception(self):
2296 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002297 :py:obj:`dump_privatekey` should not overwrite the exception raised
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002298 by the passphrase callback.
2299 """
2300 def cb(ignored):
2301 raise ArithmeticError
2302
2303 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2304 self.assertRaises(ArithmeticError,
2305 dump_privatekey, FILETYPE_PEM, key, "blowfish", cb)
2306
2307
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002308 def test_dump_privatekey_passphraseCallbackLength(self):
2309 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002310 :py:obj:`crypto.dump_privatekey` should raise an error when the passphrase
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002311 provided by the callback is too long, not silently truncate it.
2312 """
2313 def cb(ignored):
2314 return "a" * 1025
2315
2316 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2317 self.assertRaises(ValueError,
2318 dump_privatekey, FILETYPE_PEM, key, "blowfish", cb)
2319
2320
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002321 def test_load_pkcs7_data(self):
2322 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002323 :py:obj:`load_pkcs7_data` accepts a PKCS#7 string and returns an instance of
2324 :py:obj:`PKCS7Type`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002325 """
2326 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2327 self.assertTrue(isinstance(pkcs7, PKCS7Type))
2328
2329
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002330
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002331class PKCS7Tests(TestCase):
2332 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002333 Tests for :py:obj:`PKCS7Type`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002334 """
2335 def test_type(self):
2336 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002337 :py:obj:`PKCS7Type` is a type object.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002338 """
2339 self.assertTrue(isinstance(PKCS7Type, type))
2340 self.assertEqual(PKCS7Type.__name__, 'PKCS7')
2341
2342 # XXX This doesn't currently work.
2343 # self.assertIdentical(PKCS7, PKCS7Type)
2344
2345
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002346 # XXX Opposite results for all these following methods
2347
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002348 def test_type_is_signed_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002349 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002350 :py:obj:`PKCS7Type.type_is_signed` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002351 arguments.
2352 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002353 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2354 self.assertRaises(TypeError, pkcs7.type_is_signed, None)
2355
2356
2357 def test_type_is_signed(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002358 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002359 :py:obj:`PKCS7Type.type_is_signed` returns :py:obj:`True` if the PKCS7 object is of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002360 the type *signed*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002361 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002362 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2363 self.assertTrue(pkcs7.type_is_signed())
2364
2365
2366 def test_type_is_enveloped_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002367 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002368 :py:obj:`PKCS7Type.type_is_enveloped` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002369 arguments.
2370 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002371 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2372 self.assertRaises(TypeError, pkcs7.type_is_enveloped, None)
2373
2374
2375 def test_type_is_enveloped(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002376 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002377 :py:obj:`PKCS7Type.type_is_enveloped` returns :py:obj:`False` if the PKCS7 object is
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002378 not of the type *enveloped*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002379 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002380 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2381 self.assertFalse(pkcs7.type_is_enveloped())
2382
2383
2384 def test_type_is_signedAndEnveloped_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002385 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002386 :py:obj:`PKCS7Type.type_is_signedAndEnveloped` raises :py:obj:`TypeError` if called
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002387 with any arguments.
2388 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002389 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2390 self.assertRaises(TypeError, pkcs7.type_is_signedAndEnveloped, None)
2391
2392
2393 def test_type_is_signedAndEnveloped(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002394 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002395 :py:obj:`PKCS7Type.type_is_signedAndEnveloped` returns :py:obj:`False` if the PKCS7
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002396 object is not of the type *signed and enveloped*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002397 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002398 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2399 self.assertFalse(pkcs7.type_is_signedAndEnveloped())
2400
2401
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002402 def test_type_is_data(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002403 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002404 :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 -04002405 the type data.
2406 """
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002407 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2408 self.assertFalse(pkcs7.type_is_data())
2409
2410
2411 def test_type_is_data_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002412 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002413 :py:obj:`PKCS7Type.type_is_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002414 arguments.
2415 """
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002416 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2417 self.assertRaises(TypeError, pkcs7.type_is_data, None)
2418
2419
Jean-Paul Calderone97b28ca2010-07-30 10:56:07 -04002420 def test_get_type_name_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002421 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002422 :py:obj:`PKCS7Type.get_type_name` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002423 arguments.
2424 """
Jean-Paul Calderone97b28ca2010-07-30 10:56:07 -04002425 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2426 self.assertRaises(TypeError, pkcs7.get_type_name, None)
2427
2428
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002429 def test_get_type_name(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002430 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002431 :py:obj:`PKCS7Type.get_type_name` returns a :py:obj:`str` giving the type name.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002432 """
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002433 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
Jean-Paul Calderone07640f12010-08-22 17:14:43 -04002434 self.assertEquals(pkcs7.get_type_name(), b('pkcs7-signedData'))
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002435
2436
2437 def test_attribute(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002438 """
2439 If an attribute other than one of the methods tested here is accessed on
Jonathan Ballet648875f2011-07-16 14:14:58 +09002440 an instance of :py:obj:`PKCS7Type`, :py:obj:`AttributeError` is raised.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002441 """
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002442 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2443 self.assertRaises(AttributeError, getattr, pkcs7, "foo")
2444
2445
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002446
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002447class NetscapeSPKITests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002448 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002449 Tests for :py:obj:`OpenSSL.crypto.NetscapeSPKI`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002450 """
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002451 def signable(self):
2452 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002453 Return a new :py:obj:`NetscapeSPKI` for use with signing tests.
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002454 """
2455 return NetscapeSPKI()
2456
2457
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002458 def test_type(self):
2459 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002460 :py:obj:`NetscapeSPKI` and :py:obj:`NetscapeSPKIType` refer to the same type object
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002461 and can be used to create instances of that type.
2462 """
2463 self.assertIdentical(NetscapeSPKI, NetscapeSPKIType)
2464 self.assertConsistentType(NetscapeSPKI, 'NetscapeSPKI')
2465
2466
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002467 def test_construction(self):
2468 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002469 :py:obj:`NetscapeSPKI` returns an instance of :py:obj:`NetscapeSPKIType`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002470 """
2471 nspki = NetscapeSPKI()
2472 self.assertTrue(isinstance(nspki, NetscapeSPKIType))
2473
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002474
Jean-Paul Calderone969efaa2010-08-03 18:19:19 -04002475 def test_invalid_attribute(self):
2476 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002477 Accessing a non-existent attribute of a :py:obj:`NetscapeSPKI` instance causes
2478 an :py:obj:`AttributeError` to be raised.
Jean-Paul Calderone969efaa2010-08-03 18:19:19 -04002479 """
2480 nspki = NetscapeSPKI()
2481 self.assertRaises(AttributeError, lambda: nspki.foo)
2482
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002483
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002484 def test_b64_encode(self):
2485 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002486 :py:obj:`NetscapeSPKI.b64_encode` encodes the certificate to a base64 blob.
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002487 """
2488 nspki = NetscapeSPKI()
2489 blob = nspki.b64_encode()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002490 self.assertTrue(isinstance(blob, bytes))
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002491
2492
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002493
Rick Dean536ba022009-07-24 23:57:27 -05002494class RevokedTests(TestCase):
2495 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002496 Tests for :py:obj:`OpenSSL.crypto.Revoked`
Rick Dean536ba022009-07-24 23:57:27 -05002497 """
2498 def test_construction(self):
2499 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002500 Confirm we can create :py:obj:`OpenSSL.crypto.Revoked`. Check
Rick Dean536ba022009-07-24 23:57:27 -05002501 that it is empty.
2502 """
2503 revoked = Revoked()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002504 self.assertTrue(isinstance(revoked, Revoked))
2505 self.assertEquals(type(revoked), Revoked)
2506 self.assertEquals(revoked.get_serial(), b('00'))
2507 self.assertEquals(revoked.get_rev_date(), None)
2508 self.assertEquals(revoked.get_reason(), None)
Rick Dean536ba022009-07-24 23:57:27 -05002509
2510
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002511 def test_construction_wrong_args(self):
2512 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002513 Calling :py:obj:`OpenSSL.crypto.Revoked` with any arguments results
2514 in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002515 """
2516 self.assertRaises(TypeError, Revoked, None)
2517 self.assertRaises(TypeError, Revoked, 1)
2518 self.assertRaises(TypeError, Revoked, "foo")
2519
2520
Rick Dean536ba022009-07-24 23:57:27 -05002521 def test_serial(self):
2522 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002523 Confirm we can set and get serial numbers 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()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002528 ret = revoked.set_serial(b('10b'))
2529 self.assertEquals(ret, None)
Rick Dean536ba022009-07-24 23:57:27 -05002530 ser = revoked.get_serial()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002531 self.assertEquals(ser, b('010B'))
Rick Dean536ba022009-07-24 23:57:27 -05002532
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002533 revoked.set_serial(b('31ppp')) # a type error would be nice
Rick Dean536ba022009-07-24 23:57:27 -05002534 ser = revoked.get_serial()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002535 self.assertEquals(ser, b('31'))
Rick Dean536ba022009-07-24 23:57:27 -05002536
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002537 self.assertRaises(ValueError, revoked.set_serial, b('pqrst'))
Rick Dean536ba022009-07-24 23:57:27 -05002538 self.assertRaises(TypeError, revoked.set_serial, 100)
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002539 self.assertRaises(TypeError, revoked.get_serial, 1)
2540 self.assertRaises(TypeError, revoked.get_serial, None)
2541 self.assertRaises(TypeError, revoked.get_serial, "")
Rick Dean536ba022009-07-24 23:57:27 -05002542
2543
2544 def test_date(self):
2545 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002546 Confirm we can set and get revocation dates from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002547 :py:obj:`OpenSSL.crypto.Revoked`. Confirm errors are handled
Rick Dean536ba022009-07-24 23:57:27 -05002548 with grace.
2549 """
2550 revoked = Revoked()
2551 date = revoked.get_rev_date()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002552 self.assertEquals(date, None)
Rick Dean536ba022009-07-24 23:57:27 -05002553
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002554 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05002555 ret = revoked.set_rev_date(now)
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002556 self.assertEqual(ret, None)
Rick Dean536ba022009-07-24 23:57:27 -05002557 date = revoked.get_rev_date()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002558 self.assertEqual(date, now)
Rick Dean536ba022009-07-24 23:57:27 -05002559
2560
Rick Dean6385faf2009-07-26 00:07:47 -05002561 def test_reason(self):
2562 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002563 Confirm we can set and get revocation reasons from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002564 :py:obj:`OpenSSL.crypto.Revoked`. The "get" need to work
Rick Dean6385faf2009-07-26 00:07:47 -05002565 as "set". Likewise, each reason of all_reasons() must work.
2566 """
2567 revoked = Revoked()
2568 for r in revoked.all_reasons():
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002569 for x in range(2):
Rick Dean6385faf2009-07-26 00:07:47 -05002570 ret = revoked.set_reason(r)
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002571 self.assertEquals(ret, None)
Rick Dean6385faf2009-07-26 00:07:47 -05002572 reason = revoked.get_reason()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002573 self.assertEquals(
2574 reason.lower().replace(b(' '), b('')),
2575 r.lower().replace(b(' '), b('')))
Rick Dean6385faf2009-07-26 00:07:47 -05002576 r = reason # again with the resp of get
2577
2578 revoked.set_reason(None)
2579 self.assertEqual(revoked.get_reason(), None)
2580
2581
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002582 def test_set_reason_wrong_arguments(self):
Rick Dean6385faf2009-07-26 00:07:47 -05002583 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002584 Calling :py:obj:`OpenSSL.crypto.Revoked.set_reason` with other than
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002585 one argument, or an argument which isn't a valid reason,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002586 results in :py:obj:`TypeError` or :py:obj:`ValueError` being raised.
Rick Dean6385faf2009-07-26 00:07:47 -05002587 """
2588 revoked = Revoked()
2589 self.assertRaises(TypeError, revoked.set_reason, 100)
Jean-Paul Calderone281b62b2010-08-28 14:22:29 -04002590 self.assertRaises(ValueError, revoked.set_reason, b('blue'))
Rick Dean6385faf2009-07-26 00:07:47 -05002591
Rick Dean536ba022009-07-24 23:57:27 -05002592
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002593 def test_get_reason_wrong_arguments(self):
2594 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002595 Calling :py:obj:`OpenSSL.crypto.Revoked.get_reason` with any
2596 arguments results in :py:obj:`TypeError` being raised.
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002597 """
2598 revoked = Revoked()
2599 self.assertRaises(TypeError, revoked.get_reason, None)
2600 self.assertRaises(TypeError, revoked.get_reason, 1)
2601 self.assertRaises(TypeError, revoked.get_reason, "foo")
2602
2603
2604
Rick Dean536ba022009-07-24 23:57:27 -05002605class CRLTests(TestCase):
2606 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002607 Tests for :py:obj:`OpenSSL.crypto.CRL`
Rick Dean536ba022009-07-24 23:57:27 -05002608 """
2609 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
2610 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2611
2612 def test_construction(self):
2613 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002614 Confirm we can create :py:obj:`OpenSSL.crypto.CRL`. Check
Rick Dean536ba022009-07-24 23:57:27 -05002615 that it is empty
2616 """
2617 crl = CRL()
2618 self.assertTrue( isinstance(crl, CRL) )
2619 self.assertEqual(crl.get_revoked(), None)
2620
2621
Jean-Paul Calderone2efd03e2010-01-30 13:59:55 -05002622 def test_construction_wrong_args(self):
2623 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002624 Calling :py:obj:`OpenSSL.crypto.CRL` with any number of arguments
2625 results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone2efd03e2010-01-30 13:59:55 -05002626 """
2627 self.assertRaises(TypeError, CRL, 1)
2628 self.assertRaises(TypeError, CRL, "")
2629 self.assertRaises(TypeError, CRL, None)
2630
2631
Rick Dean536ba022009-07-24 23:57:27 -05002632 def test_export(self):
2633 """
2634 Use python to create a simple CRL with a revocation, and export
2635 the CRL in formats of PEM, DER and text. Those outputs are verified
2636 with the openssl program.
2637 """
2638 crl = CRL()
2639 revoked = Revoked()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002640 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05002641 revoked.set_rev_date(now)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002642 revoked.set_serial(b('3ab'))
2643 revoked.set_reason(b('sUpErSeDEd'))
Rick Dean536ba022009-07-24 23:57:27 -05002644 crl.add_revoked(revoked)
2645
2646 # PEM format
2647 dumped_crl = crl.export(self.cert, self.pkey, days=20)
2648 text = _runopenssl(dumped_crl, "crl", "-noout", "-text")
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002649 text.index(b('Serial Number: 03AB'))
2650 text.index(b('Superseded'))
2651 text.index(b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA'))
Rick Dean536ba022009-07-24 23:57:27 -05002652
2653 # DER format
2654 dumped_crl = crl.export(self.cert, self.pkey, FILETYPE_ASN1)
2655 text = _runopenssl(dumped_crl, "crl", "-noout", "-text", "-inform", "DER")
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002656 text.index(b('Serial Number: 03AB'))
2657 text.index(b('Superseded'))
2658 text.index(b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA'))
Rick Dean536ba022009-07-24 23:57:27 -05002659
2660 # text format
2661 dumped_text = crl.export(self.cert, self.pkey, type=FILETYPE_TEXT)
2662 self.assertEqual(text, dumped_text)
2663
2664
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -04002665 def test_export_invalid(self):
2666 """
2667 If :py:obj:`CRL.export` is used with an uninitialized :py:obj:`X509`
Jean-Paul Calderoneb5871072012-03-09 14:58:00 -08002668 instance, :py:obj:`OpenSSL.crypto.Error` is raised.
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -04002669 """
2670 crl = CRL()
2671 self.assertRaises(Error, crl.export, X509(), PKey())
2672
2673
Jean-Paul Calderone56515342010-01-30 13:49:38 -05002674 def test_add_revoked_keyword(self):
2675 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002676 :py:obj:`OpenSSL.CRL.add_revoked` accepts its single argument as the
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002677 ``revoked`` keyword argument.
Jean-Paul Calderone56515342010-01-30 13:49:38 -05002678 """
2679 crl = CRL()
2680 revoked = Revoked()
2681 crl.add_revoked(revoked=revoked)
2682 self.assertTrue(isinstance(crl.get_revoked()[0], Revoked))
2683
Rick Dean6385faf2009-07-26 00:07:47 -05002684
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05002685 def test_export_wrong_args(self):
2686 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002687 Calling :py:obj:`OpenSSL.CRL.export` with fewer than two or more than
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05002688 four arguments, or with arguments other than the certificate,
2689 private key, integer file type, and integer number of days it
Jonathan Ballet648875f2011-07-16 14:14:58 +09002690 expects, results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05002691 """
2692 crl = CRL()
2693 self.assertRaises(TypeError, crl.export)
2694 self.assertRaises(TypeError, crl.export, self.cert)
2695 self.assertRaises(TypeError, crl.export, self.cert, self.pkey, FILETYPE_PEM, 10, "foo")
2696
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05002697 self.assertRaises(TypeError, crl.export, None, self.pkey, FILETYPE_PEM, 10)
2698 self.assertRaises(TypeError, crl.export, self.cert, None, FILETYPE_PEM, 10)
2699 self.assertRaises(TypeError, crl.export, self.cert, self.pkey, None, 10)
2700 self.assertRaises(TypeError, crl.export, self.cert, FILETYPE_PEM, None)
2701
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05002702
Jean-Paul Calderoneea198422010-01-30 13:58:23 -05002703 def test_export_unknown_filetype(self):
2704 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002705 Calling :py:obj:`OpenSSL.CRL.export` with a file type other than
2706 :py:obj:`FILETYPE_PEM`, :py:obj:`FILETYPE_ASN1`, or :py:obj:`FILETYPE_TEXT` results
2707 in a :py:obj:`ValueError` being raised.
Jean-Paul Calderoneea198422010-01-30 13:58:23 -05002708 """
2709 crl = CRL()
2710 self.assertRaises(ValueError, crl.export, self.cert, self.pkey, 100, 10)
2711
2712
Rick Dean536ba022009-07-24 23:57:27 -05002713 def test_get_revoked(self):
2714 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002715 Use python to create a simple CRL with two revocations.
Jonathan Ballet648875f2011-07-16 14:14:58 +09002716 Get back the :py:obj:`Revoked` using :py:obj:`OpenSSL.CRL.get_revoked` and
Rick Dean536ba022009-07-24 23:57:27 -05002717 verify them.
2718 """
2719 crl = CRL()
2720
2721 revoked = Revoked()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002722 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05002723 revoked.set_rev_date(now)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002724 revoked.set_serial(b('3ab'))
Rick Dean536ba022009-07-24 23:57:27 -05002725 crl.add_revoked(revoked)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002726 revoked.set_serial(b('100'))
2727 revoked.set_reason(b('sUpErSeDEd'))
Rick Dean536ba022009-07-24 23:57:27 -05002728 crl.add_revoked(revoked)
2729
2730 revs = crl.get_revoked()
2731 self.assertEqual(len(revs), 2)
2732 self.assertEqual(type(revs[0]), Revoked)
2733 self.assertEqual(type(revs[1]), Revoked)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002734 self.assertEqual(revs[0].get_serial(), b('03AB'))
2735 self.assertEqual(revs[1].get_serial(), b('0100'))
Rick Dean536ba022009-07-24 23:57:27 -05002736 self.assertEqual(revs[0].get_rev_date(), now)
2737 self.assertEqual(revs[1].get_rev_date(), now)
2738
2739
Jean-Paul Calderone46bdce42010-01-30 13:44:16 -05002740 def test_get_revoked_wrong_args(self):
2741 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002742 Calling :py:obj:`OpenSSL.CRL.get_revoked` with any arguments results
2743 in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone46bdce42010-01-30 13:44:16 -05002744 """
2745 crl = CRL()
2746 self.assertRaises(TypeError, crl.get_revoked, None)
2747 self.assertRaises(TypeError, crl.get_revoked, 1)
2748 self.assertRaises(TypeError, crl.get_revoked, "")
2749 self.assertRaises(TypeError, crl.get_revoked, "", 1, None)
2750
2751
Jean-Paul Calderoneecef6fa2010-01-30 13:47:18 -05002752 def test_add_revoked_wrong_args(self):
2753 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002754 Calling :py:obj:`OpenSSL.CRL.add_revoked` with other than one
2755 argument results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderoneecef6fa2010-01-30 13:47:18 -05002756 """
2757 crl = CRL()
2758 self.assertRaises(TypeError, crl.add_revoked)
2759 self.assertRaises(TypeError, crl.add_revoked, 1, 2)
2760 self.assertRaises(TypeError, crl.add_revoked, "foo", "bar")
2761
2762
Rick Dean536ba022009-07-24 23:57:27 -05002763 def test_load_crl(self):
2764 """
2765 Load a known CRL and inspect its revocations. Both
2766 PEM and DER formats are loaded.
2767 """
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05002768 crl = load_crl(FILETYPE_PEM, crlData)
Rick Dean536ba022009-07-24 23:57:27 -05002769 revs = crl.get_revoked()
2770 self.assertEqual(len(revs), 2)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002771 self.assertEqual(revs[0].get_serial(), b('03AB'))
Rick Dean6385faf2009-07-26 00:07:47 -05002772 self.assertEqual(revs[0].get_reason(), None)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002773 self.assertEqual(revs[1].get_serial(), b('0100'))
2774 self.assertEqual(revs[1].get_reason(), b('Superseded'))
Rick Dean536ba022009-07-24 23:57:27 -05002775
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05002776 der = _runopenssl(crlData, "crl", "-outform", "DER")
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002777 crl = load_crl(FILETYPE_ASN1, der)
Rick Dean536ba022009-07-24 23:57:27 -05002778 revs = crl.get_revoked()
2779 self.assertEqual(len(revs), 2)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002780 self.assertEqual(revs[0].get_serial(), b('03AB'))
Rick Dean6385faf2009-07-26 00:07:47 -05002781 self.assertEqual(revs[0].get_reason(), None)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002782 self.assertEqual(revs[1].get_serial(), b('0100'))
2783 self.assertEqual(revs[1].get_reason(), b('Superseded'))
Rick Dean536ba022009-07-24 23:57:27 -05002784
2785
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05002786 def test_load_crl_wrong_args(self):
2787 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002788 Calling :py:obj:`OpenSSL.crypto.load_crl` with other than two
2789 arguments results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05002790 """
2791 self.assertRaises(TypeError, load_crl)
2792 self.assertRaises(TypeError, load_crl, FILETYPE_PEM)
2793 self.assertRaises(TypeError, load_crl, FILETYPE_PEM, crlData, None)
2794
2795
2796 def test_load_crl_bad_filetype(self):
2797 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002798 Calling :py:obj:`OpenSSL.crypto.load_crl` with an unknown file type
2799 raises a :py:obj:`ValueError`.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05002800 """
2801 self.assertRaises(ValueError, load_crl, 100, crlData)
2802
2803
2804 def test_load_crl_bad_data(self):
2805 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002806 Calling :py:obj:`OpenSSL.crypto.load_crl` with file data which can't
2807 be loaded raises a :py:obj:`OpenSSL.crypto.Error`.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05002808 """
2809 self.assertRaises(Error, load_crl, FILETYPE_PEM, "hello, world")
2810
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002811
James Yonan7c2e5d32010-02-27 05:45:50 -07002812class SignVerifyTests(TestCase):
2813 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002814 Tests for :py:obj:`OpenSSL.crypto.sign` and :py:obj:`OpenSSL.crypto.verify`.
James Yonan7c2e5d32010-02-27 05:45:50 -07002815 """
2816 def test_sign_verify(self):
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04002817 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002818 :py:obj:`sign` generates a cryptographic signature which :py:obj:`verify` can check.
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04002819 """
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04002820 content = b(
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04002821 "It was a bright cold day in April, and the clocks were striking "
2822 "thirteen. Winston Smith, his chin nuzzled into his breast in an "
2823 "effort to escape the vile wind, slipped quickly through the "
2824 "glass doors of Victory Mansions, though not quickly enough to "
2825 "prevent a swirl of gritty dust from entering along with him.")
2826
2827 # sign the content with this private key
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04002828 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04002829 # verify the content with this cert
2830 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
2831 # certificate unrelated to priv_key, used to trigger an error
2832 bad_cert = load_certificate(FILETYPE_PEM, server_cert_pem)
James Yonan7c2e5d32010-02-27 05:45:50 -07002833
Jean-Paul Calderoned08feb02010-10-12 21:53:24 -04002834 for digest in ['md5', 'sha1']:
James Yonan7c2e5d32010-02-27 05:45:50 -07002835 sig = sign(priv_key, content, digest)
2836
2837 # Verify the signature of content, will throw an exception if error.
2838 verify(good_cert, sig, content, digest)
2839
2840 # This should fail because the certificate doesn't match the
2841 # private key that was used to sign the content.
2842 self.assertRaises(Error, verify, bad_cert, sig, content, digest)
2843
2844 # This should fail because we've "tainted" the content after
2845 # signing it.
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04002846 self.assertRaises(
2847 Error, verify,
2848 good_cert, sig, content + b("tainted"), digest)
James Yonan7c2e5d32010-02-27 05:45:50 -07002849
2850 # test that unknown digest types fail
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04002851 self.assertRaises(
Jean-Paul Calderone9538f142010-10-13 22:13:40 -04002852 ValueError, sign, priv_key, content, "strange-digest")
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04002853 self.assertRaises(
Jean-Paul Calderone9538f142010-10-13 22:13:40 -04002854 ValueError, verify, good_cert, sig, content, "strange-digest")
James Yonan7c2e5d32010-02-27 05:45:50 -07002855
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04002856
Jean-Paul Calderone9828f662010-12-08 22:57:26 -05002857 def test_sign_nulls(self):
2858 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002859 :py:obj:`sign` produces a signature for a string with embedded nulls.
Jean-Paul Calderone9828f662010-12-08 22:57:26 -05002860 """
2861 content = b("Watch out! \0 Did you see it?")
2862 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
2863 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
2864 sig = sign(priv_key, content, "sha1")
2865 verify(good_cert, sig, content, "sha1")
2866
2867
Rick Dean5b7b6372009-04-01 11:34:06 -05002868if __name__ == '__main__':
2869 main()