blob: 21949919a820900b174dd7c217844b2b8eb607f3 [file] [log] [blame]
Jean-Paul Calderone8671c852011-03-02 19:26:20 -05001# Copyright (c) Jean-Paul Calderone
2# See LICENSE file for details.
Jean-Paul Calderone8b63d452008-03-21 18:31:12 -04003
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -05004"""
Jonathan Ballet648875f2011-07-16 14:14:58 +09005Unit tests for :py:mod:`OpenSSL.crypto`.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -05006"""
7
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04008from unittest import main
9
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -040010import os, re
Jean-Paul Calderone62ca8da2010-08-11 19:58:08 -040011from subprocess import PIPE, Popen
Rick Dean47262da2009-07-08 16:17:17 -050012from datetime import datetime, timedelta
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -050013
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050014from six import binary_type
15
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -050016from OpenSSL.crypto import TYPE_RSA, TYPE_DSA, Error, PKey, PKeyType
Jean-Paul Calderone78381d22008-03-06 23:35:22 -050017from OpenSSL.crypto import X509, X509Type, X509Name, X509NameType
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080018from OpenSSL.crypto import X509Store, X509StoreType, X509Req, X509ReqType
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -050019from OpenSSL.crypto import X509Extension, X509ExtensionType
Rick Dean5b7b6372009-04-01 11:34:06 -050020from OpenSSL.crypto import load_certificate, load_privatekey
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -040021from OpenSSL.crypto import FILETYPE_PEM, FILETYPE_ASN1, FILETYPE_TEXT
Jean-Paul Calderone71919862009-04-01 13:01:19 -040022from OpenSSL.crypto import dump_certificate, load_certificate_request
23from OpenSSL.crypto import dump_certificate_request, dump_privatekey
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -040024from OpenSSL.crypto import PKCS7Type, load_pkcs7_data
Jean-Paul Calderone9178ee62010-01-25 17:55:30 -050025from OpenSSL.crypto import PKCS12, PKCS12Type, load_pkcs12
Rick Dean536ba022009-07-24 23:57:27 -050026from OpenSSL.crypto import CRL, Revoked, load_crl
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -040027from OpenSSL.crypto import NetscapeSPKI, NetscapeSPKIType
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -040028from OpenSSL.crypto import sign, verify
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050029from OpenSSL.test.util import TestCase, b
30from OpenSSL._util import native
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040031
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -040032def normalize_certificate_pem(pem):
33 return dump_certificate(FILETYPE_PEM, load_certificate(FILETYPE_PEM, pem))
34
35
36def normalize_privatekey_pem(pem):
37 return dump_privatekey(FILETYPE_PEM, load_privatekey(FILETYPE_PEM, pem))
38
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040039
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050040GOOD_CIPHER = "blowfish"
41BAD_CIPHER = "zippers"
42
43GOOD_DIGEST = "MD5"
44BAD_DIGEST = "monkeys"
45
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040046root_cert_pem = b("""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -050047MIIC7TCCAlagAwIBAgIIPQzE4MbeufQwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE
48BhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdU
49ZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwIhgPMjAwOTAzMjUxMjM2
50NThaGA8yMDE3MDYxMTEyMzY1OFowWDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklM
51MRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9U
52ZXN0aW5nIFJvb3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPmaQumL
53urpE527uSEHdL1pqcDRmWzu+98Y6YHzT/J7KWEamyMCNZ6fRW1JCR782UQ8a07fy
542xXsKy4WdKaxyG8CcatwmXvpvRQ44dSANMihHELpANTdyVp6DCysED6wkQFurHlF
551dshEaJw8b/ypDhmbVIo6Ci1xvCJqivbLFnbAgMBAAGjgbswgbgwHQYDVR0OBBYE
56FINVdy1eIfFJDAkk51QJEo3IfgSuMIGIBgNVHSMEgYAwfoAUg1V3LV4h8UkMCSTn
57VAkSjch+BK6hXKRaMFgxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UE
58BxMHQ2hpY2FnbzEQMA4GA1UEChMHVGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBS
59b290IENBggg9DMTgxt659DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB
60AGGCDazMJGoWNBpc03u6+smc95dEead2KlZXBATOdFT1VesY3+nUOqZhEhTGlDMi
61hkgaZnzoIq/Uamidegk4hirsCT/R+6vsKAAxNTcBjUeZjlykCJWy5ojShGftXIKY
62w/njVbKMXrvc83qmTdGl3TAM0fxQIpqgcglFLveEBgzn
63-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040064""")
Rick Dean94e46fd2009-07-18 14:51:24 -050065
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040066root_key_pem = b("""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -050067MIICXQIBAAKBgQD5mkLpi7q6ROdu7khB3S9aanA0Zls7vvfGOmB80/yeylhGpsjA
68jWen0VtSQke/NlEPGtO38tsV7CsuFnSmschvAnGrcJl76b0UOOHUgDTIoRxC6QDU
693claegwsrBA+sJEBbqx5RdXbIRGicPG/8qQ4Zm1SKOgotcbwiaor2yxZ2wIDAQAB
70AoGBAPCgMpmLxzwDaUmcFbTJUvlLW1hoxNNYSu2jIZm1k/hRAcE60JYwvBkgz3UB
71yMEh0AtLxYe0bFk6EHah11tMUPgscbCq73snJ++8koUw+csk22G65hOs51bVb7Aa
726JBe67oLzdtvgCUFAA2qfrKzWRZzAdhUirQUZgySZk+Xq1pBAkEA/kZG0A6roTSM
73BVnx7LnPfsycKUsTumorpXiylZJjTi9XtmzxhrYN6wgZlDOOwOLgSQhszGpxVoMD
74u3gByT1b2QJBAPtL3mSKdvwRu/+40zaZLwvSJRxaj0mcE4BJOS6Oqs/hS1xRlrNk
75PpQ7WJ4yM6ZOLnXzm2mKyxm50Mv64109FtMCQQDOqS2KkjHaLowTGVxwC0DijMfr
76I9Lf8sSQk32J5VWCySWf5gGTfEnpmUa41gKTMJIbqZZLucNuDcOtzUaeWZlZAkA8
77ttXigLnCqR486JDPTi9ZscoZkZ+w7y6e/hH8t6d5Vjt48JVyfjPIaJY+km58LcN3
786AWSeGAdtRFHVzR7oHjVAkB4hutvxiOeiIVQNBhM6RSI9aBPMI21DoX2JRoxvNW2
79cbvAhow217X9V0dVerEOKxnNYspXRrh36h7k4mQA+sDq
80-----END RSA PRIVATE KEY-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040081""")
Rick Dean94e46fd2009-07-18 14:51:24 -050082
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040083server_cert_pem = b("""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -050084MIICKDCCAZGgAwIBAgIJAJn/HpR21r/8MA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
85BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
86VGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBSb290IENBMCIYDzIwMDkwMzI1MTIz
87NzUzWhgPMjAxNzA2MTExMjM3NTNaMBgxFjAUBgNVBAMTDWxvdmVseSBzZXJ2ZXIw
88gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAL6m+G653V0tpBC/OKl22VxOi2Cv
89lK4TYu9LHSDP9uDVTe7V5D5Tl6qzFoRRx5pfmnkqT5B+W9byp2NU3FC5hLm5zSAr
90b45meUhjEJ/ifkZgbNUjHdBIGP9MAQUHZa5WKdkGIJvGAvs8UzUqlr4TBWQIB24+
91lJ+Ukk/CRgasrYwdAgMBAAGjNjA0MB0GA1UdDgQWBBS4kC7Ij0W1TZXZqXQFAM2e
92gKEG2DATBgNVHSUEDDAKBggrBgEFBQcDATANBgkqhkiG9w0BAQUFAAOBgQBh30Li
93dJ+NlxIOx5343WqIBka3UbsOb2kxWrbkVCrvRapCMLCASO4FqiKWM+L0VDBprqIp
942mgpFQ6FHpoIENGvJhdEKpptQ5i7KaGhnDNTfdy3x1+h852G99f1iyj0RmbuFcM8
95uzujnS8YXWvM7DM1Ilozk4MzPug8jzFp5uhKCQ==
96-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040097""")
Rick Dean94e46fd2009-07-18 14:51:24 -050098
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -040099server_key_pem = normalize_privatekey_pem(b("""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500100MIICWwIBAAKBgQC+pvhuud1dLaQQvzipdtlcTotgr5SuE2LvSx0gz/bg1U3u1eQ+
101U5eqsxaEUceaX5p5Kk+QflvW8qdjVNxQuYS5uc0gK2+OZnlIYxCf4n5GYGzVIx3Q
102SBj/TAEFB2WuVinZBiCbxgL7PFM1Kpa+EwVkCAduPpSflJJPwkYGrK2MHQIDAQAB
103AoGAbwuZ0AR6JveahBaczjfnSpiFHf+mve2UxoQdpyr6ROJ4zg/PLW5K/KXrC48G
104j6f3tXMrfKHcpEoZrQWUfYBRCUsGD5DCazEhD8zlxEHahIsqpwA0WWssJA2VOLEN
105j6DuV2pCFbw67rfTBkTSo32ahfXxEKev5KswZk0JIzH3ooECQQDgzS9AI89h0gs8
106Dt+1m11Rzqo3vZML7ZIyGApUzVan+a7hbc33nbGRkAXjHaUBJO31it/H6dTO+uwX
107msWwNG5ZAkEA2RyFKs5xR5USTFaKLWCgpH/ydV96KPOpBND7TKQx62snDenFNNbn
108FwwOhpahld+vqhYk+pfuWWUpQciE+Bu7ZQJASjfT4sQv4qbbKK/scePicnDdx9th
1094e1EeB9xwb+tXXXUo/6Bor/AcUNwfiQ6Zt9PZOK9sR3lMZSsP7rMi7kzuQJABie6
1101sXXjFH7nNJvRG4S39cIxq8YRYTy68II/dlB2QzGpKxV/POCxbJ/zu0CU79tuYK7
111NaeNCFfH3aeTrX0LyQJAMBWjWmeKM2G2sCExheeQK0ROnaBC8itCECD4Jsve4nqf
112r50+LF74iLXFwqysVCebPKMOpDWp/qQ1BbJQIPs7/A==
113-----END RSA PRIVATE KEY-----
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -0400114"""))
Rick Dean94e46fd2009-07-18 14:51:24 -0500115
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400116client_cert_pem = b("""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500117MIICJjCCAY+gAwIBAgIJAKxpFI5lODkjMA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
118BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
119VGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBSb290IENBMCIYDzIwMDkwMzI1MTIz
120ODA1WhgPMjAxNzA2MTExMjM4MDVaMBYxFDASBgNVBAMTC3VnbHkgY2xpZW50MIGf
121MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDAZh/SRtNm5ntMT4qb6YzEpTroMlq2
122rn+GrRHRiZ+xkCw/CGNhbtPir7/QxaUj26BSmQrHw1bGKEbPsWiW7bdXSespl+xK
123iku4G/KvnnmWdeJHqsiXeUZtqurMELcPQAw9xPHEuhqqUJvvEoMTsnCEqGM+7Dtb
124oCRajYyHfluARQIDAQABozYwNDAdBgNVHQ4EFgQUNQB+qkaOaEVecf1J3TTUtAff
1250fAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQEFBQADgYEAyv/Jh7gM
126Q3OHvmsFEEvRI+hsW8y66zK4K5de239Y44iZrFYkt7Q5nBPMEWDj4F2hLYWL/qtI
1279Zdr0U4UDCU9SmmGYh4o7R4TZ5pGFvBYvjhHbkSFYFQXZxKUi+WUxplP6I0wr2KJ
128PSTJCjJOn3xo2NTKRgV1gaoTf2EhL+RG8TQ=
129-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400130""")
Rick Dean94e46fd2009-07-18 14:51:24 -0500131
Jean-Paul Calderone22cbe502011-05-04 17:01:43 -0400132client_key_pem = normalize_privatekey_pem(b("""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500133MIICXgIBAAKBgQDAZh/SRtNm5ntMT4qb6YzEpTroMlq2rn+GrRHRiZ+xkCw/CGNh
134btPir7/QxaUj26BSmQrHw1bGKEbPsWiW7bdXSespl+xKiku4G/KvnnmWdeJHqsiX
135eUZtqurMELcPQAw9xPHEuhqqUJvvEoMTsnCEqGM+7DtboCRajYyHfluARQIDAQAB
136AoGATkZ+NceY5Glqyl4mD06SdcKfV65814vg2EL7V9t8+/mi9rYL8KztSXGlQWPX
137zuHgtRoMl78yQ4ZJYOBVo+nsx8KZNRCEBlE19bamSbQLCeQMenWnpeYyQUZ908gF
138h6L9qsFVJepgA9RDgAjyDoS5CaWCdCCPCH2lDkdcqC54SVUCQQDseuduc4wi8h4t
139V8AahUn9fn9gYfhoNuM0gdguTA0nPLVWz4hy1yJiWYQe0H7NLNNTmCKiLQaJpAbb
140TC6vE8C7AkEA0Ee8CMJUc20BnGEmxwgWcVuqFWaKCo8jTH1X38FlATUsyR3krjW2
141dL3yDD9NwHxsYP7nTKp/U8MV7U9IBn4y/wJBAJl7H0/BcLeRmuJk7IqJ7b635iYB
142D/9beFUw3MUXmQXZUfyYz39xf6CDZsu1GEdEC5haykeln3Of4M9d/4Kj+FcCQQCY
143si6xwT7GzMDkk/ko684AV3KPc/h6G0yGtFIrMg7J3uExpR/VdH2KgwMkZXisSMvw
144JJEQjOMCVsEJlRk54WWjAkEAzoZNH6UhDdBK5F38rVt/y4SEHgbSfJHIAmPS32Kq
145f6GGcfNpip0Uk7q7udTKuX7Q/buZi/C4YW7u3VKAquv9NA==
146-----END RSA PRIVATE KEY-----
Jean-Paul Calderone22cbe502011-05-04 17:01:43 -0400147"""))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400148
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400149cleartextCertificatePEM = b("""-----BEGIN CERTIFICATE-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400150MIIC7TCCAlagAwIBAgIIPQzE4MbeufQwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE
151BhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdU
152ZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwIhgPMjAwOTAzMjUxMjM2
153NThaGA8yMDE3MDYxMTEyMzY1OFowWDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklM
154MRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9U
155ZXN0aW5nIFJvb3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPmaQumL
156urpE527uSEHdL1pqcDRmWzu+98Y6YHzT/J7KWEamyMCNZ6fRW1JCR782UQ8a07fy
1572xXsKy4WdKaxyG8CcatwmXvpvRQ44dSANMihHELpANTdyVp6DCysED6wkQFurHlF
1581dshEaJw8b/ypDhmbVIo6Ci1xvCJqivbLFnbAgMBAAGjgbswgbgwHQYDVR0OBBYE
159FINVdy1eIfFJDAkk51QJEo3IfgSuMIGIBgNVHSMEgYAwfoAUg1V3LV4h8UkMCSTn
160VAkSjch+BK6hXKRaMFgxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UE
161BxMHQ2hpY2FnbzEQMA4GA1UEChMHVGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBS
162b290IENBggg9DMTgxt659DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB
163AGGCDazMJGoWNBpc03u6+smc95dEead2KlZXBATOdFT1VesY3+nUOqZhEhTGlDMi
164hkgaZnzoIq/Uamidegk4hirsCT/R+6vsKAAxNTcBjUeZjlykCJWy5ojShGftXIKY
165w/njVbKMXrvc83qmTdGl3TAM0fxQIpqgcglFLveEBgzn
166-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400167""")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400168
Jean-Paul Calderoned50d2042011-05-04 17:00:49 -0400169cleartextPrivateKeyPEM = normalize_privatekey_pem(b("""\
170-----BEGIN RSA PRIVATE KEY-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400171MIICXQIBAAKBgQD5mkLpi7q6ROdu7khB3S9aanA0Zls7vvfGOmB80/yeylhGpsjA
172jWen0VtSQke/NlEPGtO38tsV7CsuFnSmschvAnGrcJl76b0UOOHUgDTIoRxC6QDU
1733claegwsrBA+sJEBbqx5RdXbIRGicPG/8qQ4Zm1SKOgotcbwiaor2yxZ2wIDAQAB
174AoGBAPCgMpmLxzwDaUmcFbTJUvlLW1hoxNNYSu2jIZm1k/hRAcE60JYwvBkgz3UB
175yMEh0AtLxYe0bFk6EHah11tMUPgscbCq73snJ++8koUw+csk22G65hOs51bVb7Aa
1766JBe67oLzdtvgCUFAA2qfrKzWRZzAdhUirQUZgySZk+Xq1pBAkEA/kZG0A6roTSM
177BVnx7LnPfsycKUsTumorpXiylZJjTi9XtmzxhrYN6wgZlDOOwOLgSQhszGpxVoMD
178u3gByT1b2QJBAPtL3mSKdvwRu/+40zaZLwvSJRxaj0mcE4BJOS6Oqs/hS1xRlrNk
179PpQ7WJ4yM6ZOLnXzm2mKyxm50Mv64109FtMCQQDOqS2KkjHaLowTGVxwC0DijMfr
180I9Lf8sSQk32J5VWCySWf5gGTfEnpmUa41gKTMJIbqZZLucNuDcOtzUaeWZlZAkA8
181ttXigLnCqR486JDPTi9ZscoZkZ+w7y6e/hH8t6d5Vjt48JVyfjPIaJY+km58LcN3
1826AWSeGAdtRFHVzR7oHjVAkB4hutvxiOeiIVQNBhM6RSI9aBPMI21DoX2JRoxvNW2
183cbvAhow217X9V0dVerEOKxnNYspXRrh36h7k4mQA+sDq
184-----END RSA PRIVATE KEY-----
Jean-Paul Calderoned50d2042011-05-04 17:00:49 -0400185"""))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400186
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400187cleartextCertificateRequestPEM = b("""-----BEGIN CERTIFICATE REQUEST-----
188MIIBnjCCAQcCAQAwXjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQH
189EwdDaGljYWdvMRcwFQYDVQQKEw5NeSBDb21wYW55IEx0ZDEXMBUGA1UEAxMORnJl
190ZGVyaWNrIERlYW4wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANp6Y17WzKSw
191BsUWkXdqg6tnXy8H8hA1msCMWpc+/2KJ4mbv5NyD6UD+/SqagQqulPbF/DFea9nA
192E0zhmHJELcM8gUTIlXv/cgDWnmK4xj8YkjVUiCdqKRAKeuzLG1pGmwwF5lGeJpXN
193xQn5ecR0UYSOWj6TTGXB9VyUMQzCClcBAgMBAAGgADANBgkqhkiG9w0BAQUFAAOB
194gQAAJGuF/R/GGbeC7FbFW+aJgr9ee0Xbl6nlhu7pTe67k+iiKT2dsl2ti68MVTnu
195Vrb3HUNqOkiwsJf6kCtq5oPn3QVYzTa76Dt2y3Rtzv6boRSlmlfrgS92GNma8JfR
196oICQk3nAudi6zl1Dix3BCv1pUp5KMtGn3MeDEi6QFGy2rA==
197-----END CERTIFICATE REQUEST-----
198""")
Rick Dean5b7b6372009-04-01 11:34:06 -0500199
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400200encryptedPrivateKeyPEM = b("""-----BEGIN RSA PRIVATE KEY-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400201Proc-Type: 4,ENCRYPTED
202DEK-Info: DES-EDE3-CBC,9573604A18579E9E
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400203
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400204SHOho56WxDkT0ht10UTeKc0F5u8cqIa01kzFAmETw0MAs8ezYtK15NPdCXUm3X/2
205a17G7LSF5bkxOgZ7vpXyMzun/owrj7CzvLxyncyEFZWvtvzaAhPhvTJtTIB3kf8B
2068+qRcpTGK7NgXEgYBW5bj1y4qZkD4zCL9o9NQzsKI3Ie8i0239jsDOWR38AxjXBH
207mGwAQ4Z6ZN5dnmM4fhMIWsmFf19sNyAML4gHenQCHhmXbjXeVq47aC2ProInJbrm
208+00TcisbAQ40V9aehVbcDKtS4ZbMVDwncAjpXpcncC54G76N6j7F7wL7L/FuXa3A
209fvSVy9n2VfF/pJ3kYSflLHH2G/DFxjF7dl0GxhKPxJjp3IJi9VtuvmN9R2jZWLQF
210tfC8dXgy/P9CfFQhlinqBTEwgH0oZ/d4k4NVFDSdEMaSdmBAjlHpc+Vfdty3HVnV
211rKXj//wslsFNm9kIwJGIgKUa/n2jsOiydrsk1mgH7SmNCb3YHgZhbbnq0qLat/HC
212gHDt3FHpNQ31QzzL3yrenFB2L9osIsnRsDTPFNi4RX4SpDgNroxOQmyzCCV6H+d4
213o1mcnNiZSdxLZxVKccq0AfRpHqpPAFnJcQHP6xyT9MZp6fBa0XkxDnt9kNU8H3Qw
2147SJWZ69VXjBUzMlQViLuaWMgTnL+ZVyFZf9hTF7U/ef4HMLMAVNdiaGG+G+AjCV/
215MbzjS007Oe4qqBnCWaFPSnJX6uLApeTbqAxAeyCql56ULW5x6vDMNC3dwjvS/CEh
21611n8RkgFIQA0AhuKSIg3CbuartRsJnWOLwgLTzsrKYL4yRog1RJrtw==
217-----END RSA PRIVATE KEY-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400218""")
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400219
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400220encryptedPrivateKeyPEMPassphrase = b("foobar")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400221
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400222# Some PKCS#7 stuff. Generated with the openssl command line:
223#
224# openssl crl2pkcs7 -inform pem -outform pem -certfile s.pem -nocrl
225#
226# with a certificate and key (but the key should be irrelevant) in s.pem
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400227pkcs7Data = b("""\
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400228-----BEGIN PKCS7-----
229MIIDNwYJKoZIhvcNAQcCoIIDKDCCAyQCAQExADALBgkqhkiG9w0BBwGgggMKMIID
230BjCCAm+gAwIBAgIBATANBgkqhkiG9w0BAQQFADB7MQswCQYDVQQGEwJTRzERMA8G
231A1UEChMITTJDcnlwdG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtN
232MkNyeXB0byBDZXJ0aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNA
233cG9zdDEuY29tMB4XDTAwMDkxMDA5NTEzMFoXDTAyMDkxMDA5NTEzMFowUzELMAkG
234A1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwlsb2NhbGhvc3Qx
235HTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tMFwwDQYJKoZIhvcNAQEBBQAD
236SwAwSAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh5kwI
237zOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEAAaOCAQQwggEAMAkGA1UdEwQCMAAw
238LAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0G
239A1UdDgQWBBTPhIKSvnsmYsBVNWjj0m3M2z0qVTCBpQYDVR0jBIGdMIGagBT7hyNp
24065w6kxXlxb8pUU/+7Sg4AaF/pH0wezELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0y
241Q3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlwdG8g
242Q2VydGlmaWNhdGUgTWFzdGVyMR0wGwYJKoZIhvcNAQkBFg5uZ3BzQHBvc3QxLmNv
243bYIBADANBgkqhkiG9w0BAQQFAAOBgQA7/CqT6PoHycTdhEStWNZde7M/2Yc6BoJu
244VwnW8YxGO8Sn6UJ4FeffZNcYZddSDKosw8LtPOeWoK3JINjAk5jiPQ2cww++7QGG
245/g5NDjxFZNDJP1dGiLAxPW6JXwov4v0FmdzfLOZ01jDcgQQZqEpYlgpuI5JEWUQ9
246Ho4EzbYCOaEAMQA=
247-----END PKCS7-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400248""")
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400249
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400250crlData = b("""\
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -0500251-----BEGIN X509 CRL-----
252MIIBWzCBxTANBgkqhkiG9w0BAQQFADBYMQswCQYDVQQGEwJVUzELMAkGA1UECBMC
253SUwxEDAOBgNVBAcTB0NoaWNhZ28xEDAOBgNVBAoTB1Rlc3RpbmcxGDAWBgNVBAMT
254D1Rlc3RpbmcgUm9vdCBDQRcNMDkwNzI2MDQzNDU2WhcNMTIwOTI3MDI0MTUyWjA8
255MBUCAgOrGA8yMDA5MDcyNTIzMzQ1NlowIwICAQAYDzIwMDkwNzI1MjMzNDU2WjAM
256MAoGA1UdFQQDCgEEMA0GCSqGSIb3DQEBBAUAA4GBAEBt7xTs2htdD3d4ErrcGAw1
2574dKcVnIWTutoI7xxen26Wwvh8VCsT7i/UeP+rBl9rC/kfjWjzQk3/zleaarGTpBT
2580yp4HXRFFoRhhSE/hP+eteaPXRgrsNRLHe9ZDd69wmh7J1wMDb0m81RG7kqcbsid
259vrzEeLDRiiPl92dyyWmu
260-----END X509 CRL-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400261""")
Jean-Paul Calderonee890db32010-08-22 16:55:15 -0400262
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400263
264# A broken RSA private key which can be used to test the error path through
265# PKey.check.
266inconsistentPrivateKeyPEM = b("""-----BEGIN RSA PRIVATE KEY-----
267MIIBPAIBAAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh
2685kwIzOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEaAQJBAIqm/bz4NA1H++Vx5Ewx
269OcKp3w19QSaZAwlGRtsUxrP7436QjnREM3Bm8ygU11BjkPVmtrKm6AayQfCHqJoT
270zIECIQDW0BoMoL0HOYM/mrTLhaykYAVqgIeJsPjvkEhTFXWBuQIhAM3deFAvWNu4
271nklUQ37XsCT2c9tmNt1LAT+slG2JOTTRAiAuXDtC/m3NYVwyHfFm+zKHRzHkClk2
272HjubeEgjpj32AQIhAJqMGTaZVOwevTXvvHwNeH+vRWsAYU/gbx+OQB+7VOcBAiEA
273oolb6NMg/R3enNPvS1O4UU1H8wpaF77L4yiSWlE0p4w=
274-----END RSA PRIVATE KEY-----
275""")
276
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -0400277# certificate with NULL bytes in subjectAltName and common name
278
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400279nulbyteSubjectAltNamePEM = b("""-----BEGIN CERTIFICATE-----
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -0400280MIIE2DCCA8CgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBxTELMAkGA1UEBhMCVVMx
281DzANBgNVBAgMBk9yZWdvbjESMBAGA1UEBwwJQmVhdmVydG9uMSMwIQYDVQQKDBpQ
282eXRob24gU29mdHdhcmUgRm91bmRhdGlvbjEgMB4GA1UECwwXUHl0aG9uIENvcmUg
283RGV2ZWxvcG1lbnQxJDAiBgNVBAMMG251bGwucHl0aG9uLm9yZwBleGFtcGxlLm9y
284ZzEkMCIGCSqGSIb3DQEJARYVcHl0aG9uLWRldkBweXRob24ub3JnMB4XDTEzMDgw
285NzEzMTE1MloXDTEzMDgwNzEzMTI1MlowgcUxCzAJBgNVBAYTAlVTMQ8wDQYDVQQI
286DAZPcmVnb24xEjAQBgNVBAcMCUJlYXZlcnRvbjEjMCEGA1UECgwaUHl0aG9uIFNv
287ZnR3YXJlIEZvdW5kYXRpb24xIDAeBgNVBAsMF1B5dGhvbiBDb3JlIERldmVsb3Bt
288ZW50MSQwIgYDVQQDDBtudWxsLnB5dGhvbi5vcmcAZXhhbXBsZS5vcmcxJDAiBgkq
289hkiG9w0BCQEWFXB5dGhvbi1kZXZAcHl0aG9uLm9yZzCCASIwDQYJKoZIhvcNAQEB
290BQADggEPADCCAQoCggEBALXq7cn7Rn1vO3aA3TrzA5QLp6bb7B3f/yN0CJ2XFj+j
291pHs+Gw6WWSUDpybiiKnPec33BFawq3kyblnBMjBU61ioy5HwQqVkJ8vUVjGIUq3P
292vX/wBmQfzCe4o4uM89gpHyUL9UYGG8oCRa17dgqcv7u5rg0Wq2B1rgY+nHwx3JIv
293KRrgSwyRkGzpN8WQ1yrXlxWjgI9de0mPVDDUlywcWze1q2kwaEPTM3hLAmD1PESA
294oY/n8A/RXoeeRs9i/Pm/DGUS8ZPINXk/yOzsR/XvvkTVroIeLZqfmFpnZeF0cHzL
29508LODkVJJ9zjLdT7SA4vnne4FEbAxDbKAq5qkYzaL4UCAwEAAaOB0DCBzTAMBgNV
296HRMBAf8EAjAAMB0GA1UdDgQWBBSIWlXAUv9hzVKjNQ/qWpwkOCL3XDALBgNVHQ8E
297BAMCBeAwgZAGA1UdEQSBiDCBhYIeYWx0bnVsbC5weXRob24ub3JnAGV4YW1wbGUu
298Y29tgSBudWxsQHB5dGhvbi5vcmcAdXNlckBleGFtcGxlLm9yZ4YpaHR0cDovL251
299bGwucHl0aG9uLm9yZwBodHRwOi8vZXhhbXBsZS5vcmeHBMAAAgGHECABDbgAAAAA
300AAAAAAAAAAEwDQYJKoZIhvcNAQEFBQADggEBAKxPRe99SaghcI6IWT7UNkJw9aO9
301i9eo0Fj2MUqxpKbdb9noRDy2CnHWf7EIYZ1gznXPdwzSN4YCjV5d+Q9xtBaowT0j
302HPERs1ZuytCNNJTmhyqZ8q6uzMLoht4IqH/FBfpvgaeC5tBTnTT0rD5A/olXeimk
303kX4LxlEx5RAvpGB2zZVRGr6LobD9rVK91xuHYNIxxxfEGE8tCCWjp0+3ksri9SXx
304VHWBnbM9YaL32u3hxm8sYB/Yb8WSBavJCWJJqRStVRHM1koZlJmXNx2BX4vPo6iW
305RFEIPQsFZRLrtnCAiEhyT8bC2s/Njlu6ly9gtJZWSV46Q3ZjBL4q9sHKqZQ=
306-----END CERTIFICATE-----""")
307
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400308
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400309class X509ExtTests(TestCase):
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400310 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900311 Tests for :py:class:`OpenSSL.crypto.X509Extension`.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400312 """
313
314 def setUp(self):
315 """
316 Create a new private key and start a certificate request (for a test
317 method to finish in one way or another).
318 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -0800319 super(X509ExtTests, self).setUp()
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400320 # Basic setup stuff to generate a certificate
321 self.pkey = PKey()
322 self.pkey.generate_key(TYPE_RSA, 384)
323 self.req = X509Req()
324 self.req.set_pubkey(self.pkey)
325 # Authority good you have.
326 self.req.get_subject().commonName = "Yoda root CA"
327 self.x509 = X509()
328 self.subject = self.x509.get_subject()
329 self.subject.commonName = self.req.get_subject().commonName
330 self.x509.set_issuer(self.subject)
331 self.x509.set_pubkey(self.pkey)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400332 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
333 expire = b((datetime.now() + timedelta(days=100)).strftime("%Y%m%d%H%M%SZ"))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400334 self.x509.set_notBefore(now)
335 self.x509.set_notAfter(expire)
336
337
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -0800338 def tearDown(self):
339 """
340 Forget all of the pyOpenSSL objects so they can be garbage collected,
341 their memory released, and not interfere with the leak detection code.
342 """
343 self.pkey = self.req = self.x509 = self.subject = None
344 super(X509ExtTests, self).tearDown()
345
346
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400347 def test_str(self):
348 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900349 The string representation of :py:class:`X509Extension` instances as returned by
350 :py:data:`str` includes stuff.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400351 """
352 # This isn't necessarily the best string representation. Perhaps it
353 # will be changed/improved in the future.
354 self.assertEquals(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400355 str(X509Extension(b('basicConstraints'), True, b('CA:false'))),
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400356 'CA:FALSE')
357
358
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400359 def test_type(self):
360 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900361 :py:class:`X509Extension` and :py:class:`X509ExtensionType` refer to the same type object
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400362 and can be used to create instances of that type.
363 """
364 self.assertIdentical(X509Extension, X509ExtensionType)
365 self.assertConsistentType(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400366 X509Extension,
367 'X509Extension', b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400368
369
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500370 def test_construction(self):
371 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900372 :py:class:`X509Extension` accepts an extension type name, a critical flag,
373 and an extension value and returns an :py:class:`X509ExtensionType` instance.
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500374 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400375 basic = X509Extension(b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500376 self.assertTrue(
377 isinstance(basic, X509ExtensionType),
378 "%r is of type %r, should be %r" % (
379 basic, type(basic), X509ExtensionType))
380
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400381 comment = X509Extension(
382 b('nsComment'), False, b('pyOpenSSL unit test'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500383 self.assertTrue(
384 isinstance(comment, X509ExtensionType),
385 "%r is of type %r, should be %r" % (
386 comment, type(comment), X509ExtensionType))
387
388
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500389 def test_invalid_extension(self):
390 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900391 :py:class:`X509Extension` raises something if it is passed a bad extension
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500392 name or value.
393 """
394 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400395 Error, X509Extension, b('thisIsMadeUp'), False, b('hi'))
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500396 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400397 Error, X509Extension, b('basicConstraints'), False, b('blah blah'))
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500398
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500399 # Exercise a weird one (an extension which uses the r2i method). This
400 # exercises the codepath that requires a non-NULL ctx to be passed to
401 # X509V3_EXT_nconf. It can't work now because we provide no
402 # configuration database. It might be made to work in the future.
403 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400404 Error, X509Extension, b('proxyCertInfo'), True,
405 b('language:id-ppl-anyLanguage,pathlen:1,policy:text:AB'))
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500406
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500407
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500408 def test_get_critical(self):
409 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900410 :py:meth:`X509ExtensionType.get_critical` returns the value of the
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500411 extension's critical flag.
412 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400413 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500414 self.assertTrue(ext.get_critical())
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400415 ext = X509Extension(b('basicConstraints'), False, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500416 self.assertFalse(ext.get_critical())
417
Jean-Paul Calderone7535dab2008-03-06 18:53:11 -0500418
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500419 def test_get_short_name(self):
420 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900421 :py:meth:`X509ExtensionType.get_short_name` returns a string giving the short
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500422 type name of the extension.
423 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400424 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
425 self.assertEqual(ext.get_short_name(), b('basicConstraints'))
426 ext = X509Extension(b('nsComment'), True, b('foo bar'))
427 self.assertEqual(ext.get_short_name(), b('nsComment'))
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500428
429
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400430 def test_get_data(self):
431 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900432 :py:meth:`X509Extension.get_data` returns a string giving the data of the
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400433 extension.
434 """
435 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
436 # Expect to get back the DER encoded form of CA:true.
437 self.assertEqual(ext.get_data(), b('0\x03\x01\x01\xff'))
438
439
440 def test_get_data_wrong_args(self):
441 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900442 :py:meth:`X509Extension.get_data` raises :py:exc:`TypeError` if passed any arguments.
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400443 """
444 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
445 self.assertRaises(TypeError, ext.get_data, None)
446 self.assertRaises(TypeError, ext.get_data, "foo")
447 self.assertRaises(TypeError, ext.get_data, 7)
448
449
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400450 def test_unused_subject(self):
Rick Dean47262da2009-07-08 16:17:17 -0500451 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900452 The :py:data:`subject` parameter to :py:class:`X509Extension` may be provided for an
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400453 extension which does not use it and is ignored in this case.
Rick Dean47262da2009-07-08 16:17:17 -0500454 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400455 ext1 = X509Extension(
456 b('basicConstraints'), False, b('CA:TRUE'), subject=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400457 self.x509.add_extensions([ext1])
458 self.x509.sign(self.pkey, 'sha1')
459 # This is a little lame. Can we think of a better way?
460 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400461 self.assertTrue(b('X509v3 Basic Constraints:') in text)
462 self.assertTrue(b('CA:TRUE') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400463
464
465 def test_subject(self):
466 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900467 If an extension requires a subject, the :py:data:`subject` parameter to
468 :py:class:`X509Extension` provides its value.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400469 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400470 ext3 = X509Extension(
471 b('subjectKeyIdentifier'), False, b('hash'), subject=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400472 self.x509.add_extensions([ext3])
473 self.x509.sign(self.pkey, 'sha1')
474 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400475 self.assertTrue(b('X509v3 Subject Key Identifier:') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400476
477
478 def test_missing_subject(self):
479 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900480 If an extension requires a subject and the :py:data:`subject` parameter is
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400481 given no value, something happens.
482 """
483 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400484 Error, X509Extension, b('subjectKeyIdentifier'), False, b('hash'))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400485
486
487 def test_invalid_subject(self):
488 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900489 If the :py:data:`subject` parameter is given a value which is not an
490 :py:class:`X509` instance, :py:exc:`TypeError` is raised.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400491 """
492 for badObj in [True, object(), "hello", [], self]:
493 self.assertRaises(
494 TypeError,
495 X509Extension,
496 'basicConstraints', False, 'CA:TRUE', subject=badObj)
497
498
499 def test_unused_issuer(self):
500 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900501 The :py:data:`issuer` parameter to :py:class:`X509Extension` may be provided for an
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400502 extension which does not use it and is ignored in this case.
503 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400504 ext1 = X509Extension(
505 b('basicConstraints'), False, b('CA:TRUE'), issuer=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400506 self.x509.add_extensions([ext1])
507 self.x509.sign(self.pkey, 'sha1')
508 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400509 self.assertTrue(b('X509v3 Basic Constraints:') in text)
510 self.assertTrue(b('CA:TRUE') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400511
512
513 def test_issuer(self):
514 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900515 If an extension requires a issuer, the :py:data:`issuer` parameter to
516 :py:class:`X509Extension` provides its value.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400517 """
518 ext2 = X509Extension(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400519 b('authorityKeyIdentifier'), False, b('issuer:always'),
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400520 issuer=self.x509)
521 self.x509.add_extensions([ext2])
522 self.x509.sign(self.pkey, 'sha1')
523 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400524 self.assertTrue(b('X509v3 Authority Key Identifier:') in text)
525 self.assertTrue(b('DirName:/CN=Yoda root CA') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400526
527
528 def test_missing_issuer(self):
529 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900530 If an extension requires an issue and the :py:data:`issuer` parameter is given
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400531 no value, something happens.
532 """
533 self.assertRaises(
534 Error,
535 X509Extension,
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400536 b('authorityKeyIdentifier'), False,
537 b('keyid:always,issuer:always'))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400538
539
540 def test_invalid_issuer(self):
541 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900542 If the :py:data:`issuer` parameter is given a value which is not an
543 :py:class:`X509` instance, :py:exc:`TypeError` is raised.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400544 """
545 for badObj in [True, object(), "hello", [], self]:
546 self.assertRaises(
547 TypeError,
548 X509Extension,
549 'authorityKeyIdentifier', False, 'keyid:always,issuer:always',
550 issuer=badObj)
Rick Dean47262da2009-07-08 16:17:17 -0500551
552
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500553
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400554class PKeyTests(TestCase):
Jean-Paul Calderoneac930e12008-03-06 18:50:51 -0500555 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900556 Unit tests for :py:class:`OpenSSL.crypto.PKey`.
Jean-Paul Calderoneac930e12008-03-06 18:50:51 -0500557 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400558 def test_type(self):
559 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900560 :py:class:`PKey` and :py:class:`PKeyType` refer to the same type object
561 and can be used to create instances of that type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400562 """
563 self.assertIdentical(PKey, PKeyType)
564 self.assertConsistentType(PKey, 'PKey')
565
566
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500567 def test_construction(self):
568 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900569 :py:class:`PKey` takes no arguments and returns a new :py:class:`PKey` instance.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500570 """
571 self.assertRaises(TypeError, PKey, None)
572 key = PKey()
573 self.assertTrue(
574 isinstance(key, PKeyType),
575 "%r is of type %r, should be %r" % (key, type(key), PKeyType))
576
577
578 def test_pregeneration(self):
579 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900580 :py:attr:`PKeyType.bits` and :py:attr:`PKeyType.type` return :py:data:`0` before the key is
581 generated. :py:attr:`PKeyType.check` raises :py:exc:`TypeError` before the key is
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500582 generated.
583 """
584 key = PKey()
585 self.assertEqual(key.type(), 0)
586 self.assertEqual(key.bits(), 0)
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400587 self.assertRaises(TypeError, key.check)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500588
589
590 def test_failedGeneration(self):
591 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900592 :py:meth:`PKeyType.generate_key` takes two arguments, the first giving the key
593 type as one of :py:data:`TYPE_RSA` or :py:data:`TYPE_DSA` and the second giving the
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500594 number of bits to generate. If an invalid type is specified or
Jonathan Ballet648875f2011-07-16 14:14:58 +0900595 generation fails, :py:exc:`Error` is raised. If an invalid number of bits is
596 specified, :py:exc:`ValueError` or :py:exc:`Error` is raised.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500597 """
598 key = PKey()
599 self.assertRaises(TypeError, key.generate_key)
600 self.assertRaises(TypeError, key.generate_key, 1, 2, 3)
601 self.assertRaises(TypeError, key.generate_key, "foo", "bar")
602 self.assertRaises(Error, key.generate_key, -1, 0)
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500603
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500604 self.assertRaises(ValueError, key.generate_key, TYPE_RSA, -1)
605 self.assertRaises(ValueError, key.generate_key, TYPE_RSA, 0)
Jean-Paul Calderoned71fe982008-03-06 00:31:50 -0500606
607 # XXX RSA generation for small values of bits is fairly buggy in a wide
608 # range of OpenSSL versions. I need to figure out what the safe lower
609 # bound for a reasonable number of OpenSSL versions is and explicitly
610 # check for that in the wrapper. The failure behavior is typically an
611 # infinite loop inside OpenSSL.
612
613 # self.assertRaises(Error, key.generate_key, TYPE_RSA, 2)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500614
615 # XXX DSA generation seems happy with any number of bits. The DSS
616 # says bits must be between 512 and 1024 inclusive. OpenSSL's DSA
617 # generator doesn't seem to care about the upper limit at all. For
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500618 # the lower limit, it uses 512 if anything smaller is specified.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500619 # So, it doesn't seem possible to make generate_key fail for
620 # TYPE_DSA with a bits argument which is at least an int.
621
622 # self.assertRaises(Error, key.generate_key, TYPE_DSA, -7)
623
624
625 def test_rsaGeneration(self):
626 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900627 :py:meth:`PKeyType.generate_key` generates an RSA key when passed
628 :py:data:`TYPE_RSA` as a type and a reasonable number of bits.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500629 """
630 bits = 128
631 key = PKey()
632 key.generate_key(TYPE_RSA, bits)
633 self.assertEqual(key.type(), TYPE_RSA)
634 self.assertEqual(key.bits(), bits)
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -0400635 self.assertTrue(key.check())
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500636
637
638 def test_dsaGeneration(self):
639 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900640 :py:meth:`PKeyType.generate_key` generates a DSA key when passed
641 :py:data:`TYPE_DSA` as a type and a reasonable number of bits.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500642 """
643 # 512 is a magic number. The DSS (Digital Signature Standard)
644 # allows a minimum of 512 bits for DSA. DSA_generate_parameters
645 # will silently promote any value below 512 to 512.
646 bits = 512
647 key = PKey()
648 key.generate_key(TYPE_DSA, bits)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800649 # self.assertEqual(key.type(), TYPE_DSA)
650 # self.assertEqual(key.bits(), bits)
651 # self.assertRaises(TypeError, key.check)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500652
653
654 def test_regeneration(self):
655 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900656 :py:meth:`PKeyType.generate_key` can be called multiple times on the same
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500657 key to generate new keys.
658 """
659 key = PKey()
660 for type, bits in [(TYPE_RSA, 512), (TYPE_DSA, 576)]:
661 key.generate_key(type, bits)
662 self.assertEqual(key.type(), type)
663 self.assertEqual(key.bits(), bits)
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500664
665
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400666 def test_inconsistentKey(self):
667 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900668 :py:`PKeyType.check` returns :py:exc:`Error` if the key is not consistent.
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400669 """
670 key = load_privatekey(FILETYPE_PEM, inconsistentPrivateKeyPEM)
Jean-Paul Calderoned338e4e2009-05-13 15:45:07 -0400671 self.assertRaises(Error, key.check)
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400672
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500673
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400674 def test_check_wrong_args(self):
675 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900676 :py:meth:`PKeyType.check` raises :py:exc:`TypeError` if called with any arguments.
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400677 """
678 self.assertRaises(TypeError, PKey().check, None)
679 self.assertRaises(TypeError, PKey().check, object())
680 self.assertRaises(TypeError, PKey().check, 1)
681
682
Jean-Paul Calderone02d01972011-10-31 10:39:29 -0400683 def test_check_public_key(self):
684 """
685 :py:meth:`PKeyType.check` raises :py:exc:`TypeError` if only the public
686 part of the key is available.
687 """
688 # A trick to get a public-only key
689 key = PKey()
690 key.generate_key(TYPE_RSA, 512)
691 cert = X509()
692 cert.set_pubkey(key)
693 pub = cert.get_pubkey()
694 self.assertRaises(TypeError, pub.check)
695
696
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400697
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400698class X509NameTests(TestCase):
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500699 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900700 Unit tests for :py:class:`OpenSSL.crypto.X509Name`.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500701 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500702 def _x509name(self, **attrs):
703 # XXX There's no other way to get a new X509Name yet.
704 name = X509().get_subject()
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400705 attrs = list(attrs.items())
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500706 # Make the order stable - order matters!
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400707 def key(attr):
708 return attr[1]
709 attrs.sort(key=key)
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500710 for k, v in attrs:
711 setattr(name, k, v)
712 return name
713
714
Rick Deane15b1472009-07-09 15:53:42 -0500715 def test_type(self):
716 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900717 The type of X509Name objects is :py:class:`X509NameType`.
Rick Deane15b1472009-07-09 15:53:42 -0500718 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400719 self.assertIdentical(X509Name, X509NameType)
720 self.assertEqual(X509NameType.__name__, 'X509Name')
721 self.assertTrue(isinstance(X509NameType, type))
722
Rick Deane15b1472009-07-09 15:53:42 -0500723 name = self._x509name()
724 self.assertTrue(
725 isinstance(name, X509NameType),
726 "%r is of type %r, should be %r" % (
727 name, type(name), X509NameType))
Rick Deane15b1472009-07-09 15:53:42 -0500728
729
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400730 def test_onlyStringAttributes(self):
731 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900732 Attempting to set a non-:py:data:`str` attribute name on an :py:class:`X509NameType`
733 instance causes :py:exc:`TypeError` to be raised.
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400734 """
735 name = self._x509name()
736 # Beyond these cases, you may also think that unicode should be
737 # rejected. Sorry, you're wrong. unicode is automatically converted to
738 # str outside of the control of X509Name, so there's no way to reject
739 # it.
Jean-Paul Calderoneff363be2013-03-03 10:21:23 -0800740
741 # Also, this used to test str subclasses, but that test is less relevant
742 # now that the implementation is in Python instead of C. Also PyPy
743 # automatically converts str subclasses to str when they are passed to
744 # setattr, so we can't test it on PyPy. Apparently CPython does this
745 # sometimes as well.
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400746 self.assertRaises(TypeError, setattr, name, None, "hello")
747 self.assertRaises(TypeError, setattr, name, 30, "hello")
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400748
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -0500749
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400750 def test_setInvalidAttribute(self):
751 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900752 Attempting to set any attribute name on an :py:class:`X509NameType` instance for
753 which no corresponding NID is defined causes :py:exc:`AttributeError` to be
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400754 raised.
755 """
756 name = self._x509name()
757 self.assertRaises(AttributeError, setattr, name, "no such thing", None)
758
759
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500760 def test_attributes(self):
761 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900762 :py:class:`X509NameType` instances have attributes for each standard (?)
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500763 X509Name field.
764 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500765 name = self._x509name()
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500766 name.commonName = "foo"
767 self.assertEqual(name.commonName, "foo")
768 self.assertEqual(name.CN, "foo")
769 name.CN = "baz"
770 self.assertEqual(name.commonName, "baz")
771 self.assertEqual(name.CN, "baz")
772 name.commonName = "bar"
773 self.assertEqual(name.commonName, "bar")
774 self.assertEqual(name.CN, "bar")
775 name.CN = "quux"
776 self.assertEqual(name.commonName, "quux")
777 self.assertEqual(name.CN, "quux")
778
779
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500780 def test_copy(self):
781 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900782 :py:class:`X509Name` creates a new :py:class:`X509NameType` instance with all the same
783 attributes as an existing :py:class:`X509NameType` instance when called with
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500784 one.
785 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500786 name = self._x509name(commonName="foo", emailAddress="bar@example.com")
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500787
788 copy = X509Name(name)
789 self.assertEqual(copy.commonName, "foo")
790 self.assertEqual(copy.emailAddress, "bar@example.com")
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500791
792 # Mutate the copy and ensure the original is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500793 copy.commonName = "baz"
794 self.assertEqual(name.commonName, "foo")
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500795
796 # Mutate the original and ensure the copy is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500797 name.emailAddress = "quux@example.com"
798 self.assertEqual(copy.emailAddress, "bar@example.com")
799
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500800
801 def test_repr(self):
802 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900803 :py:func:`repr` passed an :py:class:`X509NameType` instance should return a string
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500804 containing a description of the type and the NIDs which have been set
805 on it.
806 """
807 name = self._x509name(commonName="foo", emailAddress="bar")
808 self.assertEqual(
809 repr(name),
810 "<X509Name object '/emailAddress=bar/CN=foo'>")
811
812
813 def test_comparison(self):
814 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900815 :py:class:`X509NameType` instances should compare based on their NIDs.
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500816 """
817 def _equality(a, b, assertTrue, assertFalse):
818 assertTrue(a == b, "(%r == %r) --> False" % (a, b))
819 assertFalse(a != b)
820 assertTrue(b == a)
821 assertFalse(b != a)
822
823 def assertEqual(a, b):
824 _equality(a, b, self.assertTrue, self.assertFalse)
825
826 # Instances compare equal to themselves.
827 name = self._x509name()
828 assertEqual(name, name)
829
830 # Empty instances should compare equal to each other.
831 assertEqual(self._x509name(), self._x509name())
832
833 # Instances with equal NIDs should compare equal to each other.
834 assertEqual(self._x509name(commonName="foo"),
835 self._x509name(commonName="foo"))
836
837 # Instance with equal NIDs set using different aliases should compare
838 # equal to each other.
839 assertEqual(self._x509name(commonName="foo"),
840 self._x509name(CN="foo"))
841
842 # Instances with more than one NID with the same values should compare
843 # equal to each other.
844 assertEqual(self._x509name(CN="foo", organizationalUnitName="bar"),
845 self._x509name(commonName="foo", OU="bar"))
846
847 def assertNotEqual(a, b):
848 _equality(a, b, self.assertFalse, self.assertTrue)
849
850 # Instances with different values for the same NID should not compare
851 # equal to each other.
852 assertNotEqual(self._x509name(CN="foo"),
853 self._x509name(CN="bar"))
854
855 # Instances with different NIDs should not compare equal to each other.
856 assertNotEqual(self._x509name(CN="foo"),
857 self._x509name(OU="foo"))
858
859 def _inequality(a, b, assertTrue, assertFalse):
860 assertTrue(a < b)
861 assertTrue(a <= b)
862 assertTrue(b > a)
863 assertTrue(b >= a)
864 assertFalse(a > b)
865 assertFalse(a >= b)
866 assertFalse(b < a)
867 assertFalse(b <= a)
868
869 def assertLessThan(a, b):
870 _inequality(a, b, self.assertTrue, self.assertFalse)
871
872 # An X509Name with a NID with a value which sorts less than the value
873 # of the same NID on another X509Name compares less than the other
874 # X509Name.
875 assertLessThan(self._x509name(CN="abc"),
876 self._x509name(CN="def"))
877
878 def assertGreaterThan(a, b):
879 _inequality(a, b, self.assertFalse, self.assertTrue)
880
881 # An X509Name with a NID with a value which sorts greater than the
882 # value of the same NID on another X509Name compares greater than the
883 # other X509Name.
884 assertGreaterThan(self._x509name(CN="def"),
885 self._x509name(CN="abc"))
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -0500886
887
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400888 def test_hash(self):
889 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900890 :py:meth:`X509Name.hash` returns an integer hash based on the value of the
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400891 name.
892 """
893 a = self._x509name(CN="foo")
894 b = self._x509name(CN="foo")
895 self.assertEqual(a.hash(), b.hash())
896 a.CN = "bar"
897 self.assertNotEqual(a.hash(), b.hash())
898
899
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400900 def test_der(self):
901 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900902 :py:meth:`X509Name.der` returns the DER encoded form of the name.
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400903 """
904 a = self._x509name(CN="foo", C="US")
905 self.assertEqual(
906 a.der(),
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -0400907 b('0\x1b1\x0b0\t\x06\x03U\x04\x06\x13\x02US'
908 '1\x0c0\n\x06\x03U\x04\x03\x13\x03foo'))
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400909
910
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400911 def test_get_components(self):
912 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900913 :py:meth:`X509Name.get_components` returns a :py:data:`list` of
914 two-tuples of :py:data:`str`
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400915 giving the NIDs and associated values which make up the name.
916 """
917 a = self._x509name()
918 self.assertEqual(a.get_components(), [])
919 a.CN = "foo"
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -0400920 self.assertEqual(a.get_components(), [(b("CN"), b("foo"))])
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400921 a.organizationalUnitName = "bar"
922 self.assertEqual(
923 a.get_components(),
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -0400924 [(b("CN"), b("foo")), (b("OU"), b("bar"))])
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400925
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400926
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400927 def test_load_nul_byte_attribute(self):
928 """
Jean-Paul Calderone9af07b02013-08-23 16:07:31 -0400929 An :py:class:`OpenSSL.crypto.X509Name` from an
930 :py:class:`OpenSSL.crypto.X509` instance loaded from a file can have a
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400931 NUL byte in the value of one of its attributes.
932 """
933 cert = load_certificate(FILETYPE_PEM, nulbyteSubjectAltNamePEM)
934 subject = cert.get_subject()
935 self.assertEqual(
Jean-Paul Calderone06754fc2013-08-23 15:47:47 -0400936 "null.python.org\x00example.org", subject.commonName)
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400937
938
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -0500939 def test_setAttributeFailure(self):
940 """
941 If the value of an attribute cannot be set for some reason then
942 :py:class:`OpenSSL.crypto.Error` is raised.
943 """
944 name = self._x509name()
945 # This value is too long
946 self.assertRaises(Error, setattr, name, "O", b"x" * 512)
947
948
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400949
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400950class _PKeyInteractionTestsMixin:
951 """
952 Tests which involve another thing and a PKey.
953 """
954 def signable(self):
955 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900956 Return something with a :py:meth:`set_pubkey`, :py:meth:`set_pubkey`,
957 and :py:meth:`sign` method.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400958 """
959 raise NotImplementedError()
960
961
962 def test_signWithUngenerated(self):
963 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900964 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when pass a
965 :py:class:`PKey` with no parts.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400966 """
967 request = self.signable()
968 key = PKey()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500969 self.assertRaises(ValueError, request.sign, key, GOOD_DIGEST)
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400970
971
972 def test_signWithPublicKey(self):
973 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900974 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when pass a
975 :py:class:`PKey` with no private part as the signing key.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400976 """
977 request = self.signable()
978 key = PKey()
979 key.generate_key(TYPE_RSA, 512)
980 request.set_pubkey(key)
981 pub = request.get_pubkey()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500982 self.assertRaises(ValueError, request.sign, pub, GOOD_DIGEST)
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400983
984
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -0400985 def test_signWithUnknownDigest(self):
986 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900987 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when passed a digest name which is
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -0400988 not known.
989 """
990 request = self.signable()
991 key = PKey()
992 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500993 self.assertRaises(ValueError, request.sign, key, BAD_DIGEST)
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -0400994
995
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -0400996 def test_sign(self):
997 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900998 :py:meth:`X509Req.sign` succeeds when passed a private key object and a valid
999 digest function. :py:meth:`X509Req.verify` can be used to check the signature.
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04001000 """
1001 request = self.signable()
1002 key = PKey()
1003 key.generate_key(TYPE_RSA, 512)
1004 request.set_pubkey(key)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001005 request.sign(key, GOOD_DIGEST)
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04001006 # If the type has a verify method, cover that too.
1007 if getattr(request, 'verify', None) is not None:
1008 pub = request.get_pubkey()
1009 self.assertTrue(request.verify(pub))
1010 # Make another key that won't verify.
1011 key = PKey()
1012 key.generate_key(TYPE_RSA, 512)
1013 self.assertRaises(Error, request.verify, key)
1014
1015
1016
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001017
Jean-Paul Calderone18808652009-07-05 12:54:05 -04001018class X509ReqTests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001019 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001020 Tests for :py:class:`OpenSSL.crypto.X509Req`.
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001021 """
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001022 def signable(self):
1023 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001024 Create and return a new :py:class:`X509Req`.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001025 """
1026 return X509Req()
1027
1028
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001029 def test_type(self):
1030 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001031 :py:obj:`X509Req` and :py:obj:`X509ReqType` refer to the same type object and can be
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001032 used to create instances of that type.
1033 """
1034 self.assertIdentical(X509Req, X509ReqType)
1035 self.assertConsistentType(X509Req, 'X509Req')
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001036
1037
1038 def test_construction(self):
1039 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001040 :py:obj:`X509Req` takes no arguments and returns an :py:obj:`X509ReqType` instance.
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001041 """
1042 request = X509Req()
1043 self.assertTrue(
1044 isinstance(request, X509ReqType),
1045 "%r is of type %r, should be %r" % (request, type(request), X509ReqType))
1046
1047
Jean-Paul Calderone8dd19b82008-12-28 20:41:16 -05001048 def test_version(self):
1049 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001050 :py:obj:`X509ReqType.set_version` sets the X.509 version of the certificate
1051 request. :py:obj:`X509ReqType.get_version` returns the X.509 version of
Jean-Paul Calderone8dd19b82008-12-28 20:41:16 -05001052 the certificate request. The initial value of the version is 0.
1053 """
1054 request = X509Req()
1055 self.assertEqual(request.get_version(), 0)
1056 request.set_version(1)
1057 self.assertEqual(request.get_version(), 1)
1058 request.set_version(3)
1059 self.assertEqual(request.get_version(), 3)
1060
1061
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001062 def test_version_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001063 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001064 :py:obj:`X509ReqType.set_version` raises :py:obj:`TypeError` if called with the wrong
1065 number of arguments or with a non-:py:obj:`int` argument.
1066 :py:obj:`X509ReqType.get_version` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001067 arguments.
1068 """
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001069 request = X509Req()
1070 self.assertRaises(TypeError, request.set_version)
1071 self.assertRaises(TypeError, request.set_version, "foo")
1072 self.assertRaises(TypeError, request.set_version, 1, 2)
1073 self.assertRaises(TypeError, request.get_version, None)
1074
1075
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001076 def test_get_subject(self):
1077 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001078 :py:obj:`X509ReqType.get_subject` returns an :py:obj:`X509Name` for the subject of
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001079 the request and which is valid even after the request object is
1080 otherwise dead.
1081 """
1082 request = X509Req()
1083 subject = request.get_subject()
1084 self.assertTrue(
1085 isinstance(subject, X509NameType),
1086 "%r is of type %r, should be %r" % (subject, type(subject), X509NameType))
1087 subject.commonName = "foo"
1088 self.assertEqual(request.get_subject().commonName, "foo")
1089 del request
1090 subject.commonName = "bar"
1091 self.assertEqual(subject.commonName, "bar")
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001092
1093
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001094 def test_get_subject_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001095 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001096 :py:obj:`X509ReqType.get_subject` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001097 arguments.
1098 """
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001099 request = X509Req()
1100 self.assertRaises(TypeError, request.get_subject, None)
1101
1102
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001103 def test_add_extensions(self):
1104 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001105 :py:obj:`X509Req.add_extensions` accepts a :py:obj:`list` of :py:obj:`X509Extension`
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001106 instances and adds them to the X509 request.
1107 """
1108 request = X509Req()
1109 request.add_extensions([
Jean-Paul Calderonee16f9f32010-08-22 19:20:37 -04001110 X509Extension(b('basicConstraints'), True, b('CA:false'))])
Stephen Holsappleca545b72014-01-28 21:43:25 -08001111 exts = request.get_extensions()
Stephen Holsapple7fbdf642014-03-01 20:05:47 -08001112 self.assertEqual(len(exts), 1)
1113 self.assertEqual(exts[0].get_short_name(), b('basicConstraints'))
1114 self.assertEqual(exts[0].get_critical(), 1)
1115 self.assertEqual(exts[0].get_data(), b('0\x00'))
1116
1117
1118 def test_get_extensions(self):
1119 """
1120 :py:obj:`X509Req.get_extensions` returns a :py:obj:`list` of
1121 extensions added to this X509 request.
1122 """
1123 request = X509Req()
1124 exts = request.get_extensions()
1125 self.assertEqual(exts, [])
1126 request.add_extensions([
1127 X509Extension(b('basicConstraints'), True, b('CA:true')),
1128 X509Extension(b('keyUsage'), False, b('digitalSignature'))])
1129 exts = request.get_extensions()
1130 self.assertEqual(len(exts), 2)
1131 self.assertEqual(exts[0].get_short_name(), b('basicConstraints'))
1132 self.assertEqual(exts[0].get_critical(), 1)
1133 self.assertEqual(exts[0].get_data(), b('0\x03\x01\x01\xff'))
1134 self.assertEqual(exts[1].get_short_name(), b('keyUsage'))
1135 self.assertEqual(exts[1].get_critical(), 0)
1136 self.assertEqual(exts[1].get_data(), b('\x03\x02\x07\x80'))
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001137
1138
1139 def test_add_extensions_wrong_args(self):
1140 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001141 :py:obj:`X509Req.add_extensions` raises :py:obj:`TypeError` if called with the wrong
1142 number of arguments or with a non-:py:obj:`list`. Or it raises :py:obj:`ValueError`
1143 if called with a :py:obj:`list` containing objects other than :py:obj:`X509Extension`
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001144 instances.
1145 """
1146 request = X509Req()
1147 self.assertRaises(TypeError, request.add_extensions)
1148 self.assertRaises(TypeError, request.add_extensions, object())
1149 self.assertRaises(ValueError, request.add_extensions, [object()])
1150 self.assertRaises(TypeError, request.add_extensions, [], None)
1151
1152
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001153 def test_verify_wrong_args(self):
1154 """
1155 :py:obj:`X509Req.verify` raises :py:obj:`TypeError` if called with zero
1156 arguments or more than one argument or if passed anything other than a
1157 :py:obj:`PKey` instance as its single argument.
1158 """
1159 request = X509Req()
1160 self.assertRaises(TypeError, request.verify)
1161 self.assertRaises(TypeError, request.verify, object())
1162 self.assertRaises(TypeError, request.verify, PKey(), object())
1163
1164
1165 def test_verify_uninitialized_key(self):
1166 """
1167 :py:obj:`X509Req.verify` raises :py:obj:`OpenSSL.crypto.Error` if called
1168 with a :py:obj:`OpenSSL.crypto.PKey` which contains no key data.
1169 """
1170 request = X509Req()
1171 pkey = PKey()
1172 self.assertRaises(Error, request.verify, pkey)
1173
1174
1175 def test_verify_wrong_key(self):
1176 """
1177 :py:obj:`X509Req.verify` raises :py:obj:`OpenSSL.crypto.Error` if called
1178 with a :py:obj:`OpenSSL.crypto.PKey` which does not represent the public
1179 part of the key which signed the request.
1180 """
1181 request = X509Req()
1182 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001183 request.sign(pkey, GOOD_DIGEST)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001184 another_pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
1185 self.assertRaises(Error, request.verify, another_pkey)
1186
1187
1188 def test_verify_success(self):
1189 """
1190 :py:obj:`X509Req.verify` returns :py:obj:`True` if called with a
1191 :py:obj:`OpenSSL.crypto.PKey` which represents the public part ofthe key
1192 which signed the request.
1193 """
1194 request = X509Req()
1195 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001196 request.sign(pkey, GOOD_DIGEST)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001197 self.assertEqual(True, request.verify(pkey))
1198
1199
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001200
Jean-Paul Calderone18808652009-07-05 12:54:05 -04001201class X509Tests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001202 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001203 Tests for :py:obj:`OpenSSL.crypto.X509`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001204 """
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001205 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
Jean-Paul Calderone8114b452008-03-25 15:27:59 -04001206
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001207 extpem = """
1208-----BEGIN CERTIFICATE-----
1209MIIC3jCCAkegAwIBAgIJAJHFjlcCgnQzMA0GCSqGSIb3DQEBBQUAMEcxCzAJBgNV
1210BAYTAlNFMRUwEwYDVQQIEwxXZXN0ZXJib3R0b20xEjAQBgNVBAoTCUNhdGFsb2dp
1211eDENMAsGA1UEAxMEUm9vdDAeFw0wODA0MjIxNDQ1MzhaFw0wOTA0MjIxNDQ1Mzha
1212MFQxCzAJBgNVBAYTAlNFMQswCQYDVQQIEwJXQjEUMBIGA1UEChMLT3Blbk1ldGFk
1213aXIxIjAgBgNVBAMTGW5vZGUxLm9tMi5vcGVubWV0YWRpci5vcmcwgZ8wDQYJKoZI
1214hvcNAQEBBQADgY0AMIGJAoGBAPIcQMrwbk2nESF/0JKibj9i1x95XYAOwP+LarwT
1215Op4EQbdlI9SY+uqYqlERhF19w7CS+S6oyqx0DRZSk4Y9dZ9j9/xgm2u/f136YS1u
1216zgYFPvfUs6PqYLPSM8Bw+SjJ+7+2+TN+Tkiof9WP1cMjodQwOmdsiRbR0/J7+b1B
1217hec1AgMBAAGjgcQwgcEwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNT
1218TCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFIdHsBcMVVMbAO7j6NCj
121903HgLnHaMB8GA1UdIwQYMBaAFL2h9Bf9Mre4vTdOiHTGAt7BRY/8MEYGA1UdEQQ/
1220MD2CDSouZXhhbXBsZS5vcmeCESoub20yLmV4bWFwbGUuY29thwSC7wgKgRNvbTJA
1221b3Blbm1ldGFkaXIub3JnMA0GCSqGSIb3DQEBBQUAA4GBALd7WdXkp2KvZ7/PuWZA
1222MPlIxyjS+Ly11+BNE0xGQRp9Wz+2lABtpgNqssvU156+HkKd02rGheb2tj7MX9hG
1223uZzbwDAZzJPjzDQDD7d3cWsrVcfIdqVU7epHqIadnOF+X0ghJ39pAm6VVadnSXCt
1224WpOdIpB8KksUTCzV591Nr1wd
1225-----END CERTIFICATE-----
1226 """
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001227 def signable(self):
1228 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001229 Create and return a new :py:obj:`X509`.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001230 """
1231 return X509()
1232
1233
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001234 def test_type(self):
1235 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001236 :py:obj:`X509` and :py:obj:`X509Type` refer to the same type object and can be used
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001237 to create instances of that type.
1238 """
1239 self.assertIdentical(X509, X509Type)
1240 self.assertConsistentType(X509, 'X509')
1241
1242
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001243 def test_construction(self):
1244 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001245 :py:obj:`X509` takes no arguments and returns an instance of :py:obj:`X509Type`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001246 """
1247 certificate = X509()
1248 self.assertTrue(
1249 isinstance(certificate, X509Type),
1250 "%r is of type %r, should be %r" % (certificate,
1251 type(certificate),
1252 X509Type))
Rick Deane15b1472009-07-09 15:53:42 -05001253 self.assertEqual(type(X509Type).__name__, 'type')
1254 self.assertEqual(type(certificate).__name__, 'X509')
1255 self.assertEqual(type(certificate), X509Type)
Rick Dean04113e72009-07-16 12:06:35 -05001256 self.assertEqual(type(certificate), X509)
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001257
1258
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001259 def test_get_version_wrong_args(self):
1260 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001261 :py:obj:`X509.get_version` raises :py:obj:`TypeError` if invoked with any arguments.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001262 """
1263 cert = X509()
1264 self.assertRaises(TypeError, cert.get_version, None)
1265
1266
1267 def test_set_version_wrong_args(self):
1268 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001269 :py:obj:`X509.set_version` raises :py:obj:`TypeError` if invoked with the wrong number
1270 of arguments or an argument not of type :py:obj:`int`.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001271 """
1272 cert = X509()
1273 self.assertRaises(TypeError, cert.set_version)
1274 self.assertRaises(TypeError, cert.set_version, None)
1275 self.assertRaises(TypeError, cert.set_version, 1, None)
1276
1277
1278 def test_version(self):
1279 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001280 :py:obj:`X509.set_version` sets the certificate version number.
1281 :py:obj:`X509.get_version` retrieves it.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001282 """
1283 cert = X509()
1284 cert.set_version(1234)
1285 self.assertEquals(cert.get_version(), 1234)
1286
1287
1288 def test_get_serial_number_wrong_args(self):
1289 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001290 :py:obj:`X509.get_serial_number` raises :py:obj:`TypeError` if invoked with any
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001291 arguments.
1292 """
1293 cert = X509()
1294 self.assertRaises(TypeError, cert.get_serial_number, None)
1295
1296
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001297 def test_serial_number(self):
1298 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001299 The serial number of an :py:obj:`X509Type` can be retrieved and modified with
1300 :py:obj:`X509Type.get_serial_number` and :py:obj:`X509Type.set_serial_number`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001301 """
1302 certificate = X509()
1303 self.assertRaises(TypeError, certificate.set_serial_number)
1304 self.assertRaises(TypeError, certificate.set_serial_number, 1, 2)
1305 self.assertRaises(TypeError, certificate.set_serial_number, "1")
1306 self.assertRaises(TypeError, certificate.set_serial_number, 5.5)
1307 self.assertEqual(certificate.get_serial_number(), 0)
1308 certificate.set_serial_number(1)
1309 self.assertEqual(certificate.get_serial_number(), 1)
1310 certificate.set_serial_number(2 ** 32 + 1)
1311 self.assertEqual(certificate.get_serial_number(), 2 ** 32 + 1)
1312 certificate.set_serial_number(2 ** 64 + 1)
1313 self.assertEqual(certificate.get_serial_number(), 2 ** 64 + 1)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001314 certificate.set_serial_number(2 ** 128 + 1)
1315 self.assertEqual(certificate.get_serial_number(), 2 ** 128 + 1)
1316
1317
1318 def _setBoundTest(self, which):
1319 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001320 :py:obj:`X509Type.set_notBefore` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001321 GENERALIZEDTIME and sets the beginning of the certificate's validity
1322 period to it.
1323 """
1324 certificate = X509()
1325 set = getattr(certificate, 'set_not' + which)
1326 get = getattr(certificate, 'get_not' + which)
1327
Jean-Paul Calderonee0615b52008-03-09 21:44:46 -04001328 # Starts with no value.
1329 self.assertEqual(get(), None)
1330
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001331 # GMT (Or is it UTC?) -exarkun
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001332 when = b("20040203040506Z")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001333 set(when)
1334 self.assertEqual(get(), when)
1335
1336 # A plus two hours and thirty minutes offset
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001337 when = b("20040203040506+0530")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001338 set(when)
1339 self.assertEqual(get(), when)
1340
1341 # A minus one hour fifteen minutes offset
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001342 when = b("20040203040506-0115")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001343 set(when)
1344 self.assertEqual(get(), when)
1345
1346 # An invalid string results in a ValueError
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001347 self.assertRaises(ValueError, set, b("foo bar"))
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001348
Jean-Paul Calderone31ca2002010-01-30 15:14:43 -05001349 # The wrong number of arguments results in a TypeError.
1350 self.assertRaises(TypeError, set)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001351 self.assertRaises(TypeError, set, b("20040203040506Z"), b("20040203040506Z"))
1352 self.assertRaises(TypeError, get, b("foo bar"))
1353
Jean-Paul Calderone31ca2002010-01-30 15:14:43 -05001354
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001355 # XXX ASN1_TIME (not GENERALIZEDTIME)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001356
1357 def test_set_notBefore(self):
1358 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001359 :py:obj:`X509Type.set_notBefore` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001360 GENERALIZEDTIME and sets the beginning of the certificate's validity
1361 period to it.
1362 """
1363 self._setBoundTest("Before")
1364
1365
1366 def test_set_notAfter(self):
1367 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001368 :py:obj:`X509Type.set_notAfter` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001369 GENERALIZEDTIME and sets the end of the certificate's validity period
1370 to it.
1371 """
1372 self._setBoundTest("After")
Jean-Paul Calderone76576d52008-03-24 16:04:46 -04001373
1374
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001375 def test_get_notBefore(self):
1376 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001377 :py:obj:`X509Type.get_notBefore` returns a string in the format of an ASN1
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001378 GENERALIZEDTIME even for certificates which store it as UTCTIME
1379 internally.
1380 """
Jean-Paul Calderone8114b452008-03-25 15:27:59 -04001381 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001382 self.assertEqual(cert.get_notBefore(), b("20090325123658Z"))
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001383
Rick Dean38a05c82009-07-18 01:41:30 -05001384
1385 def test_get_notAfter(self):
1386 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001387 :py:obj:`X509Type.get_notAfter` returns a string in the format of an ASN1
Rick Dean38a05c82009-07-18 01:41:30 -05001388 GENERALIZEDTIME even for certificates which store it as UTCTIME
1389 internally.
1390 """
1391 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001392 self.assertEqual(cert.get_notAfter(), b("20170611123658Z"))
Rick Dean38a05c82009-07-18 01:41:30 -05001393
1394
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001395 def test_gmtime_adj_notBefore_wrong_args(self):
1396 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001397 :py:obj:`X509Type.gmtime_adj_notBefore` raises :py:obj:`TypeError` if called with the
1398 wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001399 """
1400 cert = X509()
1401 self.assertRaises(TypeError, cert.gmtime_adj_notBefore)
1402 self.assertRaises(TypeError, cert.gmtime_adj_notBefore, None)
1403 self.assertRaises(TypeError, cert.gmtime_adj_notBefore, 123, None)
1404
1405
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001406 def test_gmtime_adj_notBefore(self):
1407 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001408 :py:obj:`X509Type.gmtime_adj_notBefore` changes the not-before timestamp to be
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001409 the current time plus the number of seconds passed in.
1410 """
1411 cert = load_certificate(FILETYPE_PEM, self.pemData)
1412 now = datetime.utcnow() + timedelta(seconds=100)
1413 cert.gmtime_adj_notBefore(100)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001414 self.assertEqual(cert.get_notBefore(), b(now.strftime("%Y%m%d%H%M%SZ")))
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001415
1416
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001417 def test_gmtime_adj_notAfter_wrong_args(self):
1418 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001419 :py:obj:`X509Type.gmtime_adj_notAfter` raises :py:obj:`TypeError` if called with the
1420 wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001421 """
1422 cert = X509()
1423 self.assertRaises(TypeError, cert.gmtime_adj_notAfter)
1424 self.assertRaises(TypeError, cert.gmtime_adj_notAfter, None)
1425 self.assertRaises(TypeError, cert.gmtime_adj_notAfter, 123, None)
1426
1427
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001428 def test_gmtime_adj_notAfter(self):
1429 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001430 :py:obj:`X509Type.gmtime_adj_notAfter` changes the not-after timestamp to be
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001431 the current time plus the number of seconds passed in.
1432 """
1433 cert = load_certificate(FILETYPE_PEM, self.pemData)
1434 now = datetime.utcnow() + timedelta(seconds=100)
1435 cert.gmtime_adj_notAfter(100)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001436 self.assertEqual(cert.get_notAfter(), b(now.strftime("%Y%m%d%H%M%SZ")))
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001437
1438
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001439 def test_has_expired_wrong_args(self):
1440 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001441 :py:obj:`X509Type.has_expired` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001442 arguments.
1443 """
1444 cert = X509()
1445 self.assertRaises(TypeError, cert.has_expired, None)
1446
1447
1448 def test_has_expired(self):
1449 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001450 :py:obj:`X509Type.has_expired` returns :py:obj:`True` if the certificate's not-after
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001451 time is in the past.
1452 """
1453 cert = X509()
1454 cert.gmtime_adj_notAfter(-1)
1455 self.assertTrue(cert.has_expired())
1456
1457
1458 def test_has_not_expired(self):
1459 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001460 :py:obj:`X509Type.has_expired` returns :py:obj:`False` if the certificate's not-after
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001461 time is in the future.
1462 """
1463 cert = X509()
1464 cert.gmtime_adj_notAfter(2)
1465 self.assertFalse(cert.has_expired())
1466
1467
Rick Dean38a05c82009-07-18 01:41:30 -05001468 def test_digest(self):
1469 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001470 :py:obj:`X509.digest` returns a string giving ":"-separated hex-encoded words
Rick Dean38a05c82009-07-18 01:41:30 -05001471 of the digest of the certificate.
1472 """
1473 cert = X509()
1474 self.assertEqual(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001475 # This is MD5 instead of GOOD_DIGEST because the digest algorithm
1476 # actually matters to the assertion (ie, another arbitrary, good
1477 # digest will not product the same digest).
1478 cert.digest("MD5"),
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001479 b("A8:EB:07:F8:53:25:0A:F2:56:05:C5:A5:C4:C4:C7:15"))
Rick Dean38a05c82009-07-18 01:41:30 -05001480
1481
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001482 def _extcert(self, pkey, extensions):
1483 cert = X509()
1484 cert.set_pubkey(pkey)
1485 cert.get_subject().commonName = "Unit Tests"
1486 cert.get_issuer().commonName = "Unit Tests"
1487 when = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
1488 cert.set_notBefore(when)
1489 cert.set_notAfter(when)
1490
1491 cert.add_extensions(extensions)
1492 return load_certificate(
1493 FILETYPE_PEM, dump_certificate(FILETYPE_PEM, cert))
1494
1495
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001496 def test_extension_count(self):
1497 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001498 :py:obj:`X509.get_extension_count` returns the number of extensions that are
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001499 present in the certificate.
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001500 """
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001501 pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001502 ca = X509Extension(b('basicConstraints'), True, b('CA:FALSE'))
1503 key = X509Extension(b('keyUsage'), True, b('digitalSignature'))
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001504 subjectAltName = X509Extension(
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001505 b('subjectAltName'), True, b('DNS:example.com'))
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001506
1507 # Try a certificate with no extensions at all.
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001508 c = self._extcert(pkey, [])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001509 self.assertEqual(c.get_extension_count(), 0)
1510
1511 # And a certificate with one
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001512 c = self._extcert(pkey, [ca])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001513 self.assertEqual(c.get_extension_count(), 1)
1514
1515 # And a certificate with several
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001516 c = self._extcert(pkey, [ca, key, subjectAltName])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001517 self.assertEqual(c.get_extension_count(), 3)
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001518
1519
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001520 def test_get_extension(self):
1521 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001522 :py:obj:`X509.get_extension` takes an integer and returns an :py:obj:`X509Extension`
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001523 corresponding to the extension at that index.
1524 """
1525 pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001526 ca = X509Extension(b('basicConstraints'), True, b('CA:FALSE'))
1527 key = X509Extension(b('keyUsage'), True, b('digitalSignature'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001528 subjectAltName = X509Extension(
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001529 b('subjectAltName'), False, b('DNS:example.com'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001530
1531 cert = self._extcert(pkey, [ca, key, subjectAltName])
1532
1533 ext = cert.get_extension(0)
1534 self.assertTrue(isinstance(ext, X509Extension))
1535 self.assertTrue(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001536 self.assertEqual(ext.get_short_name(), b('basicConstraints'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001537
1538 ext = cert.get_extension(1)
1539 self.assertTrue(isinstance(ext, X509Extension))
1540 self.assertTrue(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001541 self.assertEqual(ext.get_short_name(), b('keyUsage'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001542
1543 ext = cert.get_extension(2)
1544 self.assertTrue(isinstance(ext, X509Extension))
1545 self.assertFalse(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001546 self.assertEqual(ext.get_short_name(), b('subjectAltName'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001547
1548 self.assertRaises(IndexError, cert.get_extension, -1)
1549 self.assertRaises(IndexError, cert.get_extension, 4)
1550 self.assertRaises(TypeError, cert.get_extension, "hello")
1551
1552
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001553 def test_nullbyte_subjectAltName(self):
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001554 """
Jean-Paul Calderone9af07b02013-08-23 16:07:31 -04001555 The fields of a `subjectAltName` extension on an X509 may contain NUL
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001556 bytes and this value is reflected in the string representation of the
1557 extension object.
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001558 """
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001559 cert = load_certificate(FILETYPE_PEM, nulbyteSubjectAltNamePEM)
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001560
1561 ext = cert.get_extension(3)
1562 self.assertEqual(ext.get_short_name(), b('subjectAltName'))
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001563 self.assertEqual(
1564 b("DNS:altnull.python.org\x00example.com, "
1565 "email:null@python.org\x00user@example.org, "
1566 "URI:http://null.python.org\x00http://example.org, "
1567 "IP Address:192.0.2.1, IP Address:2001:DB8:0:0:0:0:0:1\n"),
1568 b(str(ext)))
1569
Rick Dean38a05c82009-07-18 01:41:30 -05001570
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001571 def test_invalid_digest_algorithm(self):
1572 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001573 :py:obj:`X509.digest` raises :py:obj:`ValueError` if called with an unrecognized hash
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001574 algorithm.
1575 """
1576 cert = X509()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001577 self.assertRaises(ValueError, cert.digest, BAD_DIGEST)
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001578
1579
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001580 def test_get_subject_wrong_args(self):
1581 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001582 :py:obj:`X509.get_subject` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001583 """
1584 cert = X509()
1585 self.assertRaises(TypeError, cert.get_subject, None)
1586
1587
1588 def test_get_subject(self):
1589 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001590 :py:obj:`X509.get_subject` returns an :py:obj:`X509Name` instance.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001591 """
1592 cert = load_certificate(FILETYPE_PEM, self.pemData)
1593 subj = cert.get_subject()
1594 self.assertTrue(isinstance(subj, X509Name))
1595 self.assertEquals(
1596 subj.get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001597 [(b('C'), b('US')), (b('ST'), b('IL')), (b('L'), b('Chicago')),
1598 (b('O'), b('Testing')), (b('CN'), b('Testing Root CA'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001599
1600
1601 def test_set_subject_wrong_args(self):
1602 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001603 :py:obj:`X509.set_subject` raises a :py:obj:`TypeError` if called with the wrong
1604 number of arguments or an argument not of type :py:obj:`X509Name`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001605 """
1606 cert = X509()
1607 self.assertRaises(TypeError, cert.set_subject)
1608 self.assertRaises(TypeError, cert.set_subject, None)
1609 self.assertRaises(TypeError, cert.set_subject, cert.get_subject(), None)
1610
1611
1612 def test_set_subject(self):
1613 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001614 :py:obj:`X509.set_subject` changes the subject of the certificate to the one
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001615 passed in.
1616 """
1617 cert = X509()
1618 name = cert.get_subject()
1619 name.C = 'AU'
1620 name.O = 'Unit Tests'
1621 cert.set_subject(name)
1622 self.assertEquals(
1623 cert.get_subject().get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001624 [(b('C'), b('AU')), (b('O'), b('Unit Tests'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001625
1626
1627 def test_get_issuer_wrong_args(self):
1628 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001629 :py:obj:`X509.get_issuer` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001630 """
1631 cert = X509()
1632 self.assertRaises(TypeError, cert.get_issuer, None)
1633
1634
1635 def test_get_issuer(self):
1636 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001637 :py:obj:`X509.get_issuer` returns an :py:obj:`X509Name` instance.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001638 """
1639 cert = load_certificate(FILETYPE_PEM, self.pemData)
1640 subj = cert.get_issuer()
1641 self.assertTrue(isinstance(subj, X509Name))
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001642 comp = subj.get_components()
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001643 self.assertEquals(
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001644 comp,
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001645 [(b('C'), b('US')), (b('ST'), b('IL')), (b('L'), b('Chicago')),
1646 (b('O'), b('Testing')), (b('CN'), b('Testing Root CA'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001647
1648
1649 def test_set_issuer_wrong_args(self):
1650 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001651 :py:obj:`X509.set_issuer` raises a :py:obj:`TypeError` if called with the wrong
1652 number of arguments or an argument not of type :py:obj:`X509Name`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001653 """
1654 cert = X509()
1655 self.assertRaises(TypeError, cert.set_issuer)
1656 self.assertRaises(TypeError, cert.set_issuer, None)
1657 self.assertRaises(TypeError, cert.set_issuer, cert.get_issuer(), None)
1658
1659
1660 def test_set_issuer(self):
1661 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001662 :py:obj:`X509.set_issuer` changes the issuer of the certificate to the one
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001663 passed in.
1664 """
1665 cert = X509()
1666 name = cert.get_issuer()
1667 name.C = 'AU'
1668 name.O = 'Unit Tests'
1669 cert.set_issuer(name)
1670 self.assertEquals(
1671 cert.get_issuer().get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001672 [(b('C'), b('AU')), (b('O'), b('Unit Tests'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001673
1674
1675 def test_get_pubkey_uninitialized(self):
1676 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001677 When called on a certificate with no public key, :py:obj:`X509.get_pubkey`
1678 raises :py:obj:`OpenSSL.crypto.Error`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001679 """
1680 cert = X509()
1681 self.assertRaises(Error, cert.get_pubkey)
1682
1683
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001684 def test_subject_name_hash_wrong_args(self):
1685 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001686 :py:obj:`X509.subject_name_hash` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001687 arguments.
1688 """
1689 cert = X509()
1690 self.assertRaises(TypeError, cert.subject_name_hash, None)
1691
1692
1693 def test_subject_name_hash(self):
1694 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001695 :py:obj:`X509.subject_name_hash` returns the hash of the certificate's subject
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001696 name.
1697 """
1698 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -04001699 self.assertIn(
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001700 cert.subject_name_hash(),
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -04001701 [3350047874, # OpenSSL 0.9.8, MD5
1702 3278919224, # OpenSSL 1.0.0, SHA1
1703 ])
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001704
1705
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001706 def test_get_signature_algorithm(self):
1707 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001708 :py:obj:`X509Type.get_signature_algorithm` returns a string which means
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001709 the algorithm used to sign the certificate.
1710 """
1711 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001712 self.assertEqual(
1713 b("sha1WithRSAEncryption"), cert.get_signature_algorithm())
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001714
1715
1716 def test_get_undefined_signature_algorithm(self):
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001717 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001718 :py:obj:`X509Type.get_signature_algorithm` raises :py:obj:`ValueError` if the
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001719 signature algorithm is undefined or unknown.
1720 """
1721 # This certificate has been modified to indicate a bogus OID in the
1722 # signature algorithm field so that OpenSSL does not recognize it.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001723 certPEM = b("""\
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001724-----BEGIN CERTIFICATE-----
1725MIIC/zCCAmigAwIBAgIBATAGBgJ8BQUAMHsxCzAJBgNVBAYTAlNHMREwDwYDVQQK
1726EwhNMkNyeXB0bzEUMBIGA1UECxMLTTJDcnlwdG8gQ0ExJDAiBgNVBAMTG00yQ3J5
1727cHRvIENlcnRpZmljYXRlIE1hc3RlcjEdMBsGCSqGSIb3DQEJARYObmdwc0Bwb3N0
1728MS5jb20wHhcNMDAwOTEwMDk1MTMwWhcNMDIwOTEwMDk1MTMwWjBTMQswCQYDVQQG
1729EwJTRzERMA8GA1UEChMITTJDcnlwdG8xEjAQBgNVBAMTCWxvY2FsaG9zdDEdMBsG
1730CSqGSIb3DQEJARYObmdwc0Bwb3N0MS5jb20wXDANBgkqhkiG9w0BAQEFAANLADBI
1731AkEArL57d26W9fNXvOhNlZzlPOACmvwOZ5AdNgLzJ1/MfsQQJ7hHVeHmTAjM664V
1732+fXvwUGJLziCeBo1ysWLRnl8CQIDAQABo4IBBDCCAQAwCQYDVR0TBAIwADAsBglg
1733hkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0O
1734BBYEFM+EgpK+eyZiwFU1aOPSbczbPSpVMIGlBgNVHSMEgZ0wgZqAFPuHI2nrnDqT
1735FeXFvylRT/7tKDgBoX+kfTB7MQswCQYDVQQGEwJTRzERMA8GA1UEChMITTJDcnlw
1736dG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtNMkNyeXB0byBDZXJ0
1737aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tggEA
1738MA0GCSqGSIb3DQEBBAUAA4GBADv8KpPo+gfJxN2ERK1Y1l17sz/ZhzoGgm5XCdbx
1739jEY7xKfpQngV599k1xhl11IMqizDwu0855agrckg2MCTmOI9DZzDD77tAYb+Dk0O
1740PEVk0Mk/V0aIsDE9bolfCi/i/QWZ3N8s5nTWMNyBBBmoSliWCm4jkkRZRD0ejgTN
1741tgI5
1742-----END CERTIFICATE-----
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001743""")
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001744 cert = load_certificate(FILETYPE_PEM, certPEM)
1745 self.assertRaises(ValueError, cert.get_signature_algorithm)
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001746
1747
Rick Dean38a05c82009-07-18 01:41:30 -05001748
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001749class X509StoreTests(TestCase):
1750 """
1751 Test for :py:obj:`OpenSSL.crypto.X509Store`.
1752 """
1753 def test_type(self):
1754 """
1755 :py:obj:`X509StoreType` is a type object.
1756 """
1757 self.assertIdentical(X509Store, X509StoreType)
1758 self.assertConsistentType(X509Store, 'X509Store')
1759
1760
1761 def test_add_cert_wrong_args(self):
1762 store = X509Store()
1763 self.assertRaises(TypeError, store.add_cert)
1764 self.assertRaises(TypeError, store.add_cert, object())
1765 self.assertRaises(TypeError, store.add_cert, X509(), object())
1766
1767
1768 def test_add_cert(self):
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001769 """
1770 :py:obj:`X509Store.add_cert` adds a :py:obj:`X509` instance to the
1771 certificate store.
1772 """
1773 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001774 store = X509Store()
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001775 store.add_cert(cert)
1776
1777
1778 def test_add_cert_rejects_duplicate(self):
1779 """
1780 :py:obj:`X509Store.add_cert` raises :py:obj:`OpenSSL.crypto.Error` if an
1781 attempt is made to add the same certificate to the store more than once.
1782 """
1783 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
1784 store = X509Store()
1785 store.add_cert(cert)
1786 self.assertRaises(Error, store.add_cert, cert)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001787
1788
1789
Rick Dean623ee362009-07-17 12:22:16 -05001790class PKCS12Tests(TestCase):
1791 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001792 Test for :py:obj:`OpenSSL.crypto.PKCS12` and :py:obj:`OpenSSL.crypto.load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001793 """
1794 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
1795
Jean-Paul Calderonec3a41f72009-07-25 12:36:02 -04001796 def test_type(self):
1797 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001798 :py:obj:`PKCS12Type` is a type object.
Jean-Paul Calderonec3a41f72009-07-25 12:36:02 -04001799 """
1800 self.assertIdentical(PKCS12, PKCS12Type)
1801 self.assertConsistentType(PKCS12, 'PKCS12')
1802
1803
Rick Deanf94096c2009-07-18 14:23:06 -05001804 def test_empty_construction(self):
Rick Dean38a05c82009-07-18 01:41:30 -05001805 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001806 :py:obj:`PKCS12` returns a new instance of :py:obj:`PKCS12` with no certificate,
Jean-Paul Calderonedc857b52009-07-25 12:25:07 -04001807 private key, CA certificates, or friendly name.
Rick Dean38a05c82009-07-18 01:41:30 -05001808 """
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001809 p12 = PKCS12()
Rick Dean623ee362009-07-17 12:22:16 -05001810 self.assertEqual(None, p12.get_certificate())
1811 self.assertEqual(None, p12.get_privatekey())
1812 self.assertEqual(None, p12.get_ca_certificates())
Rick Dean42d69e12009-07-20 11:36:08 -05001813 self.assertEqual(None, p12.get_friendlyname())
Rick Dean623ee362009-07-17 12:22:16 -05001814
Rick Dean38a05c82009-07-18 01:41:30 -05001815
Rick Dean623ee362009-07-17 12:22:16 -05001816 def test_type_errors(self):
Rick Dean38a05c82009-07-18 01:41:30 -05001817 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001818 The :py:obj:`PKCS12` setter functions (:py:obj:`set_certificate`, :py:obj:`set_privatekey`,
1819 :py:obj:`set_ca_certificates`, and :py:obj:`set_friendlyname`) raise :py:obj:`TypeError`
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001820 when passed objects of types other than those expected.
Rick Dean38a05c82009-07-18 01:41:30 -05001821 """
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001822 p12 = PKCS12()
Rick Dean623ee362009-07-17 12:22:16 -05001823 self.assertRaises(TypeError, p12.set_certificate, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05001824 self.assertRaises(TypeError, p12.set_certificate, PKey())
1825 self.assertRaises(TypeError, p12.set_certificate, X509)
Rick Dean623ee362009-07-17 12:22:16 -05001826 self.assertRaises(TypeError, p12.set_privatekey, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05001827 self.assertRaises(TypeError, p12.set_privatekey, 'legbone')
1828 self.assertRaises(TypeError, p12.set_privatekey, X509())
Rick Dean623ee362009-07-17 12:22:16 -05001829 self.assertRaises(TypeError, p12.set_ca_certificates, 3)
1830 self.assertRaises(TypeError, p12.set_ca_certificates, X509())
1831 self.assertRaises(TypeError, p12.set_ca_certificates, (3, 4))
Rick Deanf94096c2009-07-18 14:23:06 -05001832 self.assertRaises(TypeError, p12.set_ca_certificates, ( PKey(), ))
Rick Dean42d69e12009-07-20 11:36:08 -05001833 self.assertRaises(TypeError, p12.set_friendlyname, 6)
1834 self.assertRaises(TypeError, p12.set_friendlyname, ('foo', 'bar'))
Rick Dean623ee362009-07-17 12:22:16 -05001835
Rick Dean38a05c82009-07-18 01:41:30 -05001836
Rick Dean623ee362009-07-17 12:22:16 -05001837 def test_key_only(self):
1838 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001839 A :py:obj:`PKCS12` with only a private key can be exported using
1840 :py:obj:`PKCS12.export` and loaded again using :py:obj:`load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001841 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001842 passwd = b"blah"
Rick Dean623ee362009-07-17 12:22:16 -05001843 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001844 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001845 p12.set_privatekey(pkey)
Rick Dean623ee362009-07-17 12:22:16 -05001846 self.assertEqual(None, p12.get_certificate())
1847 self.assertEqual(pkey, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05001848 try:
1849 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
1850 except Error:
1851 # Some versions of OpenSSL will throw an exception
1852 # for this nearly useless PKCS12 we tried to generate:
1853 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
1854 return
Rick Dean623ee362009-07-17 12:22:16 -05001855 p12 = load_pkcs12(dumped_p12, passwd)
1856 self.assertEqual(None, p12.get_ca_certificates())
1857 self.assertEqual(None, p12.get_certificate())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001858
1859 # OpenSSL fails to bring the key back to us. So sad. Perhaps in the
1860 # future this will be improved.
1861 self.assertTrue(isinstance(p12.get_privatekey(), (PKey, type(None))))
Rick Dean623ee362009-07-17 12:22:16 -05001862
Rick Dean38a05c82009-07-18 01:41:30 -05001863
Rick Dean623ee362009-07-17 12:22:16 -05001864 def test_cert_only(self):
1865 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001866 A :py:obj:`PKCS12` with only a certificate can be exported using
1867 :py:obj:`PKCS12.export` and loaded again using :py:obj:`load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001868 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001869 passwd = b"blah"
Rick Dean623ee362009-07-17 12:22:16 -05001870 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001871 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001872 p12.set_certificate(cert)
Rick Dean623ee362009-07-17 12:22:16 -05001873 self.assertEqual(cert, p12.get_certificate())
1874 self.assertEqual(None, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05001875 try:
1876 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
1877 except Error:
1878 # Some versions of OpenSSL will throw an exception
1879 # for this nearly useless PKCS12 we tried to generate:
1880 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
1881 return
Rick Dean623ee362009-07-17 12:22:16 -05001882 p12 = load_pkcs12(dumped_p12, passwd)
1883 self.assertEqual(None, p12.get_privatekey())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001884
1885 # OpenSSL fails to bring the cert back to us. Groany mcgroan.
1886 self.assertTrue(isinstance(p12.get_certificate(), (X509, type(None))))
1887
1888 # Oh ho. It puts the certificate into the ca certificates list, in
1889 # fact. Totally bogus, I would think. Nevertheless, let's exploit
1890 # that to check to see if it reconstructed the certificate we expected
1891 # it to. At some point, hopefully this will change so that
1892 # p12.get_certificate() is actually what returns the loaded
1893 # certificate.
1894 self.assertEqual(
1895 cleartextCertificatePEM,
1896 dump_certificate(FILETYPE_PEM, p12.get_ca_certificates()[0]))
Rick Dean623ee362009-07-17 12:22:16 -05001897
1898
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001899 def gen_pkcs12(self, cert_pem=None, key_pem=None, ca_pem=None, friendly_name=None):
Rick Dean623ee362009-07-17 12:22:16 -05001900 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001901 Generate a PKCS12 object with components from PEM. Verify that the set
1902 functions return None.
Rick Dean623ee362009-07-17 12:22:16 -05001903 """
Rick Deanf94096c2009-07-18 14:23:06 -05001904 p12 = PKCS12()
1905 if cert_pem:
1906 ret = p12.set_certificate(load_certificate(FILETYPE_PEM, cert_pem))
1907 self.assertEqual(ret, None)
1908 if key_pem:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001909 ret = p12.set_privatekey(load_privatekey(FILETYPE_PEM, key_pem))
Rick Deanf94096c2009-07-18 14:23:06 -05001910 self.assertEqual(ret, None)
1911 if ca_pem:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001912 ret = p12.set_ca_certificates((load_certificate(FILETYPE_PEM, ca_pem),))
Rick Deanf94096c2009-07-18 14:23:06 -05001913 self.assertEqual(ret, None)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001914 if friendly_name:
1915 ret = p12.set_friendlyname(friendly_name)
Rick Dean42d69e12009-07-20 11:36:08 -05001916 self.assertEqual(ret, None)
Rick Deanf94096c2009-07-18 14:23:06 -05001917 return p12
1918
1919
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001920 def check_recovery(self, p12_str, key=None, cert=None, ca=None, passwd=b"",
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001921 extra=()):
Rick Deanf94096c2009-07-18 14:23:06 -05001922 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001923 Use openssl program to confirm three components are recoverable from a
1924 PKCS12 string.
Rick Deanf94096c2009-07-18 14:23:06 -05001925 """
1926 if key:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001927 recovered_key = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001928 p12_str, b"pkcs12", b"-nocerts", b"-nodes", b"-passin",
1929 b"pass:" + passwd, *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001930 self.assertEqual(recovered_key[-len(key):], key)
1931 if cert:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001932 recovered_cert = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001933 p12_str, b"pkcs12", b"-clcerts", b"-nodes", b"-passin",
1934 b"pass:" + passwd, b"-nokeys", *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001935 self.assertEqual(recovered_cert[-len(cert):], cert)
1936 if ca:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001937 recovered_cert = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001938 p12_str, b"pkcs12", b"-cacerts", b"-nodes", b"-passin",
1939 b"pass:" + passwd, b"-nokeys", *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001940 self.assertEqual(recovered_cert[-len(ca):], ca)
1941
1942
Stephen Holsapple38482622014-04-05 20:29:34 -07001943 def verify_pkcs12_container(self, p12):
1944 """
1945 Verify that the PKCS#12 container contains the correct client
1946 certificate and private key.
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04001947
1948 :param p12: The PKCS12 instance to verify.
1949 :type p12: :py:class:`PKCS12`
Stephen Holsapple38482622014-04-05 20:29:34 -07001950 """
1951 cert_pem = dump_certificate(FILETYPE_PEM, p12.get_certificate())
1952 key_pem = dump_privatekey(FILETYPE_PEM, p12.get_privatekey())
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04001953 self.assertEqual(
1954 (client_cert_pem, client_key_pem, None),
1955 (cert_pem, key_pem, p12.get_ca_certificates()))
Stephen Holsapple38482622014-04-05 20:29:34 -07001956
1957
Rick Deanf94096c2009-07-18 14:23:06 -05001958 def test_load_pkcs12(self):
1959 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001960 A PKCS12 string generated using the openssl command line can be loaded
Jonathan Ballet648875f2011-07-16 14:14:58 +09001961 with :py:obj:`load_pkcs12` and its components extracted and examined.
Rick Deanf94096c2009-07-18 14:23:06 -05001962 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001963 passwd = b"whatever"
Rick Dean623ee362009-07-17 12:22:16 -05001964 pem = client_key_pem + client_cert_pem
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001965 p12_str = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001966 pem, b"pkcs12", b"-export", b"-clcerts", b"-passout", b"pass:" + passwd)
Stephen Holsapple38482622014-04-05 20:29:34 -07001967 p12 = load_pkcs12(p12_str, passphrase=passwd)
1968 self.verify_pkcs12_container(p12)
1969
1970
1971 def test_load_pkcs12_no_passphrase(self):
1972 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04001973 A PKCS12 string generated using openssl command line can be loaded with
1974 :py:obj:`load_pkcs12` without a passphrase and its components extracted
1975 and examined.
Stephen Holsapple38482622014-04-05 20:29:34 -07001976 """
1977 pem = client_key_pem + client_cert_pem
1978 p12_str = _runopenssl(
1979 pem, b"pkcs12", b"-export", b"-clcerts", b"-passout", b"pass:")
1980 p12 = load_pkcs12(p12_str)
1981 self.verify_pkcs12_container(p12)
1982
1983
1984 def _dump_and_load(self, dump_passphrase, load_passphrase):
1985 """
1986 A helper method to dump and load a PKCS12 object.
1987 """
1988 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem)
1989 dumped_p12 = p12.export(passphrase=dump_passphrase, iter=2, maciter=3)
1990 return load_pkcs12(dumped_p12, passphrase=load_passphrase)
1991
1992
1993 def test_load_pkcs12_null_passphrase_load_empty(self):
1994 """
1995 A PKCS12 string can be dumped with a null passphrase, loaded with an
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04001996 empty passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07001997 extracted and examined.
1998 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04001999 self.verify_pkcs12_container(
2000 self._dump_and_load(dump_passphrase=None, load_passphrase=b''))
Stephen Holsapple38482622014-04-05 20:29:34 -07002001
2002
2003 def test_load_pkcs12_null_passphrase_load_null(self):
2004 """
2005 A PKCS12 string can be dumped with a null passphrase, loaded with a
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002006 null passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002007 extracted and examined.
2008 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002009 self.verify_pkcs12_container(
2010 self._dump_and_load(dump_passphrase=None, load_passphrase=None))
Stephen Holsapple38482622014-04-05 20:29:34 -07002011
2012
2013 def test_load_pkcs12_empty_passphrase_load_empty(self):
2014 """
2015 A PKCS12 string can be dumped with an empty passphrase, loaded with an
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002016 empty passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002017 extracted and examined.
2018 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002019 self.verify_pkcs12_container(
2020 self._dump_and_load(dump_passphrase=b'', load_passphrase=b''))
Stephen Holsapple38482622014-04-05 20:29:34 -07002021
2022
2023 def test_load_pkcs12_empty_passphrase_load_null(self):
2024 """
2025 A PKCS12 string can be dumped with an empty passphrase, loaded with a
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002026 null passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002027 extracted and examined.
2028 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002029 self.verify_pkcs12_container(
2030 self._dump_and_load(dump_passphrase=b'', load_passphrase=None))
Rick Deanf94096c2009-07-18 14:23:06 -05002031
Rick Deanee568302009-07-24 09:56:29 -05002032
2033 def test_load_pkcs12_garbage(self):
2034 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002035 :py:obj:`load_pkcs12` raises :py:obj:`OpenSSL.crypto.Error` when passed a string
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002036 which is not a PKCS12 dump.
Rick Deanee568302009-07-24 09:56:29 -05002037 """
2038 passwd = 'whatever'
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002039 e = self.assertRaises(Error, load_pkcs12, b'fruit loops', passwd)
Jean-Paul Calderonede075462014-01-18 10:34:12 -05002040 self.assertEqual( e.args[0][0][0], 'asn1 encoding routines')
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -04002041 self.assertEqual( len(e.args[0][0]), 3)
Rick Deanee568302009-07-24 09:56:29 -05002042
2043
Rick Deanf94096c2009-07-18 14:23:06 -05002044 def test_replace(self):
2045 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002046 :py:obj:`PKCS12.set_certificate` replaces the certificate in a PKCS12 cluster.
2047 :py:obj:`PKCS12.set_privatekey` replaces the private key.
2048 :py:obj:`PKCS12.set_ca_certificates` replaces the CA certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05002049 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002050 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
2051 p12.set_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2052 p12.set_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002053 root_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05002054 client_cert = load_certificate(FILETYPE_PEM, client_cert_pem)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002055 p12.set_ca_certificates([root_cert]) # not a tuple
Rick Dean623ee362009-07-17 12:22:16 -05002056 self.assertEqual(1, len(p12.get_ca_certificates()))
2057 self.assertEqual(root_cert, p12.get_ca_certificates()[0])
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002058 p12.set_ca_certificates([client_cert, root_cert])
Rick Deanf94096c2009-07-18 14:23:06 -05002059 self.assertEqual(2, len(p12.get_ca_certificates()))
2060 self.assertEqual(client_cert, p12.get_ca_certificates()[0])
2061 self.assertEqual(root_cert, p12.get_ca_certificates()[1])
2062
2063
2064 def test_friendly_name(self):
2065 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002066 The *friendlyName* of a PKCS12 can be set and retrieved via
Jonathan Ballet648875f2011-07-16 14:14:58 +09002067 :py:obj:`PKCS12.get_friendlyname` and :py:obj:`PKCS12_set_friendlyname`, and a
2068 :py:obj:`PKCS12` with a friendly name set can be dumped with :py:obj:`PKCS12.export`.
Rick Deanf94096c2009-07-18 14:23:06 -05002069 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002070 passwd = b'Dogmeat[]{}!@#$%^&*()~`?/.,<>-_+=";:'
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002071 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -04002072 for friendly_name in [b('Serverlicious'), None, b('###')]:
Rick Dean42d69e12009-07-20 11:36:08 -05002073 p12.set_friendlyname(friendly_name)
2074 self.assertEqual(p12.get_friendlyname(), friendly_name)
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002075 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
Rick Dean42d69e12009-07-20 11:36:08 -05002076 reloaded_p12 = load_pkcs12(dumped_p12, passwd)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002077 self.assertEqual(
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -04002078 p12.get_friendlyname(), reloaded_p12.get_friendlyname())
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002079 # We would use the openssl program to confirm the friendly
2080 # name, but it is not possible. The pkcs12 command
2081 # does not store the friendly name in the cert's
Rick Dean42d69e12009-07-20 11:36:08 -05002082 # alias, which we could then extract.
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002083 self.check_recovery(
2084 dumped_p12, key=server_key_pem, cert=server_cert_pem,
2085 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05002086
2087
2088 def test_various_empty_passphrases(self):
2089 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002090 Test that missing, None, and '' passphrases are identical for PKCS12
2091 export.
Rick Deanf94096c2009-07-18 14:23:06 -05002092 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002093 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002094 passwd = b""
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002095 dumped_p12_empty = p12.export(iter=2, maciter=0, passphrase=passwd)
2096 dumped_p12_none = p12.export(iter=3, maciter=2, passphrase=None)
2097 dumped_p12_nopw = p12.export(iter=9, maciter=4)
2098 for dumped_p12 in [dumped_p12_empty, dumped_p12_none, dumped_p12_nopw]:
2099 self.check_recovery(
2100 dumped_p12, key=client_key_pem, cert=client_cert_pem,
2101 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05002102
2103
2104 def test_removing_ca_cert(self):
2105 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002106 Passing :py:obj:`None` to :py:obj:`PKCS12.set_ca_certificates` removes all CA
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002107 certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05002108 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002109 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
2110 p12.set_ca_certificates(None)
Rick Dean623ee362009-07-17 12:22:16 -05002111 self.assertEqual(None, p12.get_ca_certificates())
Rick Deanf94096c2009-07-18 14:23:06 -05002112
2113
2114 def test_export_without_mac(self):
2115 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002116 Exporting a PKCS12 with a :py:obj:`maciter` of ``-1`` excludes the MAC
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002117 entirely.
Rick Deanf94096c2009-07-18 14:23:06 -05002118 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002119 passwd = b"Lake Michigan"
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002120 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Dean623ee362009-07-17 12:22:16 -05002121 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002122 self.check_recovery(
2123 dumped_p12, key=server_key_pem, cert=server_cert_pem,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002124 passwd=passwd, extra=(b"-nomacver",))
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002125
2126
2127 def test_load_without_mac(self):
2128 """
2129 Loading a PKCS12 without a MAC does something other than crash.
2130 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002131 passwd = b"Lake Michigan"
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002132 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
2133 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Rick Dean321a0512009-08-13 17:21:29 -05002134 try:
2135 recovered_p12 = load_pkcs12(dumped_p12, passwd)
2136 # The person who generated this PCKS12 should be flogged,
2137 # or better yet we should have a means to determine
2138 # whether a PCKS12 had a MAC that was verified.
2139 # Anyway, libopenssl chooses to allow it, so the
2140 # pyopenssl binding does as well.
2141 self.assertTrue(isinstance(recovered_p12, PKCS12))
2142 except Error:
2143 # Failing here with an exception is preferred as some openssl
2144 # versions do.
2145 pass
Rick Dean623ee362009-07-17 12:22:16 -05002146
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002147
Rick Dean25bcc1f2009-07-20 11:53:13 -05002148 def test_zero_len_list_for_ca(self):
2149 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002150 A PKCS12 with an empty CA certificates list can be exported.
Rick Dean25bcc1f2009-07-20 11:53:13 -05002151 """
2152 passwd = 'Hobie 18'
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002153 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002154 # p12.set_ca_certificates([])
2155 # self.assertEqual((), p12.get_ca_certificates())
2156 # dumped_p12 = p12.export(passphrase=passwd, iter=3)
2157 # self.check_recovery(
2158 # dumped_p12, key=server_key_pem, cert=server_cert_pem,
2159 # passwd=passwd)
Rick Dean25bcc1f2009-07-20 11:53:13 -05002160
2161
Rick Deanf94096c2009-07-18 14:23:06 -05002162 def test_export_without_args(self):
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002163 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002164 All the arguments to :py:obj:`PKCS12.export` are optional.
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002165 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002166 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05002167 dumped_p12 = p12.export() # no args
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002168 self.check_recovery(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002169 dumped_p12, key=server_key_pem, cert=server_cert_pem, passwd=b"")
Rick Deanf94096c2009-07-18 14:23:06 -05002170
2171
2172 def test_key_cert_mismatch(self):
2173 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002174 :py:obj:`PKCS12.export` raises an exception when a key and certificate
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002175 mismatch.
Rick Deanf94096c2009-07-18 14:23:06 -05002176 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002177 p12 = self.gen_pkcs12(server_cert_pem, client_key_pem, root_cert_pem)
2178 self.assertRaises(Error, p12.export)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002179
2180
2181
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002182# These quoting functions taken directly from Twisted's twisted.python.win32.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002183_cmdLineQuoteRe = re.compile(br'(\\*)"')
2184_cmdLineQuoteRe2 = re.compile(br'(\\+)\Z')
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002185def cmdLineQuote(s):
2186 """
2187 Internal method for quoting a single command-line argument.
2188
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002189 See http://www.perlmonks.org/?node_id=764004
2190
Jonathan Ballet648875f2011-07-16 14:14:58 +09002191 :type: :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002192 :param s: A single unquoted string to quote for something that is expecting
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002193 cmd.exe-style quoting
2194
Jonathan Ballet648875f2011-07-16 14:14:58 +09002195 :rtype: :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002196 :return: A cmd.exe-style quoted string
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002197 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002198 s = _cmdLineQuoteRe2.sub(br"\1\1", _cmdLineQuoteRe.sub(br'\1\1\\"', s))
2199 return b'"' + s + b'"'
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002200
2201
2202
2203def quoteArguments(arguments):
2204 """
2205 Quote an iterable of command-line arguments for passing to CreateProcess or
Jonathan Ballet648875f2011-07-16 14:14:58 +09002206 a similar API. This allows the list passed to :py:obj:`reactor.spawnProcess` to
2207 match the child process's :py:obj:`sys.argv` properly.
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002208
Jonathan Ballet648875f2011-07-16 14:14:58 +09002209 :type arguments: :py:obj:`iterable` of :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002210 :param arguments: An iterable of unquoted arguments to quote
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002211
Jonathan Ballet648875f2011-07-16 14:14:58 +09002212 :rtype: :py:obj:`str`
2213 :return: A space-delimited string containing quoted versions of :py:obj:`arguments`
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002214 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002215 return b' '.join(map(cmdLineQuote, arguments))
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002216
2217
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002218
Rick Dean4c9ad612009-07-17 15:05:22 -05002219def _runopenssl(pem, *args):
2220 """
2221 Run the command line openssl tool with the given arguments and write
Rick Dean55d1ce62009-08-13 17:40:24 -05002222 the given PEM to its stdin. Not safe for quotes.
Rick Dean4c9ad612009-07-17 15:05:22 -05002223 """
Jean-Paul Calderone038de952009-08-21 12:16:06 -04002224 if os.name == 'posix':
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002225 command = b"openssl " + b" ".join([
2226 (b"'" + arg.replace(b"'", b"'\\''") + b"'")
2227 for arg in args])
Rick Dean55d1ce62009-08-13 17:40:24 -05002228 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002229 command = b"openssl " + quoteArguments(args)
2230 proc = Popen(native(command), shell=True, stdin=PIPE, stdout=PIPE)
Jean-Paul Calderone62ca8da2010-08-11 19:58:08 -04002231 proc.stdin.write(pem)
2232 proc.stdin.close()
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002233 output = proc.stdout.read()
2234 proc.stdout.close()
2235 proc.wait()
2236 return output
Rick Dean4c9ad612009-07-17 15:05:22 -05002237
2238
2239
Jean-Paul Calderone18808652009-07-05 12:54:05 -04002240class FunctionTests(TestCase):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002241 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002242 Tests for free-functions in the :py:obj:`OpenSSL.crypto` module.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002243 """
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002244
2245 def test_load_privatekey_invalid_format(self):
2246 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002247 :py:obj:`load_privatekey` raises :py:obj:`ValueError` if passed an unknown filetype.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002248 """
2249 self.assertRaises(ValueError, load_privatekey, 100, root_key_pem)
2250
2251
2252 def test_load_privatekey_invalid_passphrase_type(self):
2253 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002254 :py:obj:`load_privatekey` raises :py:obj:`TypeError` if passed a passphrase that is
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002255 neither a :py:obj:`str` nor a callable.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002256 """
2257 self.assertRaises(
2258 TypeError,
2259 load_privatekey,
2260 FILETYPE_PEM, encryptedPrivateKeyPEMPassphrase, object())
2261
2262
2263 def test_load_privatekey_wrong_args(self):
2264 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002265 :py:obj:`load_privatekey` raises :py:obj:`TypeError` if called with the wrong number
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002266 of arguments.
2267 """
2268 self.assertRaises(TypeError, load_privatekey)
2269
2270
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002271 def test_load_privatekey_wrongPassphrase(self):
2272 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002273 :py:obj:`load_privatekey` raises :py:obj:`OpenSSL.crypto.Error` when it is passed an
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002274 encrypted PEM and an incorrect passphrase.
2275 """
2276 self.assertRaises(
2277 Error,
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002278 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, b("quack"))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002279
2280
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002281 def test_load_privatekey_passphraseWrongType(self):
2282 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002283 :py:obj:`load_privatekey` raises :py:obj:`ValueError` when it is passed a passphrase
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002284 with a private key encoded in a format, that doesn't support
2285 encryption.
2286 """
2287 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2288 blob = dump_privatekey(FILETYPE_ASN1, key)
2289 self.assertRaises(ValueError,
2290 load_privatekey, FILETYPE_ASN1, blob, "secret")
2291
2292
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002293 def test_load_privatekey_passphrase(self):
2294 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002295 :py:obj:`load_privatekey` can create a :py:obj:`PKey` object from an encrypted PEM
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002296 string if given the passphrase.
2297 """
2298 key = load_privatekey(
2299 FILETYPE_PEM, encryptedPrivateKeyPEM,
2300 encryptedPrivateKeyPEMPassphrase)
2301 self.assertTrue(isinstance(key, PKeyType))
2302
2303
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002304 def test_load_privatekey_passphrase_exception(self):
2305 """
2306 If the passphrase callback raises an exception, that exception is raised
2307 by :py:obj:`load_privatekey`.
2308 """
2309 def cb(ignored):
2310 raise ArithmeticError
2311
2312 self.assertRaises(ArithmeticError,
2313 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2314
2315
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002316 def test_load_privatekey_wrongPassphraseCallback(self):
2317 """
Jean-Paul Calderoned440a082011-09-14 11:02:05 -04002318 :py:obj:`load_privatekey` raises :py:obj:`OpenSSL.crypto.Error` when it
2319 is passed an encrypted PEM and a passphrase callback which returns an
2320 incorrect passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002321 """
2322 called = []
2323 def cb(*a):
2324 called.append(None)
Jean-Paul Calderoned440a082011-09-14 11:02:05 -04002325 return b("quack")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002326 self.assertRaises(
2327 Error,
2328 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2329 self.assertTrue(called)
2330
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002331
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002332 def test_load_privatekey_passphraseCallback(self):
2333 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002334 :py:obj:`load_privatekey` can create a :py:obj:`PKey` object from an encrypted PEM
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002335 string if given a passphrase callback which returns the correct
2336 password.
2337 """
2338 called = []
2339 def cb(writing):
2340 called.append(writing)
2341 return encryptedPrivateKeyPEMPassphrase
2342 key = load_privatekey(FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2343 self.assertTrue(isinstance(key, PKeyType))
2344 self.assertEqual(called, [False])
2345
2346
Jean-Paul Calderone105cb952011-09-14 10:16:46 -04002347 def test_load_privatekey_passphrase_wrong_return_type(self):
2348 """
2349 :py:obj:`load_privatekey` raises :py:obj:`ValueError` if the passphrase
2350 callback returns something other than a byte string.
2351 """
2352 self.assertRaises(
2353 ValueError,
2354 load_privatekey,
2355 FILETYPE_PEM, encryptedPrivateKeyPEM, lambda *args: 3)
2356
2357
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002358 def test_dump_privatekey_wrong_args(self):
2359 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002360 :py:obj:`dump_privatekey` raises :py:obj:`TypeError` if called with the wrong number
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002361 of arguments.
2362 """
2363 self.assertRaises(TypeError, dump_privatekey)
Jean-Paul Calderone1eeccd82011-09-14 10:18:52 -04002364 # If cipher name is given, password is required.
2365 self.assertRaises(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002366 TypeError, dump_privatekey, FILETYPE_PEM, PKey(), GOOD_CIPHER)
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002367
2368
2369 def test_dump_privatekey_unknown_cipher(self):
2370 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002371 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` if called with an unrecognized
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002372 cipher name.
2373 """
2374 key = PKey()
2375 key.generate_key(TYPE_RSA, 512)
2376 self.assertRaises(
2377 ValueError, dump_privatekey,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002378 FILETYPE_PEM, key, BAD_CIPHER, "passphrase")
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002379
2380
2381 def test_dump_privatekey_invalid_passphrase_type(self):
2382 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002383 :py:obj:`dump_privatekey` raises :py:obj:`TypeError` if called with a passphrase which
2384 is neither a :py:obj:`str` nor a callable.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002385 """
2386 key = PKey()
2387 key.generate_key(TYPE_RSA, 512)
2388 self.assertRaises(
2389 TypeError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002390 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, object())
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002391
2392
2393 def test_dump_privatekey_invalid_filetype(self):
2394 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002395 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` if called with an unrecognized
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002396 filetype.
2397 """
2398 key = PKey()
2399 key.generate_key(TYPE_RSA, 512)
2400 self.assertRaises(ValueError, dump_privatekey, 100, key)
2401
2402
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002403 def test_load_privatekey_passphraseCallbackLength(self):
2404 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002405 :py:obj:`crypto.load_privatekey` should raise an error when the passphrase
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002406 provided by the callback is too long, not silently truncate it.
2407 """
2408 def cb(ignored):
2409 return "a" * 1025
2410
2411 self.assertRaises(ValueError,
2412 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2413
2414
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002415 def test_dump_privatekey_passphrase(self):
2416 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002417 :py:obj:`dump_privatekey` writes an encrypted PEM when given a passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002418 """
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002419 passphrase = b("foo")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002420 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002421 pem = dump_privatekey(FILETYPE_PEM, key, GOOD_CIPHER, passphrase)
2422 self.assertTrue(isinstance(pem, binary_type))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002423 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
2424 self.assertTrue(isinstance(loadedKey, PKeyType))
2425 self.assertEqual(loadedKey.type(), key.type())
2426 self.assertEqual(loadedKey.bits(), key.bits())
2427
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002428
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002429 def test_dump_privatekey_passphraseWrongType(self):
2430 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002431 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` when it is passed a passphrase
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002432 with a private key encoded in a format, that doesn't support
2433 encryption.
2434 """
2435 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2436 self.assertRaises(ValueError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002437 dump_privatekey, FILETYPE_ASN1, key, GOOD_CIPHER, "secret")
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002438
2439
Rick Dean5b7b6372009-04-01 11:34:06 -05002440 def test_dump_certificate(self):
2441 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002442 :py:obj:`dump_certificate` writes PEM, DER, and text.
Rick Dean5b7b6372009-04-01 11:34:06 -05002443 """
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002444 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
Rick Dean5b7b6372009-04-01 11:34:06 -05002445 cert = load_certificate(FILETYPE_PEM, pemData)
2446 dumped_pem = dump_certificate(FILETYPE_PEM, cert)
2447 self.assertEqual(dumped_pem, cleartextCertificatePEM)
2448 dumped_der = dump_certificate(FILETYPE_ASN1, cert)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002449 good_der = _runopenssl(dumped_pem, b"x509", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002450 self.assertEqual(dumped_der, good_der)
2451 cert2 = load_certificate(FILETYPE_ASN1, dumped_der)
2452 dumped_pem2 = dump_certificate(FILETYPE_PEM, cert2)
2453 self.assertEqual(dumped_pem2, cleartextCertificatePEM)
2454 dumped_text = dump_certificate(FILETYPE_TEXT, cert)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002455 good_text = _runopenssl(dumped_pem, b"x509", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002456 self.assertEqual(dumped_text, good_text)
2457
2458
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002459 def test_dump_privatekey_pem(self):
Rick Dean5b7b6372009-04-01 11:34:06 -05002460 """
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002461 :py:obj:`dump_privatekey` writes a PEM
Rick Dean5b7b6372009-04-01 11:34:06 -05002462 """
2463 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -04002464 self.assertTrue(key.check())
Rick Dean5b7b6372009-04-01 11:34:06 -05002465 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2466 self.assertEqual(dumped_pem, cleartextPrivateKeyPEM)
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002467
2468
2469 def test_dump_privatekey_asn1(self):
2470 """
2471 :py:obj:`dump_privatekey` writes a DER
2472 """
2473 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2474 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2475
Rick Dean5b7b6372009-04-01 11:34:06 -05002476 dumped_der = dump_privatekey(FILETYPE_ASN1, key)
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002477 # XXX This OpenSSL call writes "writing RSA key" to standard out. Sad.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002478 good_der = _runopenssl(dumped_pem, b"rsa", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002479 self.assertEqual(dumped_der, good_der)
2480 key2 = load_privatekey(FILETYPE_ASN1, dumped_der)
2481 dumped_pem2 = dump_privatekey(FILETYPE_PEM, key2)
2482 self.assertEqual(dumped_pem2, cleartextPrivateKeyPEM)
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002483
2484
2485 def test_dump_privatekey_text(self):
2486 """
2487 :py:obj:`dump_privatekey` writes a text
2488 """
2489 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2490 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2491
Rick Dean5b7b6372009-04-01 11:34:06 -05002492 dumped_text = dump_privatekey(FILETYPE_TEXT, key)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002493 good_text = _runopenssl(dumped_pem, b"rsa", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002494 self.assertEqual(dumped_text, good_text)
2495
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002496
Rick Dean5b7b6372009-04-01 11:34:06 -05002497 def test_dump_certificate_request(self):
2498 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002499 :py:obj:`dump_certificate_request` writes a PEM, DER, and text.
Rick Dean5b7b6372009-04-01 11:34:06 -05002500 """
2501 req = load_certificate_request(FILETYPE_PEM, cleartextCertificateRequestPEM)
2502 dumped_pem = dump_certificate_request(FILETYPE_PEM, req)
2503 self.assertEqual(dumped_pem, cleartextCertificateRequestPEM)
2504 dumped_der = dump_certificate_request(FILETYPE_ASN1, req)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002505 good_der = _runopenssl(dumped_pem, b"req", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002506 self.assertEqual(dumped_der, good_der)
2507 req2 = load_certificate_request(FILETYPE_ASN1, dumped_der)
2508 dumped_pem2 = dump_certificate_request(FILETYPE_PEM, req2)
2509 self.assertEqual(dumped_pem2, cleartextCertificateRequestPEM)
2510 dumped_text = dump_certificate_request(FILETYPE_TEXT, req)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002511 good_text = _runopenssl(dumped_pem, b"req", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002512 self.assertEqual(dumped_text, good_text)
Jean-Paul Calderoneaf43cdf2010-08-03 18:40:52 -04002513 self.assertRaises(ValueError, dump_certificate_request, 100, req)
Rick Dean5b7b6372009-04-01 11:34:06 -05002514
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002515
2516 def test_dump_privatekey_passphraseCallback(self):
2517 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002518 :py:obj:`dump_privatekey` writes an encrypted PEM when given a callback which
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002519 returns the correct passphrase.
2520 """
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002521 passphrase = b("foo")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002522 called = []
2523 def cb(writing):
2524 called.append(writing)
2525 return passphrase
2526 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002527 pem = dump_privatekey(FILETYPE_PEM, key, GOOD_CIPHER, cb)
2528 self.assertTrue(isinstance(pem, binary_type))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002529 self.assertEqual(called, [True])
2530 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
2531 self.assertTrue(isinstance(loadedKey, PKeyType))
2532 self.assertEqual(loadedKey.type(), key.type())
2533 self.assertEqual(loadedKey.bits(), key.bits())
Rick Dean5b7b6372009-04-01 11:34:06 -05002534
2535
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002536 def test_dump_privatekey_passphrase_exception(self):
2537 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002538 :py:obj:`dump_privatekey` should not overwrite the exception raised
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002539 by the passphrase callback.
2540 """
2541 def cb(ignored):
2542 raise ArithmeticError
2543
2544 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2545 self.assertRaises(ArithmeticError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002546 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, cb)
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002547
2548
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002549 def test_dump_privatekey_passphraseCallbackLength(self):
2550 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002551 :py:obj:`crypto.dump_privatekey` should raise an error when the passphrase
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002552 provided by the callback is too long, not silently truncate it.
2553 """
2554 def cb(ignored):
2555 return "a" * 1025
2556
2557 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2558 self.assertRaises(ValueError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002559 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, cb)
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002560
2561
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002562 def test_load_pkcs7_data(self):
2563 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002564 :py:obj:`load_pkcs7_data` accepts a PKCS#7 string and returns an instance of
2565 :py:obj:`PKCS7Type`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002566 """
2567 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2568 self.assertTrue(isinstance(pkcs7, PKCS7Type))
2569
2570
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002571 def test_load_pkcs7_data_invalid(self):
2572 """
2573 If the data passed to :py:obj:`load_pkcs7_data` is invalid,
2574 :py:obj:`Error` is raised.
2575 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002576 self.assertRaises(Error, load_pkcs7_data, FILETYPE_PEM, b"foo")
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002577
2578
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002579
Jean-Paul Calderone4a68b402013-12-29 16:54:58 -05002580class LoadCertificateTests(TestCase):
2581 """
2582 Tests for :py:obj:`load_certificate_request`.
2583 """
2584 def test_badFileType(self):
2585 """
2586 If the file type passed to :py:obj:`load_certificate_request` is
2587 neither :py:obj:`FILETYPE_PEM` nor :py:obj:`FILETYPE_ASN1` then
2588 :py:class:`ValueError` is raised.
2589 """
2590 self.assertRaises(ValueError, load_certificate_request, object(), b"")
2591
2592
2593
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002594class PKCS7Tests(TestCase):
2595 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002596 Tests for :py:obj:`PKCS7Type`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002597 """
2598 def test_type(self):
2599 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002600 :py:obj:`PKCS7Type` is a type object.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002601 """
2602 self.assertTrue(isinstance(PKCS7Type, type))
2603 self.assertEqual(PKCS7Type.__name__, 'PKCS7')
2604
2605 # XXX This doesn't currently work.
2606 # self.assertIdentical(PKCS7, PKCS7Type)
2607
2608
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002609 # XXX Opposite results for all these following methods
2610
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002611 def test_type_is_signed_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002612 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002613 :py:obj:`PKCS7Type.type_is_signed` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002614 arguments.
2615 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002616 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2617 self.assertRaises(TypeError, pkcs7.type_is_signed, None)
2618
2619
2620 def test_type_is_signed(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002621 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002622 :py:obj:`PKCS7Type.type_is_signed` returns :py:obj:`True` if the PKCS7 object is of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002623 the type *signed*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002624 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002625 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2626 self.assertTrue(pkcs7.type_is_signed())
2627
2628
2629 def test_type_is_enveloped_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002630 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002631 :py:obj:`PKCS7Type.type_is_enveloped` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002632 arguments.
2633 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002634 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2635 self.assertRaises(TypeError, pkcs7.type_is_enveloped, None)
2636
2637
2638 def test_type_is_enveloped(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002639 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002640 :py:obj:`PKCS7Type.type_is_enveloped` returns :py:obj:`False` if the PKCS7 object is
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002641 not of the type *enveloped*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002642 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002643 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2644 self.assertFalse(pkcs7.type_is_enveloped())
2645
2646
2647 def test_type_is_signedAndEnveloped_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002648 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002649 :py:obj:`PKCS7Type.type_is_signedAndEnveloped` raises :py:obj:`TypeError` if called
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002650 with any arguments.
2651 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002652 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2653 self.assertRaises(TypeError, pkcs7.type_is_signedAndEnveloped, None)
2654
2655
2656 def test_type_is_signedAndEnveloped(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002657 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002658 :py:obj:`PKCS7Type.type_is_signedAndEnveloped` returns :py:obj:`False` if the PKCS7
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002659 object is not of the type *signed and enveloped*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002660 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002661 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2662 self.assertFalse(pkcs7.type_is_signedAndEnveloped())
2663
2664
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002665 def test_type_is_data(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002666 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002667 :py:obj:`PKCS7Type.type_is_data` returns :py:obj:`False` if the PKCS7 object is not of
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002668 the type data.
2669 """
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002670 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2671 self.assertFalse(pkcs7.type_is_data())
2672
2673
2674 def test_type_is_data_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002675 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002676 :py:obj:`PKCS7Type.type_is_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002677 arguments.
2678 """
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002679 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2680 self.assertRaises(TypeError, pkcs7.type_is_data, None)
2681
2682
Jean-Paul Calderone97b28ca2010-07-30 10:56:07 -04002683 def test_get_type_name_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002684 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002685 :py:obj:`PKCS7Type.get_type_name` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002686 arguments.
2687 """
Jean-Paul Calderone97b28ca2010-07-30 10:56:07 -04002688 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2689 self.assertRaises(TypeError, pkcs7.get_type_name, None)
2690
2691
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002692 def test_get_type_name(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002693 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002694 :py:obj:`PKCS7Type.get_type_name` returns a :py:obj:`str` giving the type name.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002695 """
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002696 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
Jean-Paul Calderone07640f12010-08-22 17:14:43 -04002697 self.assertEquals(pkcs7.get_type_name(), b('pkcs7-signedData'))
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002698
2699
2700 def test_attribute(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002701 """
2702 If an attribute other than one of the methods tested here is accessed on
Jonathan Ballet648875f2011-07-16 14:14:58 +09002703 an instance of :py:obj:`PKCS7Type`, :py:obj:`AttributeError` is raised.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002704 """
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002705 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2706 self.assertRaises(AttributeError, getattr, pkcs7, "foo")
2707
2708
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002709
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002710class NetscapeSPKITests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002711 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002712 Tests for :py:obj:`OpenSSL.crypto.NetscapeSPKI`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002713 """
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002714 def signable(self):
2715 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002716 Return a new :py:obj:`NetscapeSPKI` for use with signing tests.
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002717 """
2718 return NetscapeSPKI()
2719
2720
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002721 def test_type(self):
2722 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002723 :py:obj:`NetscapeSPKI` and :py:obj:`NetscapeSPKIType` refer to the same type object
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002724 and can be used to create instances of that type.
2725 """
2726 self.assertIdentical(NetscapeSPKI, NetscapeSPKIType)
2727 self.assertConsistentType(NetscapeSPKI, 'NetscapeSPKI')
2728
2729
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002730 def test_construction(self):
2731 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002732 :py:obj:`NetscapeSPKI` returns an instance of :py:obj:`NetscapeSPKIType`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002733 """
2734 nspki = NetscapeSPKI()
2735 self.assertTrue(isinstance(nspki, NetscapeSPKIType))
2736
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002737
Jean-Paul Calderone969efaa2010-08-03 18:19:19 -04002738 def test_invalid_attribute(self):
2739 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002740 Accessing a non-existent attribute of a :py:obj:`NetscapeSPKI` instance causes
2741 an :py:obj:`AttributeError` to be raised.
Jean-Paul Calderone969efaa2010-08-03 18:19:19 -04002742 """
2743 nspki = NetscapeSPKI()
2744 self.assertRaises(AttributeError, lambda: nspki.foo)
2745
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002746
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002747 def test_b64_encode(self):
2748 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002749 :py:obj:`NetscapeSPKI.b64_encode` encodes the certificate to a base64 blob.
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002750 """
2751 nspki = NetscapeSPKI()
2752 blob = nspki.b64_encode()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002753 self.assertTrue(isinstance(blob, binary_type))
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002754
2755
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002756
Rick Dean536ba022009-07-24 23:57:27 -05002757class RevokedTests(TestCase):
2758 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002759 Tests for :py:obj:`OpenSSL.crypto.Revoked`
Rick Dean536ba022009-07-24 23:57:27 -05002760 """
2761 def test_construction(self):
2762 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002763 Confirm we can create :py:obj:`OpenSSL.crypto.Revoked`. Check
Rick Dean536ba022009-07-24 23:57:27 -05002764 that it is empty.
2765 """
2766 revoked = Revoked()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002767 self.assertTrue(isinstance(revoked, Revoked))
2768 self.assertEquals(type(revoked), Revoked)
2769 self.assertEquals(revoked.get_serial(), b('00'))
2770 self.assertEquals(revoked.get_rev_date(), None)
2771 self.assertEquals(revoked.get_reason(), None)
Rick Dean536ba022009-07-24 23:57:27 -05002772
2773
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002774 def test_construction_wrong_args(self):
2775 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002776 Calling :py:obj:`OpenSSL.crypto.Revoked` with any arguments results
2777 in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002778 """
2779 self.assertRaises(TypeError, Revoked, None)
2780 self.assertRaises(TypeError, Revoked, 1)
2781 self.assertRaises(TypeError, Revoked, "foo")
2782
2783
Rick Dean536ba022009-07-24 23:57:27 -05002784 def test_serial(self):
2785 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002786 Confirm we can set and get serial numbers from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002787 :py:obj:`OpenSSL.crypto.Revoked`. Confirm errors are handled
Rick Dean536ba022009-07-24 23:57:27 -05002788 with grace.
2789 """
2790 revoked = Revoked()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002791 ret = revoked.set_serial(b('10b'))
2792 self.assertEquals(ret, None)
Rick Dean536ba022009-07-24 23:57:27 -05002793 ser = revoked.get_serial()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002794 self.assertEquals(ser, b('010B'))
Rick Dean536ba022009-07-24 23:57:27 -05002795
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002796 revoked.set_serial(b('31ppp')) # a type error would be nice
Rick Dean536ba022009-07-24 23:57:27 -05002797 ser = revoked.get_serial()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002798 self.assertEquals(ser, b('31'))
Rick Dean536ba022009-07-24 23:57:27 -05002799
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002800 self.assertRaises(ValueError, revoked.set_serial, b('pqrst'))
Rick Dean536ba022009-07-24 23:57:27 -05002801 self.assertRaises(TypeError, revoked.set_serial, 100)
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002802 self.assertRaises(TypeError, revoked.get_serial, 1)
2803 self.assertRaises(TypeError, revoked.get_serial, None)
2804 self.assertRaises(TypeError, revoked.get_serial, "")
Rick Dean536ba022009-07-24 23:57:27 -05002805
2806
2807 def test_date(self):
2808 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002809 Confirm we can set and get revocation dates from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002810 :py:obj:`OpenSSL.crypto.Revoked`. Confirm errors are handled
Rick Dean536ba022009-07-24 23:57:27 -05002811 with grace.
2812 """
2813 revoked = Revoked()
2814 date = revoked.get_rev_date()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002815 self.assertEquals(date, None)
Rick Dean536ba022009-07-24 23:57:27 -05002816
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002817 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05002818 ret = revoked.set_rev_date(now)
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002819 self.assertEqual(ret, None)
Rick Dean536ba022009-07-24 23:57:27 -05002820 date = revoked.get_rev_date()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002821 self.assertEqual(date, now)
Rick Dean536ba022009-07-24 23:57:27 -05002822
2823
Rick Dean6385faf2009-07-26 00:07:47 -05002824 def test_reason(self):
2825 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002826 Confirm we can set and get revocation reasons from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002827 :py:obj:`OpenSSL.crypto.Revoked`. The "get" need to work
Rick Dean6385faf2009-07-26 00:07:47 -05002828 as "set". Likewise, each reason of all_reasons() must work.
2829 """
2830 revoked = Revoked()
2831 for r in revoked.all_reasons():
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002832 for x in range(2):
Rick Dean6385faf2009-07-26 00:07:47 -05002833 ret = revoked.set_reason(r)
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002834 self.assertEquals(ret, None)
Rick Dean6385faf2009-07-26 00:07:47 -05002835 reason = revoked.get_reason()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002836 self.assertEquals(
2837 reason.lower().replace(b(' '), b('')),
2838 r.lower().replace(b(' '), b('')))
Rick Dean6385faf2009-07-26 00:07:47 -05002839 r = reason # again with the resp of get
2840
2841 revoked.set_reason(None)
2842 self.assertEqual(revoked.get_reason(), None)
2843
2844
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002845 def test_set_reason_wrong_arguments(self):
Rick Dean6385faf2009-07-26 00:07:47 -05002846 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002847 Calling :py:obj:`OpenSSL.crypto.Revoked.set_reason` with other than
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002848 one argument, or an argument which isn't a valid reason,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002849 results in :py:obj:`TypeError` or :py:obj:`ValueError` being raised.
Rick Dean6385faf2009-07-26 00:07:47 -05002850 """
2851 revoked = Revoked()
2852 self.assertRaises(TypeError, revoked.set_reason, 100)
Jean-Paul Calderone281b62b2010-08-28 14:22:29 -04002853 self.assertRaises(ValueError, revoked.set_reason, b('blue'))
Rick Dean6385faf2009-07-26 00:07:47 -05002854
Rick Dean536ba022009-07-24 23:57:27 -05002855
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002856 def test_get_reason_wrong_arguments(self):
2857 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002858 Calling :py:obj:`OpenSSL.crypto.Revoked.get_reason` with any
2859 arguments results in :py:obj:`TypeError` being raised.
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002860 """
2861 revoked = Revoked()
2862 self.assertRaises(TypeError, revoked.get_reason, None)
2863 self.assertRaises(TypeError, revoked.get_reason, 1)
2864 self.assertRaises(TypeError, revoked.get_reason, "foo")
2865
2866
2867
Rick Dean536ba022009-07-24 23:57:27 -05002868class CRLTests(TestCase):
2869 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002870 Tests for :py:obj:`OpenSSL.crypto.CRL`
Rick Dean536ba022009-07-24 23:57:27 -05002871 """
2872 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
2873 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2874
2875 def test_construction(self):
2876 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002877 Confirm we can create :py:obj:`OpenSSL.crypto.CRL`. Check
Rick Dean536ba022009-07-24 23:57:27 -05002878 that it is empty
2879 """
2880 crl = CRL()
2881 self.assertTrue( isinstance(crl, CRL) )
2882 self.assertEqual(crl.get_revoked(), None)
2883
2884
Jean-Paul Calderone2efd03e2010-01-30 13:59:55 -05002885 def test_construction_wrong_args(self):
2886 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002887 Calling :py:obj:`OpenSSL.crypto.CRL` with any number of arguments
2888 results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone2efd03e2010-01-30 13:59:55 -05002889 """
2890 self.assertRaises(TypeError, CRL, 1)
2891 self.assertRaises(TypeError, CRL, "")
2892 self.assertRaises(TypeError, CRL, None)
2893
2894
Rick Dean536ba022009-07-24 23:57:27 -05002895 def test_export(self):
2896 """
2897 Use python to create a simple CRL with a revocation, and export
2898 the CRL in formats of PEM, DER and text. Those outputs are verified
2899 with the openssl program.
2900 """
2901 crl = CRL()
2902 revoked = Revoked()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002903 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05002904 revoked.set_rev_date(now)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002905 revoked.set_serial(b('3ab'))
2906 revoked.set_reason(b('sUpErSeDEd'))
Rick Dean536ba022009-07-24 23:57:27 -05002907 crl.add_revoked(revoked)
2908
2909 # PEM format
2910 dumped_crl = crl.export(self.cert, self.pkey, days=20)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002911 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002912 text.index(b('Serial Number: 03AB'))
2913 text.index(b('Superseded'))
2914 text.index(b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA'))
Rick Dean536ba022009-07-24 23:57:27 -05002915
2916 # DER format
2917 dumped_crl = crl.export(self.cert, self.pkey, FILETYPE_ASN1)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002918 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text", b"-inform", b"DER")
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002919 text.index(b('Serial Number: 03AB'))
2920 text.index(b('Superseded'))
2921 text.index(b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA'))
Rick Dean536ba022009-07-24 23:57:27 -05002922
2923 # text format
2924 dumped_text = crl.export(self.cert, self.pkey, type=FILETYPE_TEXT)
2925 self.assertEqual(text, dumped_text)
2926
2927
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -04002928 def test_export_invalid(self):
2929 """
2930 If :py:obj:`CRL.export` is used with an uninitialized :py:obj:`X509`
Jean-Paul Calderoneb5871072012-03-09 14:58:00 -08002931 instance, :py:obj:`OpenSSL.crypto.Error` is raised.
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -04002932 """
2933 crl = CRL()
2934 self.assertRaises(Error, crl.export, X509(), PKey())
2935
2936
Jean-Paul Calderone56515342010-01-30 13:49:38 -05002937 def test_add_revoked_keyword(self):
2938 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002939 :py:obj:`OpenSSL.CRL.add_revoked` accepts its single argument as the
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002940 ``revoked`` keyword argument.
Jean-Paul Calderone56515342010-01-30 13:49:38 -05002941 """
2942 crl = CRL()
2943 revoked = Revoked()
2944 crl.add_revoked(revoked=revoked)
2945 self.assertTrue(isinstance(crl.get_revoked()[0], Revoked))
2946
Rick Dean6385faf2009-07-26 00:07:47 -05002947
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05002948 def test_export_wrong_args(self):
2949 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002950 Calling :py:obj:`OpenSSL.CRL.export` with fewer than two or more than
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05002951 four arguments, or with arguments other than the certificate,
2952 private key, integer file type, and integer number of days it
Jonathan Ballet648875f2011-07-16 14:14:58 +09002953 expects, results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05002954 """
2955 crl = CRL()
2956 self.assertRaises(TypeError, crl.export)
2957 self.assertRaises(TypeError, crl.export, self.cert)
2958 self.assertRaises(TypeError, crl.export, self.cert, self.pkey, FILETYPE_PEM, 10, "foo")
2959
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05002960 self.assertRaises(TypeError, crl.export, None, self.pkey, FILETYPE_PEM, 10)
2961 self.assertRaises(TypeError, crl.export, self.cert, None, FILETYPE_PEM, 10)
2962 self.assertRaises(TypeError, crl.export, self.cert, self.pkey, None, 10)
2963 self.assertRaises(TypeError, crl.export, self.cert, FILETYPE_PEM, None)
2964
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05002965
Jean-Paul Calderoneea198422010-01-30 13:58:23 -05002966 def test_export_unknown_filetype(self):
2967 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002968 Calling :py:obj:`OpenSSL.CRL.export` with a file type other than
2969 :py:obj:`FILETYPE_PEM`, :py:obj:`FILETYPE_ASN1`, or :py:obj:`FILETYPE_TEXT` results
2970 in a :py:obj:`ValueError` being raised.
Jean-Paul Calderoneea198422010-01-30 13:58:23 -05002971 """
2972 crl = CRL()
2973 self.assertRaises(ValueError, crl.export, self.cert, self.pkey, 100, 10)
2974
2975
Rick Dean536ba022009-07-24 23:57:27 -05002976 def test_get_revoked(self):
2977 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002978 Use python to create a simple CRL with two revocations.
Jonathan Ballet648875f2011-07-16 14:14:58 +09002979 Get back the :py:obj:`Revoked` using :py:obj:`OpenSSL.CRL.get_revoked` and
Rick Dean536ba022009-07-24 23:57:27 -05002980 verify them.
2981 """
2982 crl = CRL()
2983
2984 revoked = Revoked()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002985 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05002986 revoked.set_rev_date(now)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002987 revoked.set_serial(b('3ab'))
Rick Dean536ba022009-07-24 23:57:27 -05002988 crl.add_revoked(revoked)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002989 revoked.set_serial(b('100'))
2990 revoked.set_reason(b('sUpErSeDEd'))
Rick Dean536ba022009-07-24 23:57:27 -05002991 crl.add_revoked(revoked)
2992
2993 revs = crl.get_revoked()
2994 self.assertEqual(len(revs), 2)
2995 self.assertEqual(type(revs[0]), Revoked)
2996 self.assertEqual(type(revs[1]), Revoked)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002997 self.assertEqual(revs[0].get_serial(), b('03AB'))
2998 self.assertEqual(revs[1].get_serial(), b('0100'))
Rick Dean536ba022009-07-24 23:57:27 -05002999 self.assertEqual(revs[0].get_rev_date(), now)
3000 self.assertEqual(revs[1].get_rev_date(), now)
3001
3002
Jean-Paul Calderone46bdce42010-01-30 13:44:16 -05003003 def test_get_revoked_wrong_args(self):
3004 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003005 Calling :py:obj:`OpenSSL.CRL.get_revoked` with any arguments results
3006 in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone46bdce42010-01-30 13:44:16 -05003007 """
3008 crl = CRL()
3009 self.assertRaises(TypeError, crl.get_revoked, None)
3010 self.assertRaises(TypeError, crl.get_revoked, 1)
3011 self.assertRaises(TypeError, crl.get_revoked, "")
3012 self.assertRaises(TypeError, crl.get_revoked, "", 1, None)
3013
3014
Jean-Paul Calderoneecef6fa2010-01-30 13:47:18 -05003015 def test_add_revoked_wrong_args(self):
3016 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003017 Calling :py:obj:`OpenSSL.CRL.add_revoked` with other than one
3018 argument results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderoneecef6fa2010-01-30 13:47:18 -05003019 """
3020 crl = CRL()
3021 self.assertRaises(TypeError, crl.add_revoked)
3022 self.assertRaises(TypeError, crl.add_revoked, 1, 2)
3023 self.assertRaises(TypeError, crl.add_revoked, "foo", "bar")
3024
3025
Rick Dean536ba022009-07-24 23:57:27 -05003026 def test_load_crl(self):
3027 """
3028 Load a known CRL and inspect its revocations. Both
3029 PEM and DER formats are loaded.
3030 """
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003031 crl = load_crl(FILETYPE_PEM, crlData)
Rick Dean536ba022009-07-24 23:57:27 -05003032 revs = crl.get_revoked()
3033 self.assertEqual(len(revs), 2)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003034 self.assertEqual(revs[0].get_serial(), b('03AB'))
Rick Dean6385faf2009-07-26 00:07:47 -05003035 self.assertEqual(revs[0].get_reason(), None)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003036 self.assertEqual(revs[1].get_serial(), b('0100'))
3037 self.assertEqual(revs[1].get_reason(), b('Superseded'))
Rick Dean536ba022009-07-24 23:57:27 -05003038
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003039 der = _runopenssl(crlData, b"crl", b"-outform", b"DER")
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05003040 crl = load_crl(FILETYPE_ASN1, der)
Rick Dean536ba022009-07-24 23:57:27 -05003041 revs = crl.get_revoked()
3042 self.assertEqual(len(revs), 2)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003043 self.assertEqual(revs[0].get_serial(), b('03AB'))
Rick Dean6385faf2009-07-26 00:07:47 -05003044 self.assertEqual(revs[0].get_reason(), None)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003045 self.assertEqual(revs[1].get_serial(), b('0100'))
3046 self.assertEqual(revs[1].get_reason(), b('Superseded'))
Rick Dean536ba022009-07-24 23:57:27 -05003047
3048
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003049 def test_load_crl_wrong_args(self):
3050 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003051 Calling :py:obj:`OpenSSL.crypto.load_crl` with other than two
3052 arguments results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003053 """
3054 self.assertRaises(TypeError, load_crl)
3055 self.assertRaises(TypeError, load_crl, FILETYPE_PEM)
3056 self.assertRaises(TypeError, load_crl, FILETYPE_PEM, crlData, None)
3057
3058
3059 def test_load_crl_bad_filetype(self):
3060 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003061 Calling :py:obj:`OpenSSL.crypto.load_crl` with an unknown file type
3062 raises a :py:obj:`ValueError`.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003063 """
3064 self.assertRaises(ValueError, load_crl, 100, crlData)
3065
3066
3067 def test_load_crl_bad_data(self):
3068 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003069 Calling :py:obj:`OpenSSL.crypto.load_crl` with file data which can't
3070 be loaded raises a :py:obj:`OpenSSL.crypto.Error`.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003071 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003072 self.assertRaises(Error, load_crl, FILETYPE_PEM, b"hello, world")
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003073
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04003074
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -05003075
James Yonan7c2e5d32010-02-27 05:45:50 -07003076class SignVerifyTests(TestCase):
3077 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003078 Tests for :py:obj:`OpenSSL.crypto.sign` and :py:obj:`OpenSSL.crypto.verify`.
James Yonan7c2e5d32010-02-27 05:45:50 -07003079 """
3080 def test_sign_verify(self):
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04003081 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003082 :py:obj:`sign` generates a cryptographic signature which :py:obj:`verify` can check.
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04003083 """
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003084 content = b(
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04003085 "It was a bright cold day in April, and the clocks were striking "
3086 "thirteen. Winston Smith, his chin nuzzled into his breast in an "
3087 "effort to escape the vile wind, slipped quickly through the "
3088 "glass doors of Victory Mansions, though not quickly enough to "
3089 "prevent a swirl of gritty dust from entering along with him.")
3090
3091 # sign the content with this private key
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04003092 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04003093 # verify the content with this cert
3094 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3095 # certificate unrelated to priv_key, used to trigger an error
3096 bad_cert = load_certificate(FILETYPE_PEM, server_cert_pem)
James Yonan7c2e5d32010-02-27 05:45:50 -07003097
Jean-Paul Calderoned08feb02010-10-12 21:53:24 -04003098 for digest in ['md5', 'sha1']:
James Yonan7c2e5d32010-02-27 05:45:50 -07003099 sig = sign(priv_key, content, digest)
3100
3101 # Verify the signature of content, will throw an exception if error.
3102 verify(good_cert, sig, content, digest)
3103
3104 # This should fail because the certificate doesn't match the
3105 # private key that was used to sign the content.
3106 self.assertRaises(Error, verify, bad_cert, sig, content, digest)
3107
3108 # This should fail because we've "tainted" the content after
3109 # signing it.
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003110 self.assertRaises(
3111 Error, verify,
3112 good_cert, sig, content + b("tainted"), digest)
James Yonan7c2e5d32010-02-27 05:45:50 -07003113
3114 # test that unknown digest types fail
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003115 self.assertRaises(
Jean-Paul Calderone9538f142010-10-13 22:13:40 -04003116 ValueError, sign, priv_key, content, "strange-digest")
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003117 self.assertRaises(
Jean-Paul Calderone9538f142010-10-13 22:13:40 -04003118 ValueError, verify, good_cert, sig, content, "strange-digest")
James Yonan7c2e5d32010-02-27 05:45:50 -07003119
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04003120
Jean-Paul Calderone9828f662010-12-08 22:57:26 -05003121 def test_sign_nulls(self):
3122 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003123 :py:obj:`sign` produces a signature for a string with embedded nulls.
Jean-Paul Calderone9828f662010-12-08 22:57:26 -05003124 """
3125 content = b("Watch out! \0 Did you see it?")
3126 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
3127 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3128 sig = sign(priv_key, content, "sha1")
3129 verify(good_cert, sig, content, "sha1")
3130
3131
Rick Dean5b7b6372009-04-01 11:34:06 -05003132if __name__ == '__main__':
3133 main()