blob: 111aeab51855f53bbda4c2d682441ae4bbc85a71 [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"""
5Unit tests for L{OpenSSL.crypto}.
6"""
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 Calderoneadd7bf02010-08-22 17:38:30 -0400123client_key_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 Calderoneadd7bf02010-08-22 17:38:30 -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 Calderoneadd7bf02010-08-22 17:38:30 -0400160cleartextPrivateKeyPEM = b("""-----BEGIN RSA PRIVATE KEY-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400161MIICXQIBAAKBgQD5mkLpi7q6ROdu7khB3S9aanA0Zls7vvfGOmB80/yeylhGpsjA
162jWen0VtSQke/NlEPGtO38tsV7CsuFnSmschvAnGrcJl76b0UOOHUgDTIoRxC6QDU
1633claegwsrBA+sJEBbqx5RdXbIRGicPG/8qQ4Zm1SKOgotcbwiaor2yxZ2wIDAQAB
164AoGBAPCgMpmLxzwDaUmcFbTJUvlLW1hoxNNYSu2jIZm1k/hRAcE60JYwvBkgz3UB
165yMEh0AtLxYe0bFk6EHah11tMUPgscbCq73snJ++8koUw+csk22G65hOs51bVb7Aa
1666JBe67oLzdtvgCUFAA2qfrKzWRZzAdhUirQUZgySZk+Xq1pBAkEA/kZG0A6roTSM
167BVnx7LnPfsycKUsTumorpXiylZJjTi9XtmzxhrYN6wgZlDOOwOLgSQhszGpxVoMD
168u3gByT1b2QJBAPtL3mSKdvwRu/+40zaZLwvSJRxaj0mcE4BJOS6Oqs/hS1xRlrNk
169PpQ7WJ4yM6ZOLnXzm2mKyxm50Mv64109FtMCQQDOqS2KkjHaLowTGVxwC0DijMfr
170I9Lf8sSQk32J5VWCySWf5gGTfEnpmUa41gKTMJIbqZZLucNuDcOtzUaeWZlZAkA8
171ttXigLnCqR486JDPTi9ZscoZkZ+w7y6e/hH8t6d5Vjt48JVyfjPIaJY+km58LcN3
1726AWSeGAdtRFHVzR7oHjVAkB4hutvxiOeiIVQNBhM6RSI9aBPMI21DoX2JRoxvNW2
173cbvAhow217X9V0dVerEOKxnNYspXRrh36h7k4mQA+sDq
174-----END RSA PRIVATE KEY-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400175""")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400176
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400177cleartextCertificateRequestPEM = b("""-----BEGIN CERTIFICATE REQUEST-----
178MIIBnjCCAQcCAQAwXjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQH
179EwdDaGljYWdvMRcwFQYDVQQKEw5NeSBDb21wYW55IEx0ZDEXMBUGA1UEAxMORnJl
180ZGVyaWNrIERlYW4wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANp6Y17WzKSw
181BsUWkXdqg6tnXy8H8hA1msCMWpc+/2KJ4mbv5NyD6UD+/SqagQqulPbF/DFea9nA
182E0zhmHJELcM8gUTIlXv/cgDWnmK4xj8YkjVUiCdqKRAKeuzLG1pGmwwF5lGeJpXN
183xQn5ecR0UYSOWj6TTGXB9VyUMQzCClcBAgMBAAGgADANBgkqhkiG9w0BAQUFAAOB
184gQAAJGuF/R/GGbeC7FbFW+aJgr9ee0Xbl6nlhu7pTe67k+iiKT2dsl2ti68MVTnu
185Vrb3HUNqOkiwsJf6kCtq5oPn3QVYzTa76Dt2y3Rtzv6boRSlmlfrgS92GNma8JfR
186oICQk3nAudi6zl1Dix3BCv1pUp5KMtGn3MeDEi6QFGy2rA==
187-----END CERTIFICATE REQUEST-----
188""")
Rick Dean5b7b6372009-04-01 11:34:06 -0500189
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400190encryptedPrivateKeyPEM = b("""-----BEGIN RSA PRIVATE KEY-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400191Proc-Type: 4,ENCRYPTED
192DEK-Info: DES-EDE3-CBC,9573604A18579E9E
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400193
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400194SHOho56WxDkT0ht10UTeKc0F5u8cqIa01kzFAmETw0MAs8ezYtK15NPdCXUm3X/2
195a17G7LSF5bkxOgZ7vpXyMzun/owrj7CzvLxyncyEFZWvtvzaAhPhvTJtTIB3kf8B
1968+qRcpTGK7NgXEgYBW5bj1y4qZkD4zCL9o9NQzsKI3Ie8i0239jsDOWR38AxjXBH
197mGwAQ4Z6ZN5dnmM4fhMIWsmFf19sNyAML4gHenQCHhmXbjXeVq47aC2ProInJbrm
198+00TcisbAQ40V9aehVbcDKtS4ZbMVDwncAjpXpcncC54G76N6j7F7wL7L/FuXa3A
199fvSVy9n2VfF/pJ3kYSflLHH2G/DFxjF7dl0GxhKPxJjp3IJi9VtuvmN9R2jZWLQF
200tfC8dXgy/P9CfFQhlinqBTEwgH0oZ/d4k4NVFDSdEMaSdmBAjlHpc+Vfdty3HVnV
201rKXj//wslsFNm9kIwJGIgKUa/n2jsOiydrsk1mgH7SmNCb3YHgZhbbnq0qLat/HC
202gHDt3FHpNQ31QzzL3yrenFB2L9osIsnRsDTPFNi4RX4SpDgNroxOQmyzCCV6H+d4
203o1mcnNiZSdxLZxVKccq0AfRpHqpPAFnJcQHP6xyT9MZp6fBa0XkxDnt9kNU8H3Qw
2047SJWZ69VXjBUzMlQViLuaWMgTnL+ZVyFZf9hTF7U/ef4HMLMAVNdiaGG+G+AjCV/
205MbzjS007Oe4qqBnCWaFPSnJX6uLApeTbqAxAeyCql56ULW5x6vDMNC3dwjvS/CEh
20611n8RkgFIQA0AhuKSIg3CbuartRsJnWOLwgLTzsrKYL4yRog1RJrtw==
207-----END RSA PRIVATE KEY-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400208""")
209encryptedPrivateKeyPEMPassphrase = b("foobar")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400210
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400211# Some PKCS#7 stuff. Generated with the openssl command line:
212#
213# openssl crl2pkcs7 -inform pem -outform pem -certfile s.pem -nocrl
214#
215# with a certificate and key (but the key should be irrelevant) in s.pem
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400216pkcs7Data = b("""\
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400217-----BEGIN PKCS7-----
218MIIDNwYJKoZIhvcNAQcCoIIDKDCCAyQCAQExADALBgkqhkiG9w0BBwGgggMKMIID
219BjCCAm+gAwIBAgIBATANBgkqhkiG9w0BAQQFADB7MQswCQYDVQQGEwJTRzERMA8G
220A1UEChMITTJDcnlwdG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtN
221MkNyeXB0byBDZXJ0aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNA
222cG9zdDEuY29tMB4XDTAwMDkxMDA5NTEzMFoXDTAyMDkxMDA5NTEzMFowUzELMAkG
223A1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwlsb2NhbGhvc3Qx
224HTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tMFwwDQYJKoZIhvcNAQEBBQAD
225SwAwSAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh5kwI
226zOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEAAaOCAQQwggEAMAkGA1UdEwQCMAAw
227LAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0G
228A1UdDgQWBBTPhIKSvnsmYsBVNWjj0m3M2z0qVTCBpQYDVR0jBIGdMIGagBT7hyNp
22965w6kxXlxb8pUU/+7Sg4AaF/pH0wezELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0y
230Q3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlwdG8g
231Q2VydGlmaWNhdGUgTWFzdGVyMR0wGwYJKoZIhvcNAQkBFg5uZ3BzQHBvc3QxLmNv
232bYIBADANBgkqhkiG9w0BAQQFAAOBgQA7/CqT6PoHycTdhEStWNZde7M/2Yc6BoJu
233VwnW8YxGO8Sn6UJ4FeffZNcYZddSDKosw8LtPOeWoK3JINjAk5jiPQ2cww++7QGG
234/g5NDjxFZNDJP1dGiLAxPW6JXwov4v0FmdzfLOZ01jDcgQQZqEpYlgpuI5JEWUQ9
235Ho4EzbYCOaEAMQA=
236-----END PKCS7-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400237""")
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400238
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400239crlData = b("""\
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -0500240-----BEGIN X509 CRL-----
241MIIBWzCBxTANBgkqhkiG9w0BAQQFADBYMQswCQYDVQQGEwJVUzELMAkGA1UECBMC
242SUwxEDAOBgNVBAcTB0NoaWNhZ28xEDAOBgNVBAoTB1Rlc3RpbmcxGDAWBgNVBAMT
243D1Rlc3RpbmcgUm9vdCBDQRcNMDkwNzI2MDQzNDU2WhcNMTIwOTI3MDI0MTUyWjA8
244MBUCAgOrGA8yMDA5MDcyNTIzMzQ1NlowIwICAQAYDzIwMDkwNzI1MjMzNDU2WjAM
245MAoGA1UdFQQDCgEEMA0GCSqGSIb3DQEBBAUAA4GBAEBt7xTs2htdD3d4ErrcGAw1
2464dKcVnIWTutoI7xxen26Wwvh8VCsT7i/UeP+rBl9rC/kfjWjzQk3/zleaarGTpBT
2470yp4HXRFFoRhhSE/hP+eteaPXRgrsNRLHe9ZDd69wmh7J1wMDb0m81RG7kqcbsid
248vrzEeLDRiiPl92dyyWmu
249-----END X509 CRL-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400250""")
Jean-Paul Calderonee890db32010-08-22 16:55:15 -0400251
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400252class X509ExtTests(TestCase):
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400253 """
254 Tests for L{OpenSSL.crypto.X509Extension}.
255 """
256
257 def setUp(self):
258 """
259 Create a new private key and start a certificate request (for a test
260 method to finish in one way or another).
261 """
262 # Basic setup stuff to generate a certificate
263 self.pkey = PKey()
264 self.pkey.generate_key(TYPE_RSA, 384)
265 self.req = X509Req()
266 self.req.set_pubkey(self.pkey)
267 # Authority good you have.
268 self.req.get_subject().commonName = "Yoda root CA"
269 self.x509 = X509()
270 self.subject = self.x509.get_subject()
271 self.subject.commonName = self.req.get_subject().commonName
272 self.x509.set_issuer(self.subject)
273 self.x509.set_pubkey(self.pkey)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400274 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
275 expire = b((datetime.now() + timedelta(days=100)).strftime("%Y%m%d%H%M%SZ"))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400276 self.x509.set_notBefore(now)
277 self.x509.set_notAfter(expire)
278
279
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400280 def test_str(self):
281 """
282 The string representation of L{X509Extension} instances as returned by
283 C{str} includes stuff.
284 """
285 # This isn't necessarily the best string representation. Perhaps it
286 # will be changed/improved in the future.
287 self.assertEquals(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400288 str(X509Extension(b('basicConstraints'), True, b('CA:false'))),
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400289 'CA:FALSE')
290
291
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400292 def test_type(self):
293 """
294 L{X509Extension} and L{X509ExtensionType} refer to the same type object
295 and can be used to create instances of that type.
296 """
297 self.assertIdentical(X509Extension, X509ExtensionType)
298 self.assertConsistentType(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400299 X509Extension,
300 'X509Extension', b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400301
302
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500303 def test_construction(self):
304 """
305 L{X509Extension} accepts an extension type name, a critical flag,
306 and an extension value and returns an L{X509ExtensionType} instance.
307 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400308 basic = X509Extension(b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500309 self.assertTrue(
310 isinstance(basic, X509ExtensionType),
311 "%r is of type %r, should be %r" % (
312 basic, type(basic), X509ExtensionType))
313
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400314 comment = X509Extension(
315 b('nsComment'), False, b('pyOpenSSL unit test'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500316 self.assertTrue(
317 isinstance(comment, X509ExtensionType),
318 "%r is of type %r, should be %r" % (
319 comment, type(comment), X509ExtensionType))
320
321
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500322 def test_invalid_extension(self):
323 """
324 L{X509Extension} raises something if it is passed a bad extension
325 name or value.
326 """
327 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400328 Error, X509Extension, b('thisIsMadeUp'), False, b('hi'))
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500329 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400330 Error, X509Extension, b('basicConstraints'), False, b('blah blah'))
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500331
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500332 # Exercise a weird one (an extension which uses the r2i method). This
333 # exercises the codepath that requires a non-NULL ctx to be passed to
334 # X509V3_EXT_nconf. It can't work now because we provide no
335 # configuration database. It might be made to work in the future.
336 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400337 Error, X509Extension, b('proxyCertInfo'), True,
338 b('language:id-ppl-anyLanguage,pathlen:1,policy:text:AB'))
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500339
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500340
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500341 def test_get_critical(self):
342 """
343 L{X509ExtensionType.get_critical} returns the value of the
344 extension's critical flag.
345 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400346 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500347 self.assertTrue(ext.get_critical())
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400348 ext = X509Extension(b('basicConstraints'), False, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500349 self.assertFalse(ext.get_critical())
350
Jean-Paul Calderone7535dab2008-03-06 18:53:11 -0500351
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500352 def test_get_short_name(self):
353 """
354 L{X509ExtensionType.get_short_name} returns a string giving the short
355 type name of the extension.
356 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400357 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
358 self.assertEqual(ext.get_short_name(), b('basicConstraints'))
359 ext = X509Extension(b('nsComment'), True, b('foo bar'))
360 self.assertEqual(ext.get_short_name(), b('nsComment'))
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500361
362
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400363 def test_get_data(self):
364 """
365 L{X509Extension.get_data} returns a string giving the data of the
366 extension.
367 """
368 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
369 # Expect to get back the DER encoded form of CA:true.
370 self.assertEqual(ext.get_data(), b('0\x03\x01\x01\xff'))
371
372
373 def test_get_data_wrong_args(self):
374 """
375 L{X509Extension.get_data} raises L{TypeError} if passed any arguments.
376 """
377 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
378 self.assertRaises(TypeError, ext.get_data, None)
379 self.assertRaises(TypeError, ext.get_data, "foo")
380 self.assertRaises(TypeError, ext.get_data, 7)
381
382
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400383 def test_unused_subject(self):
Rick Dean47262da2009-07-08 16:17:17 -0500384 """
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400385 The C{subject} parameter to L{X509Extension} may be provided for an
386 extension which does not use it and is ignored in this case.
Rick Dean47262da2009-07-08 16:17:17 -0500387 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400388 ext1 = X509Extension(
389 b('basicConstraints'), False, b('CA:TRUE'), subject=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400390 self.x509.add_extensions([ext1])
391 self.x509.sign(self.pkey, 'sha1')
392 # This is a little lame. Can we think of a better way?
393 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400394 self.assertTrue(b('X509v3 Basic Constraints:') in text)
395 self.assertTrue(b('CA:TRUE') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400396
397
398 def test_subject(self):
399 """
400 If an extension requires a subject, the C{subject} parameter to
401 L{X509Extension} provides its value.
402 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400403 ext3 = X509Extension(
404 b('subjectKeyIdentifier'), False, b('hash'), subject=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400405 self.x509.add_extensions([ext3])
406 self.x509.sign(self.pkey, 'sha1')
407 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400408 self.assertTrue(b('X509v3 Subject Key Identifier:') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400409
410
411 def test_missing_subject(self):
412 """
413 If an extension requires a subject and the C{subject} parameter is
414 given no value, something happens.
415 """
416 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400417 Error, X509Extension, b('subjectKeyIdentifier'), False, b('hash'))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400418
419
420 def test_invalid_subject(self):
421 """
422 If the C{subject} parameter is given a value which is not an L{X509}
423 instance, L{TypeError} is raised.
424 """
425 for badObj in [True, object(), "hello", [], self]:
426 self.assertRaises(
427 TypeError,
428 X509Extension,
429 'basicConstraints', False, 'CA:TRUE', subject=badObj)
430
431
432 def test_unused_issuer(self):
433 """
434 The C{issuer} parameter to L{X509Extension} may be provided for an
435 extension which does not use it and is ignored in this case.
436 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400437 ext1 = X509Extension(
438 b('basicConstraints'), False, b('CA:TRUE'), issuer=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400439 self.x509.add_extensions([ext1])
440 self.x509.sign(self.pkey, 'sha1')
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_issuer(self):
447 """
448 If an extension requires a issuer, the C{issuer} parameter to
449 L{X509Extension} provides its value.
450 """
451 ext2 = X509Extension(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400452 b('authorityKeyIdentifier'), False, b('issuer:always'),
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400453 issuer=self.x509)
454 self.x509.add_extensions([ext2])
455 self.x509.sign(self.pkey, 'sha1')
456 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400457 self.assertTrue(b('X509v3 Authority Key Identifier:') in text)
458 self.assertTrue(b('DirName:/CN=Yoda root CA') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400459
460
461 def test_missing_issuer(self):
462 """
463 If an extension requires an issue and the C{issuer} parameter is given
464 no value, something happens.
465 """
466 self.assertRaises(
467 Error,
468 X509Extension,
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400469 b('authorityKeyIdentifier'), False,
470 b('keyid:always,issuer:always'))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400471
472
473 def test_invalid_issuer(self):
474 """
475 If the C{issuer} parameter is given a value which is not an L{X509}
476 instance, L{TypeError} is raised.
477 """
478 for badObj in [True, object(), "hello", [], self]:
479 self.assertRaises(
480 TypeError,
481 X509Extension,
482 'authorityKeyIdentifier', False, 'keyid:always,issuer:always',
483 issuer=badObj)
Rick Dean47262da2009-07-08 16:17:17 -0500484
485
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500486
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400487class PKeyTests(TestCase):
Jean-Paul Calderoneac930e12008-03-06 18:50:51 -0500488 """
489 Unit tests for L{OpenSSL.crypto.PKey}.
490 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400491 def test_type(self):
492 """
493 L{PKey} and L{PKeyType} refer to the same type object and can be used
494 to create instances of that type.
495 """
496 self.assertIdentical(PKey, PKeyType)
497 self.assertConsistentType(PKey, 'PKey')
498
499
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500500 def test_construction(self):
501 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400502 L{PKey} takes no arguments and returns a new L{PKey} instance.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500503 """
504 self.assertRaises(TypeError, PKey, None)
505 key = PKey()
506 self.assertTrue(
507 isinstance(key, PKeyType),
508 "%r is of type %r, should be %r" % (key, type(key), PKeyType))
509
510
511 def test_pregeneration(self):
512 """
513 L{PKeyType.bits} and L{PKeyType.type} return C{0} before the key is
514 generated.
515 """
516 key = PKey()
517 self.assertEqual(key.type(), 0)
518 self.assertEqual(key.bits(), 0)
519
520
521 def test_failedGeneration(self):
522 """
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500523 L{PKeyType.generate_key} takes two arguments, the first giving the key
524 type as one of L{TYPE_RSA} or L{TYPE_DSA} and the second giving the
525 number of bits to generate. If an invalid type is specified or
526 generation fails, L{Error} is raised. If an invalid number of bits is
527 specified, L{ValueError} or L{Error} is raised.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500528 """
529 key = PKey()
530 self.assertRaises(TypeError, key.generate_key)
531 self.assertRaises(TypeError, key.generate_key, 1, 2, 3)
532 self.assertRaises(TypeError, key.generate_key, "foo", "bar")
533 self.assertRaises(Error, key.generate_key, -1, 0)
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500534
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500535 self.assertRaises(ValueError, key.generate_key, TYPE_RSA, -1)
536 self.assertRaises(ValueError, key.generate_key, TYPE_RSA, 0)
Jean-Paul Calderoned71fe982008-03-06 00:31:50 -0500537
538 # XXX RSA generation for small values of bits is fairly buggy in a wide
539 # range of OpenSSL versions. I need to figure out what the safe lower
540 # bound for a reasonable number of OpenSSL versions is and explicitly
541 # check for that in the wrapper. The failure behavior is typically an
542 # infinite loop inside OpenSSL.
543
544 # self.assertRaises(Error, key.generate_key, TYPE_RSA, 2)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500545
546 # XXX DSA generation seems happy with any number of bits. The DSS
547 # says bits must be between 512 and 1024 inclusive. OpenSSL's DSA
548 # generator doesn't seem to care about the upper limit at all. For
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500549 # the lower limit, it uses 512 if anything smaller is specified.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500550 # So, it doesn't seem possible to make generate_key fail for
551 # TYPE_DSA with a bits argument which is at least an int.
552
553 # self.assertRaises(Error, key.generate_key, TYPE_DSA, -7)
554
555
556 def test_rsaGeneration(self):
557 """
558 L{PKeyType.generate_key} generates an RSA key when passed
559 L{TYPE_RSA} as a type and a reasonable number of bits.
560 """
561 bits = 128
562 key = PKey()
563 key.generate_key(TYPE_RSA, bits)
564 self.assertEqual(key.type(), TYPE_RSA)
565 self.assertEqual(key.bits(), bits)
566
567
568 def test_dsaGeneration(self):
569 """
570 L{PKeyType.generate_key} generates a DSA key when passed
571 L{TYPE_DSA} as a type and a reasonable number of bits.
572 """
573 # 512 is a magic number. The DSS (Digital Signature Standard)
574 # allows a minimum of 512 bits for DSA. DSA_generate_parameters
575 # will silently promote any value below 512 to 512.
576 bits = 512
577 key = PKey()
578 key.generate_key(TYPE_DSA, bits)
579 self.assertEqual(key.type(), TYPE_DSA)
580 self.assertEqual(key.bits(), bits)
581
582
583 def test_regeneration(self):
584 """
585 L{PKeyType.generate_key} can be called multiple times on the same
586 key to generate new keys.
587 """
588 key = PKey()
589 for type, bits in [(TYPE_RSA, 512), (TYPE_DSA, 576)]:
590 key.generate_key(type, bits)
591 self.assertEqual(key.type(), type)
592 self.assertEqual(key.bits(), bits)
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500593
594
595
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400596class X509NameTests(TestCase):
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500597 """
598 Unit tests for L{OpenSSL.crypto.X509Name}.
599 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500600 def _x509name(self, **attrs):
601 # XXX There's no other way to get a new X509Name yet.
602 name = X509().get_subject()
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400603 attrs = list(attrs.items())
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500604 # Make the order stable - order matters!
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400605 def key(attr):
606 return attr[1]
607 attrs.sort(key=key)
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500608 for k, v in attrs:
609 setattr(name, k, v)
610 return name
611
612
Rick Deane15b1472009-07-09 15:53:42 -0500613 def test_type(self):
614 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400615 The type of X509Name objects is L{X509NameType}.
Rick Deane15b1472009-07-09 15:53:42 -0500616 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400617 self.assertIdentical(X509Name, X509NameType)
618 self.assertEqual(X509NameType.__name__, 'X509Name')
619 self.assertTrue(isinstance(X509NameType, type))
620
Rick Deane15b1472009-07-09 15:53:42 -0500621 name = self._x509name()
622 self.assertTrue(
623 isinstance(name, X509NameType),
624 "%r is of type %r, should be %r" % (
625 name, type(name), X509NameType))
Rick Deane15b1472009-07-09 15:53:42 -0500626
627
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500628 def test_attributes(self):
629 """
630 L{X509NameType} instances have attributes for each standard (?)
631 X509Name field.
632 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500633 name = self._x509name()
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500634 name.commonName = "foo"
635 self.assertEqual(name.commonName, "foo")
636 self.assertEqual(name.CN, "foo")
637 name.CN = "baz"
638 self.assertEqual(name.commonName, "baz")
639 self.assertEqual(name.CN, "baz")
640 name.commonName = "bar"
641 self.assertEqual(name.commonName, "bar")
642 self.assertEqual(name.CN, "bar")
643 name.CN = "quux"
644 self.assertEqual(name.commonName, "quux")
645 self.assertEqual(name.CN, "quux")
646
647
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500648 def test_copy(self):
649 """
650 L{X509Name} creates a new L{X509NameType} instance with all the same
651 attributes as an existing L{X509NameType} instance when called with
652 one.
653 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500654 name = self._x509name(commonName="foo", emailAddress="bar@example.com")
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500655
656 copy = X509Name(name)
657 self.assertEqual(copy.commonName, "foo")
658 self.assertEqual(copy.emailAddress, "bar@example.com")
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500659
660 # Mutate the copy and ensure the original is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500661 copy.commonName = "baz"
662 self.assertEqual(name.commonName, "foo")
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500663
664 # Mutate the original and ensure the copy is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500665 name.emailAddress = "quux@example.com"
666 self.assertEqual(copy.emailAddress, "bar@example.com")
667
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500668
669 def test_repr(self):
670 """
671 L{repr} passed an L{X509NameType} instance should return a string
672 containing a description of the type and the NIDs which have been set
673 on it.
674 """
675 name = self._x509name(commonName="foo", emailAddress="bar")
676 self.assertEqual(
677 repr(name),
678 "<X509Name object '/emailAddress=bar/CN=foo'>")
679
680
681 def test_comparison(self):
682 """
683 L{X509NameType} instances should compare based on their NIDs.
684 """
685 def _equality(a, b, assertTrue, assertFalse):
686 assertTrue(a == b, "(%r == %r) --> False" % (a, b))
687 assertFalse(a != b)
688 assertTrue(b == a)
689 assertFalse(b != a)
690
691 def assertEqual(a, b):
692 _equality(a, b, self.assertTrue, self.assertFalse)
693
694 # Instances compare equal to themselves.
695 name = self._x509name()
696 assertEqual(name, name)
697
698 # Empty instances should compare equal to each other.
699 assertEqual(self._x509name(), self._x509name())
700
701 # Instances with equal NIDs should compare equal to each other.
702 assertEqual(self._x509name(commonName="foo"),
703 self._x509name(commonName="foo"))
704
705 # Instance with equal NIDs set using different aliases should compare
706 # equal to each other.
707 assertEqual(self._x509name(commonName="foo"),
708 self._x509name(CN="foo"))
709
710 # Instances with more than one NID with the same values should compare
711 # equal to each other.
712 assertEqual(self._x509name(CN="foo", organizationalUnitName="bar"),
713 self._x509name(commonName="foo", OU="bar"))
714
715 def assertNotEqual(a, b):
716 _equality(a, b, self.assertFalse, self.assertTrue)
717
718 # Instances with different values for the same NID should not compare
719 # equal to each other.
720 assertNotEqual(self._x509name(CN="foo"),
721 self._x509name(CN="bar"))
722
723 # Instances with different NIDs should not compare equal to each other.
724 assertNotEqual(self._x509name(CN="foo"),
725 self._x509name(OU="foo"))
726
727 def _inequality(a, b, assertTrue, assertFalse):
728 assertTrue(a < b)
729 assertTrue(a <= b)
730 assertTrue(b > a)
731 assertTrue(b >= a)
732 assertFalse(a > b)
733 assertFalse(a >= b)
734 assertFalse(b < a)
735 assertFalse(b <= a)
736
737 def assertLessThan(a, b):
738 _inequality(a, b, self.assertTrue, self.assertFalse)
739
740 # An X509Name with a NID with a value which sorts less than the value
741 # of the same NID on another X509Name compares less than the other
742 # X509Name.
743 assertLessThan(self._x509name(CN="abc"),
744 self._x509name(CN="def"))
745
746 def assertGreaterThan(a, b):
747 _inequality(a, b, self.assertFalse, self.assertTrue)
748
749 # An X509Name with a NID with a value which sorts greater than the
750 # value of the same NID on another X509Name compares greater than the
751 # other X509Name.
752 assertGreaterThan(self._x509name(CN="def"),
753 self._x509name(CN="abc"))
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -0500754
755
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400756 def test_hash(self):
757 """
758 L{X509Name.hash} returns an integer hash based on the value of the
759 name.
760 """
761 a = self._x509name(CN="foo")
762 b = self._x509name(CN="foo")
763 self.assertEqual(a.hash(), b.hash())
764 a.CN = "bar"
765 self.assertNotEqual(a.hash(), b.hash())
766
767
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400768 def test_der(self):
769 """
770 L{X509Name.der} returns the DER encoded form of the name.
771 """
772 a = self._x509name(CN="foo", C="US")
773 self.assertEqual(
774 a.der(),
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -0400775 b('0\x1b1\x0b0\t\x06\x03U\x04\x06\x13\x02US'
776 '1\x0c0\n\x06\x03U\x04\x03\x13\x03foo'))
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400777
778
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400779 def test_get_components(self):
780 """
781 L{X509Name.get_components} returns a C{list} of two-tuples of C{str}
782 giving the NIDs and associated values which make up the name.
783 """
784 a = self._x509name()
785 self.assertEqual(a.get_components(), [])
786 a.CN = "foo"
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -0400787 self.assertEqual(a.get_components(), [(b("CN"), b("foo"))])
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400788 a.organizationalUnitName = "bar"
789 self.assertEqual(
790 a.get_components(),
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -0400791 [(b("CN"), b("foo")), (b("OU"), b("bar"))])
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400792
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400793
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400794class _PKeyInteractionTestsMixin:
795 """
796 Tests which involve another thing and a PKey.
797 """
798 def signable(self):
799 """
800 Return something with a C{set_pubkey}, C{set_pubkey}, and C{sign} method.
801 """
802 raise NotImplementedError()
803
804
805 def test_signWithUngenerated(self):
806 """
807 L{X509Req.sign} raises L{ValueError} when pass a L{PKey} with no parts.
808 """
809 request = self.signable()
810 key = PKey()
811 self.assertRaises(ValueError, request.sign, key, 'MD5')
812
813
814 def test_signWithPublicKey(self):
815 """
816 L{X509Req.sign} raises L{ValueError} when pass a L{PKey} with no
817 private part as the signing key.
818 """
819 request = self.signable()
820 key = PKey()
821 key.generate_key(TYPE_RSA, 512)
822 request.set_pubkey(key)
823 pub = request.get_pubkey()
824 self.assertRaises(ValueError, request.sign, pub, 'MD5')
825
826
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -0400827 def test_signWithUnknownDigest(self):
828 """
829 L{X509Req.sign} raises L{ValueError} when passed a digest name which is
830 not known.
831 """
832 request = self.signable()
833 key = PKey()
834 key.generate_key(TYPE_RSA, 512)
835 self.assertRaises(ValueError, request.sign, key, "monkeys")
836
837
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -0400838 def test_sign(self):
839 """
840 L{X509Req.sign} succeeds when passed a private key object and a valid
841 digest function. C{X509Req.verify} can be used to check the signature.
842 """
843 request = self.signable()
844 key = PKey()
845 key.generate_key(TYPE_RSA, 512)
846 request.set_pubkey(key)
847 request.sign(key, 'MD5')
848 # If the type has a verify method, cover that too.
849 if getattr(request, 'verify', None) is not None:
850 pub = request.get_pubkey()
851 self.assertTrue(request.verify(pub))
852 # Make another key that won't verify.
853 key = PKey()
854 key.generate_key(TYPE_RSA, 512)
855 self.assertRaises(Error, request.verify, key)
856
857
858
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400859
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400860class X509ReqTests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -0500861 """
862 Tests for L{OpenSSL.crypto.X509Req}.
863 """
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400864 def signable(self):
865 """
866 Create and return a new L{X509Req}.
867 """
868 return X509Req()
869
870
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400871 def test_type(self):
872 """
873 L{X509Req} and L{X509ReqType} refer to the same type object and can be
874 used to create instances of that type.
875 """
876 self.assertIdentical(X509Req, X509ReqType)
877 self.assertConsistentType(X509Req, 'X509Req')
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -0500878
879
880 def test_construction(self):
881 """
882 L{X509Req} takes no arguments and returns an L{X509ReqType} instance.
883 """
884 request = X509Req()
885 self.assertTrue(
886 isinstance(request, X509ReqType),
887 "%r is of type %r, should be %r" % (request, type(request), X509ReqType))
888
889
Jean-Paul Calderone8dd19b82008-12-28 20:41:16 -0500890 def test_version(self):
891 """
892 L{X509ReqType.set_version} sets the X.509 version of the certificate
893 request. L{X509ReqType.get_version} returns the X.509 version of
894 the certificate request. The initial value of the version is 0.
895 """
896 request = X509Req()
897 self.assertEqual(request.get_version(), 0)
898 request.set_version(1)
899 self.assertEqual(request.get_version(), 1)
900 request.set_version(3)
901 self.assertEqual(request.get_version(), 3)
902
903
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -0400904 def test_version_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -0400905 """
906 L{X509ReqType.set_version} raises L{TypeError} if called with the wrong
907 number of arguments or with a non-C{int} argument.
908 L{X509ReqType.get_version} raises L{TypeError} if called with any
909 arguments.
910 """
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -0400911 request = X509Req()
912 self.assertRaises(TypeError, request.set_version)
913 self.assertRaises(TypeError, request.set_version, "foo")
914 self.assertRaises(TypeError, request.set_version, 1, 2)
915 self.assertRaises(TypeError, request.get_version, None)
916
917
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -0500918 def test_get_subject(self):
919 """
920 L{X509ReqType.get_subject} returns an L{X509Name} for the subject of
921 the request and which is valid even after the request object is
922 otherwise dead.
923 """
924 request = X509Req()
925 subject = request.get_subject()
926 self.assertTrue(
927 isinstance(subject, X509NameType),
928 "%r is of type %r, should be %r" % (subject, type(subject), X509NameType))
929 subject.commonName = "foo"
930 self.assertEqual(request.get_subject().commonName, "foo")
931 del request
932 subject.commonName = "bar"
933 self.assertEqual(subject.commonName, "bar")
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500934
935
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -0400936 def test_get_subject_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -0400937 """
938 L{X509ReqType.get_subject} raises L{TypeError} if called with any
939 arguments.
940 """
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -0400941 request = X509Req()
942 self.assertRaises(TypeError, request.get_subject, None)
943
944
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400945 def test_add_extensions(self):
946 """
947 L{X509Req.add_extensions} accepts a C{list} of L{X509Extension}
948 instances and adds them to the X509 request.
949 """
950 request = X509Req()
951 request.add_extensions([
Jean-Paul Calderonee16f9f32010-08-22 19:20:37 -0400952 X509Extension(b('basicConstraints'), True, b('CA:false'))])
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400953 # XXX Add get_extensions so the rest of this unit test can be written.
954
955
956 def test_add_extensions_wrong_args(self):
957 """
958 L{X509Req.add_extensions} raises L{TypeError} if called with the wrong
959 number of arguments or with a non-C{list}. Or it raises L{ValueError}
960 if called with a C{list} containing objects other than L{X509Extension}
961 instances.
962 """
963 request = X509Req()
964 self.assertRaises(TypeError, request.add_extensions)
965 self.assertRaises(TypeError, request.add_extensions, object())
966 self.assertRaises(ValueError, request.add_extensions, [object()])
967 self.assertRaises(TypeError, request.add_extensions, [], None)
968
969
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500970
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400971class X509Tests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500972 """
973 Tests for L{OpenSSL.crypto.X509}.
974 """
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400975 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
Jean-Paul Calderone8114b452008-03-25 15:27:59 -0400976
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200977 extpem = """
978-----BEGIN CERTIFICATE-----
979MIIC3jCCAkegAwIBAgIJAJHFjlcCgnQzMA0GCSqGSIb3DQEBBQUAMEcxCzAJBgNV
980BAYTAlNFMRUwEwYDVQQIEwxXZXN0ZXJib3R0b20xEjAQBgNVBAoTCUNhdGFsb2dp
981eDENMAsGA1UEAxMEUm9vdDAeFw0wODA0MjIxNDQ1MzhaFw0wOTA0MjIxNDQ1Mzha
982MFQxCzAJBgNVBAYTAlNFMQswCQYDVQQIEwJXQjEUMBIGA1UEChMLT3Blbk1ldGFk
983aXIxIjAgBgNVBAMTGW5vZGUxLm9tMi5vcGVubWV0YWRpci5vcmcwgZ8wDQYJKoZI
984hvcNAQEBBQADgY0AMIGJAoGBAPIcQMrwbk2nESF/0JKibj9i1x95XYAOwP+LarwT
985Op4EQbdlI9SY+uqYqlERhF19w7CS+S6oyqx0DRZSk4Y9dZ9j9/xgm2u/f136YS1u
986zgYFPvfUs6PqYLPSM8Bw+SjJ+7+2+TN+Tkiof9WP1cMjodQwOmdsiRbR0/J7+b1B
987hec1AgMBAAGjgcQwgcEwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNT
988TCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFIdHsBcMVVMbAO7j6NCj
98903HgLnHaMB8GA1UdIwQYMBaAFL2h9Bf9Mre4vTdOiHTGAt7BRY/8MEYGA1UdEQQ/
990MD2CDSouZXhhbXBsZS5vcmeCESoub20yLmV4bWFwbGUuY29thwSC7wgKgRNvbTJA
991b3Blbm1ldGFkaXIub3JnMA0GCSqGSIb3DQEBBQUAA4GBALd7WdXkp2KvZ7/PuWZA
992MPlIxyjS+Ly11+BNE0xGQRp9Wz+2lABtpgNqssvU156+HkKd02rGheb2tj7MX9hG
993uZzbwDAZzJPjzDQDD7d3cWsrVcfIdqVU7epHqIadnOF+X0ghJ39pAm6VVadnSXCt
994WpOdIpB8KksUTCzV591Nr1wd
995-----END CERTIFICATE-----
996 """
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400997 def signable(self):
998 """
999 Create and return a new L{X509}.
1000 """
1001 return X509()
1002
1003
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001004 def test_type(self):
1005 """
1006 L{X509} and L{X509Type} refer to the same type object and can be used
1007 to create instances of that type.
1008 """
1009 self.assertIdentical(X509, X509Type)
1010 self.assertConsistentType(X509, 'X509')
1011
1012
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001013 def test_construction(self):
1014 """
1015 L{X509} takes no arguments and returns an instance of L{X509Type}.
1016 """
1017 certificate = X509()
1018 self.assertTrue(
1019 isinstance(certificate, X509Type),
1020 "%r is of type %r, should be %r" % (certificate,
1021 type(certificate),
1022 X509Type))
Rick Deane15b1472009-07-09 15:53:42 -05001023 self.assertEqual(type(X509Type).__name__, 'type')
1024 self.assertEqual(type(certificate).__name__, 'X509')
1025 self.assertEqual(type(certificate), X509Type)
Rick Dean04113e72009-07-16 12:06:35 -05001026 self.assertEqual(type(certificate), X509)
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001027
1028
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001029 def test_get_version_wrong_args(self):
1030 """
1031 L{X509.get_version} raises L{TypeError} if invoked with any arguments.
1032 """
1033 cert = X509()
1034 self.assertRaises(TypeError, cert.get_version, None)
1035
1036
1037 def test_set_version_wrong_args(self):
1038 """
1039 L{X509.set_version} raises L{TypeError} if invoked with the wrong number
1040 of arguments or an argument not of type C{int}.
1041 """
1042 cert = X509()
1043 self.assertRaises(TypeError, cert.set_version)
1044 self.assertRaises(TypeError, cert.set_version, None)
1045 self.assertRaises(TypeError, cert.set_version, 1, None)
1046
1047
1048 def test_version(self):
1049 """
1050 L{X509.set_version} sets the certificate version number.
1051 L{X509.get_version} retrieves it.
1052 """
1053 cert = X509()
1054 cert.set_version(1234)
1055 self.assertEquals(cert.get_version(), 1234)
1056
1057
1058 def test_get_serial_number_wrong_args(self):
1059 """
1060 L{X509.get_serial_number} raises L{TypeError} if invoked with any
1061 arguments.
1062 """
1063 cert = X509()
1064 self.assertRaises(TypeError, cert.get_serial_number, None)
1065
1066
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001067 def test_serial_number(self):
1068 """
1069 The serial number of an L{X509Type} can be retrieved and modified with
1070 L{X509Type.get_serial_number} and L{X509Type.set_serial_number}.
1071 """
1072 certificate = X509()
1073 self.assertRaises(TypeError, certificate.set_serial_number)
1074 self.assertRaises(TypeError, certificate.set_serial_number, 1, 2)
1075 self.assertRaises(TypeError, certificate.set_serial_number, "1")
1076 self.assertRaises(TypeError, certificate.set_serial_number, 5.5)
1077 self.assertEqual(certificate.get_serial_number(), 0)
1078 certificate.set_serial_number(1)
1079 self.assertEqual(certificate.get_serial_number(), 1)
1080 certificate.set_serial_number(2 ** 32 + 1)
1081 self.assertEqual(certificate.get_serial_number(), 2 ** 32 + 1)
1082 certificate.set_serial_number(2 ** 64 + 1)
1083 self.assertEqual(certificate.get_serial_number(), 2 ** 64 + 1)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001084 certificate.set_serial_number(2 ** 128 + 1)
1085 self.assertEqual(certificate.get_serial_number(), 2 ** 128 + 1)
1086
1087
1088 def _setBoundTest(self, which):
1089 """
1090 L{X509Type.set_notBefore} takes a string in the format of an ASN1
1091 GENERALIZEDTIME and sets the beginning of the certificate's validity
1092 period to it.
1093 """
1094 certificate = X509()
1095 set = getattr(certificate, 'set_not' + which)
1096 get = getattr(certificate, 'get_not' + which)
1097
Jean-Paul Calderonee0615b52008-03-09 21:44:46 -04001098 # Starts with no value.
1099 self.assertEqual(get(), None)
1100
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001101 # GMT (Or is it UTC?) -exarkun
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001102 when = b("20040203040506Z")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001103 set(when)
1104 self.assertEqual(get(), when)
1105
1106 # A plus two hours and thirty minutes offset
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001107 when = b("20040203040506+0530")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001108 set(when)
1109 self.assertEqual(get(), when)
1110
1111 # A minus one hour fifteen minutes offset
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001112 when = b("20040203040506-0115")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001113 set(when)
1114 self.assertEqual(get(), when)
1115
1116 # An invalid string results in a ValueError
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001117 self.assertRaises(ValueError, set, b("foo bar"))
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001118
Jean-Paul Calderone31ca2002010-01-30 15:14:43 -05001119 # The wrong number of arguments results in a TypeError.
1120 self.assertRaises(TypeError, set)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001121 self.assertRaises(TypeError, set, b("20040203040506Z"), b("20040203040506Z"))
1122 self.assertRaises(TypeError, get, b("foo bar"))
1123
Jean-Paul Calderone31ca2002010-01-30 15:14:43 -05001124
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001125 # XXX ASN1_TIME (not GENERALIZEDTIME)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001126
1127 def test_set_notBefore(self):
1128 """
1129 L{X509Type.set_notBefore} takes a string in the format of an ASN1
1130 GENERALIZEDTIME and sets the beginning of the certificate's validity
1131 period to it.
1132 """
1133 self._setBoundTest("Before")
1134
1135
1136 def test_set_notAfter(self):
1137 """
1138 L{X509Type.set_notAfter} takes a string in the format of an ASN1
1139 GENERALIZEDTIME and sets the end of the certificate's validity period
1140 to it.
1141 """
1142 self._setBoundTest("After")
Jean-Paul Calderone76576d52008-03-24 16:04:46 -04001143
1144
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001145 def test_get_notBefore(self):
1146 """
1147 L{X509Type.get_notBefore} returns a string in the format of an ASN1
1148 GENERALIZEDTIME even for certificates which store it as UTCTIME
1149 internally.
1150 """
Jean-Paul Calderone8114b452008-03-25 15:27:59 -04001151 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001152 self.assertEqual(cert.get_notBefore(), b("20090325123658Z"))
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001153
Rick Dean38a05c82009-07-18 01:41:30 -05001154
1155 def test_get_notAfter(self):
1156 """
1157 L{X509Type.get_notAfter} returns a string in the format of an ASN1
1158 GENERALIZEDTIME even for certificates which store it as UTCTIME
1159 internally.
1160 """
1161 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001162 self.assertEqual(cert.get_notAfter(), b("20170611123658Z"))
Rick Dean38a05c82009-07-18 01:41:30 -05001163
1164
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001165 def test_gmtime_adj_notBefore_wrong_args(self):
1166 """
1167 L{X509Type.gmtime_adj_notBefore} raises L{TypeError} if called with the
1168 wrong number of arguments or a non-C{int} argument.
1169 """
1170 cert = X509()
1171 self.assertRaises(TypeError, cert.gmtime_adj_notBefore)
1172 self.assertRaises(TypeError, cert.gmtime_adj_notBefore, None)
1173 self.assertRaises(TypeError, cert.gmtime_adj_notBefore, 123, None)
1174
1175
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001176 def test_gmtime_adj_notBefore(self):
1177 """
1178 L{X509Type.gmtime_adj_notBefore} changes the not-before timestamp to be
1179 the current time plus the number of seconds passed in.
1180 """
1181 cert = load_certificate(FILETYPE_PEM, self.pemData)
1182 now = datetime.utcnow() + timedelta(seconds=100)
1183 cert.gmtime_adj_notBefore(100)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001184 self.assertEqual(cert.get_notBefore(), b(now.strftime("%Y%m%d%H%M%SZ")))
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001185
1186
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001187 def test_gmtime_adj_notAfter_wrong_args(self):
1188 """
1189 L{X509Type.gmtime_adj_notAfter} raises L{TypeError} if called with the
1190 wrong number of arguments or a non-C{int} argument.
1191 """
1192 cert = X509()
1193 self.assertRaises(TypeError, cert.gmtime_adj_notAfter)
1194 self.assertRaises(TypeError, cert.gmtime_adj_notAfter, None)
1195 self.assertRaises(TypeError, cert.gmtime_adj_notAfter, 123, None)
1196
1197
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001198 def test_gmtime_adj_notAfter(self):
1199 """
1200 L{X509Type.gmtime_adj_notAfter} changes the not-after timestamp to be
1201 the current time plus the number of seconds passed in.
1202 """
1203 cert = load_certificate(FILETYPE_PEM, self.pemData)
1204 now = datetime.utcnow() + timedelta(seconds=100)
1205 cert.gmtime_adj_notAfter(100)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001206 self.assertEqual(cert.get_notAfter(), b(now.strftime("%Y%m%d%H%M%SZ")))
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001207
1208
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001209 def test_has_expired_wrong_args(self):
1210 """
1211 L{X509Type.has_expired} raises L{TypeError} if called with any
1212 arguments.
1213 """
1214 cert = X509()
1215 self.assertRaises(TypeError, cert.has_expired, None)
1216
1217
1218 def test_has_expired(self):
1219 """
1220 L{X509Type.has_expired} returns C{True} if the certificate's not-after
1221 time is in the past.
1222 """
1223 cert = X509()
1224 cert.gmtime_adj_notAfter(-1)
1225 self.assertTrue(cert.has_expired())
1226
1227
1228 def test_has_not_expired(self):
1229 """
1230 L{X509Type.has_expired} returns C{False} if the certificate's not-after
1231 time is in the future.
1232 """
1233 cert = X509()
1234 cert.gmtime_adj_notAfter(2)
1235 self.assertFalse(cert.has_expired())
1236
1237
Rick Dean38a05c82009-07-18 01:41:30 -05001238 def test_digest(self):
1239 """
1240 L{X509.digest} returns a string giving ":"-separated hex-encoded words
1241 of the digest of the certificate.
1242 """
1243 cert = X509()
1244 self.assertEqual(
1245 cert.digest("md5"),
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001246 b("A8:EB:07:F8:53:25:0A:F2:56:05:C5:A5:C4:C4:C7:15"))
Rick Dean38a05c82009-07-18 01:41:30 -05001247
1248
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001249 def _extcert(self, pkey, extensions):
1250 cert = X509()
1251 cert.set_pubkey(pkey)
1252 cert.get_subject().commonName = "Unit Tests"
1253 cert.get_issuer().commonName = "Unit Tests"
1254 when = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
1255 cert.set_notBefore(when)
1256 cert.set_notAfter(when)
1257
1258 cert.add_extensions(extensions)
1259 return load_certificate(
1260 FILETYPE_PEM, dump_certificate(FILETYPE_PEM, cert))
1261
1262
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001263 def test_extension_count(self):
1264 """
1265 L{X509.get_extension_count} returns the number of extensions that are
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001266 present in the certificate.
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001267 """
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001268 pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001269 ca = X509Extension(b('basicConstraints'), True, b('CA:FALSE'))
1270 key = X509Extension(b('keyUsage'), True, b('digitalSignature'))
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001271 subjectAltName = X509Extension(
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001272 b('subjectAltName'), True, b('DNS:example.com'))
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001273
1274 # Try a certificate with no extensions at all.
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001275 c = self._extcert(pkey, [])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001276 self.assertEqual(c.get_extension_count(), 0)
1277
1278 # And a certificate with one
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001279 c = self._extcert(pkey, [ca])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001280 self.assertEqual(c.get_extension_count(), 1)
1281
1282 # And a certificate with several
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001283 c = self._extcert(pkey, [ca, key, subjectAltName])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001284 self.assertEqual(c.get_extension_count(), 3)
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001285
1286
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001287 def test_get_extension(self):
1288 """
1289 L{X509.get_extension} takes an integer and returns an L{X509Extension}
1290 corresponding to the extension at that index.
1291 """
1292 pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001293 ca = X509Extension(b('basicConstraints'), True, b('CA:FALSE'))
1294 key = X509Extension(b('keyUsage'), True, b('digitalSignature'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001295 subjectAltName = X509Extension(
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001296 b('subjectAltName'), False, b('DNS:example.com'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001297
1298 cert = self._extcert(pkey, [ca, key, subjectAltName])
1299
1300 ext = cert.get_extension(0)
1301 self.assertTrue(isinstance(ext, X509Extension))
1302 self.assertTrue(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001303 self.assertEqual(ext.get_short_name(), b('basicConstraints'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001304
1305 ext = cert.get_extension(1)
1306 self.assertTrue(isinstance(ext, X509Extension))
1307 self.assertTrue(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001308 self.assertEqual(ext.get_short_name(), b('keyUsage'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001309
1310 ext = cert.get_extension(2)
1311 self.assertTrue(isinstance(ext, X509Extension))
1312 self.assertFalse(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001313 self.assertEqual(ext.get_short_name(), b('subjectAltName'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001314
1315 self.assertRaises(IndexError, cert.get_extension, -1)
1316 self.assertRaises(IndexError, cert.get_extension, 4)
1317 self.assertRaises(TypeError, cert.get_extension, "hello")
1318
1319
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001320 def test_invalid_digest_algorithm(self):
1321 """
1322 L{X509.digest} raises L{ValueError} if called with an unrecognized hash
1323 algorithm.
1324 """
1325 cert = X509()
1326 self.assertRaises(ValueError, cert.digest, "monkeys")
1327
1328
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001329 def test_get_subject_wrong_args(self):
1330 """
1331 L{X509.get_subject} raises L{TypeError} if called with any arguments.
1332 """
1333 cert = X509()
1334 self.assertRaises(TypeError, cert.get_subject, None)
1335
1336
1337 def test_get_subject(self):
1338 """
1339 L{X509.get_subject} returns an L{X509Name} instance.
1340 """
1341 cert = load_certificate(FILETYPE_PEM, self.pemData)
1342 subj = cert.get_subject()
1343 self.assertTrue(isinstance(subj, X509Name))
1344 self.assertEquals(
1345 subj.get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001346 [(b('C'), b('US')), (b('ST'), b('IL')), (b('L'), b('Chicago')),
1347 (b('O'), b('Testing')), (b('CN'), b('Testing Root CA'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001348
1349
1350 def test_set_subject_wrong_args(self):
1351 """
1352 L{X509.set_subject} raises a L{TypeError} if called with the wrong
1353 number of arguments or an argument not of type L{X509Name}.
1354 """
1355 cert = X509()
1356 self.assertRaises(TypeError, cert.set_subject)
1357 self.assertRaises(TypeError, cert.set_subject, None)
1358 self.assertRaises(TypeError, cert.set_subject, cert.get_subject(), None)
1359
1360
1361 def test_set_subject(self):
1362 """
1363 L{X509.set_subject} changes the subject of the certificate to the one
1364 passed in.
1365 """
1366 cert = X509()
1367 name = cert.get_subject()
1368 name.C = 'AU'
1369 name.O = 'Unit Tests'
1370 cert.set_subject(name)
1371 self.assertEquals(
1372 cert.get_subject().get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001373 [(b('C'), b('AU')), (b('O'), b('Unit Tests'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001374
1375
1376 def test_get_issuer_wrong_args(self):
1377 """
1378 L{X509.get_issuer} raises L{TypeError} if called with any arguments.
1379 """
1380 cert = X509()
1381 self.assertRaises(TypeError, cert.get_issuer, None)
1382
1383
1384 def test_get_issuer(self):
1385 """
1386 L{X509.get_issuer} returns an L{X509Name} instance.
1387 """
1388 cert = load_certificate(FILETYPE_PEM, self.pemData)
1389 subj = cert.get_issuer()
1390 self.assertTrue(isinstance(subj, X509Name))
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001391 comp = subj.get_components()
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001392 self.assertEquals(
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001393 comp,
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001394 [(b('C'), b('US')), (b('ST'), b('IL')), (b('L'), b('Chicago')),
1395 (b('O'), b('Testing')), (b('CN'), b('Testing Root CA'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001396
1397
1398 def test_set_issuer_wrong_args(self):
1399 """
1400 L{X509.set_issuer} raises a L{TypeError} if called with the wrong
1401 number of arguments or an argument not of type L{X509Name}.
1402 """
1403 cert = X509()
1404 self.assertRaises(TypeError, cert.set_issuer)
1405 self.assertRaises(TypeError, cert.set_issuer, None)
1406 self.assertRaises(TypeError, cert.set_issuer, cert.get_issuer(), None)
1407
1408
1409 def test_set_issuer(self):
1410 """
1411 L{X509.set_issuer} changes the issuer of the certificate to the one
1412 passed in.
1413 """
1414 cert = X509()
1415 name = cert.get_issuer()
1416 name.C = 'AU'
1417 name.O = 'Unit Tests'
1418 cert.set_issuer(name)
1419 self.assertEquals(
1420 cert.get_issuer().get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001421 [(b('C'), b('AU')), (b('O'), b('Unit Tests'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001422
1423
1424 def test_get_pubkey_uninitialized(self):
1425 """
1426 When called on a certificate with no public key, L{X509.get_pubkey}
1427 raises L{OpenSSL.crypto.Error}.
1428 """
1429 cert = X509()
1430 self.assertRaises(Error, cert.get_pubkey)
1431
1432
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001433 def test_subject_name_hash_wrong_args(self):
1434 """
1435 L{X509.subject_name_hash} raises L{TypeError} if called with any
1436 arguments.
1437 """
1438 cert = X509()
1439 self.assertRaises(TypeError, cert.subject_name_hash, None)
1440
1441
1442 def test_subject_name_hash(self):
1443 """
1444 L{X509.subject_name_hash} returns the hash of the certificate's subject
1445 name.
1446 """
1447 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderone37306a62010-08-28 15:09:24 -04001448 self.assertEquals(cert.subject_name_hash(), 3350047874)
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001449
1450
Rick Dean38a05c82009-07-18 01:41:30 -05001451
Rick Dean623ee362009-07-17 12:22:16 -05001452class PKCS12Tests(TestCase):
1453 """
Jean-Paul Calderone9389c922009-07-25 12:24:04 -04001454 Test for L{OpenSSL.crypto.PKCS12} and L{OpenSSL.crypto.load_pkcs12}.
Rick Dean623ee362009-07-17 12:22:16 -05001455 """
1456 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
1457
Jean-Paul Calderonec3a41f72009-07-25 12:36:02 -04001458 def test_type(self):
1459 """
1460 L{PKCS12Type} is a type object.
1461 """
1462 self.assertIdentical(PKCS12, PKCS12Type)
1463 self.assertConsistentType(PKCS12, 'PKCS12')
1464
1465
Rick Deanf94096c2009-07-18 14:23:06 -05001466 def test_empty_construction(self):
Rick Dean38a05c82009-07-18 01:41:30 -05001467 """
Jean-Paul Calderonedc857b52009-07-25 12:25:07 -04001468 L{PKCS12} returns a new instance of L{PKCS12} with no certificate,
1469 private key, CA certificates, or friendly name.
Rick Dean38a05c82009-07-18 01:41:30 -05001470 """
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001471 p12 = PKCS12()
Rick Dean623ee362009-07-17 12:22:16 -05001472 self.assertEqual(None, p12.get_certificate())
1473 self.assertEqual(None, p12.get_privatekey())
1474 self.assertEqual(None, p12.get_ca_certificates())
Rick Dean42d69e12009-07-20 11:36:08 -05001475 self.assertEqual(None, p12.get_friendlyname())
Rick Dean623ee362009-07-17 12:22:16 -05001476
Rick Dean38a05c82009-07-18 01:41:30 -05001477
Rick Dean623ee362009-07-17 12:22:16 -05001478 def test_type_errors(self):
Rick Dean38a05c82009-07-18 01:41:30 -05001479 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001480 The L{PKCS12} setter functions (C{set_certificate}, C{set_privatekey},
1481 C{set_ca_certificates}, and C{set_friendlyname}) raise L{TypeError}
1482 when passed objects of types other than those expected.
Rick Dean38a05c82009-07-18 01:41:30 -05001483 """
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001484 p12 = PKCS12()
Rick Dean623ee362009-07-17 12:22:16 -05001485 self.assertRaises(TypeError, p12.set_certificate, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05001486 self.assertRaises(TypeError, p12.set_certificate, PKey())
1487 self.assertRaises(TypeError, p12.set_certificate, X509)
Rick Dean623ee362009-07-17 12:22:16 -05001488 self.assertRaises(TypeError, p12.set_privatekey, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05001489 self.assertRaises(TypeError, p12.set_privatekey, 'legbone')
1490 self.assertRaises(TypeError, p12.set_privatekey, X509())
Rick Dean623ee362009-07-17 12:22:16 -05001491 self.assertRaises(TypeError, p12.set_ca_certificates, 3)
1492 self.assertRaises(TypeError, p12.set_ca_certificates, X509())
1493 self.assertRaises(TypeError, p12.set_ca_certificates, (3, 4))
Rick Deanf94096c2009-07-18 14:23:06 -05001494 self.assertRaises(TypeError, p12.set_ca_certificates, ( PKey(), ))
Rick Dean42d69e12009-07-20 11:36:08 -05001495 self.assertRaises(TypeError, p12.set_friendlyname, 6)
1496 self.assertRaises(TypeError, p12.set_friendlyname, ('foo', 'bar'))
Rick Dean623ee362009-07-17 12:22:16 -05001497
Rick Dean38a05c82009-07-18 01:41:30 -05001498
Rick Dean623ee362009-07-17 12:22:16 -05001499 def test_key_only(self):
1500 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001501 A L{PKCS12} with only a private key can be exported using
1502 L{PKCS12.export} and loaded again using L{load_pkcs12}.
Rick Dean623ee362009-07-17 12:22:16 -05001503 """
1504 passwd = 'blah'
1505 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001506 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001507 p12.set_privatekey(pkey)
Rick Dean623ee362009-07-17 12:22:16 -05001508 self.assertEqual(None, p12.get_certificate())
1509 self.assertEqual(pkey, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05001510 try:
1511 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
1512 except Error:
1513 # Some versions of OpenSSL will throw an exception
1514 # for this nearly useless PKCS12 we tried to generate:
1515 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
1516 return
Rick Dean623ee362009-07-17 12:22:16 -05001517 p12 = load_pkcs12(dumped_p12, passwd)
1518 self.assertEqual(None, p12.get_ca_certificates())
1519 self.assertEqual(None, p12.get_certificate())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001520
1521 # OpenSSL fails to bring the key back to us. So sad. Perhaps in the
1522 # future this will be improved.
1523 self.assertTrue(isinstance(p12.get_privatekey(), (PKey, type(None))))
Rick Dean623ee362009-07-17 12:22:16 -05001524
Rick Dean38a05c82009-07-18 01:41:30 -05001525
Rick Dean623ee362009-07-17 12:22:16 -05001526 def test_cert_only(self):
1527 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001528 A L{PKCS12} with only a certificate can be exported using
1529 L{PKCS12.export} and loaded again using L{load_pkcs12}.
Rick Dean623ee362009-07-17 12:22:16 -05001530 """
1531 passwd = 'blah'
1532 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001533 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001534 p12.set_certificate(cert)
Rick Dean623ee362009-07-17 12:22:16 -05001535 self.assertEqual(cert, p12.get_certificate())
1536 self.assertEqual(None, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05001537 try:
1538 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
1539 except Error:
1540 # Some versions of OpenSSL will throw an exception
1541 # for this nearly useless PKCS12 we tried to generate:
1542 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
1543 return
Rick Dean623ee362009-07-17 12:22:16 -05001544 p12 = load_pkcs12(dumped_p12, passwd)
1545 self.assertEqual(None, p12.get_privatekey())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001546
1547 # OpenSSL fails to bring the cert back to us. Groany mcgroan.
1548 self.assertTrue(isinstance(p12.get_certificate(), (X509, type(None))))
1549
1550 # Oh ho. It puts the certificate into the ca certificates list, in
1551 # fact. Totally bogus, I would think. Nevertheless, let's exploit
1552 # that to check to see if it reconstructed the certificate we expected
1553 # it to. At some point, hopefully this will change so that
1554 # p12.get_certificate() is actually what returns the loaded
1555 # certificate.
1556 self.assertEqual(
1557 cleartextCertificatePEM,
1558 dump_certificate(FILETYPE_PEM, p12.get_ca_certificates()[0]))
Rick Dean623ee362009-07-17 12:22:16 -05001559
1560
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001561 def gen_pkcs12(self, cert_pem=None, key_pem=None, ca_pem=None, friendly_name=None):
Rick Dean623ee362009-07-17 12:22:16 -05001562 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001563 Generate a PKCS12 object with components from PEM. Verify that the set
1564 functions return None.
Rick Dean623ee362009-07-17 12:22:16 -05001565 """
Rick Deanf94096c2009-07-18 14:23:06 -05001566 p12 = PKCS12()
1567 if cert_pem:
1568 ret = p12.set_certificate(load_certificate(FILETYPE_PEM, cert_pem))
1569 self.assertEqual(ret, None)
1570 if key_pem:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001571 ret = p12.set_privatekey(load_privatekey(FILETYPE_PEM, key_pem))
Rick Deanf94096c2009-07-18 14:23:06 -05001572 self.assertEqual(ret, None)
1573 if ca_pem:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001574 ret = p12.set_ca_certificates((load_certificate(FILETYPE_PEM, ca_pem),))
Rick Deanf94096c2009-07-18 14:23:06 -05001575 self.assertEqual(ret, None)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001576 if friendly_name:
1577 ret = p12.set_friendlyname(friendly_name)
Rick Dean42d69e12009-07-20 11:36:08 -05001578 self.assertEqual(ret, None)
Rick Deanf94096c2009-07-18 14:23:06 -05001579 return p12
1580
1581
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001582 def check_recovery(self, p12_str, key=None, cert=None, ca=None, passwd='',
1583 extra=()):
Rick Deanf94096c2009-07-18 14:23:06 -05001584 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001585 Use openssl program to confirm three components are recoverable from a
1586 PKCS12 string.
Rick Deanf94096c2009-07-18 14:23:06 -05001587 """
1588 if key:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001589 recovered_key = _runopenssl(
1590 p12_str, "pkcs12", '-nocerts', '-nodes', '-passin',
1591 'pass:' + passwd, *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001592 self.assertEqual(recovered_key[-len(key):], key)
1593 if cert:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001594 recovered_cert = _runopenssl(
1595 p12_str, "pkcs12", '-clcerts', '-nodes', '-passin',
1596 'pass:' + passwd, '-nokeys', *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001597 self.assertEqual(recovered_cert[-len(cert):], cert)
1598 if ca:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001599 recovered_cert = _runopenssl(
1600 p12_str, "pkcs12", '-cacerts', '-nodes', '-passin',
1601 'pass:' + passwd, '-nokeys', *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001602 self.assertEqual(recovered_cert[-len(ca):], ca)
1603
1604
1605 def test_load_pkcs12(self):
1606 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001607 A PKCS12 string generated using the openssl command line can be loaded
1608 with L{load_pkcs12} and its components extracted and examined.
Rick Deanf94096c2009-07-18 14:23:06 -05001609 """
Rick Dean623ee362009-07-17 12:22:16 -05001610 passwd = 'whatever'
1611 pem = client_key_pem + client_cert_pem
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001612 p12_str = _runopenssl(
1613 pem, "pkcs12", '-export', '-clcerts', '-passout', 'pass:' + passwd)
Rick Dean623ee362009-07-17 12:22:16 -05001614 p12 = load_pkcs12(p12_str, passwd)
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001615 # verify
Rick Deanf94096c2009-07-18 14:23:06 -05001616 self.assertTrue(isinstance(p12, PKCS12))
Rick Dean623ee362009-07-17 12:22:16 -05001617 cert_pem = dump_certificate(FILETYPE_PEM, p12.get_certificate())
1618 self.assertEqual(cert_pem, client_cert_pem)
1619 key_pem = dump_privatekey(FILETYPE_PEM, p12.get_privatekey())
1620 self.assertEqual(key_pem, client_key_pem)
1621 self.assertEqual(None, p12.get_ca_certificates())
Rick Deanf94096c2009-07-18 14:23:06 -05001622
Rick Deanee568302009-07-24 09:56:29 -05001623
1624 def test_load_pkcs12_garbage(self):
1625 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001626 L{load_pkcs12} raises L{OpenSSL.crypto.Error} when passed a string
1627 which is not a PKCS12 dump.
Rick Deanee568302009-07-24 09:56:29 -05001628 """
1629 passwd = 'whatever'
1630 e = self.assertRaises(Error, load_pkcs12, 'fruit loops', passwd)
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -04001631 self.assertEqual( e.args[0][0][0], 'asn1 encoding routines')
1632 self.assertEqual( len(e.args[0][0]), 3)
Rick Deanee568302009-07-24 09:56:29 -05001633
1634
Rick Deanf94096c2009-07-18 14:23:06 -05001635 def test_replace(self):
1636 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001637 L{PKCS12.set_certificate} replaces the certificate in a PKCS12 cluster.
1638 L{PKCS12.set_privatekey} replaces the private key.
1639 L{PKCS12.set_ca_certificates} replaces the CA certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05001640 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001641 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
1642 p12.set_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1643 p12.set_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001644 root_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05001645 client_cert = load_certificate(FILETYPE_PEM, client_cert_pem)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001646 p12.set_ca_certificates([root_cert]) # not a tuple
Rick Dean623ee362009-07-17 12:22:16 -05001647 self.assertEqual(1, len(p12.get_ca_certificates()))
1648 self.assertEqual(root_cert, p12.get_ca_certificates()[0])
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001649 p12.set_ca_certificates([client_cert, root_cert])
Rick Deanf94096c2009-07-18 14:23:06 -05001650 self.assertEqual(2, len(p12.get_ca_certificates()))
1651 self.assertEqual(client_cert, p12.get_ca_certificates()[0])
1652 self.assertEqual(root_cert, p12.get_ca_certificates()[1])
1653
1654
1655 def test_friendly_name(self):
1656 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001657 The I{friendlyName} of a PKCS12 can be set and retrieved via
1658 L{PKCS12.get_friendlyname} and L{PKCS12_set_friendlyname}, and a
1659 L{PKCS12} with a friendly name set can be dumped with L{PKCS12.export}.
Rick Deanf94096c2009-07-18 14:23:06 -05001660 """
Rick Deanf94096c2009-07-18 14:23:06 -05001661 passwd = 'Dogmeat[]{}!@#$%^&*()~`?/.,<>-_+=";:'
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001662 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -04001663 for friendly_name in [b('Serverlicious'), None, b('###')]:
Rick Dean42d69e12009-07-20 11:36:08 -05001664 p12.set_friendlyname(friendly_name)
1665 self.assertEqual(p12.get_friendlyname(), friendly_name)
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001666 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
Rick Dean42d69e12009-07-20 11:36:08 -05001667 reloaded_p12 = load_pkcs12(dumped_p12, passwd)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001668 self.assertEqual(
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -04001669 p12.get_friendlyname(), reloaded_p12.get_friendlyname())
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001670 # We would use the openssl program to confirm the friendly
1671 # name, but it is not possible. The pkcs12 command
1672 # does not store the friendly name in the cert's
Rick Dean42d69e12009-07-20 11:36:08 -05001673 # alias, which we could then extract.
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001674 self.check_recovery(
1675 dumped_p12, key=server_key_pem, cert=server_cert_pem,
1676 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05001677
1678
1679 def test_various_empty_passphrases(self):
1680 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001681 Test that missing, None, and '' passphrases are identical for PKCS12
1682 export.
Rick Deanf94096c2009-07-18 14:23:06 -05001683 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001684 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
Rick Dean623ee362009-07-17 12:22:16 -05001685 passwd = ''
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001686 dumped_p12_empty = p12.export(iter=2, maciter=0, passphrase=passwd)
1687 dumped_p12_none = p12.export(iter=3, maciter=2, passphrase=None)
1688 dumped_p12_nopw = p12.export(iter=9, maciter=4)
1689 for dumped_p12 in [dumped_p12_empty, dumped_p12_none, dumped_p12_nopw]:
1690 self.check_recovery(
1691 dumped_p12, key=client_key_pem, cert=client_cert_pem,
1692 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05001693
1694
1695 def test_removing_ca_cert(self):
1696 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001697 Passing C{None} to L{PKCS12.set_ca_certificates} removes all CA
1698 certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05001699 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001700 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
1701 p12.set_ca_certificates(None)
Rick Dean623ee362009-07-17 12:22:16 -05001702 self.assertEqual(None, p12.get_ca_certificates())
Rick Deanf94096c2009-07-18 14:23:06 -05001703
1704
1705 def test_export_without_mac(self):
1706 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001707 Exporting a PKCS12 with a C{maciter} of C{-1} excludes the MAC
1708 entirely.
Rick Deanf94096c2009-07-18 14:23:06 -05001709 """
1710 passwd = 'Lake Michigan'
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001711 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Dean623ee362009-07-17 12:22:16 -05001712 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001713 self.check_recovery(
1714 dumped_p12, key=server_key_pem, cert=server_cert_pem,
1715 passwd=passwd, extra=('-nomacver',))
1716
1717
1718 def test_load_without_mac(self):
1719 """
1720 Loading a PKCS12 without a MAC does something other than crash.
1721 """
1722 passwd = 'Lake Michigan'
1723 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
1724 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Rick Dean321a0512009-08-13 17:21:29 -05001725 try:
1726 recovered_p12 = load_pkcs12(dumped_p12, passwd)
1727 # The person who generated this PCKS12 should be flogged,
1728 # or better yet we should have a means to determine
1729 # whether a PCKS12 had a MAC that was verified.
1730 # Anyway, libopenssl chooses to allow it, so the
1731 # pyopenssl binding does as well.
1732 self.assertTrue(isinstance(recovered_p12, PKCS12))
1733 except Error:
1734 # Failing here with an exception is preferred as some openssl
1735 # versions do.
1736 pass
Rick Dean623ee362009-07-17 12:22:16 -05001737
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001738
Rick Dean25bcc1f2009-07-20 11:53:13 -05001739 def test_zero_len_list_for_ca(self):
1740 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04001741 A PKCS12 with an empty CA certificates list can be exported.
Rick Dean25bcc1f2009-07-20 11:53:13 -05001742 """
1743 passwd = 'Hobie 18'
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04001744 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem)
1745 p12.set_ca_certificates([])
Rick Dean25bcc1f2009-07-20 11:53:13 -05001746 self.assertEqual((), p12.get_ca_certificates())
1747 dumped_p12 = p12.export(passphrase=passwd, iter=3)
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04001748 self.check_recovery(
1749 dumped_p12, key=server_key_pem, cert=server_cert_pem,
1750 passwd=passwd)
Rick Dean25bcc1f2009-07-20 11:53:13 -05001751
1752
Rick Deanf94096c2009-07-18 14:23:06 -05001753 def test_export_without_args(self):
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001754 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04001755 All the arguments to L{PKCS12.export} are optional.
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001756 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04001757 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05001758 dumped_p12 = p12.export() # no args
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04001759 self.check_recovery(
1760 dumped_p12, key=server_key_pem, cert=server_cert_pem, passwd='')
Rick Deanf94096c2009-07-18 14:23:06 -05001761
1762
1763 def test_key_cert_mismatch(self):
1764 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04001765 L{PKCS12.export} raises an exception when a key and certificate
1766 mismatch.
Rick Deanf94096c2009-07-18 14:23:06 -05001767 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04001768 p12 = self.gen_pkcs12(server_cert_pem, client_key_pem, root_cert_pem)
1769 self.assertRaises(Error, p12.export)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04001770
1771
1772
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04001773# These quoting functions taken directly from Twisted's twisted.python.win32.
1774_cmdLineQuoteRe = re.compile(r'(\\*)"')
1775_cmdLineQuoteRe2 = re.compile(r'(\\+)\Z')
1776def cmdLineQuote(s):
1777 """
1778 Internal method for quoting a single command-line argument.
1779
1780 @type: C{str}
1781 @param s: A single unquoted string to quote for something that is expecting
1782 cmd.exe-style quoting
1783
1784 @rtype: C{str}
1785 @return: A cmd.exe-style quoted string
1786
1787 @see: U{http://www.perlmonks.org/?node_id=764004}
1788 """
1789 s = _cmdLineQuoteRe2.sub(r"\1\1", _cmdLineQuoteRe.sub(r'\1\1\\"', s))
1790 return '"%s"' % s
1791
1792
1793
1794def quoteArguments(arguments):
1795 """
1796 Quote an iterable of command-line arguments for passing to CreateProcess or
1797 a similar API. This allows the list passed to C{reactor.spawnProcess} to
1798 match the child process's C{sys.argv} properly.
1799
1800 @type arguments: C{iterable} of C{str}
1801 @param arguments: An iterable of unquoted arguments to quote
1802
1803 @rtype: C{str}
1804 @return: A space-delimited string containing quoted versions of L{arguments}
1805 """
1806 return ' '.join(map(cmdLineQuote, arguments))
1807
1808
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05001809
Rick Dean4c9ad612009-07-17 15:05:22 -05001810def _runopenssl(pem, *args):
1811 """
1812 Run the command line openssl tool with the given arguments and write
Rick Dean55d1ce62009-08-13 17:40:24 -05001813 the given PEM to its stdin. Not safe for quotes.
Rick Dean4c9ad612009-07-17 15:05:22 -05001814 """
Jean-Paul Calderone038de952009-08-21 12:16:06 -04001815 if os.name == 'posix':
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001816 command = "openssl " + " ".join([
1817 "'%s'" % (arg.replace("'", "'\\''"),) for arg in args])
Rick Dean55d1ce62009-08-13 17:40:24 -05001818 else:
Jean-Paul Calderone50924502009-08-27 12:47:55 -04001819 command = "openssl " + quoteArguments(args)
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001820 proc = Popen(command, shell=True, stdin=PIPE, stdout=PIPE)
Jean-Paul Calderone62ca8da2010-08-11 19:58:08 -04001821 proc.stdin.write(pem)
1822 proc.stdin.close()
1823 return proc.stdout.read()
Rick Dean4c9ad612009-07-17 15:05:22 -05001824
1825
1826
Jean-Paul Calderone18808652009-07-05 12:54:05 -04001827class FunctionTests(TestCase):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04001828 """
1829 Tests for free-functions in the L{OpenSSL.crypto} module.
1830 """
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001831
1832 def test_load_privatekey_invalid_format(self):
1833 """
1834 L{load_privatekey} raises L{ValueError} if passed an unknown filetype.
1835 """
1836 self.assertRaises(ValueError, load_privatekey, 100, root_key_pem)
1837
1838
1839 def test_load_privatekey_invalid_passphrase_type(self):
1840 """
1841 L{load_privatekey} raises L{TypeError} if passed a passphrase that is
1842 neither a c{str} nor a callable.
1843 """
1844 self.assertRaises(
1845 TypeError,
1846 load_privatekey,
1847 FILETYPE_PEM, encryptedPrivateKeyPEMPassphrase, object())
1848
1849
1850 def test_load_privatekey_wrong_args(self):
1851 """
1852 L{load_privatekey} raises L{TypeError} if called with the wrong number
1853 of arguments.
1854 """
1855 self.assertRaises(TypeError, load_privatekey)
1856
1857
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04001858 def test_load_privatekey_wrongPassphrase(self):
1859 """
1860 L{load_privatekey} raises L{OpenSSL.crypto.Error} when it is passed an
1861 encrypted PEM and an incorrect passphrase.
1862 """
1863 self.assertRaises(
1864 Error,
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04001865 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, b("quack"))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04001866
1867
1868 def test_load_privatekey_passphrase(self):
1869 """
1870 L{load_privatekey} can create a L{PKey} object from an encrypted PEM
1871 string if given the passphrase.
1872 """
1873 key = load_privatekey(
1874 FILETYPE_PEM, encryptedPrivateKeyPEM,
1875 encryptedPrivateKeyPEMPassphrase)
1876 self.assertTrue(isinstance(key, PKeyType))
1877
1878
1879 def test_load_privatekey_wrongPassphraseCallback(self):
1880 """
1881 L{load_privatekey} raises L{OpenSSL.crypto.Error} when it is passed an
1882 encrypted PEM and a passphrase callback which returns an incorrect
1883 passphrase.
1884 """
1885 called = []
1886 def cb(*a):
1887 called.append(None)
1888 return "quack"
1889 self.assertRaises(
1890 Error,
1891 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
1892 self.assertTrue(called)
1893
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001894
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04001895 def test_load_privatekey_passphraseCallback(self):
1896 """
1897 L{load_privatekey} can create a L{PKey} object from an encrypted PEM
1898 string if given a passphrase callback which returns the correct
1899 password.
1900 """
1901 called = []
1902 def cb(writing):
1903 called.append(writing)
1904 return encryptedPrivateKeyPEMPassphrase
1905 key = load_privatekey(FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
1906 self.assertTrue(isinstance(key, PKeyType))
1907 self.assertEqual(called, [False])
1908
1909
Jean-Paul Calderoneaf43cdf2010-08-03 18:40:52 -04001910 def test_load_privatekey_passphrase_exception(self):
1911 """
1912 An exception raised by the passphrase callback passed to
1913 L{load_privatekey} causes L{OpenSSL.crypto.Error} to be raised.
1914
1915 This isn't as nice as just letting the exception pass through. The
1916 behavior might be changed to that eventually.
1917 """
1918 def broken(ignored):
1919 raise RuntimeError("This is not working.")
1920 self.assertRaises(
1921 Error,
1922 load_privatekey,
1923 FILETYPE_PEM, encryptedPrivateKeyPEM, broken)
1924
1925
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001926 def test_dump_privatekey_wrong_args(self):
1927 """
1928 L{dump_privatekey} raises L{TypeError} if called with the wrong number
1929 of arguments.
1930 """
1931 self.assertRaises(TypeError, dump_privatekey)
1932
1933
1934 def test_dump_privatekey_unknown_cipher(self):
1935 """
1936 L{dump_privatekey} raises L{ValueError} if called with an unrecognized
1937 cipher name.
1938 """
1939 key = PKey()
1940 key.generate_key(TYPE_RSA, 512)
1941 self.assertRaises(
1942 ValueError, dump_privatekey,
1943 FILETYPE_PEM, key, "zippers", "passphrase")
1944
1945
1946 def test_dump_privatekey_invalid_passphrase_type(self):
1947 """
1948 L{dump_privatekey} raises L{TypeError} if called with a passphrase which
1949 is neither a C{str} nor a callable.
1950 """
1951 key = PKey()
1952 key.generate_key(TYPE_RSA, 512)
1953 self.assertRaises(
1954 TypeError,
1955 dump_privatekey, FILETYPE_PEM, key, "blowfish", object())
1956
1957
1958 def test_dump_privatekey_invalid_filetype(self):
1959 """
1960 L{dump_privatekey} raises L{ValueError} if called with an unrecognized
1961 filetype.
1962 """
1963 key = PKey()
1964 key.generate_key(TYPE_RSA, 512)
1965 self.assertRaises(ValueError, dump_privatekey, 100, key)
1966
1967
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04001968 def test_dump_privatekey_passphrase(self):
1969 """
1970 L{dump_privatekey} writes an encrypted PEM when given a passphrase.
1971 """
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04001972 passphrase = b("foo")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04001973 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
1974 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04001975 self.assertTrue(isinstance(pem, bytes))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04001976 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
1977 self.assertTrue(isinstance(loadedKey, PKeyType))
1978 self.assertEqual(loadedKey.type(), key.type())
1979 self.assertEqual(loadedKey.bits(), key.bits())
1980
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04001981
Rick Dean5b7b6372009-04-01 11:34:06 -05001982 def test_dump_certificate(self):
1983 """
1984 L{dump_certificate} writes PEM, DER, and text.
1985 """
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04001986 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
Rick Dean5b7b6372009-04-01 11:34:06 -05001987 cert = load_certificate(FILETYPE_PEM, pemData)
1988 dumped_pem = dump_certificate(FILETYPE_PEM, cert)
1989 self.assertEqual(dumped_pem, cleartextCertificatePEM)
1990 dumped_der = dump_certificate(FILETYPE_ASN1, cert)
Rick Dean4c9ad612009-07-17 15:05:22 -05001991 good_der = _runopenssl(dumped_pem, "x509", "-outform", "DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05001992 self.assertEqual(dumped_der, good_der)
1993 cert2 = load_certificate(FILETYPE_ASN1, dumped_der)
1994 dumped_pem2 = dump_certificate(FILETYPE_PEM, cert2)
1995 self.assertEqual(dumped_pem2, cleartextCertificatePEM)
1996 dumped_text = dump_certificate(FILETYPE_TEXT, cert)
Rick Dean4c9ad612009-07-17 15:05:22 -05001997 good_text = _runopenssl(dumped_pem, "x509", "-noout", "-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05001998 self.assertEqual(dumped_text, good_text)
1999
2000
2001 def test_dump_privatekey(self):
2002 """
2003 L{dump_privatekey} writes a PEM, DER, and text.
2004 """
2005 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2006 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2007 self.assertEqual(dumped_pem, cleartextPrivateKeyPEM)
2008 dumped_der = dump_privatekey(FILETYPE_ASN1, key)
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002009 # XXX This OpenSSL call writes "writing RSA key" to standard out. Sad.
Rick Dean4c9ad612009-07-17 15:05:22 -05002010 good_der = _runopenssl(dumped_pem, "rsa", "-outform", "DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002011 self.assertEqual(dumped_der, good_der)
2012 key2 = load_privatekey(FILETYPE_ASN1, dumped_der)
2013 dumped_pem2 = dump_privatekey(FILETYPE_PEM, key2)
2014 self.assertEqual(dumped_pem2, cleartextPrivateKeyPEM)
2015 dumped_text = dump_privatekey(FILETYPE_TEXT, key)
Rick Dean4c9ad612009-07-17 15:05:22 -05002016 good_text = _runopenssl(dumped_pem, "rsa", "-noout", "-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002017 self.assertEqual(dumped_text, good_text)
2018
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002019
Rick Dean5b7b6372009-04-01 11:34:06 -05002020 def test_dump_certificate_request(self):
2021 """
2022 L{dump_certificate_request} writes a PEM, DER, and text.
2023 """
2024 req = load_certificate_request(FILETYPE_PEM, cleartextCertificateRequestPEM)
2025 dumped_pem = dump_certificate_request(FILETYPE_PEM, req)
2026 self.assertEqual(dumped_pem, cleartextCertificateRequestPEM)
2027 dumped_der = dump_certificate_request(FILETYPE_ASN1, req)
Rick Dean4c9ad612009-07-17 15:05:22 -05002028 good_der = _runopenssl(dumped_pem, "req", "-outform", "DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002029 self.assertEqual(dumped_der, good_der)
2030 req2 = load_certificate_request(FILETYPE_ASN1, dumped_der)
2031 dumped_pem2 = dump_certificate_request(FILETYPE_PEM, req2)
2032 self.assertEqual(dumped_pem2, cleartextCertificateRequestPEM)
2033 dumped_text = dump_certificate_request(FILETYPE_TEXT, req)
Rick Dean4c9ad612009-07-17 15:05:22 -05002034 good_text = _runopenssl(dumped_pem, "req", "-noout", "-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002035 self.assertEqual(dumped_text, good_text)
Jean-Paul Calderoneaf43cdf2010-08-03 18:40:52 -04002036 self.assertRaises(ValueError, dump_certificate_request, 100, req)
Rick Dean5b7b6372009-04-01 11:34:06 -05002037
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002038
2039 def test_dump_privatekey_passphraseCallback(self):
2040 """
2041 L{dump_privatekey} writes an encrypted PEM when given a callback which
2042 returns the correct passphrase.
2043 """
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002044 passphrase = b("foo")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002045 called = []
2046 def cb(writing):
2047 called.append(writing)
2048 return passphrase
2049 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2050 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", cb)
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002051 self.assertTrue(isinstance(pem, bytes))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002052 self.assertEqual(called, [True])
2053 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
2054 self.assertTrue(isinstance(loadedKey, PKeyType))
2055 self.assertEqual(loadedKey.type(), key.type())
2056 self.assertEqual(loadedKey.bits(), key.bits())
Rick Dean5b7b6372009-04-01 11:34:06 -05002057
2058
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002059 def test_load_pkcs7_data(self):
2060 """
2061 L{load_pkcs7_data} accepts a PKCS#7 string and returns an instance of
2062 L{PKCS7Type}.
2063 """
2064 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2065 self.assertTrue(isinstance(pkcs7, PKCS7Type))
2066
2067
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002068
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002069class PKCS7Tests(TestCase):
2070 """
2071 Tests for L{PKCS7Type}.
2072 """
2073 def test_type(self):
2074 """
2075 L{PKCS7Type} is a type object.
2076 """
2077 self.assertTrue(isinstance(PKCS7Type, type))
2078 self.assertEqual(PKCS7Type.__name__, 'PKCS7')
2079
2080 # XXX This doesn't currently work.
2081 # self.assertIdentical(PKCS7, PKCS7Type)
2082
2083
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002084 # XXX Opposite results for all these following methods
2085
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002086 def test_type_is_signed_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002087 """
2088 L{PKCS7Type.type_is_signed} raises L{TypeError} if called with any
2089 arguments.
2090 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002091 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2092 self.assertRaises(TypeError, pkcs7.type_is_signed, None)
2093
2094
2095 def test_type_is_signed(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002096 """
2097 L{PKCS7Type.type_is_signed} returns C{True} if the PKCS7 object is of
2098 the type I{signed}.
2099 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002100 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2101 self.assertTrue(pkcs7.type_is_signed())
2102
2103
2104 def test_type_is_enveloped_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002105 """
2106 L{PKCS7Type.type_is_enveloped} raises L{TypeError} if called with any
2107 arguments.
2108 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002109 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2110 self.assertRaises(TypeError, pkcs7.type_is_enveloped, None)
2111
2112
2113 def test_type_is_enveloped(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002114 """
Jean-Paul Calderone94f9abd2010-09-08 23:51:20 -04002115 L{PKCS7Type.type_is_enveloped} returns C{False} if the PKCS7 object is
2116 not of the type I{enveloped}.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002117 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002118 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2119 self.assertFalse(pkcs7.type_is_enveloped())
2120
2121
2122 def test_type_is_signedAndEnveloped_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002123 """
2124 L{PKCS7Type.type_is_signedAndEnveloped} raises L{TypeError} if called
2125 with any arguments.
2126 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002127 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2128 self.assertRaises(TypeError, pkcs7.type_is_signedAndEnveloped, None)
2129
2130
2131 def test_type_is_signedAndEnveloped(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002132 """
2133 L{PKCS7Type.type_is_signedAndEnveloped} returns C{False} if the PKCS7
2134 object is not of the type I{signed and enveloped}.
2135 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002136 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2137 self.assertFalse(pkcs7.type_is_signedAndEnveloped())
2138
2139
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002140 def test_type_is_data(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002141 """
2142 L{PKCS7Type.type_is_data} returns C{False} if the PKCS7 object is not of
2143 the type data.
2144 """
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002145 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2146 self.assertFalse(pkcs7.type_is_data())
2147
2148
2149 def test_type_is_data_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002150 """
2151 L{PKCS7Type.type_is_data} raises L{TypeError} if called with any
2152 arguments.
2153 """
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002154 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2155 self.assertRaises(TypeError, pkcs7.type_is_data, None)
2156
2157
Jean-Paul Calderone97b28ca2010-07-30 10:56:07 -04002158 def test_get_type_name_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002159 """
2160 L{PKCS7Type.get_type_name} raises L{TypeError} if called with any
2161 arguments.
2162 """
Jean-Paul Calderone97b28ca2010-07-30 10:56:07 -04002163 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2164 self.assertRaises(TypeError, pkcs7.get_type_name, None)
2165
2166
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002167 def test_get_type_name(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002168 """
2169 L{PKCS7Type.get_type_name} returns a C{str} giving the type name.
2170 """
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002171 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
Jean-Paul Calderone07640f12010-08-22 17:14:43 -04002172 self.assertEquals(pkcs7.get_type_name(), b('pkcs7-signedData'))
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002173
2174
2175 def test_attribute(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002176 """
2177 If an attribute other than one of the methods tested here is accessed on
2178 an instance of L{PKCS7Type}, L{AttributeError} is raised.
2179 """
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002180 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2181 self.assertRaises(AttributeError, getattr, pkcs7, "foo")
2182
2183
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002184
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002185class NetscapeSPKITests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002186 """
2187 Tests for L{OpenSSL.crypto.NetscapeSPKI}.
2188 """
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002189 def signable(self):
2190 """
2191 Return a new L{NetscapeSPKI} for use with signing tests.
2192 """
2193 return NetscapeSPKI()
2194
2195
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002196 def test_type(self):
2197 """
2198 L{NetscapeSPKI} and L{NetscapeSPKIType} refer to the same type object
2199 and can be used to create instances of that type.
2200 """
2201 self.assertIdentical(NetscapeSPKI, NetscapeSPKIType)
2202 self.assertConsistentType(NetscapeSPKI, 'NetscapeSPKI')
2203
2204
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002205 def test_construction(self):
2206 """
2207 L{NetscapeSPKI} returns an instance of L{NetscapeSPKIType}.
2208 """
2209 nspki = NetscapeSPKI()
2210 self.assertTrue(isinstance(nspki, NetscapeSPKIType))
2211
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002212
Jean-Paul Calderone969efaa2010-08-03 18:19:19 -04002213 def test_invalid_attribute(self):
2214 """
2215 Accessing a non-existent attribute of a L{NetscapeSPKI} instance causes
2216 an L{AttributeError} to be raised.
2217 """
2218 nspki = NetscapeSPKI()
2219 self.assertRaises(AttributeError, lambda: nspki.foo)
2220
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002221
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002222 def test_b64_encode(self):
2223 """
2224 L{NetscapeSPKI.b64_encode} encodes the certificate to a base64 blob.
2225 """
2226 nspki = NetscapeSPKI()
2227 blob = nspki.b64_encode()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002228 self.assertTrue(isinstance(blob, bytes))
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002229
2230
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002231
Rick Dean536ba022009-07-24 23:57:27 -05002232class RevokedTests(TestCase):
2233 """
2234 Tests for L{OpenSSL.crypto.Revoked}
2235 """
2236 def test_construction(self):
2237 """
2238 Confirm we can create L{OpenSSL.crypto.Revoked}. Check
2239 that it is empty.
2240 """
2241 revoked = Revoked()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002242 self.assertTrue(isinstance(revoked, Revoked))
2243 self.assertEquals(type(revoked), Revoked)
2244 self.assertEquals(revoked.get_serial(), b('00'))
2245 self.assertEquals(revoked.get_rev_date(), None)
2246 self.assertEquals(revoked.get_reason(), None)
Rick Dean536ba022009-07-24 23:57:27 -05002247
2248
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002249 def test_construction_wrong_args(self):
2250 """
2251 Calling L{OpenSSL.crypto.Revoked} with any arguments results
2252 in a L{TypeError} being raised.
2253 """
2254 self.assertRaises(TypeError, Revoked, None)
2255 self.assertRaises(TypeError, Revoked, 1)
2256 self.assertRaises(TypeError, Revoked, "foo")
2257
2258
Rick Dean536ba022009-07-24 23:57:27 -05002259 def test_serial(self):
2260 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002261 Confirm we can set and get serial numbers from
Rick Dean536ba022009-07-24 23:57:27 -05002262 L{OpenSSL.crypto.Revoked}. Confirm errors are handled
2263 with grace.
2264 """
2265 revoked = Revoked()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002266 ret = revoked.set_serial(b('10b'))
2267 self.assertEquals(ret, None)
Rick Dean536ba022009-07-24 23:57:27 -05002268 ser = revoked.get_serial()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002269 self.assertEquals(ser, b('010B'))
Rick Dean536ba022009-07-24 23:57:27 -05002270
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002271 revoked.set_serial(b('31ppp')) # a type error would be nice
Rick Dean536ba022009-07-24 23:57:27 -05002272 ser = revoked.get_serial()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002273 self.assertEquals(ser, b('31'))
Rick Dean536ba022009-07-24 23:57:27 -05002274
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002275 self.assertRaises(ValueError, revoked.set_serial, b('pqrst'))
Rick Dean536ba022009-07-24 23:57:27 -05002276 self.assertRaises(TypeError, revoked.set_serial, 100)
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002277 self.assertRaises(TypeError, revoked.get_serial, 1)
2278 self.assertRaises(TypeError, revoked.get_serial, None)
2279 self.assertRaises(TypeError, revoked.get_serial, "")
Rick Dean536ba022009-07-24 23:57:27 -05002280
2281
2282 def test_date(self):
2283 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002284 Confirm we can set and get revocation dates from
Rick Dean536ba022009-07-24 23:57:27 -05002285 L{OpenSSL.crypto.Revoked}. Confirm errors are handled
2286 with grace.
2287 """
2288 revoked = Revoked()
2289 date = revoked.get_rev_date()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002290 self.assertEquals(date, None)
Rick Dean536ba022009-07-24 23:57:27 -05002291
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002292 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05002293 ret = revoked.set_rev_date(now)
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002294 self.assertEqual(ret, None)
Rick Dean536ba022009-07-24 23:57:27 -05002295 date = revoked.get_rev_date()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002296 self.assertEqual(date, now)
Rick Dean536ba022009-07-24 23:57:27 -05002297
2298
Rick Dean6385faf2009-07-26 00:07:47 -05002299 def test_reason(self):
2300 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002301 Confirm we can set and get revocation reasons from
Rick Dean6385faf2009-07-26 00:07:47 -05002302 L{OpenSSL.crypto.Revoked}. The "get" need to work
2303 as "set". Likewise, each reason of all_reasons() must work.
2304 """
2305 revoked = Revoked()
2306 for r in revoked.all_reasons():
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002307 for x in range(2):
Rick Dean6385faf2009-07-26 00:07:47 -05002308 ret = revoked.set_reason(r)
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002309 self.assertEquals(ret, None)
Rick Dean6385faf2009-07-26 00:07:47 -05002310 reason = revoked.get_reason()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002311 self.assertEquals(
2312 reason.lower().replace(b(' '), b('')),
2313 r.lower().replace(b(' '), b('')))
Rick Dean6385faf2009-07-26 00:07:47 -05002314 r = reason # again with the resp of get
2315
2316 revoked.set_reason(None)
2317 self.assertEqual(revoked.get_reason(), None)
2318
2319
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002320 def test_set_reason_wrong_arguments(self):
Rick Dean6385faf2009-07-26 00:07:47 -05002321 """
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002322 Calling L{OpenSSL.crypto.Revoked.set_reason} with other than
2323 one argument, or an argument which isn't a valid reason,
2324 results in L{TypeError} or L{ValueError} being raised.
Rick Dean6385faf2009-07-26 00:07:47 -05002325 """
2326 revoked = Revoked()
2327 self.assertRaises(TypeError, revoked.set_reason, 100)
Jean-Paul Calderone281b62b2010-08-28 14:22:29 -04002328 self.assertRaises(ValueError, revoked.set_reason, b('blue'))
Rick Dean6385faf2009-07-26 00:07:47 -05002329
Rick Dean536ba022009-07-24 23:57:27 -05002330
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002331 def test_get_reason_wrong_arguments(self):
2332 """
2333 Calling L{OpenSSL.crypto.Revoked.get_reason} with any
2334 arguments results in L{TypeError} being raised.
2335 """
2336 revoked = Revoked()
2337 self.assertRaises(TypeError, revoked.get_reason, None)
2338 self.assertRaises(TypeError, revoked.get_reason, 1)
2339 self.assertRaises(TypeError, revoked.get_reason, "foo")
2340
2341
2342
Rick Dean536ba022009-07-24 23:57:27 -05002343class CRLTests(TestCase):
2344 """
2345 Tests for L{OpenSSL.crypto.CRL}
2346 """
2347 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
2348 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2349
2350 def test_construction(self):
2351 """
2352 Confirm we can create L{OpenSSL.crypto.CRL}. Check
2353 that it is empty
2354 """
2355 crl = CRL()
2356 self.assertTrue( isinstance(crl, CRL) )
2357 self.assertEqual(crl.get_revoked(), None)
2358
2359
Jean-Paul Calderone2efd03e2010-01-30 13:59:55 -05002360 def test_construction_wrong_args(self):
2361 """
2362 Calling L{OpenSSL.crypto.CRL} with any number of arguments
2363 results in a L{TypeError} being raised.
2364 """
2365 self.assertRaises(TypeError, CRL, 1)
2366 self.assertRaises(TypeError, CRL, "")
2367 self.assertRaises(TypeError, CRL, None)
2368
2369
Rick Dean536ba022009-07-24 23:57:27 -05002370 def test_export(self):
2371 """
2372 Use python to create a simple CRL with a revocation, and export
2373 the CRL in formats of PEM, DER and text. Those outputs are verified
2374 with the openssl program.
2375 """
2376 crl = CRL()
2377 revoked = Revoked()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002378 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05002379 revoked.set_rev_date(now)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002380 revoked.set_serial(b('3ab'))
2381 revoked.set_reason(b('sUpErSeDEd'))
Rick Dean536ba022009-07-24 23:57:27 -05002382 crl.add_revoked(revoked)
2383
2384 # PEM format
2385 dumped_crl = crl.export(self.cert, self.pkey, days=20)
2386 text = _runopenssl(dumped_crl, "crl", "-noout", "-text")
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002387 text.index(b('Serial Number: 03AB'))
2388 text.index(b('Superseded'))
2389 text.index(b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA'))
Rick Dean536ba022009-07-24 23:57:27 -05002390
2391 # DER format
2392 dumped_crl = crl.export(self.cert, self.pkey, FILETYPE_ASN1)
2393 text = _runopenssl(dumped_crl, "crl", "-noout", "-text", "-inform", "DER")
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002394 text.index(b('Serial Number: 03AB'))
2395 text.index(b('Superseded'))
2396 text.index(b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA'))
Rick Dean536ba022009-07-24 23:57:27 -05002397
2398 # text format
2399 dumped_text = crl.export(self.cert, self.pkey, type=FILETYPE_TEXT)
2400 self.assertEqual(text, dumped_text)
2401
2402
Jean-Paul Calderone56515342010-01-30 13:49:38 -05002403 def test_add_revoked_keyword(self):
2404 """
2405 L{OpenSSL.CRL.add_revoked} accepts its single argument as the
2406 I{revoked} keyword argument.
2407 """
2408 crl = CRL()
2409 revoked = Revoked()
2410 crl.add_revoked(revoked=revoked)
2411 self.assertTrue(isinstance(crl.get_revoked()[0], Revoked))
2412
Rick Dean6385faf2009-07-26 00:07:47 -05002413
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05002414 def test_export_wrong_args(self):
2415 """
2416 Calling L{OpenSSL.CRL.export} with fewer than two or more than
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05002417 four arguments, or with arguments other than the certificate,
2418 private key, integer file type, and integer number of days it
2419 expects, results in a L{TypeError} being raised.
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05002420 """
2421 crl = CRL()
2422 self.assertRaises(TypeError, crl.export)
2423 self.assertRaises(TypeError, crl.export, self.cert)
2424 self.assertRaises(TypeError, crl.export, self.cert, self.pkey, FILETYPE_PEM, 10, "foo")
2425
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05002426 self.assertRaises(TypeError, crl.export, None, self.pkey, FILETYPE_PEM, 10)
2427 self.assertRaises(TypeError, crl.export, self.cert, None, FILETYPE_PEM, 10)
2428 self.assertRaises(TypeError, crl.export, self.cert, self.pkey, None, 10)
2429 self.assertRaises(TypeError, crl.export, self.cert, FILETYPE_PEM, None)
2430
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05002431
Jean-Paul Calderoneea198422010-01-30 13:58:23 -05002432 def test_export_unknown_filetype(self):
2433 """
2434 Calling L{OpenSSL.CRL.export} with a file type other than
2435 L{FILETYPE_PEM}, L{FILETYPE_ASN1}, or L{FILETYPE_TEXT} results
2436 in a L{ValueError} being raised.
2437 """
2438 crl = CRL()
2439 self.assertRaises(ValueError, crl.export, self.cert, self.pkey, 100, 10)
2440
2441
Rick Dean536ba022009-07-24 23:57:27 -05002442 def test_get_revoked(self):
2443 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002444 Use python to create a simple CRL with two revocations.
2445 Get back the L{Revoked} using L{OpenSSL.CRL.get_revoked} and
Rick Dean536ba022009-07-24 23:57:27 -05002446 verify them.
2447 """
2448 crl = CRL()
2449
2450 revoked = Revoked()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002451 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05002452 revoked.set_rev_date(now)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002453 revoked.set_serial(b('3ab'))
Rick Dean536ba022009-07-24 23:57:27 -05002454 crl.add_revoked(revoked)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002455 revoked.set_serial(b('100'))
2456 revoked.set_reason(b('sUpErSeDEd'))
Rick Dean536ba022009-07-24 23:57:27 -05002457 crl.add_revoked(revoked)
2458
2459 revs = crl.get_revoked()
2460 self.assertEqual(len(revs), 2)
2461 self.assertEqual(type(revs[0]), Revoked)
2462 self.assertEqual(type(revs[1]), Revoked)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002463 self.assertEqual(revs[0].get_serial(), b('03AB'))
2464 self.assertEqual(revs[1].get_serial(), b('0100'))
Rick Dean536ba022009-07-24 23:57:27 -05002465 self.assertEqual(revs[0].get_rev_date(), now)
2466 self.assertEqual(revs[1].get_rev_date(), now)
2467
2468
Jean-Paul Calderone46bdce42010-01-30 13:44:16 -05002469 def test_get_revoked_wrong_args(self):
2470 """
2471 Calling L{OpenSSL.CRL.get_revoked} with any arguments results
2472 in a L{TypeError} being raised.
2473 """
2474 crl = CRL()
2475 self.assertRaises(TypeError, crl.get_revoked, None)
2476 self.assertRaises(TypeError, crl.get_revoked, 1)
2477 self.assertRaises(TypeError, crl.get_revoked, "")
2478 self.assertRaises(TypeError, crl.get_revoked, "", 1, None)
2479
2480
Jean-Paul Calderoneecef6fa2010-01-30 13:47:18 -05002481 def test_add_revoked_wrong_args(self):
2482 """
2483 Calling L{OpenSSL.CRL.add_revoked} with other than one
2484 argument results in a L{TypeError} being raised.
2485 """
2486 crl = CRL()
2487 self.assertRaises(TypeError, crl.add_revoked)
2488 self.assertRaises(TypeError, crl.add_revoked, 1, 2)
2489 self.assertRaises(TypeError, crl.add_revoked, "foo", "bar")
2490
2491
Rick Dean536ba022009-07-24 23:57:27 -05002492 def test_load_crl(self):
2493 """
2494 Load a known CRL and inspect its revocations. Both
2495 PEM and DER formats are loaded.
2496 """
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05002497 crl = load_crl(FILETYPE_PEM, crlData)
Rick Dean536ba022009-07-24 23:57:27 -05002498 revs = crl.get_revoked()
2499 self.assertEqual(len(revs), 2)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002500 self.assertEqual(revs[0].get_serial(), b('03AB'))
Rick Dean6385faf2009-07-26 00:07:47 -05002501 self.assertEqual(revs[0].get_reason(), None)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002502 self.assertEqual(revs[1].get_serial(), b('0100'))
2503 self.assertEqual(revs[1].get_reason(), b('Superseded'))
Rick Dean536ba022009-07-24 23:57:27 -05002504
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05002505 der = _runopenssl(crlData, "crl", "-outform", "DER")
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002506 crl = load_crl(FILETYPE_ASN1, der)
Rick Dean536ba022009-07-24 23:57:27 -05002507 revs = crl.get_revoked()
2508 self.assertEqual(len(revs), 2)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002509 self.assertEqual(revs[0].get_serial(), b('03AB'))
Rick Dean6385faf2009-07-26 00:07:47 -05002510 self.assertEqual(revs[0].get_reason(), None)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002511 self.assertEqual(revs[1].get_serial(), b('0100'))
2512 self.assertEqual(revs[1].get_reason(), b('Superseded'))
Rick Dean536ba022009-07-24 23:57:27 -05002513
2514
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05002515 def test_load_crl_wrong_args(self):
2516 """
2517 Calling L{OpenSSL.crypto.load_crl} with other than two
2518 arguments results in a L{TypeError} being raised.
2519 """
2520 self.assertRaises(TypeError, load_crl)
2521 self.assertRaises(TypeError, load_crl, FILETYPE_PEM)
2522 self.assertRaises(TypeError, load_crl, FILETYPE_PEM, crlData, None)
2523
2524
2525 def test_load_crl_bad_filetype(self):
2526 """
2527 Calling L{OpenSSL.crypto.load_crl} with an unknown file type
2528 raises a L{ValueError}.
2529 """
2530 self.assertRaises(ValueError, load_crl, 100, crlData)
2531
2532
2533 def test_load_crl_bad_data(self):
2534 """
2535 Calling L{OpenSSL.crypto.load_crl} with file data which can't
2536 be loaded raises a L{OpenSSL.crypto.Error}.
2537 """
2538 self.assertRaises(Error, load_crl, FILETYPE_PEM, "hello, world")
2539
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002540
James Yonan7c2e5d32010-02-27 05:45:50 -07002541class SignVerifyTests(TestCase):
2542 """
2543 Tests for L{OpenSSL.crypto.sign} and L{OpenSSL.crypto.verify}.
2544 """
2545 def test_sign_verify(self):
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04002546 """
2547 L{sign} generates a cryptographic signature which L{verify} can check.
2548 """
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04002549 content = b(
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04002550 "It was a bright cold day in April, and the clocks were striking "
2551 "thirteen. Winston Smith, his chin nuzzled into his breast in an "
2552 "effort to escape the vile wind, slipped quickly through the "
2553 "glass doors of Victory Mansions, though not quickly enough to "
2554 "prevent a swirl of gritty dust from entering along with him.")
2555
2556 # sign the content with this private key
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04002557 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04002558 # verify the content with this cert
2559 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
2560 # certificate unrelated to priv_key, used to trigger an error
2561 bad_cert = load_certificate(FILETYPE_PEM, server_cert_pem)
James Yonan7c2e5d32010-02-27 05:45:50 -07002562
Jean-Paul Calderoned08feb02010-10-12 21:53:24 -04002563 for digest in ['md5', 'sha1']:
James Yonan7c2e5d32010-02-27 05:45:50 -07002564 sig = sign(priv_key, content, digest)
2565
2566 # Verify the signature of content, will throw an exception if error.
2567 verify(good_cert, sig, content, digest)
2568
2569 # This should fail because the certificate doesn't match the
2570 # private key that was used to sign the content.
2571 self.assertRaises(Error, verify, bad_cert, sig, content, digest)
2572
2573 # This should fail because we've "tainted" the content after
2574 # signing it.
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04002575 self.assertRaises(
2576 Error, verify,
2577 good_cert, sig, content + b("tainted"), digest)
James Yonan7c2e5d32010-02-27 05:45:50 -07002578
2579 # test that unknown digest types fail
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04002580 self.assertRaises(
Jean-Paul Calderone9538f142010-10-13 22:13:40 -04002581 ValueError, sign, priv_key, content, "strange-digest")
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04002582 self.assertRaises(
Jean-Paul Calderone9538f142010-10-13 22:13:40 -04002583 ValueError, verify, good_cert, sig, content, "strange-digest")
James Yonan7c2e5d32010-02-27 05:45:50 -07002584
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04002585
Rick Dean5b7b6372009-04-01 11:34:06 -05002586if __name__ == '__main__':
2587 main()