blob: bbe5d050b856d7c2b116ba291215786ce3cb6c2c [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 Calderoneeb86f3a2014-04-19 09:45:57 -040014from six import u, b, binary_type
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050015
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 Calderonec09fd582014-04-18 22:00:10 -040028from OpenSSL.crypto import (
29 sign, verify, get_elliptic_curve, get_elliptic_curves)
Jean-Paul Calderone1be77082014-04-30 18:17:41 -040030from OpenSSL.test.util import EqualityTestsMixin, TestCase
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040031from OpenSSL._util import native, lib
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040032
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -040033def normalize_certificate_pem(pem):
34 return dump_certificate(FILETYPE_PEM, load_certificate(FILETYPE_PEM, pem))
35
36
37def normalize_privatekey_pem(pem):
38 return dump_privatekey(FILETYPE_PEM, load_privatekey(FILETYPE_PEM, pem))
39
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040040
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050041GOOD_CIPHER = "blowfish"
42BAD_CIPHER = "zippers"
43
44GOOD_DIGEST = "MD5"
45BAD_DIGEST = "monkeys"
46
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040047root_cert_pem = b("""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -050048MIIC7TCCAlagAwIBAgIIPQzE4MbeufQwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE
49BhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdU
50ZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwIhgPMjAwOTAzMjUxMjM2
51NThaGA8yMDE3MDYxMTEyMzY1OFowWDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklM
52MRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9U
53ZXN0aW5nIFJvb3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPmaQumL
54urpE527uSEHdL1pqcDRmWzu+98Y6YHzT/J7KWEamyMCNZ6fRW1JCR782UQ8a07fy
552xXsKy4WdKaxyG8CcatwmXvpvRQ44dSANMihHELpANTdyVp6DCysED6wkQFurHlF
561dshEaJw8b/ypDhmbVIo6Ci1xvCJqivbLFnbAgMBAAGjgbswgbgwHQYDVR0OBBYE
57FINVdy1eIfFJDAkk51QJEo3IfgSuMIGIBgNVHSMEgYAwfoAUg1V3LV4h8UkMCSTn
58VAkSjch+BK6hXKRaMFgxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UE
59BxMHQ2hpY2FnbzEQMA4GA1UEChMHVGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBS
60b290IENBggg9DMTgxt659DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB
61AGGCDazMJGoWNBpc03u6+smc95dEead2KlZXBATOdFT1VesY3+nUOqZhEhTGlDMi
62hkgaZnzoIq/Uamidegk4hirsCT/R+6vsKAAxNTcBjUeZjlykCJWy5ojShGftXIKY
63w/njVbKMXrvc83qmTdGl3TAM0fxQIpqgcglFLveEBgzn
64-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040065""")
Rick Dean94e46fd2009-07-18 14:51:24 -050066
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040067root_key_pem = b("""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -050068MIICXQIBAAKBgQD5mkLpi7q6ROdu7khB3S9aanA0Zls7vvfGOmB80/yeylhGpsjA
69jWen0VtSQke/NlEPGtO38tsV7CsuFnSmschvAnGrcJl76b0UOOHUgDTIoRxC6QDU
703claegwsrBA+sJEBbqx5RdXbIRGicPG/8qQ4Zm1SKOgotcbwiaor2yxZ2wIDAQAB
71AoGBAPCgMpmLxzwDaUmcFbTJUvlLW1hoxNNYSu2jIZm1k/hRAcE60JYwvBkgz3UB
72yMEh0AtLxYe0bFk6EHah11tMUPgscbCq73snJ++8koUw+csk22G65hOs51bVb7Aa
736JBe67oLzdtvgCUFAA2qfrKzWRZzAdhUirQUZgySZk+Xq1pBAkEA/kZG0A6roTSM
74BVnx7LnPfsycKUsTumorpXiylZJjTi9XtmzxhrYN6wgZlDOOwOLgSQhszGpxVoMD
75u3gByT1b2QJBAPtL3mSKdvwRu/+40zaZLwvSJRxaj0mcE4BJOS6Oqs/hS1xRlrNk
76PpQ7WJ4yM6ZOLnXzm2mKyxm50Mv64109FtMCQQDOqS2KkjHaLowTGVxwC0DijMfr
77I9Lf8sSQk32J5VWCySWf5gGTfEnpmUa41gKTMJIbqZZLucNuDcOtzUaeWZlZAkA8
78ttXigLnCqR486JDPTi9ZscoZkZ+w7y6e/hH8t6d5Vjt48JVyfjPIaJY+km58LcN3
796AWSeGAdtRFHVzR7oHjVAkB4hutvxiOeiIVQNBhM6RSI9aBPMI21DoX2JRoxvNW2
80cbvAhow217X9V0dVerEOKxnNYspXRrh36h7k4mQA+sDq
81-----END RSA PRIVATE KEY-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040082""")
Rick Dean94e46fd2009-07-18 14:51:24 -050083
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040084server_cert_pem = b("""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -050085MIICKDCCAZGgAwIBAgIJAJn/HpR21r/8MA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
86BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
87VGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBSb290IENBMCIYDzIwMDkwMzI1MTIz
88NzUzWhgPMjAxNzA2MTExMjM3NTNaMBgxFjAUBgNVBAMTDWxvdmVseSBzZXJ2ZXIw
89gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAL6m+G653V0tpBC/OKl22VxOi2Cv
90lK4TYu9LHSDP9uDVTe7V5D5Tl6qzFoRRx5pfmnkqT5B+W9byp2NU3FC5hLm5zSAr
91b45meUhjEJ/ifkZgbNUjHdBIGP9MAQUHZa5WKdkGIJvGAvs8UzUqlr4TBWQIB24+
92lJ+Ukk/CRgasrYwdAgMBAAGjNjA0MB0GA1UdDgQWBBS4kC7Ij0W1TZXZqXQFAM2e
93gKEG2DATBgNVHSUEDDAKBggrBgEFBQcDATANBgkqhkiG9w0BAQUFAAOBgQBh30Li
94dJ+NlxIOx5343WqIBka3UbsOb2kxWrbkVCrvRapCMLCASO4FqiKWM+L0VDBprqIp
952mgpFQ6FHpoIENGvJhdEKpptQ5i7KaGhnDNTfdy3x1+h852G99f1iyj0RmbuFcM8
96uzujnS8YXWvM7DM1Ilozk4MzPug8jzFp5uhKCQ==
97-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -040098""")
Rick Dean94e46fd2009-07-18 14:51:24 -050099
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -0400100server_key_pem = normalize_privatekey_pem(b("""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500101MIICWwIBAAKBgQC+pvhuud1dLaQQvzipdtlcTotgr5SuE2LvSx0gz/bg1U3u1eQ+
102U5eqsxaEUceaX5p5Kk+QflvW8qdjVNxQuYS5uc0gK2+OZnlIYxCf4n5GYGzVIx3Q
103SBj/TAEFB2WuVinZBiCbxgL7PFM1Kpa+EwVkCAduPpSflJJPwkYGrK2MHQIDAQAB
104AoGAbwuZ0AR6JveahBaczjfnSpiFHf+mve2UxoQdpyr6ROJ4zg/PLW5K/KXrC48G
105j6f3tXMrfKHcpEoZrQWUfYBRCUsGD5DCazEhD8zlxEHahIsqpwA0WWssJA2VOLEN
106j6DuV2pCFbw67rfTBkTSo32ahfXxEKev5KswZk0JIzH3ooECQQDgzS9AI89h0gs8
107Dt+1m11Rzqo3vZML7ZIyGApUzVan+a7hbc33nbGRkAXjHaUBJO31it/H6dTO+uwX
108msWwNG5ZAkEA2RyFKs5xR5USTFaKLWCgpH/ydV96KPOpBND7TKQx62snDenFNNbn
109FwwOhpahld+vqhYk+pfuWWUpQciE+Bu7ZQJASjfT4sQv4qbbKK/scePicnDdx9th
1104e1EeB9xwb+tXXXUo/6Bor/AcUNwfiQ6Zt9PZOK9sR3lMZSsP7rMi7kzuQJABie6
1111sXXjFH7nNJvRG4S39cIxq8YRYTy68II/dlB2QzGpKxV/POCxbJ/zu0CU79tuYK7
112NaeNCFfH3aeTrX0LyQJAMBWjWmeKM2G2sCExheeQK0ROnaBC8itCECD4Jsve4nqf
113r50+LF74iLXFwqysVCebPKMOpDWp/qQ1BbJQIPs7/A==
114-----END RSA PRIVATE KEY-----
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -0400115"""))
Rick Dean94e46fd2009-07-18 14:51:24 -0500116
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400117client_cert_pem = b("""-----BEGIN CERTIFICATE-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500118MIICJjCCAY+gAwIBAgIJAKxpFI5lODkjMA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
119BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
120VGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBSb290IENBMCIYDzIwMDkwMzI1MTIz
121ODA1WhgPMjAxNzA2MTExMjM4MDVaMBYxFDASBgNVBAMTC3VnbHkgY2xpZW50MIGf
122MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDAZh/SRtNm5ntMT4qb6YzEpTroMlq2
123rn+GrRHRiZ+xkCw/CGNhbtPir7/QxaUj26BSmQrHw1bGKEbPsWiW7bdXSespl+xK
124iku4G/KvnnmWdeJHqsiXeUZtqurMELcPQAw9xPHEuhqqUJvvEoMTsnCEqGM+7Dtb
125oCRajYyHfluARQIDAQABozYwNDAdBgNVHQ4EFgQUNQB+qkaOaEVecf1J3TTUtAff
1260fAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQEFBQADgYEAyv/Jh7gM
127Q3OHvmsFEEvRI+hsW8y66zK4K5de239Y44iZrFYkt7Q5nBPMEWDj4F2hLYWL/qtI
1289Zdr0U4UDCU9SmmGYh4o7R4TZ5pGFvBYvjhHbkSFYFQXZxKUi+WUxplP6I0wr2KJ
129PSTJCjJOn3xo2NTKRgV1gaoTf2EhL+RG8TQ=
130-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400131""")
Rick Dean94e46fd2009-07-18 14:51:24 -0500132
Jean-Paul Calderone22cbe502011-05-04 17:01:43 -0400133client_key_pem = normalize_privatekey_pem(b("""-----BEGIN RSA PRIVATE KEY-----
Rick Dean94e46fd2009-07-18 14:51:24 -0500134MIICXgIBAAKBgQDAZh/SRtNm5ntMT4qb6YzEpTroMlq2rn+GrRHRiZ+xkCw/CGNh
135btPir7/QxaUj26BSmQrHw1bGKEbPsWiW7bdXSespl+xKiku4G/KvnnmWdeJHqsiX
136eUZtqurMELcPQAw9xPHEuhqqUJvvEoMTsnCEqGM+7DtboCRajYyHfluARQIDAQAB
137AoGATkZ+NceY5Glqyl4mD06SdcKfV65814vg2EL7V9t8+/mi9rYL8KztSXGlQWPX
138zuHgtRoMl78yQ4ZJYOBVo+nsx8KZNRCEBlE19bamSbQLCeQMenWnpeYyQUZ908gF
139h6L9qsFVJepgA9RDgAjyDoS5CaWCdCCPCH2lDkdcqC54SVUCQQDseuduc4wi8h4t
140V8AahUn9fn9gYfhoNuM0gdguTA0nPLVWz4hy1yJiWYQe0H7NLNNTmCKiLQaJpAbb
141TC6vE8C7AkEA0Ee8CMJUc20BnGEmxwgWcVuqFWaKCo8jTH1X38FlATUsyR3krjW2
142dL3yDD9NwHxsYP7nTKp/U8MV7U9IBn4y/wJBAJl7H0/BcLeRmuJk7IqJ7b635iYB
143D/9beFUw3MUXmQXZUfyYz39xf6CDZsu1GEdEC5haykeln3Of4M9d/4Kj+FcCQQCY
144si6xwT7GzMDkk/ko684AV3KPc/h6G0yGtFIrMg7J3uExpR/VdH2KgwMkZXisSMvw
145JJEQjOMCVsEJlRk54WWjAkEAzoZNH6UhDdBK5F38rVt/y4SEHgbSfJHIAmPS32Kq
146f6GGcfNpip0Uk7q7udTKuX7Q/buZi/C4YW7u3VKAquv9NA==
147-----END RSA PRIVATE KEY-----
Jean-Paul Calderone22cbe502011-05-04 17:01:43 -0400148"""))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400149
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400150cleartextCertificatePEM = b("""-----BEGIN CERTIFICATE-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400151MIIC7TCCAlagAwIBAgIIPQzE4MbeufQwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE
152BhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdU
153ZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwIhgPMjAwOTAzMjUxMjM2
154NThaGA8yMDE3MDYxMTEyMzY1OFowWDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklM
155MRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9U
156ZXN0aW5nIFJvb3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPmaQumL
157urpE527uSEHdL1pqcDRmWzu+98Y6YHzT/J7KWEamyMCNZ6fRW1JCR782UQ8a07fy
1582xXsKy4WdKaxyG8CcatwmXvpvRQ44dSANMihHELpANTdyVp6DCysED6wkQFurHlF
1591dshEaJw8b/ypDhmbVIo6Ci1xvCJqivbLFnbAgMBAAGjgbswgbgwHQYDVR0OBBYE
160FINVdy1eIfFJDAkk51QJEo3IfgSuMIGIBgNVHSMEgYAwfoAUg1V3LV4h8UkMCSTn
161VAkSjch+BK6hXKRaMFgxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UE
162BxMHQ2hpY2FnbzEQMA4GA1UEChMHVGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBS
163b290IENBggg9DMTgxt659DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB
164AGGCDazMJGoWNBpc03u6+smc95dEead2KlZXBATOdFT1VesY3+nUOqZhEhTGlDMi
165hkgaZnzoIq/Uamidegk4hirsCT/R+6vsKAAxNTcBjUeZjlykCJWy5ojShGftXIKY
166w/njVbKMXrvc83qmTdGl3TAM0fxQIpqgcglFLveEBgzn
167-----END CERTIFICATE-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400168""")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400169
Jean-Paul Calderoned50d2042011-05-04 17:00:49 -0400170cleartextPrivateKeyPEM = normalize_privatekey_pem(b("""\
171-----BEGIN RSA PRIVATE KEY-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400172MIICXQIBAAKBgQD5mkLpi7q6ROdu7khB3S9aanA0Zls7vvfGOmB80/yeylhGpsjA
173jWen0VtSQke/NlEPGtO38tsV7CsuFnSmschvAnGrcJl76b0UOOHUgDTIoRxC6QDU
1743claegwsrBA+sJEBbqx5RdXbIRGicPG/8qQ4Zm1SKOgotcbwiaor2yxZ2wIDAQAB
175AoGBAPCgMpmLxzwDaUmcFbTJUvlLW1hoxNNYSu2jIZm1k/hRAcE60JYwvBkgz3UB
176yMEh0AtLxYe0bFk6EHah11tMUPgscbCq73snJ++8koUw+csk22G65hOs51bVb7Aa
1776JBe67oLzdtvgCUFAA2qfrKzWRZzAdhUirQUZgySZk+Xq1pBAkEA/kZG0A6roTSM
178BVnx7LnPfsycKUsTumorpXiylZJjTi9XtmzxhrYN6wgZlDOOwOLgSQhszGpxVoMD
179u3gByT1b2QJBAPtL3mSKdvwRu/+40zaZLwvSJRxaj0mcE4BJOS6Oqs/hS1xRlrNk
180PpQ7WJ4yM6ZOLnXzm2mKyxm50Mv64109FtMCQQDOqS2KkjHaLowTGVxwC0DijMfr
181I9Lf8sSQk32J5VWCySWf5gGTfEnpmUa41gKTMJIbqZZLucNuDcOtzUaeWZlZAkA8
182ttXigLnCqR486JDPTi9ZscoZkZ+w7y6e/hH8t6d5Vjt48JVyfjPIaJY+km58LcN3
1836AWSeGAdtRFHVzR7oHjVAkB4hutvxiOeiIVQNBhM6RSI9aBPMI21DoX2JRoxvNW2
184cbvAhow217X9V0dVerEOKxnNYspXRrh36h7k4mQA+sDq
185-----END RSA PRIVATE KEY-----
Jean-Paul Calderoned50d2042011-05-04 17:00:49 -0400186"""))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400187
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400188cleartextCertificateRequestPEM = b("""-----BEGIN CERTIFICATE REQUEST-----
189MIIBnjCCAQcCAQAwXjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQH
190EwdDaGljYWdvMRcwFQYDVQQKEw5NeSBDb21wYW55IEx0ZDEXMBUGA1UEAxMORnJl
191ZGVyaWNrIERlYW4wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANp6Y17WzKSw
192BsUWkXdqg6tnXy8H8hA1msCMWpc+/2KJ4mbv5NyD6UD+/SqagQqulPbF/DFea9nA
193E0zhmHJELcM8gUTIlXv/cgDWnmK4xj8YkjVUiCdqKRAKeuzLG1pGmwwF5lGeJpXN
194xQn5ecR0UYSOWj6TTGXB9VyUMQzCClcBAgMBAAGgADANBgkqhkiG9w0BAQUFAAOB
195gQAAJGuF/R/GGbeC7FbFW+aJgr9ee0Xbl6nlhu7pTe67k+iiKT2dsl2ti68MVTnu
196Vrb3HUNqOkiwsJf6kCtq5oPn3QVYzTa76Dt2y3Rtzv6boRSlmlfrgS92GNma8JfR
197oICQk3nAudi6zl1Dix3BCv1pUp5KMtGn3MeDEi6QFGy2rA==
198-----END CERTIFICATE REQUEST-----
199""")
Rick Dean5b7b6372009-04-01 11:34:06 -0500200
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400201encryptedPrivateKeyPEM = b("""-----BEGIN RSA PRIVATE KEY-----
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400202Proc-Type: 4,ENCRYPTED
203DEK-Info: DES-EDE3-CBC,9573604A18579E9E
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400204
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400205SHOho56WxDkT0ht10UTeKc0F5u8cqIa01kzFAmETw0MAs8ezYtK15NPdCXUm3X/2
206a17G7LSF5bkxOgZ7vpXyMzun/owrj7CzvLxyncyEFZWvtvzaAhPhvTJtTIB3kf8B
2078+qRcpTGK7NgXEgYBW5bj1y4qZkD4zCL9o9NQzsKI3Ie8i0239jsDOWR38AxjXBH
208mGwAQ4Z6ZN5dnmM4fhMIWsmFf19sNyAML4gHenQCHhmXbjXeVq47aC2ProInJbrm
209+00TcisbAQ40V9aehVbcDKtS4ZbMVDwncAjpXpcncC54G76N6j7F7wL7L/FuXa3A
210fvSVy9n2VfF/pJ3kYSflLHH2G/DFxjF7dl0GxhKPxJjp3IJi9VtuvmN9R2jZWLQF
211tfC8dXgy/P9CfFQhlinqBTEwgH0oZ/d4k4NVFDSdEMaSdmBAjlHpc+Vfdty3HVnV
212rKXj//wslsFNm9kIwJGIgKUa/n2jsOiydrsk1mgH7SmNCb3YHgZhbbnq0qLat/HC
213gHDt3FHpNQ31QzzL3yrenFB2L9osIsnRsDTPFNi4RX4SpDgNroxOQmyzCCV6H+d4
214o1mcnNiZSdxLZxVKccq0AfRpHqpPAFnJcQHP6xyT9MZp6fBa0XkxDnt9kNU8H3Qw
2157SJWZ69VXjBUzMlQViLuaWMgTnL+ZVyFZf9hTF7U/ef4HMLMAVNdiaGG+G+AjCV/
216MbzjS007Oe4qqBnCWaFPSnJX6uLApeTbqAxAeyCql56ULW5x6vDMNC3dwjvS/CEh
21711n8RkgFIQA0AhuKSIg3CbuartRsJnWOLwgLTzsrKYL4yRog1RJrtw==
218-----END RSA PRIVATE KEY-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400219""")
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400220
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400221encryptedPrivateKeyPEMPassphrase = b("foobar")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400222
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400223# Some PKCS#7 stuff. Generated with the openssl command line:
224#
225# openssl crl2pkcs7 -inform pem -outform pem -certfile s.pem -nocrl
226#
227# with a certificate and key (but the key should be irrelevant) in s.pem
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400228pkcs7Data = b("""\
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400229-----BEGIN PKCS7-----
230MIIDNwYJKoZIhvcNAQcCoIIDKDCCAyQCAQExADALBgkqhkiG9w0BBwGgggMKMIID
231BjCCAm+gAwIBAgIBATANBgkqhkiG9w0BAQQFADB7MQswCQYDVQQGEwJTRzERMA8G
232A1UEChMITTJDcnlwdG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtN
233MkNyeXB0byBDZXJ0aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNA
234cG9zdDEuY29tMB4XDTAwMDkxMDA5NTEzMFoXDTAyMDkxMDA5NTEzMFowUzELMAkG
235A1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwlsb2NhbGhvc3Qx
236HTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tMFwwDQYJKoZIhvcNAQEBBQAD
237SwAwSAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh5kwI
238zOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEAAaOCAQQwggEAMAkGA1UdEwQCMAAw
239LAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0G
240A1UdDgQWBBTPhIKSvnsmYsBVNWjj0m3M2z0qVTCBpQYDVR0jBIGdMIGagBT7hyNp
24165w6kxXlxb8pUU/+7Sg4AaF/pH0wezELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0y
242Q3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlwdG8g
243Q2VydGlmaWNhdGUgTWFzdGVyMR0wGwYJKoZIhvcNAQkBFg5uZ3BzQHBvc3QxLmNv
244bYIBADANBgkqhkiG9w0BAQQFAAOBgQA7/CqT6PoHycTdhEStWNZde7M/2Yc6BoJu
245VwnW8YxGO8Sn6UJ4FeffZNcYZddSDKosw8LtPOeWoK3JINjAk5jiPQ2cww++7QGG
246/g5NDjxFZNDJP1dGiLAxPW6JXwov4v0FmdzfLOZ01jDcgQQZqEpYlgpuI5JEWUQ9
247Ho4EzbYCOaEAMQA=
248-----END PKCS7-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400249""")
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400250
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400251crlData = b("""\
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -0500252-----BEGIN X509 CRL-----
253MIIBWzCBxTANBgkqhkiG9w0BAQQFADBYMQswCQYDVQQGEwJVUzELMAkGA1UECBMC
254SUwxEDAOBgNVBAcTB0NoaWNhZ28xEDAOBgNVBAoTB1Rlc3RpbmcxGDAWBgNVBAMT
255D1Rlc3RpbmcgUm9vdCBDQRcNMDkwNzI2MDQzNDU2WhcNMTIwOTI3MDI0MTUyWjA8
256MBUCAgOrGA8yMDA5MDcyNTIzMzQ1NlowIwICAQAYDzIwMDkwNzI1MjMzNDU2WjAM
257MAoGA1UdFQQDCgEEMA0GCSqGSIb3DQEBBAUAA4GBAEBt7xTs2htdD3d4ErrcGAw1
2584dKcVnIWTutoI7xxen26Wwvh8VCsT7i/UeP+rBl9rC/kfjWjzQk3/zleaarGTpBT
2590yp4HXRFFoRhhSE/hP+eteaPXRgrsNRLHe9ZDd69wmh7J1wMDb0m81RG7kqcbsid
260vrzEeLDRiiPl92dyyWmu
261-----END X509 CRL-----
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -0400262""")
Jean-Paul Calderonee890db32010-08-22 16:55:15 -0400263
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400264
265# A broken RSA private key which can be used to test the error path through
266# PKey.check.
267inconsistentPrivateKeyPEM = b("""-----BEGIN RSA PRIVATE KEY-----
268MIIBPAIBAAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh
2695kwIzOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEaAQJBAIqm/bz4NA1H++Vx5Ewx
270OcKp3w19QSaZAwlGRtsUxrP7436QjnREM3Bm8ygU11BjkPVmtrKm6AayQfCHqJoT
271zIECIQDW0BoMoL0HOYM/mrTLhaykYAVqgIeJsPjvkEhTFXWBuQIhAM3deFAvWNu4
272nklUQ37XsCT2c9tmNt1LAT+slG2JOTTRAiAuXDtC/m3NYVwyHfFm+zKHRzHkClk2
273HjubeEgjpj32AQIhAJqMGTaZVOwevTXvvHwNeH+vRWsAYU/gbx+OQB+7VOcBAiEA
274oolb6NMg/R3enNPvS1O4UU1H8wpaF77L4yiSWlE0p4w=
275-----END RSA PRIVATE KEY-----
276""")
277
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -0400278# certificate with NULL bytes in subjectAltName and common name
279
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400280nulbyteSubjectAltNamePEM = b("""-----BEGIN CERTIFICATE-----
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -0400281MIIE2DCCA8CgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBxTELMAkGA1UEBhMCVVMx
282DzANBgNVBAgMBk9yZWdvbjESMBAGA1UEBwwJQmVhdmVydG9uMSMwIQYDVQQKDBpQ
283eXRob24gU29mdHdhcmUgRm91bmRhdGlvbjEgMB4GA1UECwwXUHl0aG9uIENvcmUg
284RGV2ZWxvcG1lbnQxJDAiBgNVBAMMG251bGwucHl0aG9uLm9yZwBleGFtcGxlLm9y
285ZzEkMCIGCSqGSIb3DQEJARYVcHl0aG9uLWRldkBweXRob24ub3JnMB4XDTEzMDgw
286NzEzMTE1MloXDTEzMDgwNzEzMTI1MlowgcUxCzAJBgNVBAYTAlVTMQ8wDQYDVQQI
287DAZPcmVnb24xEjAQBgNVBAcMCUJlYXZlcnRvbjEjMCEGA1UECgwaUHl0aG9uIFNv
288ZnR3YXJlIEZvdW5kYXRpb24xIDAeBgNVBAsMF1B5dGhvbiBDb3JlIERldmVsb3Bt
289ZW50MSQwIgYDVQQDDBtudWxsLnB5dGhvbi5vcmcAZXhhbXBsZS5vcmcxJDAiBgkq
290hkiG9w0BCQEWFXB5dGhvbi1kZXZAcHl0aG9uLm9yZzCCASIwDQYJKoZIhvcNAQEB
291BQADggEPADCCAQoCggEBALXq7cn7Rn1vO3aA3TrzA5QLp6bb7B3f/yN0CJ2XFj+j
292pHs+Gw6WWSUDpybiiKnPec33BFawq3kyblnBMjBU61ioy5HwQqVkJ8vUVjGIUq3P
293vX/wBmQfzCe4o4uM89gpHyUL9UYGG8oCRa17dgqcv7u5rg0Wq2B1rgY+nHwx3JIv
294KRrgSwyRkGzpN8WQ1yrXlxWjgI9de0mPVDDUlywcWze1q2kwaEPTM3hLAmD1PESA
295oY/n8A/RXoeeRs9i/Pm/DGUS8ZPINXk/yOzsR/XvvkTVroIeLZqfmFpnZeF0cHzL
29608LODkVJJ9zjLdT7SA4vnne4FEbAxDbKAq5qkYzaL4UCAwEAAaOB0DCBzTAMBgNV
297HRMBAf8EAjAAMB0GA1UdDgQWBBSIWlXAUv9hzVKjNQ/qWpwkOCL3XDALBgNVHQ8E
298BAMCBeAwgZAGA1UdEQSBiDCBhYIeYWx0bnVsbC5weXRob24ub3JnAGV4YW1wbGUu
299Y29tgSBudWxsQHB5dGhvbi5vcmcAdXNlckBleGFtcGxlLm9yZ4YpaHR0cDovL251
300bGwucHl0aG9uLm9yZwBodHRwOi8vZXhhbXBsZS5vcmeHBMAAAgGHECABDbgAAAAA
301AAAAAAAAAAEwDQYJKoZIhvcNAQEFBQADggEBAKxPRe99SaghcI6IWT7UNkJw9aO9
302i9eo0Fj2MUqxpKbdb9noRDy2CnHWf7EIYZ1gznXPdwzSN4YCjV5d+Q9xtBaowT0j
303HPERs1ZuytCNNJTmhyqZ8q6uzMLoht4IqH/FBfpvgaeC5tBTnTT0rD5A/olXeimk
304kX4LxlEx5RAvpGB2zZVRGr6LobD9rVK91xuHYNIxxxfEGE8tCCWjp0+3ksri9SXx
305VHWBnbM9YaL32u3hxm8sYB/Yb8WSBavJCWJJqRStVRHM1koZlJmXNx2BX4vPo6iW
306RFEIPQsFZRLrtnCAiEhyT8bC2s/Njlu6ly9gtJZWSV46Q3ZjBL4q9sHKqZQ=
307-----END CERTIFICATE-----""")
308
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400309
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400310class X509ExtTests(TestCase):
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400311 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900312 Tests for :py:class:`OpenSSL.crypto.X509Extension`.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400313 """
314
315 def setUp(self):
316 """
317 Create a new private key and start a certificate request (for a test
318 method to finish in one way or another).
319 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -0800320 super(X509ExtTests, self).setUp()
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400321 # Basic setup stuff to generate a certificate
322 self.pkey = PKey()
323 self.pkey.generate_key(TYPE_RSA, 384)
324 self.req = X509Req()
325 self.req.set_pubkey(self.pkey)
326 # Authority good you have.
327 self.req.get_subject().commonName = "Yoda root CA"
328 self.x509 = X509()
329 self.subject = self.x509.get_subject()
330 self.subject.commonName = self.req.get_subject().commonName
331 self.x509.set_issuer(self.subject)
332 self.x509.set_pubkey(self.pkey)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400333 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
334 expire = b((datetime.now() + timedelta(days=100)).strftime("%Y%m%d%H%M%SZ"))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400335 self.x509.set_notBefore(now)
336 self.x509.set_notAfter(expire)
337
338
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -0800339 def tearDown(self):
340 """
341 Forget all of the pyOpenSSL objects so they can be garbage collected,
342 their memory released, and not interfere with the leak detection code.
343 """
344 self.pkey = self.req = self.x509 = self.subject = None
345 super(X509ExtTests, self).tearDown()
346
347
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400348 def test_str(self):
349 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900350 The string representation of :py:class:`X509Extension` instances as returned by
351 :py:data:`str` includes stuff.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400352 """
353 # This isn't necessarily the best string representation. Perhaps it
354 # will be changed/improved in the future.
355 self.assertEquals(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400356 str(X509Extension(b('basicConstraints'), True, b('CA:false'))),
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -0400357 'CA:FALSE')
358
359
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400360 def test_type(self):
361 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900362 :py:class:`X509Extension` and :py:class:`X509ExtensionType` refer to the same type object
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400363 and can be used to create instances of that type.
364 """
365 self.assertIdentical(X509Extension, X509ExtensionType)
366 self.assertConsistentType(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400367 X509Extension,
368 'X509Extension', b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400369
370
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500371 def test_construction(self):
372 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900373 :py:class:`X509Extension` accepts an extension type name, a critical flag,
374 and an extension value and returns an :py:class:`X509ExtensionType` instance.
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500375 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400376 basic = X509Extension(b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500377 self.assertTrue(
378 isinstance(basic, X509ExtensionType),
379 "%r is of type %r, should be %r" % (
380 basic, type(basic), X509ExtensionType))
381
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400382 comment = X509Extension(
383 b('nsComment'), False, b('pyOpenSSL unit test'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500384 self.assertTrue(
385 isinstance(comment, X509ExtensionType),
386 "%r is of type %r, should be %r" % (
387 comment, type(comment), X509ExtensionType))
388
389
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500390 def test_invalid_extension(self):
391 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900392 :py:class:`X509Extension` raises something if it is passed a bad extension
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500393 name or value.
394 """
395 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400396 Error, X509Extension, b('thisIsMadeUp'), False, b('hi'))
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500397 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400398 Error, X509Extension, b('basicConstraints'), False, b('blah blah'))
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500399
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500400 # Exercise a weird one (an extension which uses the r2i method). This
401 # exercises the codepath that requires a non-NULL ctx to be passed to
402 # X509V3_EXT_nconf. It can't work now because we provide no
403 # configuration database. It might be made to work in the future.
404 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400405 Error, X509Extension, b('proxyCertInfo'), True,
406 b('language:id-ppl-anyLanguage,pathlen:1,policy:text:AB'))
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500407
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500408
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500409 def test_get_critical(self):
410 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900411 :py:meth:`X509ExtensionType.get_critical` returns the value of the
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500412 extension's critical flag.
413 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400414 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500415 self.assertTrue(ext.get_critical())
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400416 ext = X509Extension(b('basicConstraints'), False, b('CA:true'))
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500417 self.assertFalse(ext.get_critical())
418
Jean-Paul Calderone7535dab2008-03-06 18:53:11 -0500419
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500420 def test_get_short_name(self):
421 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900422 :py:meth:`X509ExtensionType.get_short_name` returns a string giving the short
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500423 type name of the extension.
424 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400425 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
426 self.assertEqual(ext.get_short_name(), b('basicConstraints'))
427 ext = X509Extension(b('nsComment'), True, b('foo bar'))
428 self.assertEqual(ext.get_short_name(), b('nsComment'))
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500429
430
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400431 def test_get_data(self):
432 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900433 :py:meth:`X509Extension.get_data` returns a string giving the data of the
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400434 extension.
435 """
436 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
437 # Expect to get back the DER encoded form of CA:true.
438 self.assertEqual(ext.get_data(), b('0\x03\x01\x01\xff'))
439
440
441 def test_get_data_wrong_args(self):
442 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900443 :py:meth:`X509Extension.get_data` raises :py:exc:`TypeError` if passed any arguments.
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -0400444 """
445 ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
446 self.assertRaises(TypeError, ext.get_data, None)
447 self.assertRaises(TypeError, ext.get_data, "foo")
448 self.assertRaises(TypeError, ext.get_data, 7)
449
450
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400451 def test_unused_subject(self):
Rick Dean47262da2009-07-08 16:17:17 -0500452 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900453 The :py:data:`subject` parameter to :py:class:`X509Extension` may be provided for an
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400454 extension which does not use it and is ignored in this case.
Rick Dean47262da2009-07-08 16:17:17 -0500455 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400456 ext1 = X509Extension(
457 b('basicConstraints'), False, b('CA:TRUE'), subject=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400458 self.x509.add_extensions([ext1])
459 self.x509.sign(self.pkey, 'sha1')
460 # This is a little lame. Can we think of a better way?
461 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400462 self.assertTrue(b('X509v3 Basic Constraints:') in text)
463 self.assertTrue(b('CA:TRUE') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400464
465
466 def test_subject(self):
467 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900468 If an extension requires a subject, the :py:data:`subject` parameter to
469 :py:class:`X509Extension` provides its value.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400470 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400471 ext3 = X509Extension(
472 b('subjectKeyIdentifier'), False, b('hash'), subject=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400473 self.x509.add_extensions([ext3])
474 self.x509.sign(self.pkey, 'sha1')
475 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400476 self.assertTrue(b('X509v3 Subject Key Identifier:') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400477
478
479 def test_missing_subject(self):
480 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900481 If an extension requires a subject and the :py:data:`subject` parameter is
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400482 given no value, something happens.
483 """
484 self.assertRaises(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400485 Error, X509Extension, b('subjectKeyIdentifier'), False, b('hash'))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400486
487
488 def test_invalid_subject(self):
489 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900490 If the :py:data:`subject` parameter is given a value which is not an
491 :py:class:`X509` instance, :py:exc:`TypeError` is raised.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400492 """
493 for badObj in [True, object(), "hello", [], self]:
494 self.assertRaises(
495 TypeError,
496 X509Extension,
497 'basicConstraints', False, 'CA:TRUE', subject=badObj)
498
499
500 def test_unused_issuer(self):
501 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900502 The :py:data:`issuer` parameter to :py:class:`X509Extension` may be provided for an
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400503 extension which does not use it and is ignored in this case.
504 """
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400505 ext1 = X509Extension(
506 b('basicConstraints'), False, b('CA:TRUE'), issuer=self.x509)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400507 self.x509.add_extensions([ext1])
508 self.x509.sign(self.pkey, 'sha1')
509 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400510 self.assertTrue(b('X509v3 Basic Constraints:') in text)
511 self.assertTrue(b('CA:TRUE') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400512
513
514 def test_issuer(self):
515 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900516 If an extension requires a issuer, the :py:data:`issuer` parameter to
517 :py:class:`X509Extension` provides its value.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400518 """
519 ext2 = X509Extension(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400520 b('authorityKeyIdentifier'), False, b('issuer:always'),
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400521 issuer=self.x509)
522 self.x509.add_extensions([ext2])
523 self.x509.sign(self.pkey, 'sha1')
524 text = dump_certificate(FILETYPE_TEXT, self.x509)
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400525 self.assertTrue(b('X509v3 Authority Key Identifier:') in text)
526 self.assertTrue(b('DirName:/CN=Yoda root CA') in text)
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400527
528
529 def test_missing_issuer(self):
530 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900531 If an extension requires an issue and the :py:data:`issuer` parameter is given
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400532 no value, something happens.
533 """
534 self.assertRaises(
535 Error,
536 X509Extension,
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400537 b('authorityKeyIdentifier'), False,
538 b('keyid:always,issuer:always'))
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400539
540
541 def test_invalid_issuer(self):
542 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900543 If the :py:data:`issuer` parameter is given a value which is not an
544 :py:class:`X509` instance, :py:exc:`TypeError` is raised.
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400545 """
546 for badObj in [True, object(), "hello", [], self]:
547 self.assertRaises(
548 TypeError,
549 X509Extension,
550 'authorityKeyIdentifier', False, 'keyid:always,issuer:always',
551 issuer=badObj)
Rick Dean47262da2009-07-08 16:17:17 -0500552
553
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500554
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400555class PKeyTests(TestCase):
Jean-Paul Calderoneac930e12008-03-06 18:50:51 -0500556 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900557 Unit tests for :py:class:`OpenSSL.crypto.PKey`.
Jean-Paul Calderoneac930e12008-03-06 18:50:51 -0500558 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400559 def test_type(self):
560 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900561 :py:class:`PKey` and :py:class:`PKeyType` refer to the same type object
562 and can be used to create instances of that type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400563 """
564 self.assertIdentical(PKey, PKeyType)
565 self.assertConsistentType(PKey, 'PKey')
566
567
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500568 def test_construction(self):
569 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900570 :py:class:`PKey` takes no arguments and returns a new :py:class:`PKey` instance.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500571 """
572 self.assertRaises(TypeError, PKey, None)
573 key = PKey()
574 self.assertTrue(
575 isinstance(key, PKeyType),
576 "%r is of type %r, should be %r" % (key, type(key), PKeyType))
577
578
579 def test_pregeneration(self):
580 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900581 :py:attr:`PKeyType.bits` and :py:attr:`PKeyType.type` return :py:data:`0` before the key is
582 generated. :py:attr:`PKeyType.check` raises :py:exc:`TypeError` before the key is
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500583 generated.
584 """
585 key = PKey()
586 self.assertEqual(key.type(), 0)
587 self.assertEqual(key.bits(), 0)
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400588 self.assertRaises(TypeError, key.check)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500589
590
591 def test_failedGeneration(self):
592 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900593 :py:meth:`PKeyType.generate_key` takes two arguments, the first giving the key
594 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 -0500595 number of bits to generate. If an invalid type is specified or
Jonathan Ballet648875f2011-07-16 14:14:58 +0900596 generation fails, :py:exc:`Error` is raised. If an invalid number of bits is
597 specified, :py:exc:`ValueError` or :py:exc:`Error` is raised.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500598 """
599 key = PKey()
600 self.assertRaises(TypeError, key.generate_key)
601 self.assertRaises(TypeError, key.generate_key, 1, 2, 3)
602 self.assertRaises(TypeError, key.generate_key, "foo", "bar")
603 self.assertRaises(Error, key.generate_key, -1, 0)
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500604
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500605 self.assertRaises(ValueError, key.generate_key, TYPE_RSA, -1)
606 self.assertRaises(ValueError, key.generate_key, TYPE_RSA, 0)
Jean-Paul Calderoned71fe982008-03-06 00:31:50 -0500607
608 # XXX RSA generation for small values of bits is fairly buggy in a wide
609 # range of OpenSSL versions. I need to figure out what the safe lower
610 # bound for a reasonable number of OpenSSL versions is and explicitly
611 # check for that in the wrapper. The failure behavior is typically an
612 # infinite loop inside OpenSSL.
613
614 # self.assertRaises(Error, key.generate_key, TYPE_RSA, 2)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500615
616 # XXX DSA generation seems happy with any number of bits. The DSS
617 # says bits must be between 512 and 1024 inclusive. OpenSSL's DSA
618 # generator doesn't seem to care about the upper limit at all. For
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500619 # the lower limit, it uses 512 if anything smaller is specified.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500620 # So, it doesn't seem possible to make generate_key fail for
621 # TYPE_DSA with a bits argument which is at least an int.
622
623 # self.assertRaises(Error, key.generate_key, TYPE_DSA, -7)
624
625
626 def test_rsaGeneration(self):
627 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900628 :py:meth:`PKeyType.generate_key` generates an RSA key when passed
629 :py:data:`TYPE_RSA` as a type and a reasonable number of bits.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500630 """
631 bits = 128
632 key = PKey()
633 key.generate_key(TYPE_RSA, bits)
634 self.assertEqual(key.type(), TYPE_RSA)
635 self.assertEqual(key.bits(), bits)
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -0400636 self.assertTrue(key.check())
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500637
638
639 def test_dsaGeneration(self):
640 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900641 :py:meth:`PKeyType.generate_key` generates a DSA key when passed
642 :py:data:`TYPE_DSA` as a type and a reasonable number of bits.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500643 """
644 # 512 is a magic number. The DSS (Digital Signature Standard)
645 # allows a minimum of 512 bits for DSA. DSA_generate_parameters
646 # will silently promote any value below 512 to 512.
647 bits = 512
648 key = PKey()
649 key.generate_key(TYPE_DSA, bits)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800650 # self.assertEqual(key.type(), TYPE_DSA)
651 # self.assertEqual(key.bits(), bits)
652 # self.assertRaises(TypeError, key.check)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500653
654
655 def test_regeneration(self):
656 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900657 :py:meth:`PKeyType.generate_key` can be called multiple times on the same
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500658 key to generate new keys.
659 """
660 key = PKey()
661 for type, bits in [(TYPE_RSA, 512), (TYPE_DSA, 576)]:
662 key.generate_key(type, bits)
663 self.assertEqual(key.type(), type)
664 self.assertEqual(key.bits(), bits)
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500665
666
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400667 def test_inconsistentKey(self):
668 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900669 :py:`PKeyType.check` returns :py:exc:`Error` if the key is not consistent.
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400670 """
671 key = load_privatekey(FILETYPE_PEM, inconsistentPrivateKeyPEM)
Jean-Paul Calderoned338e4e2009-05-13 15:45:07 -0400672 self.assertRaises(Error, key.check)
Jean-Paul Calderone55ec1712009-05-13 14:14:30 -0400673
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500674
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400675 def test_check_wrong_args(self):
676 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900677 :py:meth:`PKeyType.check` raises :py:exc:`TypeError` if called with any arguments.
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400678 """
679 self.assertRaises(TypeError, PKey().check, None)
680 self.assertRaises(TypeError, PKey().check, object())
681 self.assertRaises(TypeError, PKey().check, 1)
682
683
Jean-Paul Calderone02d01972011-10-31 10:39:29 -0400684 def test_check_public_key(self):
685 """
686 :py:meth:`PKeyType.check` raises :py:exc:`TypeError` if only the public
687 part of the key is available.
688 """
689 # A trick to get a public-only key
690 key = PKey()
691 key.generate_key(TYPE_RSA, 512)
692 cert = X509()
693 cert.set_pubkey(key)
694 pub = cert.get_pubkey()
695 self.assertRaises(TypeError, pub.check)
696
697
Jean-Paul Calderonee81020e2011-06-12 21:48:57 -0400698
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400699class X509NameTests(TestCase):
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500700 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900701 Unit tests for :py:class:`OpenSSL.crypto.X509Name`.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500702 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500703 def _x509name(self, **attrs):
704 # XXX There's no other way to get a new X509Name yet.
705 name = X509().get_subject()
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400706 attrs = list(attrs.items())
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500707 # Make the order stable - order matters!
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400708 def key(attr):
709 return attr[1]
710 attrs.sort(key=key)
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500711 for k, v in attrs:
712 setattr(name, k, v)
713 return name
714
715
Rick Deane15b1472009-07-09 15:53:42 -0500716 def test_type(self):
717 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900718 The type of X509Name objects is :py:class:`X509NameType`.
Rick Deane15b1472009-07-09 15:53:42 -0500719 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400720 self.assertIdentical(X509Name, X509NameType)
721 self.assertEqual(X509NameType.__name__, 'X509Name')
722 self.assertTrue(isinstance(X509NameType, type))
723
Rick Deane15b1472009-07-09 15:53:42 -0500724 name = self._x509name()
725 self.assertTrue(
726 isinstance(name, X509NameType),
727 "%r is of type %r, should be %r" % (
728 name, type(name), X509NameType))
Rick Deane15b1472009-07-09 15:53:42 -0500729
730
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400731 def test_onlyStringAttributes(self):
732 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900733 Attempting to set a non-:py:data:`str` attribute name on an :py:class:`X509NameType`
734 instance causes :py:exc:`TypeError` to be raised.
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400735 """
736 name = self._x509name()
737 # Beyond these cases, you may also think that unicode should be
738 # rejected. Sorry, you're wrong. unicode is automatically converted to
739 # str outside of the control of X509Name, so there's no way to reject
740 # it.
Jean-Paul Calderoneff363be2013-03-03 10:21:23 -0800741
742 # Also, this used to test str subclasses, but that test is less relevant
743 # now that the implementation is in Python instead of C. Also PyPy
744 # automatically converts str subclasses to str when they are passed to
745 # setattr, so we can't test it on PyPy. Apparently CPython does this
746 # sometimes as well.
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400747 self.assertRaises(TypeError, setattr, name, None, "hello")
748 self.assertRaises(TypeError, setattr, name, 30, "hello")
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400749
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -0500750
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400751 def test_setInvalidAttribute(self):
752 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900753 Attempting to set any attribute name on an :py:class:`X509NameType` instance for
754 which no corresponding NID is defined causes :py:exc:`AttributeError` to be
Jean-Paul Calderone9ce9afb2011-04-22 18:16:22 -0400755 raised.
756 """
757 name = self._x509name()
758 self.assertRaises(AttributeError, setattr, name, "no such thing", None)
759
760
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500761 def test_attributes(self):
762 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900763 :py:class:`X509NameType` instances have attributes for each standard (?)
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500764 X509Name field.
765 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500766 name = self._x509name()
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500767 name.commonName = "foo"
768 self.assertEqual(name.commonName, "foo")
769 self.assertEqual(name.CN, "foo")
770 name.CN = "baz"
771 self.assertEqual(name.commonName, "baz")
772 self.assertEqual(name.CN, "baz")
773 name.commonName = "bar"
774 self.assertEqual(name.commonName, "bar")
775 self.assertEqual(name.CN, "bar")
776 name.CN = "quux"
777 self.assertEqual(name.commonName, "quux")
778 self.assertEqual(name.CN, "quux")
779
780
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500781 def test_copy(self):
782 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900783 :py:class:`X509Name` creates a new :py:class:`X509NameType` instance with all the same
784 attributes as an existing :py:class:`X509NameType` instance when called with
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500785 one.
786 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500787 name = self._x509name(commonName="foo", emailAddress="bar@example.com")
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500788
789 copy = X509Name(name)
790 self.assertEqual(copy.commonName, "foo")
791 self.assertEqual(copy.emailAddress, "bar@example.com")
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500792
793 # Mutate the copy and ensure the original is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500794 copy.commonName = "baz"
795 self.assertEqual(name.commonName, "foo")
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500796
797 # Mutate the original and ensure the copy is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500798 name.emailAddress = "quux@example.com"
799 self.assertEqual(copy.emailAddress, "bar@example.com")
800
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500801
802 def test_repr(self):
803 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900804 :py:func:`repr` passed an :py:class:`X509NameType` instance should return a string
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500805 containing a description of the type and the NIDs which have been set
806 on it.
807 """
808 name = self._x509name(commonName="foo", emailAddress="bar")
809 self.assertEqual(
810 repr(name),
811 "<X509Name object '/emailAddress=bar/CN=foo'>")
812
813
814 def test_comparison(self):
815 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900816 :py:class:`X509NameType` instances should compare based on their NIDs.
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500817 """
818 def _equality(a, b, assertTrue, assertFalse):
819 assertTrue(a == b, "(%r == %r) --> False" % (a, b))
820 assertFalse(a != b)
821 assertTrue(b == a)
822 assertFalse(b != a)
823
824 def assertEqual(a, b):
825 _equality(a, b, self.assertTrue, self.assertFalse)
826
827 # Instances compare equal to themselves.
828 name = self._x509name()
829 assertEqual(name, name)
830
831 # Empty instances should compare equal to each other.
832 assertEqual(self._x509name(), self._x509name())
833
834 # Instances with equal NIDs should compare equal to each other.
835 assertEqual(self._x509name(commonName="foo"),
836 self._x509name(commonName="foo"))
837
838 # Instance with equal NIDs set using different aliases should compare
839 # equal to each other.
840 assertEqual(self._x509name(commonName="foo"),
841 self._x509name(CN="foo"))
842
843 # Instances with more than one NID with the same values should compare
844 # equal to each other.
845 assertEqual(self._x509name(CN="foo", organizationalUnitName="bar"),
846 self._x509name(commonName="foo", OU="bar"))
847
848 def assertNotEqual(a, b):
849 _equality(a, b, self.assertFalse, self.assertTrue)
850
851 # Instances with different values for the same NID should not compare
852 # equal to each other.
853 assertNotEqual(self._x509name(CN="foo"),
854 self._x509name(CN="bar"))
855
856 # Instances with different NIDs should not compare equal to each other.
857 assertNotEqual(self._x509name(CN="foo"),
858 self._x509name(OU="foo"))
859
860 def _inequality(a, b, assertTrue, assertFalse):
861 assertTrue(a < b)
862 assertTrue(a <= b)
863 assertTrue(b > a)
864 assertTrue(b >= a)
865 assertFalse(a > b)
866 assertFalse(a >= b)
867 assertFalse(b < a)
868 assertFalse(b <= a)
869
870 def assertLessThan(a, b):
871 _inequality(a, b, self.assertTrue, self.assertFalse)
872
873 # An X509Name with a NID with a value which sorts less than the value
874 # of the same NID on another X509Name compares less than the other
875 # X509Name.
876 assertLessThan(self._x509name(CN="abc"),
877 self._x509name(CN="def"))
878
879 def assertGreaterThan(a, b):
880 _inequality(a, b, self.assertFalse, self.assertTrue)
881
882 # An X509Name with a NID with a value which sorts greater than the
883 # value of the same NID on another X509Name compares greater than the
884 # other X509Name.
885 assertGreaterThan(self._x509name(CN="def"),
886 self._x509name(CN="abc"))
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -0500887
888
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400889 def test_hash(self):
890 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900891 :py:meth:`X509Name.hash` returns an integer hash based on the value of the
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400892 name.
893 """
894 a = self._x509name(CN="foo")
895 b = self._x509name(CN="foo")
896 self.assertEqual(a.hash(), b.hash())
897 a.CN = "bar"
898 self.assertNotEqual(a.hash(), b.hash())
899
900
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400901 def test_der(self):
902 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900903 :py:meth:`X509Name.der` returns the DER encoded form of the name.
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400904 """
905 a = self._x509name(CN="foo", C="US")
906 self.assertEqual(
907 a.der(),
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -0400908 b('0\x1b1\x0b0\t\x06\x03U\x04\x06\x13\x02US'
909 '1\x0c0\n\x06\x03U\x04\x03\x13\x03foo'))
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400910
911
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400912 def test_get_components(self):
913 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900914 :py:meth:`X509Name.get_components` returns a :py:data:`list` of
915 two-tuples of :py:data:`str`
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400916 giving the NIDs and associated values which make up the name.
917 """
918 a = self._x509name()
919 self.assertEqual(a.get_components(), [])
920 a.CN = "foo"
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -0400921 self.assertEqual(a.get_components(), [(b("CN"), b("foo"))])
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400922 a.organizationalUnitName = "bar"
923 self.assertEqual(
924 a.get_components(),
Jean-Paul Calderone2ac721b2010-08-22 19:20:00 -0400925 [(b("CN"), b("foo")), (b("OU"), b("bar"))])
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400926
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400927
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400928 def test_load_nul_byte_attribute(self):
929 """
Jean-Paul Calderone9af07b02013-08-23 16:07:31 -0400930 An :py:class:`OpenSSL.crypto.X509Name` from an
931 :py:class:`OpenSSL.crypto.X509` instance loaded from a file can have a
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400932 NUL byte in the value of one of its attributes.
933 """
934 cert = load_certificate(FILETYPE_PEM, nulbyteSubjectAltNamePEM)
935 subject = cert.get_subject()
936 self.assertEqual(
Jean-Paul Calderone06754fc2013-08-23 15:47:47 -0400937 "null.python.org\x00example.org", subject.commonName)
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400938
939
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -0500940 def test_setAttributeFailure(self):
941 """
942 If the value of an attribute cannot be set for some reason then
943 :py:class:`OpenSSL.crypto.Error` is raised.
944 """
945 name = self._x509name()
946 # This value is too long
947 self.assertRaises(Error, setattr, name, "O", b"x" * 512)
948
949
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -0400950
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400951class _PKeyInteractionTestsMixin:
952 """
953 Tests which involve another thing and a PKey.
954 """
955 def signable(self):
956 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900957 Return something with a :py:meth:`set_pubkey`, :py:meth:`set_pubkey`,
958 and :py:meth:`sign` method.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400959 """
960 raise NotImplementedError()
961
962
963 def test_signWithUngenerated(self):
964 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900965 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when pass a
966 :py:class:`PKey` with no parts.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400967 """
968 request = self.signable()
969 key = PKey()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500970 self.assertRaises(ValueError, request.sign, key, GOOD_DIGEST)
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400971
972
973 def test_signWithPublicKey(self):
974 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900975 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when pass a
976 :py:class:`PKey` with no private part as the signing key.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400977 """
978 request = self.signable()
979 key = PKey()
980 key.generate_key(TYPE_RSA, 512)
981 request.set_pubkey(key)
982 pub = request.get_pubkey()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500983 self.assertRaises(ValueError, request.sign, pub, GOOD_DIGEST)
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400984
985
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -0400986 def test_signWithUnknownDigest(self):
987 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900988 :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when passed a digest name which is
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -0400989 not known.
990 """
991 request = self.signable()
992 key = PKey()
993 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500994 self.assertRaises(ValueError, request.sign, key, BAD_DIGEST)
Jean-Paul Calderonecc05a912010-08-03 18:24:19 -0400995
996
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -0400997 def test_sign(self):
998 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900999 :py:meth:`X509Req.sign` succeeds when passed a private key object and a valid
1000 digest function. :py:meth:`X509Req.verify` can be used to check the signature.
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04001001 """
1002 request = self.signable()
1003 key = PKey()
1004 key.generate_key(TYPE_RSA, 512)
1005 request.set_pubkey(key)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001006 request.sign(key, GOOD_DIGEST)
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04001007 # If the type has a verify method, cover that too.
1008 if getattr(request, 'verify', None) is not None:
1009 pub = request.get_pubkey()
1010 self.assertTrue(request.verify(pub))
1011 # Make another key that won't verify.
1012 key = PKey()
1013 key.generate_key(TYPE_RSA, 512)
1014 self.assertRaises(Error, request.verify, key)
1015
1016
1017
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001018
Jean-Paul Calderone18808652009-07-05 12:54:05 -04001019class X509ReqTests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001020 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001021 Tests for :py:class:`OpenSSL.crypto.X509Req`.
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001022 """
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001023 def signable(self):
1024 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001025 Create and return a new :py:class:`X509Req`.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001026 """
1027 return X509Req()
1028
1029
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001030 def test_type(self):
1031 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001032 :py:obj:`X509Req` and :py:obj:`X509ReqType` refer to the same type object and can be
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001033 used to create instances of that type.
1034 """
1035 self.assertIdentical(X509Req, X509ReqType)
1036 self.assertConsistentType(X509Req, 'X509Req')
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001037
1038
1039 def test_construction(self):
1040 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001041 :py:obj:`X509Req` takes no arguments and returns an :py:obj:`X509ReqType` instance.
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001042 """
1043 request = X509Req()
1044 self.assertTrue(
1045 isinstance(request, X509ReqType),
1046 "%r is of type %r, should be %r" % (request, type(request), X509ReqType))
1047
1048
Jean-Paul Calderone8dd19b82008-12-28 20:41:16 -05001049 def test_version(self):
1050 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001051 :py:obj:`X509ReqType.set_version` sets the X.509 version of the certificate
1052 request. :py:obj:`X509ReqType.get_version` returns the X.509 version of
Jean-Paul Calderone8dd19b82008-12-28 20:41:16 -05001053 the certificate request. The initial value of the version is 0.
1054 """
1055 request = X509Req()
1056 self.assertEqual(request.get_version(), 0)
1057 request.set_version(1)
1058 self.assertEqual(request.get_version(), 1)
1059 request.set_version(3)
1060 self.assertEqual(request.get_version(), 3)
1061
1062
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001063 def test_version_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001064 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001065 :py:obj:`X509ReqType.set_version` raises :py:obj:`TypeError` if called with the wrong
1066 number of arguments or with a non-:py:obj:`int` argument.
1067 :py:obj:`X509ReqType.get_version` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001068 arguments.
1069 """
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001070 request = X509Req()
1071 self.assertRaises(TypeError, request.set_version)
1072 self.assertRaises(TypeError, request.set_version, "foo")
1073 self.assertRaises(TypeError, request.set_version, 1, 2)
1074 self.assertRaises(TypeError, request.get_version, None)
1075
1076
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001077 def test_get_subject(self):
1078 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001079 :py:obj:`X509ReqType.get_subject` returns an :py:obj:`X509Name` for the subject of
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -05001080 the request and which is valid even after the request object is
1081 otherwise dead.
1082 """
1083 request = X509Req()
1084 subject = request.get_subject()
1085 self.assertTrue(
1086 isinstance(subject, X509NameType),
1087 "%r is of type %r, should be %r" % (subject, type(subject), X509NameType))
1088 subject.commonName = "foo"
1089 self.assertEqual(request.get_subject().commonName, "foo")
1090 del request
1091 subject.commonName = "bar"
1092 self.assertEqual(subject.commonName, "bar")
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001093
1094
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001095 def test_get_subject_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001096 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001097 :py:obj:`X509ReqType.get_subject` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04001098 arguments.
1099 """
Jean-Paul Calderone54e49e92010-07-30 11:04:46 -04001100 request = X509Req()
1101 self.assertRaises(TypeError, request.get_subject, None)
1102
1103
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001104 def test_add_extensions(self):
1105 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001106 :py:obj:`X509Req.add_extensions` accepts a :py:obj:`list` of :py:obj:`X509Extension`
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001107 instances and adds them to the X509 request.
1108 """
1109 request = X509Req()
1110 request.add_extensions([
Jean-Paul Calderonee16f9f32010-08-22 19:20:37 -04001111 X509Extension(b('basicConstraints'), True, b('CA:false'))])
Stephen Holsappleca545b72014-01-28 21:43:25 -08001112 exts = request.get_extensions()
Stephen Holsapple7fbdf642014-03-01 20:05:47 -08001113 self.assertEqual(len(exts), 1)
1114 self.assertEqual(exts[0].get_short_name(), b('basicConstraints'))
1115 self.assertEqual(exts[0].get_critical(), 1)
1116 self.assertEqual(exts[0].get_data(), b('0\x00'))
1117
1118
1119 def test_get_extensions(self):
1120 """
1121 :py:obj:`X509Req.get_extensions` returns a :py:obj:`list` of
1122 extensions added to this X509 request.
1123 """
1124 request = X509Req()
1125 exts = request.get_extensions()
1126 self.assertEqual(exts, [])
1127 request.add_extensions([
1128 X509Extension(b('basicConstraints'), True, b('CA:true')),
1129 X509Extension(b('keyUsage'), False, b('digitalSignature'))])
1130 exts = request.get_extensions()
1131 self.assertEqual(len(exts), 2)
1132 self.assertEqual(exts[0].get_short_name(), b('basicConstraints'))
1133 self.assertEqual(exts[0].get_critical(), 1)
1134 self.assertEqual(exts[0].get_data(), b('0\x03\x01\x01\xff'))
1135 self.assertEqual(exts[1].get_short_name(), b('keyUsage'))
1136 self.assertEqual(exts[1].get_critical(), 0)
1137 self.assertEqual(exts[1].get_data(), b('\x03\x02\x07\x80'))
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001138
1139
1140 def test_add_extensions_wrong_args(self):
1141 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001142 :py:obj:`X509Req.add_extensions` raises :py:obj:`TypeError` if called with the wrong
1143 number of arguments or with a non-:py:obj:`list`. Or it raises :py:obj:`ValueError`
1144 if called with a :py:obj:`list` containing objects other than :py:obj:`X509Extension`
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001145 instances.
1146 """
1147 request = X509Req()
1148 self.assertRaises(TypeError, request.add_extensions)
1149 self.assertRaises(TypeError, request.add_extensions, object())
1150 self.assertRaises(ValueError, request.add_extensions, [object()])
1151 self.assertRaises(TypeError, request.add_extensions, [], None)
1152
1153
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001154 def test_verify_wrong_args(self):
1155 """
1156 :py:obj:`X509Req.verify` raises :py:obj:`TypeError` if called with zero
1157 arguments or more than one argument or if passed anything other than a
1158 :py:obj:`PKey` instance as its single argument.
1159 """
1160 request = X509Req()
1161 self.assertRaises(TypeError, request.verify)
1162 self.assertRaises(TypeError, request.verify, object())
1163 self.assertRaises(TypeError, request.verify, PKey(), object())
1164
1165
1166 def test_verify_uninitialized_key(self):
1167 """
1168 :py:obj:`X509Req.verify` raises :py:obj:`OpenSSL.crypto.Error` if called
1169 with a :py:obj:`OpenSSL.crypto.PKey` which contains no key data.
1170 """
1171 request = X509Req()
1172 pkey = PKey()
1173 self.assertRaises(Error, request.verify, pkey)
1174
1175
1176 def test_verify_wrong_key(self):
1177 """
1178 :py:obj:`X509Req.verify` raises :py:obj:`OpenSSL.crypto.Error` if called
1179 with a :py:obj:`OpenSSL.crypto.PKey` which does not represent the public
1180 part of the key which signed the request.
1181 """
1182 request = X509Req()
1183 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001184 request.sign(pkey, GOOD_DIGEST)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001185 another_pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
1186 self.assertRaises(Error, request.verify, another_pkey)
1187
1188
1189 def test_verify_success(self):
1190 """
1191 :py:obj:`X509Req.verify` returns :py:obj:`True` if called with a
1192 :py:obj:`OpenSSL.crypto.PKey` which represents the public part ofthe key
1193 which signed the request.
1194 """
1195 request = X509Req()
1196 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001197 request.sign(pkey, GOOD_DIGEST)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001198 self.assertEqual(True, request.verify(pkey))
1199
1200
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001201
Jean-Paul Calderone18808652009-07-05 12:54:05 -04001202class X509Tests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001203 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001204 Tests for :py:obj:`OpenSSL.crypto.X509`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001205 """
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001206 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
Jean-Paul Calderone8114b452008-03-25 15:27:59 -04001207
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001208 extpem = """
1209-----BEGIN CERTIFICATE-----
1210MIIC3jCCAkegAwIBAgIJAJHFjlcCgnQzMA0GCSqGSIb3DQEBBQUAMEcxCzAJBgNV
1211BAYTAlNFMRUwEwYDVQQIEwxXZXN0ZXJib3R0b20xEjAQBgNVBAoTCUNhdGFsb2dp
1212eDENMAsGA1UEAxMEUm9vdDAeFw0wODA0MjIxNDQ1MzhaFw0wOTA0MjIxNDQ1Mzha
1213MFQxCzAJBgNVBAYTAlNFMQswCQYDVQQIEwJXQjEUMBIGA1UEChMLT3Blbk1ldGFk
1214aXIxIjAgBgNVBAMTGW5vZGUxLm9tMi5vcGVubWV0YWRpci5vcmcwgZ8wDQYJKoZI
1215hvcNAQEBBQADgY0AMIGJAoGBAPIcQMrwbk2nESF/0JKibj9i1x95XYAOwP+LarwT
1216Op4EQbdlI9SY+uqYqlERhF19w7CS+S6oyqx0DRZSk4Y9dZ9j9/xgm2u/f136YS1u
1217zgYFPvfUs6PqYLPSM8Bw+SjJ+7+2+TN+Tkiof9WP1cMjodQwOmdsiRbR0/J7+b1B
1218hec1AgMBAAGjgcQwgcEwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNT
1219TCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFIdHsBcMVVMbAO7j6NCj
122003HgLnHaMB8GA1UdIwQYMBaAFL2h9Bf9Mre4vTdOiHTGAt7BRY/8MEYGA1UdEQQ/
1221MD2CDSouZXhhbXBsZS5vcmeCESoub20yLmV4bWFwbGUuY29thwSC7wgKgRNvbTJA
1222b3Blbm1ldGFkaXIub3JnMA0GCSqGSIb3DQEBBQUAA4GBALd7WdXkp2KvZ7/PuWZA
1223MPlIxyjS+Ly11+BNE0xGQRp9Wz+2lABtpgNqssvU156+HkKd02rGheb2tj7MX9hG
1224uZzbwDAZzJPjzDQDD7d3cWsrVcfIdqVU7epHqIadnOF+X0ghJ39pAm6VVadnSXCt
1225WpOdIpB8KksUTCzV591Nr1wd
1226-----END CERTIFICATE-----
1227 """
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001228 def signable(self):
1229 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001230 Create and return a new :py:obj:`X509`.
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -04001231 """
1232 return X509()
1233
1234
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001235 def test_type(self):
1236 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001237 :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 -04001238 to create instances of that type.
1239 """
1240 self.assertIdentical(X509, X509Type)
1241 self.assertConsistentType(X509, 'X509')
1242
1243
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001244 def test_construction(self):
1245 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001246 :py:obj:`X509` takes no arguments and returns an instance of :py:obj:`X509Type`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001247 """
1248 certificate = X509()
1249 self.assertTrue(
1250 isinstance(certificate, X509Type),
1251 "%r is of type %r, should be %r" % (certificate,
1252 type(certificate),
1253 X509Type))
Rick Deane15b1472009-07-09 15:53:42 -05001254 self.assertEqual(type(X509Type).__name__, 'type')
1255 self.assertEqual(type(certificate).__name__, 'X509')
1256 self.assertEqual(type(certificate), X509Type)
Rick Dean04113e72009-07-16 12:06:35 -05001257 self.assertEqual(type(certificate), X509)
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001258
1259
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001260 def test_get_version_wrong_args(self):
1261 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001262 :py:obj:`X509.get_version` raises :py:obj:`TypeError` if invoked with any arguments.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001263 """
1264 cert = X509()
1265 self.assertRaises(TypeError, cert.get_version, None)
1266
1267
1268 def test_set_version_wrong_args(self):
1269 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001270 :py:obj:`X509.set_version` raises :py:obj:`TypeError` if invoked with the wrong number
1271 of arguments or an argument not of type :py:obj:`int`.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001272 """
1273 cert = X509()
1274 self.assertRaises(TypeError, cert.set_version)
1275 self.assertRaises(TypeError, cert.set_version, None)
1276 self.assertRaises(TypeError, cert.set_version, 1, None)
1277
1278
1279 def test_version(self):
1280 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001281 :py:obj:`X509.set_version` sets the certificate version number.
1282 :py:obj:`X509.get_version` retrieves it.
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001283 """
1284 cert = X509()
1285 cert.set_version(1234)
1286 self.assertEquals(cert.get_version(), 1234)
1287
1288
1289 def test_get_serial_number_wrong_args(self):
1290 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001291 :py:obj:`X509.get_serial_number` raises :py:obj:`TypeError` if invoked with any
Jean-Paul Calderone3544eb42010-07-30 22:09:47 -04001292 arguments.
1293 """
1294 cert = X509()
1295 self.assertRaises(TypeError, cert.get_serial_number, None)
1296
1297
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001298 def test_serial_number(self):
1299 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001300 The serial number of an :py:obj:`X509Type` can be retrieved and modified with
1301 :py:obj:`X509Type.get_serial_number` and :py:obj:`X509Type.set_serial_number`.
Jean-Paul Calderone78381d22008-03-06 23:35:22 -05001302 """
1303 certificate = X509()
1304 self.assertRaises(TypeError, certificate.set_serial_number)
1305 self.assertRaises(TypeError, certificate.set_serial_number, 1, 2)
1306 self.assertRaises(TypeError, certificate.set_serial_number, "1")
1307 self.assertRaises(TypeError, certificate.set_serial_number, 5.5)
1308 self.assertEqual(certificate.get_serial_number(), 0)
1309 certificate.set_serial_number(1)
1310 self.assertEqual(certificate.get_serial_number(), 1)
1311 certificate.set_serial_number(2 ** 32 + 1)
1312 self.assertEqual(certificate.get_serial_number(), 2 ** 32 + 1)
1313 certificate.set_serial_number(2 ** 64 + 1)
1314 self.assertEqual(certificate.get_serial_number(), 2 ** 64 + 1)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001315 certificate.set_serial_number(2 ** 128 + 1)
1316 self.assertEqual(certificate.get_serial_number(), 2 ** 128 + 1)
1317
1318
1319 def _setBoundTest(self, which):
1320 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001321 :py:obj:`X509Type.set_notBefore` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001322 GENERALIZEDTIME and sets the beginning of the certificate's validity
1323 period to it.
1324 """
1325 certificate = X509()
1326 set = getattr(certificate, 'set_not' + which)
1327 get = getattr(certificate, 'get_not' + which)
1328
Jean-Paul Calderonee0615b52008-03-09 21:44:46 -04001329 # Starts with no value.
1330 self.assertEqual(get(), None)
1331
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001332 # GMT (Or is it UTC?) -exarkun
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001333 when = b("20040203040506Z")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001334 set(when)
1335 self.assertEqual(get(), when)
1336
1337 # A plus two hours and thirty minutes offset
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001338 when = b("20040203040506+0530")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001339 set(when)
1340 self.assertEqual(get(), when)
1341
1342 # A minus one hour fifteen minutes offset
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001343 when = b("20040203040506-0115")
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001344 set(when)
1345 self.assertEqual(get(), when)
1346
1347 # An invalid string results in a ValueError
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001348 self.assertRaises(ValueError, set, b("foo bar"))
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001349
Jean-Paul Calderone31ca2002010-01-30 15:14:43 -05001350 # The wrong number of arguments results in a TypeError.
1351 self.assertRaises(TypeError, set)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001352 self.assertRaises(TypeError, set, b("20040203040506Z"), b("20040203040506Z"))
1353 self.assertRaises(TypeError, get, b("foo bar"))
1354
Jean-Paul Calderone31ca2002010-01-30 15:14:43 -05001355
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001356 # XXX ASN1_TIME (not GENERALIZEDTIME)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001357
1358 def test_set_notBefore(self):
1359 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001360 :py:obj:`X509Type.set_notBefore` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001361 GENERALIZEDTIME and sets the beginning of the certificate's validity
1362 period to it.
1363 """
1364 self._setBoundTest("Before")
1365
1366
1367 def test_set_notAfter(self):
1368 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001369 :py:obj:`X509Type.set_notAfter` takes a string in the format of an ASN1
Jean-Paul Calderone525ef802008-03-09 20:39:42 -04001370 GENERALIZEDTIME and sets the end of the certificate's validity period
1371 to it.
1372 """
1373 self._setBoundTest("After")
Jean-Paul Calderone76576d52008-03-24 16:04:46 -04001374
1375
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001376 def test_get_notBefore(self):
1377 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001378 :py:obj:`X509Type.get_notBefore` returns a string in the format of an ASN1
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001379 GENERALIZEDTIME even for certificates which store it as UTCTIME
1380 internally.
1381 """
Jean-Paul Calderone8114b452008-03-25 15:27:59 -04001382 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001383 self.assertEqual(cert.get_notBefore(), b("20090325123658Z"))
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001384
Rick Dean38a05c82009-07-18 01:41:30 -05001385
1386 def test_get_notAfter(self):
1387 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001388 :py:obj:`X509Type.get_notAfter` returns a string in the format of an ASN1
Rick Dean38a05c82009-07-18 01:41:30 -05001389 GENERALIZEDTIME even for certificates which store it as UTCTIME
1390 internally.
1391 """
1392 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001393 self.assertEqual(cert.get_notAfter(), b("20170611123658Z"))
Rick Dean38a05c82009-07-18 01:41:30 -05001394
1395
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001396 def test_gmtime_adj_notBefore_wrong_args(self):
1397 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001398 :py:obj:`X509Type.gmtime_adj_notBefore` raises :py:obj:`TypeError` if called with the
1399 wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001400 """
1401 cert = X509()
1402 self.assertRaises(TypeError, cert.gmtime_adj_notBefore)
1403 self.assertRaises(TypeError, cert.gmtime_adj_notBefore, None)
1404 self.assertRaises(TypeError, cert.gmtime_adj_notBefore, 123, None)
1405
1406
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001407 def test_gmtime_adj_notBefore(self):
1408 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001409 :py:obj:`X509Type.gmtime_adj_notBefore` changes the not-before timestamp to be
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001410 the current time plus the number of seconds passed in.
1411 """
1412 cert = load_certificate(FILETYPE_PEM, self.pemData)
1413 now = datetime.utcnow() + timedelta(seconds=100)
1414 cert.gmtime_adj_notBefore(100)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001415 self.assertEqual(cert.get_notBefore(), b(now.strftime("%Y%m%d%H%M%SZ")))
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001416
1417
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001418 def test_gmtime_adj_notAfter_wrong_args(self):
1419 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001420 :py:obj:`X509Type.gmtime_adj_notAfter` raises :py:obj:`TypeError` if called with the
1421 wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001422 """
1423 cert = X509()
1424 self.assertRaises(TypeError, cert.gmtime_adj_notAfter)
1425 self.assertRaises(TypeError, cert.gmtime_adj_notAfter, None)
1426 self.assertRaises(TypeError, cert.gmtime_adj_notAfter, 123, None)
1427
1428
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001429 def test_gmtime_adj_notAfter(self):
1430 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001431 :py:obj:`X509Type.gmtime_adj_notAfter` changes the not-after timestamp to be
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001432 the current time plus the number of seconds passed in.
1433 """
1434 cert = load_certificate(FILETYPE_PEM, self.pemData)
1435 now = datetime.utcnow() + timedelta(seconds=100)
1436 cert.gmtime_adj_notAfter(100)
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001437 self.assertEqual(cert.get_notAfter(), b(now.strftime("%Y%m%d%H%M%SZ")))
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001438
1439
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001440 def test_has_expired_wrong_args(self):
1441 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001442 :py:obj:`X509Type.has_expired` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001443 arguments.
1444 """
1445 cert = X509()
1446 self.assertRaises(TypeError, cert.has_expired, None)
1447
1448
1449 def test_has_expired(self):
1450 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001451 :py:obj:`X509Type.has_expired` returns :py:obj:`True` if the certificate's not-after
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001452 time is in the past.
1453 """
1454 cert = X509()
1455 cert.gmtime_adj_notAfter(-1)
1456 self.assertTrue(cert.has_expired())
1457
1458
1459 def test_has_not_expired(self):
1460 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001461 :py:obj:`X509Type.has_expired` returns :py:obj:`False` if the certificate's not-after
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001462 time is in the future.
1463 """
1464 cert = X509()
1465 cert.gmtime_adj_notAfter(2)
1466 self.assertFalse(cert.has_expired())
1467
1468
Rick Dean38a05c82009-07-18 01:41:30 -05001469 def test_digest(self):
1470 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001471 :py:obj:`X509.digest` returns a string giving ":"-separated hex-encoded words
Rick Dean38a05c82009-07-18 01:41:30 -05001472 of the digest of the certificate.
1473 """
1474 cert = X509()
1475 self.assertEqual(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001476 # This is MD5 instead of GOOD_DIGEST because the digest algorithm
1477 # actually matters to the assertion (ie, another arbitrary, good
1478 # digest will not product the same digest).
1479 cert.digest("MD5"),
Jean-Paul Calderonee890db32010-08-22 16:55:15 -04001480 b("A8:EB:07:F8:53:25:0A:F2:56:05:C5:A5:C4:C4:C7:15"))
Rick Dean38a05c82009-07-18 01:41:30 -05001481
1482
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001483 def _extcert(self, pkey, extensions):
1484 cert = X509()
1485 cert.set_pubkey(pkey)
1486 cert.get_subject().commonName = "Unit Tests"
1487 cert.get_issuer().commonName = "Unit Tests"
1488 when = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
1489 cert.set_notBefore(when)
1490 cert.set_notAfter(when)
1491
1492 cert.add_extensions(extensions)
1493 return load_certificate(
1494 FILETYPE_PEM, dump_certificate(FILETYPE_PEM, cert))
1495
1496
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001497 def test_extension_count(self):
1498 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001499 :py:obj:`X509.get_extension_count` returns the number of extensions that are
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001500 present in the certificate.
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001501 """
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001502 pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001503 ca = X509Extension(b('basicConstraints'), True, b('CA:FALSE'))
1504 key = X509Extension(b('keyUsage'), True, b('digitalSignature'))
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001505 subjectAltName = X509Extension(
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001506 b('subjectAltName'), True, b('DNS:example.com'))
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001507
1508 # Try a certificate with no extensions at all.
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001509 c = self._extcert(pkey, [])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001510 self.assertEqual(c.get_extension_count(), 0)
1511
1512 # And a certificate with one
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001513 c = self._extcert(pkey, [ca])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001514 self.assertEqual(c.get_extension_count(), 1)
1515
1516 # And a certificate with several
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001517 c = self._extcert(pkey, [ca, key, subjectAltName])
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -04001518 self.assertEqual(c.get_extension_count(), 3)
Roland Hedberg7e4930e2008-04-22 22:58:50 +02001519
1520
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001521 def test_get_extension(self):
1522 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001523 :py:obj:`X509.get_extension` takes an integer and returns an :py:obj:`X509Extension`
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001524 corresponding to the extension at that index.
1525 """
1526 pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001527 ca = X509Extension(b('basicConstraints'), True, b('CA:FALSE'))
1528 key = X509Extension(b('keyUsage'), True, b('digitalSignature'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001529 subjectAltName = X509Extension(
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001530 b('subjectAltName'), False, b('DNS:example.com'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001531
1532 cert = self._extcert(pkey, [ca, key, subjectAltName])
1533
1534 ext = cert.get_extension(0)
1535 self.assertTrue(isinstance(ext, X509Extension))
1536 self.assertTrue(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001537 self.assertEqual(ext.get_short_name(), b('basicConstraints'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001538
1539 ext = cert.get_extension(1)
1540 self.assertTrue(isinstance(ext, X509Extension))
1541 self.assertTrue(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001542 self.assertEqual(ext.get_short_name(), b('keyUsage'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001543
1544 ext = cert.get_extension(2)
1545 self.assertTrue(isinstance(ext, X509Extension))
1546 self.assertFalse(ext.get_critical())
Jean-Paul Calderone90abbc02011-04-06 18:20:22 -04001547 self.assertEqual(ext.get_short_name(), b('subjectAltName'))
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -04001548
1549 self.assertRaises(IndexError, cert.get_extension, -1)
1550 self.assertRaises(IndexError, cert.get_extension, 4)
1551 self.assertRaises(TypeError, cert.get_extension, "hello")
1552
1553
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001554 def test_nullbyte_subjectAltName(self):
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001555 """
Jean-Paul Calderone9af07b02013-08-23 16:07:31 -04001556 The fields of a `subjectAltName` extension on an X509 may contain NUL
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001557 bytes and this value is reflected in the string representation of the
1558 extension object.
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001559 """
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001560 cert = load_certificate(FILETYPE_PEM, nulbyteSubjectAltNamePEM)
Jean-Paul Calderoneff83cdd2013-08-12 18:05:51 -04001561
1562 ext = cert.get_extension(3)
1563 self.assertEqual(ext.get_short_name(), b('subjectAltName'))
Jean-Paul Calderone4bf75c62013-08-23 15:39:53 -04001564 self.assertEqual(
1565 b("DNS:altnull.python.org\x00example.com, "
1566 "email:null@python.org\x00user@example.org, "
1567 "URI:http://null.python.org\x00http://example.org, "
1568 "IP Address:192.0.2.1, IP Address:2001:DB8:0:0:0:0:0:1\n"),
1569 b(str(ext)))
1570
Rick Dean38a05c82009-07-18 01:41:30 -05001571
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001572 def test_invalid_digest_algorithm(self):
1573 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001574 :py:obj:`X509.digest` raises :py:obj:`ValueError` if called with an unrecognized hash
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001575 algorithm.
1576 """
1577 cert = X509()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001578 self.assertRaises(ValueError, cert.digest, BAD_DIGEST)
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04001579
1580
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001581 def test_get_subject_wrong_args(self):
1582 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001583 :py:obj:`X509.get_subject` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001584 """
1585 cert = X509()
1586 self.assertRaises(TypeError, cert.get_subject, None)
1587
1588
1589 def test_get_subject(self):
1590 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001591 :py:obj:`X509.get_subject` returns an :py:obj:`X509Name` instance.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001592 """
1593 cert = load_certificate(FILETYPE_PEM, self.pemData)
1594 subj = cert.get_subject()
1595 self.assertTrue(isinstance(subj, X509Name))
1596 self.assertEquals(
1597 subj.get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001598 [(b('C'), b('US')), (b('ST'), b('IL')), (b('L'), b('Chicago')),
1599 (b('O'), b('Testing')), (b('CN'), b('Testing Root CA'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001600
1601
1602 def test_set_subject_wrong_args(self):
1603 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001604 :py:obj:`X509.set_subject` raises a :py:obj:`TypeError` if called with the wrong
1605 number of arguments or an argument not of type :py:obj:`X509Name`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001606 """
1607 cert = X509()
1608 self.assertRaises(TypeError, cert.set_subject)
1609 self.assertRaises(TypeError, cert.set_subject, None)
1610 self.assertRaises(TypeError, cert.set_subject, cert.get_subject(), None)
1611
1612
1613 def test_set_subject(self):
1614 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001615 :py:obj:`X509.set_subject` changes the subject of the certificate to the one
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001616 passed in.
1617 """
1618 cert = X509()
1619 name = cert.get_subject()
1620 name.C = 'AU'
1621 name.O = 'Unit Tests'
1622 cert.set_subject(name)
1623 self.assertEquals(
1624 cert.get_subject().get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001625 [(b('C'), b('AU')), (b('O'), b('Unit Tests'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001626
1627
1628 def test_get_issuer_wrong_args(self):
1629 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001630 :py:obj:`X509.get_issuer` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001631 """
1632 cert = X509()
1633 self.assertRaises(TypeError, cert.get_issuer, None)
1634
1635
1636 def test_get_issuer(self):
1637 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001638 :py:obj:`X509.get_issuer` returns an :py:obj:`X509Name` instance.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001639 """
1640 cert = load_certificate(FILETYPE_PEM, self.pemData)
1641 subj = cert.get_issuer()
1642 self.assertTrue(isinstance(subj, X509Name))
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001643 comp = subj.get_components()
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001644 self.assertEquals(
Jean-Paul Calderone30a4cb32010-08-11 23:54:12 -04001645 comp,
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001646 [(b('C'), b('US')), (b('ST'), b('IL')), (b('L'), b('Chicago')),
1647 (b('O'), b('Testing')), (b('CN'), b('Testing Root CA'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001648
1649
1650 def test_set_issuer_wrong_args(self):
1651 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001652 :py:obj:`X509.set_issuer` raises a :py:obj:`TypeError` if called with the wrong
1653 number of arguments or an argument not of type :py:obj:`X509Name`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001654 """
1655 cert = X509()
1656 self.assertRaises(TypeError, cert.set_issuer)
1657 self.assertRaises(TypeError, cert.set_issuer, None)
1658 self.assertRaises(TypeError, cert.set_issuer, cert.get_issuer(), None)
1659
1660
1661 def test_set_issuer(self):
1662 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001663 :py:obj:`X509.set_issuer` changes the issuer of the certificate to the one
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001664 passed in.
1665 """
1666 cert = X509()
1667 name = cert.get_issuer()
1668 name.C = 'AU'
1669 name.O = 'Unit Tests'
1670 cert.set_issuer(name)
1671 self.assertEquals(
1672 cert.get_issuer().get_components(),
Jean-Paul Calderonedc3275f2010-08-22 17:04:09 -04001673 [(b('C'), b('AU')), (b('O'), b('Unit Tests'))])
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001674
1675
1676 def test_get_pubkey_uninitialized(self):
1677 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001678 When called on a certificate with no public key, :py:obj:`X509.get_pubkey`
1679 raises :py:obj:`OpenSSL.crypto.Error`.
Jean-Paul Calderone4f237b22010-07-30 22:29:39 -04001680 """
1681 cert = X509()
1682 self.assertRaises(Error, cert.get_pubkey)
1683
1684
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001685 def test_subject_name_hash_wrong_args(self):
1686 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001687 :py:obj:`X509.subject_name_hash` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001688 arguments.
1689 """
1690 cert = X509()
1691 self.assertRaises(TypeError, cert.subject_name_hash, None)
1692
1693
1694 def test_subject_name_hash(self):
1695 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001696 :py:obj:`X509.subject_name_hash` returns the hash of the certificate's subject
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001697 name.
1698 """
1699 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -04001700 self.assertIn(
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001701 cert.subject_name_hash(),
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -04001702 [3350047874, # OpenSSL 0.9.8, MD5
1703 3278919224, # OpenSSL 1.0.0, SHA1
1704 ])
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001705
1706
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001707 def test_get_signature_algorithm(self):
1708 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001709 :py:obj:`X509Type.get_signature_algorithm` returns a string which means
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001710 the algorithm used to sign the certificate.
1711 """
1712 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001713 self.assertEqual(
1714 b("sha1WithRSAEncryption"), cert.get_signature_algorithm())
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001715
1716
1717 def test_get_undefined_signature_algorithm(self):
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001718 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001719 :py:obj:`X509Type.get_signature_algorithm` raises :py:obj:`ValueError` if the
Jean-Paul Calderone5d8e4052011-05-19 17:51:43 -04001720 signature algorithm is undefined or unknown.
1721 """
1722 # This certificate has been modified to indicate a bogus OID in the
1723 # signature algorithm field so that OpenSSL does not recognize it.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001724 certPEM = b("""\
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001725-----BEGIN CERTIFICATE-----
1726MIIC/zCCAmigAwIBAgIBATAGBgJ8BQUAMHsxCzAJBgNVBAYTAlNHMREwDwYDVQQK
1727EwhNMkNyeXB0bzEUMBIGA1UECxMLTTJDcnlwdG8gQ0ExJDAiBgNVBAMTG00yQ3J5
1728cHRvIENlcnRpZmljYXRlIE1hc3RlcjEdMBsGCSqGSIb3DQEJARYObmdwc0Bwb3N0
1729MS5jb20wHhcNMDAwOTEwMDk1MTMwWhcNMDIwOTEwMDk1MTMwWjBTMQswCQYDVQQG
1730EwJTRzERMA8GA1UEChMITTJDcnlwdG8xEjAQBgNVBAMTCWxvY2FsaG9zdDEdMBsG
1731CSqGSIb3DQEJARYObmdwc0Bwb3N0MS5jb20wXDANBgkqhkiG9w0BAQEFAANLADBI
1732AkEArL57d26W9fNXvOhNlZzlPOACmvwOZ5AdNgLzJ1/MfsQQJ7hHVeHmTAjM664V
1733+fXvwUGJLziCeBo1ysWLRnl8CQIDAQABo4IBBDCCAQAwCQYDVR0TBAIwADAsBglg
1734hkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0O
1735BBYEFM+EgpK+eyZiwFU1aOPSbczbPSpVMIGlBgNVHSMEgZ0wgZqAFPuHI2nrnDqT
1736FeXFvylRT/7tKDgBoX+kfTB7MQswCQYDVQQGEwJTRzERMA8GA1UEChMITTJDcnlw
1737dG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtNMkNyeXB0byBDZXJ0
1738aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tggEA
1739MA0GCSqGSIb3DQEBBAUAA4GBADv8KpPo+gfJxN2ERK1Y1l17sz/ZhzoGgm5XCdbx
1740jEY7xKfpQngV599k1xhl11IMqizDwu0855agrckg2MCTmOI9DZzDD77tAYb+Dk0O
1741PEVk0Mk/V0aIsDE9bolfCi/i/QWZ3N8s5nTWMNyBBBmoSliWCm4jkkRZRD0ejgTN
1742tgI5
1743-----END CERTIFICATE-----
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001744""")
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -04001745 cert = load_certificate(FILETYPE_PEM, certPEM)
1746 self.assertRaises(ValueError, cert.get_signature_algorithm)
Jean-Paul Calderoneccf9d482010-07-30 22:36:42 -04001747
1748
Rick Dean38a05c82009-07-18 01:41:30 -05001749
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001750class X509StoreTests(TestCase):
1751 """
1752 Test for :py:obj:`OpenSSL.crypto.X509Store`.
1753 """
1754 def test_type(self):
1755 """
1756 :py:obj:`X509StoreType` is a type object.
1757 """
1758 self.assertIdentical(X509Store, X509StoreType)
1759 self.assertConsistentType(X509Store, 'X509Store')
1760
1761
1762 def test_add_cert_wrong_args(self):
1763 store = X509Store()
1764 self.assertRaises(TypeError, store.add_cert)
1765 self.assertRaises(TypeError, store.add_cert, object())
1766 self.assertRaises(TypeError, store.add_cert, X509(), object())
1767
1768
1769 def test_add_cert(self):
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001770 """
1771 :py:obj:`X509Store.add_cert` adds a :py:obj:`X509` instance to the
1772 certificate store.
1773 """
1774 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001775 store = X509Store()
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001776 store.add_cert(cert)
1777
1778
1779 def test_add_cert_rejects_duplicate(self):
1780 """
1781 :py:obj:`X509Store.add_cert` raises :py:obj:`OpenSSL.crypto.Error` if an
1782 attempt is made to add the same certificate to the store more than once.
1783 """
1784 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
1785 store = X509Store()
1786 store.add_cert(cert)
1787 self.assertRaises(Error, store.add_cert, cert)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001788
1789
1790
Rick Dean623ee362009-07-17 12:22:16 -05001791class PKCS12Tests(TestCase):
1792 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001793 Test for :py:obj:`OpenSSL.crypto.PKCS12` and :py:obj:`OpenSSL.crypto.load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001794 """
1795 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
1796
Jean-Paul Calderonec3a41f72009-07-25 12:36:02 -04001797 def test_type(self):
1798 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001799 :py:obj:`PKCS12Type` is a type object.
Jean-Paul Calderonec3a41f72009-07-25 12:36:02 -04001800 """
1801 self.assertIdentical(PKCS12, PKCS12Type)
1802 self.assertConsistentType(PKCS12, 'PKCS12')
1803
1804
Rick Deanf94096c2009-07-18 14:23:06 -05001805 def test_empty_construction(self):
Rick Dean38a05c82009-07-18 01:41:30 -05001806 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001807 :py:obj:`PKCS12` returns a new instance of :py:obj:`PKCS12` with no certificate,
Jean-Paul Calderonedc857b52009-07-25 12:25:07 -04001808 private key, CA certificates, or friendly name.
Rick Dean38a05c82009-07-18 01:41:30 -05001809 """
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001810 p12 = PKCS12()
Rick Dean623ee362009-07-17 12:22:16 -05001811 self.assertEqual(None, p12.get_certificate())
1812 self.assertEqual(None, p12.get_privatekey())
1813 self.assertEqual(None, p12.get_ca_certificates())
Rick Dean42d69e12009-07-20 11:36:08 -05001814 self.assertEqual(None, p12.get_friendlyname())
Rick Dean623ee362009-07-17 12:22:16 -05001815
Rick Dean38a05c82009-07-18 01:41:30 -05001816
Rick Dean623ee362009-07-17 12:22:16 -05001817 def test_type_errors(self):
Rick Dean38a05c82009-07-18 01:41:30 -05001818 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001819 The :py:obj:`PKCS12` setter functions (:py:obj:`set_certificate`, :py:obj:`set_privatekey`,
1820 :py:obj:`set_ca_certificates`, and :py:obj:`set_friendlyname`) raise :py:obj:`TypeError`
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001821 when passed objects of types other than those expected.
Rick Dean38a05c82009-07-18 01:41:30 -05001822 """
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001823 p12 = PKCS12()
Rick Dean623ee362009-07-17 12:22:16 -05001824 self.assertRaises(TypeError, p12.set_certificate, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05001825 self.assertRaises(TypeError, p12.set_certificate, PKey())
1826 self.assertRaises(TypeError, p12.set_certificate, X509)
Rick Dean623ee362009-07-17 12:22:16 -05001827 self.assertRaises(TypeError, p12.set_privatekey, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05001828 self.assertRaises(TypeError, p12.set_privatekey, 'legbone')
1829 self.assertRaises(TypeError, p12.set_privatekey, X509())
Rick Dean623ee362009-07-17 12:22:16 -05001830 self.assertRaises(TypeError, p12.set_ca_certificates, 3)
1831 self.assertRaises(TypeError, p12.set_ca_certificates, X509())
1832 self.assertRaises(TypeError, p12.set_ca_certificates, (3, 4))
Rick Deanf94096c2009-07-18 14:23:06 -05001833 self.assertRaises(TypeError, p12.set_ca_certificates, ( PKey(), ))
Rick Dean42d69e12009-07-20 11:36:08 -05001834 self.assertRaises(TypeError, p12.set_friendlyname, 6)
1835 self.assertRaises(TypeError, p12.set_friendlyname, ('foo', 'bar'))
Rick Dean623ee362009-07-17 12:22:16 -05001836
Rick Dean38a05c82009-07-18 01:41:30 -05001837
Rick Dean623ee362009-07-17 12:22:16 -05001838 def test_key_only(self):
1839 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001840 A :py:obj:`PKCS12` with only a private key can be exported using
1841 :py:obj:`PKCS12.export` and loaded again using :py:obj:`load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001842 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001843 passwd = b"blah"
Rick Dean623ee362009-07-17 12:22:16 -05001844 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001845 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001846 p12.set_privatekey(pkey)
Rick Dean623ee362009-07-17 12:22:16 -05001847 self.assertEqual(None, p12.get_certificate())
1848 self.assertEqual(pkey, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05001849 try:
1850 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
1851 except Error:
1852 # Some versions of OpenSSL will throw an exception
1853 # for this nearly useless PKCS12 we tried to generate:
1854 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
1855 return
Rick Dean623ee362009-07-17 12:22:16 -05001856 p12 = load_pkcs12(dumped_p12, passwd)
1857 self.assertEqual(None, p12.get_ca_certificates())
1858 self.assertEqual(None, p12.get_certificate())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001859
1860 # OpenSSL fails to bring the key back to us. So sad. Perhaps in the
1861 # future this will be improved.
1862 self.assertTrue(isinstance(p12.get_privatekey(), (PKey, type(None))))
Rick Dean623ee362009-07-17 12:22:16 -05001863
Rick Dean38a05c82009-07-18 01:41:30 -05001864
Rick Dean623ee362009-07-17 12:22:16 -05001865 def test_cert_only(self):
1866 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001867 A :py:obj:`PKCS12` with only a certificate can be exported using
1868 :py:obj:`PKCS12.export` and loaded again using :py:obj:`load_pkcs12`.
Rick Dean623ee362009-07-17 12:22:16 -05001869 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001870 passwd = b"blah"
Rick Dean623ee362009-07-17 12:22:16 -05001871 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001872 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001873 p12.set_certificate(cert)
Rick Dean623ee362009-07-17 12:22:16 -05001874 self.assertEqual(cert, p12.get_certificate())
1875 self.assertEqual(None, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05001876 try:
1877 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
1878 except Error:
1879 # Some versions of OpenSSL will throw an exception
1880 # for this nearly useless PKCS12 we tried to generate:
1881 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
1882 return
Rick Dean623ee362009-07-17 12:22:16 -05001883 p12 = load_pkcs12(dumped_p12, passwd)
1884 self.assertEqual(None, p12.get_privatekey())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001885
1886 # OpenSSL fails to bring the cert back to us. Groany mcgroan.
1887 self.assertTrue(isinstance(p12.get_certificate(), (X509, type(None))))
1888
1889 # Oh ho. It puts the certificate into the ca certificates list, in
1890 # fact. Totally bogus, I would think. Nevertheless, let's exploit
1891 # that to check to see if it reconstructed the certificate we expected
1892 # it to. At some point, hopefully this will change so that
1893 # p12.get_certificate() is actually what returns the loaded
1894 # certificate.
1895 self.assertEqual(
1896 cleartextCertificatePEM,
1897 dump_certificate(FILETYPE_PEM, p12.get_ca_certificates()[0]))
Rick Dean623ee362009-07-17 12:22:16 -05001898
1899
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001900 def gen_pkcs12(self, cert_pem=None, key_pem=None, ca_pem=None, friendly_name=None):
Rick Dean623ee362009-07-17 12:22:16 -05001901 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001902 Generate a PKCS12 object with components from PEM. Verify that the set
1903 functions return None.
Rick Dean623ee362009-07-17 12:22:16 -05001904 """
Rick Deanf94096c2009-07-18 14:23:06 -05001905 p12 = PKCS12()
1906 if cert_pem:
1907 ret = p12.set_certificate(load_certificate(FILETYPE_PEM, cert_pem))
1908 self.assertEqual(ret, None)
1909 if key_pem:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001910 ret = p12.set_privatekey(load_privatekey(FILETYPE_PEM, key_pem))
Rick Deanf94096c2009-07-18 14:23:06 -05001911 self.assertEqual(ret, None)
1912 if ca_pem:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001913 ret = p12.set_ca_certificates((load_certificate(FILETYPE_PEM, ca_pem),))
Rick Deanf94096c2009-07-18 14:23:06 -05001914 self.assertEqual(ret, None)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001915 if friendly_name:
1916 ret = p12.set_friendlyname(friendly_name)
Rick Dean42d69e12009-07-20 11:36:08 -05001917 self.assertEqual(ret, None)
Rick Deanf94096c2009-07-18 14:23:06 -05001918 return p12
1919
1920
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001921 def check_recovery(self, p12_str, key=None, cert=None, ca=None, passwd=b"",
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001922 extra=()):
Rick Deanf94096c2009-07-18 14:23:06 -05001923 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001924 Use openssl program to confirm three components are recoverable from a
1925 PKCS12 string.
Rick Deanf94096c2009-07-18 14:23:06 -05001926 """
1927 if key:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001928 recovered_key = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001929 p12_str, b"pkcs12", b"-nocerts", b"-nodes", b"-passin",
1930 b"pass:" + passwd, *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001931 self.assertEqual(recovered_key[-len(key):], key)
1932 if cert:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001933 recovered_cert = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001934 p12_str, b"pkcs12", b"-clcerts", b"-nodes", b"-passin",
1935 b"pass:" + passwd, b"-nokeys", *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001936 self.assertEqual(recovered_cert[-len(cert):], cert)
1937 if ca:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001938 recovered_cert = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001939 p12_str, b"pkcs12", b"-cacerts", b"-nodes", b"-passin",
1940 b"pass:" + passwd, b"-nokeys", *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001941 self.assertEqual(recovered_cert[-len(ca):], ca)
1942
1943
Stephen Holsapple38482622014-04-05 20:29:34 -07001944 def verify_pkcs12_container(self, p12):
1945 """
1946 Verify that the PKCS#12 container contains the correct client
1947 certificate and private key.
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04001948
1949 :param p12: The PKCS12 instance to verify.
1950 :type p12: :py:class:`PKCS12`
Stephen Holsapple38482622014-04-05 20:29:34 -07001951 """
1952 cert_pem = dump_certificate(FILETYPE_PEM, p12.get_certificate())
1953 key_pem = dump_privatekey(FILETYPE_PEM, p12.get_privatekey())
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04001954 self.assertEqual(
1955 (client_cert_pem, client_key_pem, None),
1956 (cert_pem, key_pem, p12.get_ca_certificates()))
Stephen Holsapple38482622014-04-05 20:29:34 -07001957
1958
Rick Deanf94096c2009-07-18 14:23:06 -05001959 def test_load_pkcs12(self):
1960 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001961 A PKCS12 string generated using the openssl command line can be loaded
Jonathan Ballet648875f2011-07-16 14:14:58 +09001962 with :py:obj:`load_pkcs12` and its components extracted and examined.
Rick Deanf94096c2009-07-18 14:23:06 -05001963 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001964 passwd = b"whatever"
Rick Dean623ee362009-07-17 12:22:16 -05001965 pem = client_key_pem + client_cert_pem
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001966 p12_str = _runopenssl(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001967 pem, b"pkcs12", b"-export", b"-clcerts", b"-passout", b"pass:" + passwd)
Stephen Holsapple38482622014-04-05 20:29:34 -07001968 p12 = load_pkcs12(p12_str, passphrase=passwd)
1969 self.verify_pkcs12_container(p12)
1970
1971
1972 def test_load_pkcs12_no_passphrase(self):
1973 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04001974 A PKCS12 string generated using openssl command line can be loaded with
1975 :py:obj:`load_pkcs12` without a passphrase and its components extracted
1976 and examined.
Stephen Holsapple38482622014-04-05 20:29:34 -07001977 """
1978 pem = client_key_pem + client_cert_pem
1979 p12_str = _runopenssl(
1980 pem, b"pkcs12", b"-export", b"-clcerts", b"-passout", b"pass:")
1981 p12 = load_pkcs12(p12_str)
1982 self.verify_pkcs12_container(p12)
1983
1984
1985 def _dump_and_load(self, dump_passphrase, load_passphrase):
1986 """
1987 A helper method to dump and load a PKCS12 object.
1988 """
1989 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem)
1990 dumped_p12 = p12.export(passphrase=dump_passphrase, iter=2, maciter=3)
1991 return load_pkcs12(dumped_p12, passphrase=load_passphrase)
1992
1993
1994 def test_load_pkcs12_null_passphrase_load_empty(self):
1995 """
1996 A PKCS12 string can be dumped with a null passphrase, loaded with an
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04001997 empty passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07001998 extracted and examined.
1999 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002000 self.verify_pkcs12_container(
2001 self._dump_and_load(dump_passphrase=None, load_passphrase=b''))
Stephen Holsapple38482622014-04-05 20:29:34 -07002002
2003
2004 def test_load_pkcs12_null_passphrase_load_null(self):
2005 """
2006 A PKCS12 string can be dumped with a null passphrase, loaded with a
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002007 null passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002008 extracted and examined.
2009 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002010 self.verify_pkcs12_container(
2011 self._dump_and_load(dump_passphrase=None, load_passphrase=None))
Stephen Holsapple38482622014-04-05 20:29:34 -07002012
2013
2014 def test_load_pkcs12_empty_passphrase_load_empty(self):
2015 """
2016 A PKCS12 string can be dumped with an empty passphrase, loaded with an
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002017 empty passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002018 extracted and examined.
2019 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002020 self.verify_pkcs12_container(
2021 self._dump_and_load(dump_passphrase=b'', load_passphrase=b''))
Stephen Holsapple38482622014-04-05 20:29:34 -07002022
2023
2024 def test_load_pkcs12_empty_passphrase_load_null(self):
2025 """
2026 A PKCS12 string can be dumped with an empty passphrase, loaded with a
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002027 null passphrase with :py:obj:`load_pkcs12`, and its components
Stephen Holsapple38482622014-04-05 20:29:34 -07002028 extracted and examined.
2029 """
Jean-Paul Calderonef0ff13b2014-05-05 12:48:33 -04002030 self.verify_pkcs12_container(
2031 self._dump_and_load(dump_passphrase=b'', load_passphrase=None))
Rick Deanf94096c2009-07-18 14:23:06 -05002032
Rick Deanee568302009-07-24 09:56:29 -05002033
2034 def test_load_pkcs12_garbage(self):
2035 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002036 :py:obj:`load_pkcs12` raises :py:obj:`OpenSSL.crypto.Error` when passed a string
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002037 which is not a PKCS12 dump.
Rick Deanee568302009-07-24 09:56:29 -05002038 """
2039 passwd = 'whatever'
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002040 e = self.assertRaises(Error, load_pkcs12, b'fruit loops', passwd)
Jean-Paul Calderonede075462014-01-18 10:34:12 -05002041 self.assertEqual( e.args[0][0][0], 'asn1 encoding routines')
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -04002042 self.assertEqual( len(e.args[0][0]), 3)
Rick Deanee568302009-07-24 09:56:29 -05002043
2044
Rick Deanf94096c2009-07-18 14:23:06 -05002045 def test_replace(self):
2046 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002047 :py:obj:`PKCS12.set_certificate` replaces the certificate in a PKCS12 cluster.
2048 :py:obj:`PKCS12.set_privatekey` replaces the private key.
2049 :py:obj:`PKCS12.set_ca_certificates` replaces the CA certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05002050 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002051 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
2052 p12.set_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2053 p12.set_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002054 root_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05002055 client_cert = load_certificate(FILETYPE_PEM, client_cert_pem)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002056 p12.set_ca_certificates([root_cert]) # not a tuple
Rick Dean623ee362009-07-17 12:22:16 -05002057 self.assertEqual(1, len(p12.get_ca_certificates()))
2058 self.assertEqual(root_cert, p12.get_ca_certificates()[0])
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002059 p12.set_ca_certificates([client_cert, root_cert])
Rick Deanf94096c2009-07-18 14:23:06 -05002060 self.assertEqual(2, len(p12.get_ca_certificates()))
2061 self.assertEqual(client_cert, p12.get_ca_certificates()[0])
2062 self.assertEqual(root_cert, p12.get_ca_certificates()[1])
2063
2064
2065 def test_friendly_name(self):
2066 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002067 The *friendlyName* of a PKCS12 can be set and retrieved via
Jonathan Ballet648875f2011-07-16 14:14:58 +09002068 :py:obj:`PKCS12.get_friendlyname` and :py:obj:`PKCS12_set_friendlyname`, and a
2069 :py:obj:`PKCS12` with a friendly name set can be dumped with :py:obj:`PKCS12.export`.
Rick Deanf94096c2009-07-18 14:23:06 -05002070 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002071 passwd = b'Dogmeat[]{}!@#$%^&*()~`?/.,<>-_+=";:'
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002072 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Jean-Paul Calderoneadd7bf02010-08-22 17:38:30 -04002073 for friendly_name in [b('Serverlicious'), None, b('###')]:
Rick Dean42d69e12009-07-20 11:36:08 -05002074 p12.set_friendlyname(friendly_name)
2075 self.assertEqual(p12.get_friendlyname(), friendly_name)
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002076 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
Rick Dean42d69e12009-07-20 11:36:08 -05002077 reloaded_p12 = load_pkcs12(dumped_p12, passwd)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002078 self.assertEqual(
Jean-Paul Calderone9da338d2011-05-04 11:40:54 -04002079 p12.get_friendlyname(), reloaded_p12.get_friendlyname())
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04002080 # We would use the openssl program to confirm the friendly
2081 # name, but it is not possible. The pkcs12 command
2082 # does not store the friendly name in the cert's
Rick Dean42d69e12009-07-20 11:36:08 -05002083 # alias, which we could then extract.
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002084 self.check_recovery(
2085 dumped_p12, key=server_key_pem, cert=server_cert_pem,
2086 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05002087
2088
2089 def test_various_empty_passphrases(self):
2090 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002091 Test that missing, None, and '' passphrases are identical for PKCS12
2092 export.
Rick Deanf94096c2009-07-18 14:23:06 -05002093 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002094 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002095 passwd = b""
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002096 dumped_p12_empty = p12.export(iter=2, maciter=0, passphrase=passwd)
2097 dumped_p12_none = p12.export(iter=3, maciter=2, passphrase=None)
2098 dumped_p12_nopw = p12.export(iter=9, maciter=4)
2099 for dumped_p12 in [dumped_p12_empty, dumped_p12_none, dumped_p12_nopw]:
2100 self.check_recovery(
2101 dumped_p12, key=client_key_pem, cert=client_cert_pem,
2102 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05002103
2104
2105 def test_removing_ca_cert(self):
2106 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002107 Passing :py:obj:`None` to :py:obj:`PKCS12.set_ca_certificates` removes all CA
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002108 certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05002109 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002110 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
2111 p12.set_ca_certificates(None)
Rick Dean623ee362009-07-17 12:22:16 -05002112 self.assertEqual(None, p12.get_ca_certificates())
Rick Deanf94096c2009-07-18 14:23:06 -05002113
2114
2115 def test_export_without_mac(self):
2116 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002117 Exporting a PKCS12 with a :py:obj:`maciter` of ``-1`` excludes the MAC
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002118 entirely.
Rick Deanf94096c2009-07-18 14:23:06 -05002119 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002120 passwd = b"Lake Michigan"
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002121 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Dean623ee362009-07-17 12:22:16 -05002122 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002123 self.check_recovery(
2124 dumped_p12, key=server_key_pem, cert=server_cert_pem,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002125 passwd=passwd, extra=(b"-nomacver",))
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002126
2127
2128 def test_load_without_mac(self):
2129 """
2130 Loading a PKCS12 without a MAC does something other than crash.
2131 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002132 passwd = b"Lake Michigan"
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04002133 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
2134 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Rick Dean321a0512009-08-13 17:21:29 -05002135 try:
2136 recovered_p12 = load_pkcs12(dumped_p12, passwd)
2137 # The person who generated this PCKS12 should be flogged,
2138 # or better yet we should have a means to determine
2139 # whether a PCKS12 had a MAC that was verified.
2140 # Anyway, libopenssl chooses to allow it, so the
2141 # pyopenssl binding does as well.
2142 self.assertTrue(isinstance(recovered_p12, PKCS12))
2143 except Error:
2144 # Failing here with an exception is preferred as some openssl
2145 # versions do.
2146 pass
Rick Dean623ee362009-07-17 12:22:16 -05002147
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002148
Rick Dean25bcc1f2009-07-20 11:53:13 -05002149 def test_zero_len_list_for_ca(self):
2150 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002151 A PKCS12 with an empty CA certificates list can be exported.
Rick Dean25bcc1f2009-07-20 11:53:13 -05002152 """
2153 passwd = 'Hobie 18'
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002154 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002155 # p12.set_ca_certificates([])
2156 # self.assertEqual((), p12.get_ca_certificates())
2157 # dumped_p12 = p12.export(passphrase=passwd, iter=3)
2158 # self.check_recovery(
2159 # dumped_p12, key=server_key_pem, cert=server_cert_pem,
2160 # passwd=passwd)
Rick Dean25bcc1f2009-07-20 11:53:13 -05002161
2162
Rick Deanf94096c2009-07-18 14:23:06 -05002163 def test_export_without_args(self):
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002164 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002165 All the arguments to :py:obj:`PKCS12.export` are optional.
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04002166 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002167 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05002168 dumped_p12 = p12.export() # no args
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002169 self.check_recovery(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002170 dumped_p12, key=server_key_pem, cert=server_cert_pem, passwd=b"")
Rick Deanf94096c2009-07-18 14:23:06 -05002171
2172
2173 def test_key_cert_mismatch(self):
2174 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002175 :py:obj:`PKCS12.export` raises an exception when a key and certificate
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002176 mismatch.
Rick Deanf94096c2009-07-18 14:23:06 -05002177 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04002178 p12 = self.gen_pkcs12(server_cert_pem, client_key_pem, root_cert_pem)
2179 self.assertRaises(Error, p12.export)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002180
2181
2182
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002183# These quoting functions taken directly from Twisted's twisted.python.win32.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002184_cmdLineQuoteRe = re.compile(br'(\\*)"')
2185_cmdLineQuoteRe2 = re.compile(br'(\\+)\Z')
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002186def cmdLineQuote(s):
2187 """
2188 Internal method for quoting a single command-line argument.
2189
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002190 See http://www.perlmonks.org/?node_id=764004
2191
Jonathan Ballet648875f2011-07-16 14:14:58 +09002192 :type: :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002193 :param s: A single unquoted string to quote for something that is expecting
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002194 cmd.exe-style quoting
2195
Jonathan Ballet648875f2011-07-16 14:14:58 +09002196 :rtype: :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002197 :return: A cmd.exe-style quoted string
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002198 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002199 s = _cmdLineQuoteRe2.sub(br"\1\1", _cmdLineQuoteRe.sub(br'\1\1\\"', s))
2200 return b'"' + s + b'"'
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002201
2202
2203
2204def quoteArguments(arguments):
2205 """
2206 Quote an iterable of command-line arguments for passing to CreateProcess or
Jonathan Ballet648875f2011-07-16 14:14:58 +09002207 a similar API. This allows the list passed to :py:obj:`reactor.spawnProcess` to
2208 match the child process's :py:obj:`sys.argv` properly.
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002209
Jonathan Ballet648875f2011-07-16 14:14:58 +09002210 :type arguments: :py:obj:`iterable` of :py:obj:`str`
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002211 :param arguments: An iterable of unquoted arguments to quote
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002212
Jonathan Ballet648875f2011-07-16 14:14:58 +09002213 :rtype: :py:obj:`str`
2214 :return: A space-delimited string containing quoted versions of :py:obj:`arguments`
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002215 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002216 return b' '.join(map(cmdLineQuote, arguments))
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04002217
2218
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002219
Rick Dean4c9ad612009-07-17 15:05:22 -05002220def _runopenssl(pem, *args):
2221 """
2222 Run the command line openssl tool with the given arguments and write
Rick Dean55d1ce62009-08-13 17:40:24 -05002223 the given PEM to its stdin. Not safe for quotes.
Rick Dean4c9ad612009-07-17 15:05:22 -05002224 """
Jean-Paul Calderone038de952009-08-21 12:16:06 -04002225 if os.name == 'posix':
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002226 command = b"openssl " + b" ".join([
2227 (b"'" + arg.replace(b"'", b"'\\''") + b"'")
2228 for arg in args])
Rick Dean55d1ce62009-08-13 17:40:24 -05002229 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002230 command = b"openssl " + quoteArguments(args)
2231 proc = Popen(native(command), shell=True, stdin=PIPE, stdout=PIPE)
Jean-Paul Calderone62ca8da2010-08-11 19:58:08 -04002232 proc.stdin.write(pem)
2233 proc.stdin.close()
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002234 output = proc.stdout.read()
2235 proc.stdout.close()
2236 proc.wait()
2237 return output
Rick Dean4c9ad612009-07-17 15:05:22 -05002238
2239
2240
Jean-Paul Calderone18808652009-07-05 12:54:05 -04002241class FunctionTests(TestCase):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002242 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002243 Tests for free-functions in the :py:obj:`OpenSSL.crypto` module.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002244 """
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002245
2246 def test_load_privatekey_invalid_format(self):
2247 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002248 :py:obj:`load_privatekey` raises :py:obj:`ValueError` if passed an unknown filetype.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002249 """
2250 self.assertRaises(ValueError, load_privatekey, 100, root_key_pem)
2251
2252
2253 def test_load_privatekey_invalid_passphrase_type(self):
2254 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002255 :py:obj:`load_privatekey` raises :py:obj:`TypeError` if passed a passphrase that is
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002256 neither a :py:obj:`str` nor a callable.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002257 """
2258 self.assertRaises(
2259 TypeError,
2260 load_privatekey,
2261 FILETYPE_PEM, encryptedPrivateKeyPEMPassphrase, object())
2262
2263
2264 def test_load_privatekey_wrong_args(self):
2265 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002266 :py:obj:`load_privatekey` raises :py:obj:`TypeError` if called with the wrong number
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002267 of arguments.
2268 """
2269 self.assertRaises(TypeError, load_privatekey)
2270
2271
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002272 def test_load_privatekey_wrongPassphrase(self):
2273 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002274 :py:obj:`load_privatekey` raises :py:obj:`OpenSSL.crypto.Error` when it is passed an
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002275 encrypted PEM and an incorrect passphrase.
2276 """
2277 self.assertRaises(
2278 Error,
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002279 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, b("quack"))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002280
2281
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002282 def test_load_privatekey_passphraseWrongType(self):
2283 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002284 :py:obj:`load_privatekey` raises :py:obj:`ValueError` when it is passed a passphrase
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002285 with a private key encoded in a format, that doesn't support
2286 encryption.
2287 """
2288 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2289 blob = dump_privatekey(FILETYPE_ASN1, key)
2290 self.assertRaises(ValueError,
2291 load_privatekey, FILETYPE_ASN1, blob, "secret")
2292
2293
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002294 def test_load_privatekey_passphrase(self):
2295 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002296 :py:obj:`load_privatekey` can create a :py:obj:`PKey` object from an encrypted PEM
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002297 string if given the passphrase.
2298 """
2299 key = load_privatekey(
2300 FILETYPE_PEM, encryptedPrivateKeyPEM,
2301 encryptedPrivateKeyPEMPassphrase)
2302 self.assertTrue(isinstance(key, PKeyType))
2303
2304
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002305 def test_load_privatekey_passphrase_exception(self):
2306 """
2307 If the passphrase callback raises an exception, that exception is raised
2308 by :py:obj:`load_privatekey`.
2309 """
2310 def cb(ignored):
2311 raise ArithmeticError
2312
2313 self.assertRaises(ArithmeticError,
2314 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2315
2316
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002317 def test_load_privatekey_wrongPassphraseCallback(self):
2318 """
Jean-Paul Calderoned440a082011-09-14 11:02:05 -04002319 :py:obj:`load_privatekey` raises :py:obj:`OpenSSL.crypto.Error` when it
2320 is passed an encrypted PEM and a passphrase callback which returns an
2321 incorrect passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002322 """
2323 called = []
2324 def cb(*a):
2325 called.append(None)
Jean-Paul Calderoned440a082011-09-14 11:02:05 -04002326 return b("quack")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002327 self.assertRaises(
2328 Error,
2329 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2330 self.assertTrue(called)
2331
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002332
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002333 def test_load_privatekey_passphraseCallback(self):
2334 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002335 :py:obj:`load_privatekey` can create a :py:obj:`PKey` object from an encrypted PEM
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002336 string if given a passphrase callback which returns the correct
2337 password.
2338 """
2339 called = []
2340 def cb(writing):
2341 called.append(writing)
2342 return encryptedPrivateKeyPEMPassphrase
2343 key = load_privatekey(FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2344 self.assertTrue(isinstance(key, PKeyType))
2345 self.assertEqual(called, [False])
2346
2347
Jean-Paul Calderone105cb952011-09-14 10:16:46 -04002348 def test_load_privatekey_passphrase_wrong_return_type(self):
2349 """
2350 :py:obj:`load_privatekey` raises :py:obj:`ValueError` if the passphrase
2351 callback returns something other than a byte string.
2352 """
2353 self.assertRaises(
2354 ValueError,
2355 load_privatekey,
2356 FILETYPE_PEM, encryptedPrivateKeyPEM, lambda *args: 3)
2357
2358
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002359 def test_dump_privatekey_wrong_args(self):
2360 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002361 :py:obj:`dump_privatekey` raises :py:obj:`TypeError` if called with the wrong number
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002362 of arguments.
2363 """
2364 self.assertRaises(TypeError, dump_privatekey)
Jean-Paul Calderone1eeccd82011-09-14 10:18:52 -04002365 # If cipher name is given, password is required.
2366 self.assertRaises(
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002367 TypeError, dump_privatekey, FILETYPE_PEM, PKey(), GOOD_CIPHER)
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002368
2369
2370 def test_dump_privatekey_unknown_cipher(self):
2371 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002372 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` if called with an unrecognized
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002373 cipher name.
2374 """
2375 key = PKey()
2376 key.generate_key(TYPE_RSA, 512)
2377 self.assertRaises(
2378 ValueError, dump_privatekey,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002379 FILETYPE_PEM, key, BAD_CIPHER, "passphrase")
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002380
2381
2382 def test_dump_privatekey_invalid_passphrase_type(self):
2383 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002384 :py:obj:`dump_privatekey` raises :py:obj:`TypeError` if called with a passphrase which
2385 is neither a :py:obj:`str` nor a callable.
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002386 """
2387 key = PKey()
2388 key.generate_key(TYPE_RSA, 512)
2389 self.assertRaises(
2390 TypeError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002391 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, object())
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002392
2393
2394 def test_dump_privatekey_invalid_filetype(self):
2395 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002396 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` if called with an unrecognized
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002397 filetype.
2398 """
2399 key = PKey()
2400 key.generate_key(TYPE_RSA, 512)
2401 self.assertRaises(ValueError, dump_privatekey, 100, key)
2402
2403
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002404 def test_load_privatekey_passphraseCallbackLength(self):
2405 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002406 :py:obj:`crypto.load_privatekey` should raise an error when the passphrase
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002407 provided by the callback is too long, not silently truncate it.
2408 """
2409 def cb(ignored):
2410 return "a" * 1025
2411
2412 self.assertRaises(ValueError,
2413 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
2414
2415
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002416 def test_dump_privatekey_passphrase(self):
2417 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002418 :py:obj:`dump_privatekey` writes an encrypted PEM when given a passphrase.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002419 """
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002420 passphrase = b("foo")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002421 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002422 pem = dump_privatekey(FILETYPE_PEM, key, GOOD_CIPHER, passphrase)
2423 self.assertTrue(isinstance(pem, binary_type))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002424 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
2425 self.assertTrue(isinstance(loadedKey, PKeyType))
2426 self.assertEqual(loadedKey.type(), key.type())
2427 self.assertEqual(loadedKey.bits(), key.bits())
2428
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002429
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002430 def test_dump_privatekey_passphraseWrongType(self):
2431 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002432 :py:obj:`dump_privatekey` raises :py:obj:`ValueError` when it is passed a passphrase
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002433 with a private key encoded in a format, that doesn't support
2434 encryption.
2435 """
2436 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2437 self.assertRaises(ValueError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002438 dump_privatekey, FILETYPE_ASN1, key, GOOD_CIPHER, "secret")
Ziga Seilnacht376cf972009-12-22 16:04:10 +01002439
2440
Rick Dean5b7b6372009-04-01 11:34:06 -05002441 def test_dump_certificate(self):
2442 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002443 :py:obj:`dump_certificate` writes PEM, DER, and text.
Rick Dean5b7b6372009-04-01 11:34:06 -05002444 """
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002445 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
Rick Dean5b7b6372009-04-01 11:34:06 -05002446 cert = load_certificate(FILETYPE_PEM, pemData)
2447 dumped_pem = dump_certificate(FILETYPE_PEM, cert)
2448 self.assertEqual(dumped_pem, cleartextCertificatePEM)
2449 dumped_der = dump_certificate(FILETYPE_ASN1, cert)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002450 good_der = _runopenssl(dumped_pem, b"x509", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002451 self.assertEqual(dumped_der, good_der)
2452 cert2 = load_certificate(FILETYPE_ASN1, dumped_der)
2453 dumped_pem2 = dump_certificate(FILETYPE_PEM, cert2)
2454 self.assertEqual(dumped_pem2, cleartextCertificatePEM)
2455 dumped_text = dump_certificate(FILETYPE_TEXT, cert)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002456 good_text = _runopenssl(dumped_pem, b"x509", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002457 self.assertEqual(dumped_text, good_text)
2458
2459
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002460 def test_dump_privatekey_pem(self):
Rick Dean5b7b6372009-04-01 11:34:06 -05002461 """
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002462 :py:obj:`dump_privatekey` writes a PEM
Rick Dean5b7b6372009-04-01 11:34:06 -05002463 """
2464 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -04002465 self.assertTrue(key.check())
Rick Dean5b7b6372009-04-01 11:34:06 -05002466 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2467 self.assertEqual(dumped_pem, cleartextPrivateKeyPEM)
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002468
2469
2470 def test_dump_privatekey_asn1(self):
2471 """
2472 :py:obj:`dump_privatekey` writes a DER
2473 """
2474 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2475 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2476
Rick Dean5b7b6372009-04-01 11:34:06 -05002477 dumped_der = dump_privatekey(FILETYPE_ASN1, key)
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002478 # XXX This OpenSSL call writes "writing RSA key" to standard out. Sad.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002479 good_der = _runopenssl(dumped_pem, b"rsa", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002480 self.assertEqual(dumped_der, good_der)
2481 key2 = load_privatekey(FILETYPE_ASN1, dumped_der)
2482 dumped_pem2 = dump_privatekey(FILETYPE_PEM, key2)
2483 self.assertEqual(dumped_pem2, cleartextPrivateKeyPEM)
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002484
2485
2486 def test_dump_privatekey_text(self):
2487 """
2488 :py:obj:`dump_privatekey` writes a text
2489 """
2490 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2491 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
2492
Rick Dean5b7b6372009-04-01 11:34:06 -05002493 dumped_text = dump_privatekey(FILETYPE_TEXT, key)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002494 good_text = _runopenssl(dumped_pem, b"rsa", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002495 self.assertEqual(dumped_text, good_text)
2496
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04002497
Rick Dean5b7b6372009-04-01 11:34:06 -05002498 def test_dump_certificate_request(self):
2499 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002500 :py:obj:`dump_certificate_request` writes a PEM, DER, and text.
Rick Dean5b7b6372009-04-01 11:34:06 -05002501 """
2502 req = load_certificate_request(FILETYPE_PEM, cleartextCertificateRequestPEM)
2503 dumped_pem = dump_certificate_request(FILETYPE_PEM, req)
2504 self.assertEqual(dumped_pem, cleartextCertificateRequestPEM)
2505 dumped_der = dump_certificate_request(FILETYPE_ASN1, req)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002506 good_der = _runopenssl(dumped_pem, b"req", b"-outform", b"DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05002507 self.assertEqual(dumped_der, good_der)
2508 req2 = load_certificate_request(FILETYPE_ASN1, dumped_der)
2509 dumped_pem2 = dump_certificate_request(FILETYPE_PEM, req2)
2510 self.assertEqual(dumped_pem2, cleartextCertificateRequestPEM)
2511 dumped_text = dump_certificate_request(FILETYPE_TEXT, req)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002512 good_text = _runopenssl(dumped_pem, b"req", b"-noout", b"-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05002513 self.assertEqual(dumped_text, good_text)
Jean-Paul Calderoneaf43cdf2010-08-03 18:40:52 -04002514 self.assertRaises(ValueError, dump_certificate_request, 100, req)
Rick Dean5b7b6372009-04-01 11:34:06 -05002515
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002516
2517 def test_dump_privatekey_passphraseCallback(self):
2518 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002519 :py:obj:`dump_privatekey` writes an encrypted PEM when given a callback which
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002520 returns the correct passphrase.
2521 """
Jean-Paul Calderone5be230f2010-08-22 19:27:58 -04002522 passphrase = b("foo")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002523 called = []
2524 def cb(writing):
2525 called.append(writing)
2526 return passphrase
2527 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002528 pem = dump_privatekey(FILETYPE_PEM, key, GOOD_CIPHER, cb)
2529 self.assertTrue(isinstance(pem, binary_type))
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04002530 self.assertEqual(called, [True])
2531 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
2532 self.assertTrue(isinstance(loadedKey, PKeyType))
2533 self.assertEqual(loadedKey.type(), key.type())
2534 self.assertEqual(loadedKey.bits(), key.bits())
Rick Dean5b7b6372009-04-01 11:34:06 -05002535
2536
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002537 def test_dump_privatekey_passphrase_exception(self):
2538 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002539 :py:obj:`dump_privatekey` should not overwrite the exception raised
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002540 by the passphrase callback.
2541 """
2542 def cb(ignored):
2543 raise ArithmeticError
2544
2545 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2546 self.assertRaises(ArithmeticError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002547 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, cb)
Ziga Seilnacht6b90a402009-12-22 14:33:47 +01002548
2549
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002550 def test_dump_privatekey_passphraseCallbackLength(self):
2551 """
Jean-Paul Calderone5d9d7f12011-09-14 09:48:58 -04002552 :py:obj:`crypto.dump_privatekey` should raise an error when the passphrase
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002553 provided by the callback is too long, not silently truncate it.
2554 """
2555 def cb(ignored):
2556 return "a" * 1025
2557
2558 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2559 self.assertRaises(ValueError,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002560 dump_privatekey, FILETYPE_PEM, key, GOOD_CIPHER, cb)
Ziga Seilnacht781295a2009-12-22 14:58:01 +01002561
2562
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002563 def test_load_pkcs7_data(self):
2564 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002565 :py:obj:`load_pkcs7_data` accepts a PKCS#7 string and returns an instance of
2566 :py:obj:`PKCS7Type`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002567 """
2568 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2569 self.assertTrue(isinstance(pkcs7, PKCS7Type))
2570
2571
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002572 def test_load_pkcs7_data_invalid(self):
2573 """
2574 If the data passed to :py:obj:`load_pkcs7_data` is invalid,
2575 :py:obj:`Error` is raised.
2576 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002577 self.assertRaises(Error, load_pkcs7_data, FILETYPE_PEM, b"foo")
Jean-Paul Calderonee82e3252013-03-03 10:14:10 -08002578
2579
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002580
Jean-Paul Calderone4a68b402013-12-29 16:54:58 -05002581class LoadCertificateTests(TestCase):
2582 """
2583 Tests for :py:obj:`load_certificate_request`.
2584 """
2585 def test_badFileType(self):
2586 """
2587 If the file type passed to :py:obj:`load_certificate_request` is
2588 neither :py:obj:`FILETYPE_PEM` nor :py:obj:`FILETYPE_ASN1` then
2589 :py:class:`ValueError` is raised.
2590 """
2591 self.assertRaises(ValueError, load_certificate_request, object(), b"")
2592
2593
2594
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002595class PKCS7Tests(TestCase):
2596 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002597 Tests for :py:obj:`PKCS7Type`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002598 """
2599 def test_type(self):
2600 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002601 :py:obj:`PKCS7Type` is a type object.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002602 """
2603 self.assertTrue(isinstance(PKCS7Type, type))
2604 self.assertEqual(PKCS7Type.__name__, 'PKCS7')
2605
2606 # XXX This doesn't currently work.
2607 # self.assertIdentical(PKCS7, PKCS7Type)
2608
2609
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002610 # XXX Opposite results for all these following methods
2611
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002612 def test_type_is_signed_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002613 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002614 :py:obj:`PKCS7Type.type_is_signed` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002615 arguments.
2616 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002617 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2618 self.assertRaises(TypeError, pkcs7.type_is_signed, None)
2619
2620
2621 def test_type_is_signed(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002622 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002623 :py:obj:`PKCS7Type.type_is_signed` returns :py:obj:`True` if the PKCS7 object is of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002624 the type *signed*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002625 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002626 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2627 self.assertTrue(pkcs7.type_is_signed())
2628
2629
2630 def test_type_is_enveloped_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002631 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002632 :py:obj:`PKCS7Type.type_is_enveloped` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002633 arguments.
2634 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002635 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2636 self.assertRaises(TypeError, pkcs7.type_is_enveloped, None)
2637
2638
2639 def test_type_is_enveloped(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002640 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002641 :py:obj:`PKCS7Type.type_is_enveloped` returns :py:obj:`False` if the PKCS7 object is
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002642 not of the type *enveloped*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002643 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002644 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2645 self.assertFalse(pkcs7.type_is_enveloped())
2646
2647
2648 def test_type_is_signedAndEnveloped_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002649 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002650 :py:obj:`PKCS7Type.type_is_signedAndEnveloped` raises :py:obj:`TypeError` if called
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002651 with any arguments.
2652 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002653 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2654 self.assertRaises(TypeError, pkcs7.type_is_signedAndEnveloped, None)
2655
2656
2657 def test_type_is_signedAndEnveloped(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002658 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002659 :py:obj:`PKCS7Type.type_is_signedAndEnveloped` returns :py:obj:`False` if the PKCS7
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002660 object is not of the type *signed and enveloped*.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002661 """
Jean-Paul Calderone07c93742010-07-30 10:53:41 -04002662 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2663 self.assertFalse(pkcs7.type_is_signedAndEnveloped())
2664
2665
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002666 def test_type_is_data(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002667 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002668 :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 -04002669 the type data.
2670 """
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002671 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2672 self.assertFalse(pkcs7.type_is_data())
2673
2674
2675 def test_type_is_data_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002676 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002677 :py:obj:`PKCS7Type.type_is_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002678 arguments.
2679 """
Jean-Paul Calderoneb4754b92010-07-30 11:00:08 -04002680 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2681 self.assertRaises(TypeError, pkcs7.type_is_data, None)
2682
2683
Jean-Paul Calderone97b28ca2010-07-30 10:56:07 -04002684 def test_get_type_name_wrong_args(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002685 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002686 :py:obj:`PKCS7Type.get_type_name` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002687 arguments.
2688 """
Jean-Paul Calderone97b28ca2010-07-30 10:56:07 -04002689 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2690 self.assertRaises(TypeError, pkcs7.get_type_name, None)
2691
2692
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002693 def test_get_type_name(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002694 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002695 :py:obj:`PKCS7Type.get_type_name` returns a :py:obj:`str` giving the type name.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002696 """
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002697 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
Jean-Paul Calderone07640f12010-08-22 17:14:43 -04002698 self.assertEquals(pkcs7.get_type_name(), b('pkcs7-signedData'))
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002699
2700
2701 def test_attribute(self):
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002702 """
2703 If an attribute other than one of the methods tested here is accessed on
Jonathan Ballet648875f2011-07-16 14:14:58 +09002704 an instance of :py:obj:`PKCS7Type`, :py:obj:`AttributeError` is raised.
Jean-Paul Calderoneaa6c0692010-09-08 22:43:09 -04002705 """
Jean-Paul Calderone4cbe05e2010-07-30 10:55:30 -04002706 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
2707 self.assertRaises(AttributeError, getattr, pkcs7, "foo")
2708
2709
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002710
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002711class NetscapeSPKITests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002712 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002713 Tests for :py:obj:`OpenSSL.crypto.NetscapeSPKI`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002714 """
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002715 def signable(self):
2716 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002717 Return a new :py:obj:`NetscapeSPKI` for use with signing tests.
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002718 """
2719 return NetscapeSPKI()
2720
2721
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002722 def test_type(self):
2723 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002724 :py:obj:`NetscapeSPKI` and :py:obj:`NetscapeSPKIType` refer to the same type object
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002725 and can be used to create instances of that type.
2726 """
2727 self.assertIdentical(NetscapeSPKI, NetscapeSPKIType)
2728 self.assertConsistentType(NetscapeSPKI, 'NetscapeSPKI')
2729
2730
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002731 def test_construction(self):
2732 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002733 :py:obj:`NetscapeSPKI` returns an instance of :py:obj:`NetscapeSPKIType`.
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002734 """
2735 nspki = NetscapeSPKI()
2736 self.assertTrue(isinstance(nspki, NetscapeSPKIType))
2737
Jean-Paul Calderoneb9725592010-08-03 18:17:22 -04002738
Jean-Paul Calderone969efaa2010-08-03 18:19:19 -04002739 def test_invalid_attribute(self):
2740 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002741 Accessing a non-existent attribute of a :py:obj:`NetscapeSPKI` instance causes
2742 an :py:obj:`AttributeError` to be raised.
Jean-Paul Calderone969efaa2010-08-03 18:19:19 -04002743 """
2744 nspki = NetscapeSPKI()
2745 self.assertRaises(AttributeError, lambda: nspki.foo)
2746
Jean-Paul Calderonefe1b9bd2010-08-03 18:00:21 -04002747
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002748 def test_b64_encode(self):
2749 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002750 :py:obj:`NetscapeSPKI.b64_encode` encodes the certificate to a base64 blob.
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002751 """
2752 nspki = NetscapeSPKI()
2753 blob = nspki.b64_encode()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002754 self.assertTrue(isinstance(blob, binary_type))
Jean-Paul Calderone06ada9f2010-08-03 18:26:52 -04002755
2756
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04002757
Rick Dean536ba022009-07-24 23:57:27 -05002758class RevokedTests(TestCase):
2759 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002760 Tests for :py:obj:`OpenSSL.crypto.Revoked`
Rick Dean536ba022009-07-24 23:57:27 -05002761 """
2762 def test_construction(self):
2763 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002764 Confirm we can create :py:obj:`OpenSSL.crypto.Revoked`. Check
Rick Dean536ba022009-07-24 23:57:27 -05002765 that it is empty.
2766 """
2767 revoked = Revoked()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002768 self.assertTrue(isinstance(revoked, Revoked))
2769 self.assertEquals(type(revoked), Revoked)
2770 self.assertEquals(revoked.get_serial(), b('00'))
2771 self.assertEquals(revoked.get_rev_date(), None)
2772 self.assertEquals(revoked.get_reason(), None)
Rick Dean536ba022009-07-24 23:57:27 -05002773
2774
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002775 def test_construction_wrong_args(self):
2776 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002777 Calling :py:obj:`OpenSSL.crypto.Revoked` with any arguments results
2778 in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002779 """
2780 self.assertRaises(TypeError, Revoked, None)
2781 self.assertRaises(TypeError, Revoked, 1)
2782 self.assertRaises(TypeError, Revoked, "foo")
2783
2784
Rick Dean536ba022009-07-24 23:57:27 -05002785 def test_serial(self):
2786 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002787 Confirm we can set and get serial numbers from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002788 :py:obj:`OpenSSL.crypto.Revoked`. Confirm errors are handled
Rick Dean536ba022009-07-24 23:57:27 -05002789 with grace.
2790 """
2791 revoked = Revoked()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002792 ret = revoked.set_serial(b('10b'))
2793 self.assertEquals(ret, None)
Rick Dean536ba022009-07-24 23:57:27 -05002794 ser = revoked.get_serial()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002795 self.assertEquals(ser, b('010B'))
Rick Dean536ba022009-07-24 23:57:27 -05002796
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002797 revoked.set_serial(b('31ppp')) # a type error would be nice
Rick Dean536ba022009-07-24 23:57:27 -05002798 ser = revoked.get_serial()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002799 self.assertEquals(ser, b('31'))
Rick Dean536ba022009-07-24 23:57:27 -05002800
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002801 self.assertRaises(ValueError, revoked.set_serial, b('pqrst'))
Rick Dean536ba022009-07-24 23:57:27 -05002802 self.assertRaises(TypeError, revoked.set_serial, 100)
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002803 self.assertRaises(TypeError, revoked.get_serial, 1)
2804 self.assertRaises(TypeError, revoked.get_serial, None)
2805 self.assertRaises(TypeError, revoked.get_serial, "")
Rick Dean536ba022009-07-24 23:57:27 -05002806
2807
2808 def test_date(self):
2809 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002810 Confirm we can set and get revocation dates from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002811 :py:obj:`OpenSSL.crypto.Revoked`. Confirm errors are handled
Rick Dean536ba022009-07-24 23:57:27 -05002812 with grace.
2813 """
2814 revoked = Revoked()
2815 date = revoked.get_rev_date()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002816 self.assertEquals(date, None)
Rick Dean536ba022009-07-24 23:57:27 -05002817
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002818 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05002819 ret = revoked.set_rev_date(now)
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002820 self.assertEqual(ret, None)
Rick Dean536ba022009-07-24 23:57:27 -05002821 date = revoked.get_rev_date()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002822 self.assertEqual(date, now)
Rick Dean536ba022009-07-24 23:57:27 -05002823
2824
Rick Dean6385faf2009-07-26 00:07:47 -05002825 def test_reason(self):
2826 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002827 Confirm we can set and get revocation reasons from
Jonathan Ballet648875f2011-07-16 14:14:58 +09002828 :py:obj:`OpenSSL.crypto.Revoked`. The "get" need to work
Rick Dean6385faf2009-07-26 00:07:47 -05002829 as "set". Likewise, each reason of all_reasons() must work.
2830 """
2831 revoked = Revoked()
2832 for r in revoked.all_reasons():
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002833 for x in range(2):
Rick Dean6385faf2009-07-26 00:07:47 -05002834 ret = revoked.set_reason(r)
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002835 self.assertEquals(ret, None)
Rick Dean6385faf2009-07-26 00:07:47 -05002836 reason = revoked.get_reason()
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -04002837 self.assertEquals(
2838 reason.lower().replace(b(' '), b('')),
2839 r.lower().replace(b(' '), b('')))
Rick Dean6385faf2009-07-26 00:07:47 -05002840 r = reason # again with the resp of get
2841
2842 revoked.set_reason(None)
2843 self.assertEqual(revoked.get_reason(), None)
2844
2845
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002846 def test_set_reason_wrong_arguments(self):
Rick Dean6385faf2009-07-26 00:07:47 -05002847 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002848 Calling :py:obj:`OpenSSL.crypto.Revoked.set_reason` with other than
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002849 one argument, or an argument which isn't a valid reason,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002850 results in :py:obj:`TypeError` or :py:obj:`ValueError` being raised.
Rick Dean6385faf2009-07-26 00:07:47 -05002851 """
2852 revoked = Revoked()
2853 self.assertRaises(TypeError, revoked.set_reason, 100)
Jean-Paul Calderone281b62b2010-08-28 14:22:29 -04002854 self.assertRaises(ValueError, revoked.set_reason, b('blue'))
Rick Dean6385faf2009-07-26 00:07:47 -05002855
Rick Dean536ba022009-07-24 23:57:27 -05002856
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002857 def test_get_reason_wrong_arguments(self):
2858 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002859 Calling :py:obj:`OpenSSL.crypto.Revoked.get_reason` with any
2860 arguments results in :py:obj:`TypeError` being raised.
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05002861 """
2862 revoked = Revoked()
2863 self.assertRaises(TypeError, revoked.get_reason, None)
2864 self.assertRaises(TypeError, revoked.get_reason, 1)
2865 self.assertRaises(TypeError, revoked.get_reason, "foo")
2866
2867
2868
Rick Dean536ba022009-07-24 23:57:27 -05002869class CRLTests(TestCase):
2870 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002871 Tests for :py:obj:`OpenSSL.crypto.CRL`
Rick Dean536ba022009-07-24 23:57:27 -05002872 """
2873 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
2874 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
2875
2876 def test_construction(self):
2877 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002878 Confirm we can create :py:obj:`OpenSSL.crypto.CRL`. Check
Rick Dean536ba022009-07-24 23:57:27 -05002879 that it is empty
2880 """
2881 crl = CRL()
2882 self.assertTrue( isinstance(crl, CRL) )
2883 self.assertEqual(crl.get_revoked(), None)
2884
2885
Jean-Paul Calderone2efd03e2010-01-30 13:59:55 -05002886 def test_construction_wrong_args(self):
2887 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002888 Calling :py:obj:`OpenSSL.crypto.CRL` with any number of arguments
2889 results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone2efd03e2010-01-30 13:59:55 -05002890 """
2891 self.assertRaises(TypeError, CRL, 1)
2892 self.assertRaises(TypeError, CRL, "")
2893 self.assertRaises(TypeError, CRL, None)
2894
2895
Rick Dean536ba022009-07-24 23:57:27 -05002896 def test_export(self):
2897 """
2898 Use python to create a simple CRL with a revocation, and export
2899 the CRL in formats of PEM, DER and text. Those outputs are verified
2900 with the openssl program.
2901 """
2902 crl = CRL()
2903 revoked = Revoked()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002904 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05002905 revoked.set_rev_date(now)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002906 revoked.set_serial(b('3ab'))
2907 revoked.set_reason(b('sUpErSeDEd'))
Rick Dean536ba022009-07-24 23:57:27 -05002908 crl.add_revoked(revoked)
2909
2910 # PEM format
2911 dumped_crl = crl.export(self.cert, self.pkey, days=20)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002912 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text")
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002913 text.index(b('Serial Number: 03AB'))
2914 text.index(b('Superseded'))
2915 text.index(b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA'))
Rick Dean536ba022009-07-24 23:57:27 -05002916
2917 # DER format
2918 dumped_crl = crl.export(self.cert, self.pkey, FILETYPE_ASN1)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002919 text = _runopenssl(dumped_crl, b"crl", b"-noout", b"-text", b"-inform", b"DER")
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002920 text.index(b('Serial Number: 03AB'))
2921 text.index(b('Superseded'))
2922 text.index(b('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA'))
Rick Dean536ba022009-07-24 23:57:27 -05002923
2924 # text format
2925 dumped_text = crl.export(self.cert, self.pkey, type=FILETYPE_TEXT)
2926 self.assertEqual(text, dumped_text)
2927
2928
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -04002929 def test_export_invalid(self):
2930 """
2931 If :py:obj:`CRL.export` is used with an uninitialized :py:obj:`X509`
Jean-Paul Calderoneb5871072012-03-09 14:58:00 -08002932 instance, :py:obj:`OpenSSL.crypto.Error` is raised.
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -04002933 """
2934 crl = CRL()
2935 self.assertRaises(Error, crl.export, X509(), PKey())
2936
2937
Jean-Paul Calderone56515342010-01-30 13:49:38 -05002938 def test_add_revoked_keyword(self):
2939 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002940 :py:obj:`OpenSSL.CRL.add_revoked` accepts its single argument as the
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002941 ``revoked`` keyword argument.
Jean-Paul Calderone56515342010-01-30 13:49:38 -05002942 """
2943 crl = CRL()
2944 revoked = Revoked()
2945 crl.add_revoked(revoked=revoked)
2946 self.assertTrue(isinstance(crl.get_revoked()[0], Revoked))
2947
Rick Dean6385faf2009-07-26 00:07:47 -05002948
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05002949 def test_export_wrong_args(self):
2950 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002951 Calling :py:obj:`OpenSSL.CRL.export` with fewer than two or more than
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05002952 four arguments, or with arguments other than the certificate,
2953 private key, integer file type, and integer number of days it
Jonathan Ballet648875f2011-07-16 14:14:58 +09002954 expects, results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05002955 """
2956 crl = CRL()
2957 self.assertRaises(TypeError, crl.export)
2958 self.assertRaises(TypeError, crl.export, self.cert)
2959 self.assertRaises(TypeError, crl.export, self.cert, self.pkey, FILETYPE_PEM, 10, "foo")
2960
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05002961 self.assertRaises(TypeError, crl.export, None, self.pkey, FILETYPE_PEM, 10)
2962 self.assertRaises(TypeError, crl.export, self.cert, None, FILETYPE_PEM, 10)
2963 self.assertRaises(TypeError, crl.export, self.cert, self.pkey, None, 10)
2964 self.assertRaises(TypeError, crl.export, self.cert, FILETYPE_PEM, None)
2965
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05002966
Jean-Paul Calderoneea198422010-01-30 13:58:23 -05002967 def test_export_unknown_filetype(self):
2968 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002969 Calling :py:obj:`OpenSSL.CRL.export` with a file type other than
2970 :py:obj:`FILETYPE_PEM`, :py:obj:`FILETYPE_ASN1`, or :py:obj:`FILETYPE_TEXT` results
2971 in a :py:obj:`ValueError` being raised.
Jean-Paul Calderoneea198422010-01-30 13:58:23 -05002972 """
2973 crl = CRL()
2974 self.assertRaises(ValueError, crl.export, self.cert, self.pkey, 100, 10)
2975
2976
Rick Dean536ba022009-07-24 23:57:27 -05002977 def test_get_revoked(self):
2978 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05002979 Use python to create a simple CRL with two revocations.
Jonathan Ballet648875f2011-07-16 14:14:58 +09002980 Get back the :py:obj:`Revoked` using :py:obj:`OpenSSL.CRL.get_revoked` and
Rick Dean536ba022009-07-24 23:57:27 -05002981 verify them.
2982 """
2983 crl = CRL()
2984
2985 revoked = Revoked()
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002986 now = b(datetime.now().strftime("%Y%m%d%H%M%SZ"))
Rick Dean536ba022009-07-24 23:57:27 -05002987 revoked.set_rev_date(now)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002988 revoked.set_serial(b('3ab'))
Rick Dean536ba022009-07-24 23:57:27 -05002989 crl.add_revoked(revoked)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002990 revoked.set_serial(b('100'))
2991 revoked.set_reason(b('sUpErSeDEd'))
Rick Dean536ba022009-07-24 23:57:27 -05002992 crl.add_revoked(revoked)
2993
2994 revs = crl.get_revoked()
2995 self.assertEqual(len(revs), 2)
2996 self.assertEqual(type(revs[0]), Revoked)
2997 self.assertEqual(type(revs[1]), Revoked)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04002998 self.assertEqual(revs[0].get_serial(), b('03AB'))
2999 self.assertEqual(revs[1].get_serial(), b('0100'))
Rick Dean536ba022009-07-24 23:57:27 -05003000 self.assertEqual(revs[0].get_rev_date(), now)
3001 self.assertEqual(revs[1].get_rev_date(), now)
3002
3003
Jean-Paul Calderone46bdce42010-01-30 13:44:16 -05003004 def test_get_revoked_wrong_args(self):
3005 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003006 Calling :py:obj:`OpenSSL.CRL.get_revoked` with any arguments results
3007 in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone46bdce42010-01-30 13:44:16 -05003008 """
3009 crl = CRL()
3010 self.assertRaises(TypeError, crl.get_revoked, None)
3011 self.assertRaises(TypeError, crl.get_revoked, 1)
3012 self.assertRaises(TypeError, crl.get_revoked, "")
3013 self.assertRaises(TypeError, crl.get_revoked, "", 1, None)
3014
3015
Jean-Paul Calderoneecef6fa2010-01-30 13:47:18 -05003016 def test_add_revoked_wrong_args(self):
3017 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003018 Calling :py:obj:`OpenSSL.CRL.add_revoked` with other than one
3019 argument results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderoneecef6fa2010-01-30 13:47:18 -05003020 """
3021 crl = CRL()
3022 self.assertRaises(TypeError, crl.add_revoked)
3023 self.assertRaises(TypeError, crl.add_revoked, 1, 2)
3024 self.assertRaises(TypeError, crl.add_revoked, "foo", "bar")
3025
3026
Rick Dean536ba022009-07-24 23:57:27 -05003027 def test_load_crl(self):
3028 """
3029 Load a known CRL and inspect its revocations. Both
3030 PEM and DER formats are loaded.
3031 """
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003032 crl = load_crl(FILETYPE_PEM, crlData)
Rick Dean536ba022009-07-24 23:57:27 -05003033 revs = crl.get_revoked()
3034 self.assertEqual(len(revs), 2)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003035 self.assertEqual(revs[0].get_serial(), b('03AB'))
Rick Dean6385faf2009-07-26 00:07:47 -05003036 self.assertEqual(revs[0].get_reason(), None)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003037 self.assertEqual(revs[1].get_serial(), b('0100'))
3038 self.assertEqual(revs[1].get_reason(), b('Superseded'))
Rick Dean536ba022009-07-24 23:57:27 -05003039
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003040 der = _runopenssl(crlData, b"crl", b"-outform", b"DER")
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05003041 crl = load_crl(FILETYPE_ASN1, der)
Rick Dean536ba022009-07-24 23:57:27 -05003042 revs = crl.get_revoked()
3043 self.assertEqual(len(revs), 2)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003044 self.assertEqual(revs[0].get_serial(), b('03AB'))
Rick Dean6385faf2009-07-26 00:07:47 -05003045 self.assertEqual(revs[0].get_reason(), None)
Jean-Paul Calderoneb894fe12010-08-22 19:30:19 -04003046 self.assertEqual(revs[1].get_serial(), b('0100'))
3047 self.assertEqual(revs[1].get_reason(), b('Superseded'))
Rick Dean536ba022009-07-24 23:57:27 -05003048
3049
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003050 def test_load_crl_wrong_args(self):
3051 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003052 Calling :py:obj:`OpenSSL.crypto.load_crl` with other than two
3053 arguments results in a :py:obj:`TypeError` being raised.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003054 """
3055 self.assertRaises(TypeError, load_crl)
3056 self.assertRaises(TypeError, load_crl, FILETYPE_PEM)
3057 self.assertRaises(TypeError, load_crl, FILETYPE_PEM, crlData, None)
3058
3059
3060 def test_load_crl_bad_filetype(self):
3061 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003062 Calling :py:obj:`OpenSSL.crypto.load_crl` with an unknown file type
3063 raises a :py:obj:`ValueError`.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003064 """
3065 self.assertRaises(ValueError, load_crl, 100, crlData)
3066
3067
3068 def test_load_crl_bad_data(self):
3069 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003070 Calling :py:obj:`OpenSSL.crypto.load_crl` with file data which can't
3071 be loaded raises a :py:obj:`OpenSSL.crypto.Error`.
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003072 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003073 self.assertRaises(Error, load_crl, FILETYPE_PEM, b"hello, world")
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05003074
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04003075
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -05003076
James Yonan7c2e5d32010-02-27 05:45:50 -07003077class SignVerifyTests(TestCase):
3078 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003079 Tests for :py:obj:`OpenSSL.crypto.sign` and :py:obj:`OpenSSL.crypto.verify`.
James Yonan7c2e5d32010-02-27 05:45:50 -07003080 """
3081 def test_sign_verify(self):
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04003082 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003083 :py:obj:`sign` generates a cryptographic signature which :py:obj:`verify` can check.
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04003084 """
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003085 content = b(
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04003086 "It was a bright cold day in April, and the clocks were striking "
3087 "thirteen. Winston Smith, his chin nuzzled into his breast in an "
3088 "effort to escape the vile wind, slipped quickly through the "
3089 "glass doors of Victory Mansions, though not quickly enough to "
3090 "prevent a swirl of gritty dust from entering along with him.")
3091
3092 # sign the content with this private key
Jean-Paul Calderonef3cb9d82010-06-22 10:29:33 -04003093 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04003094 # verify the content with this cert
3095 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3096 # certificate unrelated to priv_key, used to trigger an error
3097 bad_cert = load_certificate(FILETYPE_PEM, server_cert_pem)
James Yonan7c2e5d32010-02-27 05:45:50 -07003098
Jean-Paul Calderoned08feb02010-10-12 21:53:24 -04003099 for digest in ['md5', 'sha1']:
James Yonan7c2e5d32010-02-27 05:45:50 -07003100 sig = sign(priv_key, content, digest)
3101
3102 # Verify the signature of content, will throw an exception if error.
3103 verify(good_cert, sig, content, digest)
3104
3105 # This should fail because the certificate doesn't match the
3106 # private key that was used to sign the content.
3107 self.assertRaises(Error, verify, bad_cert, sig, content, digest)
3108
3109 # This should fail because we've "tainted" the content after
3110 # signing it.
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003111 self.assertRaises(
3112 Error, verify,
3113 good_cert, sig, content + b("tainted"), digest)
James Yonan7c2e5d32010-02-27 05:45:50 -07003114
3115 # test that unknown digest types fail
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003116 self.assertRaises(
Jean-Paul Calderone9538f142010-10-13 22:13:40 -04003117 ValueError, sign, priv_key, content, "strange-digest")
Jean-Paul Calderoneea305c52010-08-28 14:41:07 -04003118 self.assertRaises(
Jean-Paul Calderone9538f142010-10-13 22:13:40 -04003119 ValueError, verify, good_cert, sig, content, "strange-digest")
James Yonan7c2e5d32010-02-27 05:45:50 -07003120
Jean-Paul Calderoneb98ce212010-06-22 09:46:27 -04003121
Jean-Paul Calderone9828f662010-12-08 22:57:26 -05003122 def test_sign_nulls(self):
3123 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003124 :py:obj:`sign` produces a signature for a string with embedded nulls.
Jean-Paul Calderone9828f662010-12-08 22:57:26 -05003125 """
3126 content = b("Watch out! \0 Did you see it?")
3127 priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
3128 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
3129 sig = sign(priv_key, content, "sha1")
3130 verify(good_cert, sig, content, "sha1")
3131
3132
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003133
3134class EllipticCurveTests(TestCase):
3135 """
3136 Tests for :py:class:`_EllipticCurve`, :py:obj:`get_elliptic_curve`, and
3137 :py:obj:`get_elliptic_curves`.
3138 """
3139 def test_set(self):
3140 """
3141 :py:obj:`get_elliptic_curves` returns a :py:obj:`set`.
3142 """
3143 self.assertIsInstance(get_elliptic_curves(), set)
3144
3145
3146 def test_some_curves(self):
3147 """
3148 If :py:mod:`cryptography` has elliptic curve support then the set
3149 returned by :py:obj:`get_elliptic_curves` has some elliptic curves in
3150 it.
3151
3152 There could be an OpenSSL that violates this assumption. If so, this
3153 test will fail and we'll find out.
3154 """
3155 curves = get_elliptic_curves()
3156 if lib.Cryptography_HAS_EC:
3157 self.assertTrue(curves)
3158 else:
3159 self.assertFalse(curves)
3160
3161
3162 def test_a_curve(self):
3163 """
3164 :py:obj:`get_elliptic_curve` can be used to retrieve a particular
3165 supported curve.
3166 """
3167 curves = get_elliptic_curves()
3168 if curves:
3169 curve = next(iter(curves))
3170 self.assertEqual(curve.name, get_elliptic_curve(curve.name).name)
3171 else:
Jean-Paul Calderoneeb86f3a2014-04-19 09:45:57 -04003172 self.assertRaises(ValueError, get_elliptic_curve, u("prime256v1"))
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003173
3174
3175 def test_not_a_curve(self):
3176 """
3177 :py:obj:`get_elliptic_curve` raises :py:class:`ValueError` if called
3178 with a name which does not identify a supported curve.
3179 """
3180 self.assertRaises(
Jean-Paul Calderone5a82db92014-04-19 09:51:29 -04003181 ValueError, get_elliptic_curve, u("this curve was just invented"))
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04003182
3183
3184 def test_repr(self):
3185 """
3186 The string representation of a curve object includes simply states the
3187 object is a curve and what its name is.
3188 """
3189 curves = get_elliptic_curves()
3190 if curves:
3191 curve = next(iter(curves))
3192 self.assertEqual("<Curve %r>" % (curve.name,), repr(curve))
3193
3194
3195 def test_to_EC_KEY(self):
3196 """
3197 The curve object can export a version of itself as an EC_KEY* via the
3198 private :py:meth:`_EllipticCurve._to_EC_KEY`.
3199 """
3200 curves = get_elliptic_curves()
3201 if curves:
3202 curve = next(iter(curves))
3203 # It's not easy to assert anything about this object. However, see
3204 # leakcheck/crypto.py for a test that demonstrates it at least does
3205 # not leak memory.
3206 curve._to_EC_KEY()
3207
3208
Jean-Paul Calderone1be77082014-04-30 18:17:41 -04003209
3210class EllipticCurveFactory(object):
3211 """
3212 A helper to get the names of two curves.
3213 """
3214 def __init__(self):
3215 curves = iter(get_elliptic_curves())
3216 try:
3217 self.curve_name = next(curves).name
3218 self.another_curve_name = next(curves).name
3219 except StopIteration:
3220 self.curve_name = self.another_curve_name = None
3221
3222
3223
3224class EllipticCurveEqualityTests(TestCase, EqualityTestsMixin):
3225 """
3226 Tests :py:type:`_EllipticCurve`\ 's implementation of ``==`` and ``!=``.
3227 """
3228 curve_factory = EllipticCurveFactory()
3229
3230 if curve_factory.curve_name is None:
3231 skip = "There are no curves available there can be no curve objects."
3232
3233
3234 def anInstance(self):
3235 """
3236 Get the curve object for an arbitrary curve supported by the system.
3237 """
3238 return get_elliptic_curve(self.curve_factory.curve_name)
3239
3240
3241 def anotherInstance(self):
3242 """
3243 Get the curve object for an arbitrary curve supported by the system -
3244 but not the one returned by C{anInstance}.
3245 """
3246 return get_elliptic_curve(self.curve_factory.another_curve_name)
3247
3248
3249
Jean-Paul Calderone22c31242014-05-01 07:49:47 -04003250class EllipticCurveHashTests(TestCase):
3251 """
3252 Tests for :py:type:`_EllipticCurve`\ 's implementation of hashing (thus use
3253 as an item in a :py:type:`dict` or :py:type:`set`).
3254 """
3255 curve_factory = EllipticCurveFactory()
3256
3257 if curve_factory.curve_name is None:
3258 skip = "There are no curves available there can be no curve objects."
3259
3260
3261 def test_contains(self):
3262 """
3263 The ``in`` operator reports that a :py:type:`set` containing a curve
3264 does contain that curve.
3265 """
3266 curve = get_elliptic_curve(self.curve_factory.curve_name)
3267 curves = set([curve])
3268 self.assertIn(curve, curves)
3269
3270
3271 def test_does_not_contain(self):
3272 """
3273 The ``in`` operator reports that a :py:type:`set` not containing a
3274 curve does not contain that curve.
3275 """
3276 curve = get_elliptic_curve(self.curve_factory.curve_name)
3277 curves = set([get_elliptic_curve(self.curve_factory.another_curve_name)])
3278 self.assertNotIn(curve, curves)
3279
3280
3281
Rick Dean5b7b6372009-04-01 11:34:06 -05003282if __name__ == '__main__':
3283 main()