blob: ae99fc5e621a52aa14a7bc6cb9e0859a1a56f9b2 [file] [log] [blame]
Jean-Paul Calderone8b63d452008-03-21 18:31:12 -04001# Copyright (C) Jean-Paul Calderone 2008, All rights reserved
2
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -05003"""
4Unit tests for L{OpenSSL.crypto}.
5"""
6
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04007from unittest import main
8
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04009import os, re
Jean-Paul Calderone653f5582009-04-01 14:42:32 -040010from os import popen2
Rick Dean47262da2009-07-08 16:17:17 -050011from datetime import datetime, timedelta
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -050012
13from OpenSSL.crypto import TYPE_RSA, TYPE_DSA, Error, PKey, PKeyType
Jean-Paul Calderone78381d22008-03-06 23:35:22 -050014from OpenSSL.crypto import X509, X509Type, X509Name, X509NameType
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -050015from OpenSSL.crypto import X509Req, X509ReqType
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -050016from OpenSSL.crypto import X509Extension, X509ExtensionType
Rick Dean5b7b6372009-04-01 11:34:06 -050017from OpenSSL.crypto import load_certificate, load_privatekey
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -040018from OpenSSL.crypto import FILETYPE_PEM, FILETYPE_ASN1, FILETYPE_TEXT
Jean-Paul Calderone71919862009-04-01 13:01:19 -040019from OpenSSL.crypto import dump_certificate, load_certificate_request
20from OpenSSL.crypto import dump_certificate_request, dump_privatekey
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -040021from OpenSSL.crypto import PKCS7Type, load_pkcs7_data
Jean-Paul Calderone9178ee62010-01-25 17:55:30 -050022from OpenSSL.crypto import PKCS12, PKCS12Type, load_pkcs12
Rick Dean536ba022009-07-24 23:57:27 -050023from OpenSSL.crypto import CRL, Revoked, load_crl
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -040024from OpenSSL.crypto import NetscapeSPKI, NetscapeSPKIType
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -040025from OpenSSL.test.util import TestCase
Rick Dean94e46fd2009-07-18 14:51:24 -050026
27
28root_cert_pem = """-----BEGIN CERTIFICATE-----
29MIIC7TCCAlagAwIBAgIIPQzE4MbeufQwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE
30BhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdU
31ZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwIhgPMjAwOTAzMjUxMjM2
32NThaGA8yMDE3MDYxMTEyMzY1OFowWDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklM
33MRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9U
34ZXN0aW5nIFJvb3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPmaQumL
35urpE527uSEHdL1pqcDRmWzu+98Y6YHzT/J7KWEamyMCNZ6fRW1JCR782UQ8a07fy
362xXsKy4WdKaxyG8CcatwmXvpvRQ44dSANMihHELpANTdyVp6DCysED6wkQFurHlF
371dshEaJw8b/ypDhmbVIo6Ci1xvCJqivbLFnbAgMBAAGjgbswgbgwHQYDVR0OBBYE
38FINVdy1eIfFJDAkk51QJEo3IfgSuMIGIBgNVHSMEgYAwfoAUg1V3LV4h8UkMCSTn
39VAkSjch+BK6hXKRaMFgxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UE
40BxMHQ2hpY2FnbzEQMA4GA1UEChMHVGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBS
41b290IENBggg9DMTgxt659DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB
42AGGCDazMJGoWNBpc03u6+smc95dEead2KlZXBATOdFT1VesY3+nUOqZhEhTGlDMi
43hkgaZnzoIq/Uamidegk4hirsCT/R+6vsKAAxNTcBjUeZjlykCJWy5ojShGftXIKY
44w/njVbKMXrvc83qmTdGl3TAM0fxQIpqgcglFLveEBgzn
45-----END CERTIFICATE-----
46"""
47
48root_key_pem = """-----BEGIN RSA PRIVATE KEY-----
49MIICXQIBAAKBgQD5mkLpi7q6ROdu7khB3S9aanA0Zls7vvfGOmB80/yeylhGpsjA
50jWen0VtSQke/NlEPGtO38tsV7CsuFnSmschvAnGrcJl76b0UOOHUgDTIoRxC6QDU
513claegwsrBA+sJEBbqx5RdXbIRGicPG/8qQ4Zm1SKOgotcbwiaor2yxZ2wIDAQAB
52AoGBAPCgMpmLxzwDaUmcFbTJUvlLW1hoxNNYSu2jIZm1k/hRAcE60JYwvBkgz3UB
53yMEh0AtLxYe0bFk6EHah11tMUPgscbCq73snJ++8koUw+csk22G65hOs51bVb7Aa
546JBe67oLzdtvgCUFAA2qfrKzWRZzAdhUirQUZgySZk+Xq1pBAkEA/kZG0A6roTSM
55BVnx7LnPfsycKUsTumorpXiylZJjTi9XtmzxhrYN6wgZlDOOwOLgSQhszGpxVoMD
56u3gByT1b2QJBAPtL3mSKdvwRu/+40zaZLwvSJRxaj0mcE4BJOS6Oqs/hS1xRlrNk
57PpQ7WJ4yM6ZOLnXzm2mKyxm50Mv64109FtMCQQDOqS2KkjHaLowTGVxwC0DijMfr
58I9Lf8sSQk32J5VWCySWf5gGTfEnpmUa41gKTMJIbqZZLucNuDcOtzUaeWZlZAkA8
59ttXigLnCqR486JDPTi9ZscoZkZ+w7y6e/hH8t6d5Vjt48JVyfjPIaJY+km58LcN3
606AWSeGAdtRFHVzR7oHjVAkB4hutvxiOeiIVQNBhM6RSI9aBPMI21DoX2JRoxvNW2
61cbvAhow217X9V0dVerEOKxnNYspXRrh36h7k4mQA+sDq
62-----END RSA PRIVATE KEY-----
63"""
64
65server_cert_pem = """-----BEGIN CERTIFICATE-----
66MIICKDCCAZGgAwIBAgIJAJn/HpR21r/8MA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
67BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
68VGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBSb290IENBMCIYDzIwMDkwMzI1MTIz
69NzUzWhgPMjAxNzA2MTExMjM3NTNaMBgxFjAUBgNVBAMTDWxvdmVseSBzZXJ2ZXIw
70gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAL6m+G653V0tpBC/OKl22VxOi2Cv
71lK4TYu9LHSDP9uDVTe7V5D5Tl6qzFoRRx5pfmnkqT5B+W9byp2NU3FC5hLm5zSAr
72b45meUhjEJ/ifkZgbNUjHdBIGP9MAQUHZa5WKdkGIJvGAvs8UzUqlr4TBWQIB24+
73lJ+Ukk/CRgasrYwdAgMBAAGjNjA0MB0GA1UdDgQWBBS4kC7Ij0W1TZXZqXQFAM2e
74gKEG2DATBgNVHSUEDDAKBggrBgEFBQcDATANBgkqhkiG9w0BAQUFAAOBgQBh30Li
75dJ+NlxIOx5343WqIBka3UbsOb2kxWrbkVCrvRapCMLCASO4FqiKWM+L0VDBprqIp
762mgpFQ6FHpoIENGvJhdEKpptQ5i7KaGhnDNTfdy3x1+h852G99f1iyj0RmbuFcM8
77uzujnS8YXWvM7DM1Ilozk4MzPug8jzFp5uhKCQ==
78-----END CERTIFICATE-----
79"""
80
81server_key_pem = """-----BEGIN RSA PRIVATE KEY-----
82MIICWwIBAAKBgQC+pvhuud1dLaQQvzipdtlcTotgr5SuE2LvSx0gz/bg1U3u1eQ+
83U5eqsxaEUceaX5p5Kk+QflvW8qdjVNxQuYS5uc0gK2+OZnlIYxCf4n5GYGzVIx3Q
84SBj/TAEFB2WuVinZBiCbxgL7PFM1Kpa+EwVkCAduPpSflJJPwkYGrK2MHQIDAQAB
85AoGAbwuZ0AR6JveahBaczjfnSpiFHf+mve2UxoQdpyr6ROJ4zg/PLW5K/KXrC48G
86j6f3tXMrfKHcpEoZrQWUfYBRCUsGD5DCazEhD8zlxEHahIsqpwA0WWssJA2VOLEN
87j6DuV2pCFbw67rfTBkTSo32ahfXxEKev5KswZk0JIzH3ooECQQDgzS9AI89h0gs8
88Dt+1m11Rzqo3vZML7ZIyGApUzVan+a7hbc33nbGRkAXjHaUBJO31it/H6dTO+uwX
89msWwNG5ZAkEA2RyFKs5xR5USTFaKLWCgpH/ydV96KPOpBND7TKQx62snDenFNNbn
90FwwOhpahld+vqhYk+pfuWWUpQciE+Bu7ZQJASjfT4sQv4qbbKK/scePicnDdx9th
914e1EeB9xwb+tXXXUo/6Bor/AcUNwfiQ6Zt9PZOK9sR3lMZSsP7rMi7kzuQJABie6
921sXXjFH7nNJvRG4S39cIxq8YRYTy68II/dlB2QzGpKxV/POCxbJ/zu0CU79tuYK7
93NaeNCFfH3aeTrX0LyQJAMBWjWmeKM2G2sCExheeQK0ROnaBC8itCECD4Jsve4nqf
94r50+LF74iLXFwqysVCebPKMOpDWp/qQ1BbJQIPs7/A==
95-----END RSA PRIVATE KEY-----
96"""
97
98client_cert_pem = """-----BEGIN CERTIFICATE-----
99MIICJjCCAY+gAwIBAgIJAKxpFI5lODkjMA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
100BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
101VGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBSb290IENBMCIYDzIwMDkwMzI1MTIz
102ODA1WhgPMjAxNzA2MTExMjM4MDVaMBYxFDASBgNVBAMTC3VnbHkgY2xpZW50MIGf
103MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDAZh/SRtNm5ntMT4qb6YzEpTroMlq2
104rn+GrRHRiZ+xkCw/CGNhbtPir7/QxaUj26BSmQrHw1bGKEbPsWiW7bdXSespl+xK
105iku4G/KvnnmWdeJHqsiXeUZtqurMELcPQAw9xPHEuhqqUJvvEoMTsnCEqGM+7Dtb
106oCRajYyHfluARQIDAQABozYwNDAdBgNVHQ4EFgQUNQB+qkaOaEVecf1J3TTUtAff
1070fAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQEFBQADgYEAyv/Jh7gM
108Q3OHvmsFEEvRI+hsW8y66zK4K5de239Y44iZrFYkt7Q5nBPMEWDj4F2hLYWL/qtI
1099Zdr0U4UDCU9SmmGYh4o7R4TZ5pGFvBYvjhHbkSFYFQXZxKUi+WUxplP6I0wr2KJ
110PSTJCjJOn3xo2NTKRgV1gaoTf2EhL+RG8TQ=
111-----END CERTIFICATE-----
112"""
113
114client_key_pem = """-----BEGIN RSA PRIVATE KEY-----
115MIICXgIBAAKBgQDAZh/SRtNm5ntMT4qb6YzEpTroMlq2rn+GrRHRiZ+xkCw/CGNh
116btPir7/QxaUj26BSmQrHw1bGKEbPsWiW7bdXSespl+xKiku4G/KvnnmWdeJHqsiX
117eUZtqurMELcPQAw9xPHEuhqqUJvvEoMTsnCEqGM+7DtboCRajYyHfluARQIDAQAB
118AoGATkZ+NceY5Glqyl4mD06SdcKfV65814vg2EL7V9t8+/mi9rYL8KztSXGlQWPX
119zuHgtRoMl78yQ4ZJYOBVo+nsx8KZNRCEBlE19bamSbQLCeQMenWnpeYyQUZ908gF
120h6L9qsFVJepgA9RDgAjyDoS5CaWCdCCPCH2lDkdcqC54SVUCQQDseuduc4wi8h4t
121V8AahUn9fn9gYfhoNuM0gdguTA0nPLVWz4hy1yJiWYQe0H7NLNNTmCKiLQaJpAbb
122TC6vE8C7AkEA0Ee8CMJUc20BnGEmxwgWcVuqFWaKCo8jTH1X38FlATUsyR3krjW2
123dL3yDD9NwHxsYP7nTKp/U8MV7U9IBn4y/wJBAJl7H0/BcLeRmuJk7IqJ7b635iYB
124D/9beFUw3MUXmQXZUfyYz39xf6CDZsu1GEdEC5haykeln3Of4M9d/4Kj+FcCQQCY
125si6xwT7GzMDkk/ko684AV3KPc/h6G0yGtFIrMg7J3uExpR/VdH2KgwMkZXisSMvw
126JJEQjOMCVsEJlRk54WWjAkEAzoZNH6UhDdBK5F38rVt/y4SEHgbSfJHIAmPS32Kq
127f6GGcfNpip0Uk7q7udTKuX7Q/buZi/C4YW7u3VKAquv9NA==
128-----END RSA PRIVATE KEY-----
129"""
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400130
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400131cleartextCertificatePEM = """-----BEGIN CERTIFICATE-----
132MIIC7TCCAlagAwIBAgIIPQzE4MbeufQwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE
133BhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdU
134ZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwIhgPMjAwOTAzMjUxMjM2
135NThaGA8yMDE3MDYxMTEyMzY1OFowWDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklM
136MRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9U
137ZXN0aW5nIFJvb3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPmaQumL
138urpE527uSEHdL1pqcDRmWzu+98Y6YHzT/J7KWEamyMCNZ6fRW1JCR782UQ8a07fy
1392xXsKy4WdKaxyG8CcatwmXvpvRQ44dSANMihHELpANTdyVp6DCysED6wkQFurHlF
1401dshEaJw8b/ypDhmbVIo6Ci1xvCJqivbLFnbAgMBAAGjgbswgbgwHQYDVR0OBBYE
141FINVdy1eIfFJDAkk51QJEo3IfgSuMIGIBgNVHSMEgYAwfoAUg1V3LV4h8UkMCSTn
142VAkSjch+BK6hXKRaMFgxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UE
143BxMHQ2hpY2FnbzEQMA4GA1UEChMHVGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBS
144b290IENBggg9DMTgxt659DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB
145AGGCDazMJGoWNBpc03u6+smc95dEead2KlZXBATOdFT1VesY3+nUOqZhEhTGlDMi
146hkgaZnzoIq/Uamidegk4hirsCT/R+6vsKAAxNTcBjUeZjlykCJWy5ojShGftXIKY
147w/njVbKMXrvc83qmTdGl3TAM0fxQIpqgcglFLveEBgzn
148-----END CERTIFICATE-----
149"""
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400150
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400151cleartextPrivateKeyPEM = """-----BEGIN RSA PRIVATE KEY-----
152MIICXQIBAAKBgQD5mkLpi7q6ROdu7khB3S9aanA0Zls7vvfGOmB80/yeylhGpsjA
153jWen0VtSQke/NlEPGtO38tsV7CsuFnSmschvAnGrcJl76b0UOOHUgDTIoRxC6QDU
1543claegwsrBA+sJEBbqx5RdXbIRGicPG/8qQ4Zm1SKOgotcbwiaor2yxZ2wIDAQAB
155AoGBAPCgMpmLxzwDaUmcFbTJUvlLW1hoxNNYSu2jIZm1k/hRAcE60JYwvBkgz3UB
156yMEh0AtLxYe0bFk6EHah11tMUPgscbCq73snJ++8koUw+csk22G65hOs51bVb7Aa
1576JBe67oLzdtvgCUFAA2qfrKzWRZzAdhUirQUZgySZk+Xq1pBAkEA/kZG0A6roTSM
158BVnx7LnPfsycKUsTumorpXiylZJjTi9XtmzxhrYN6wgZlDOOwOLgSQhszGpxVoMD
159u3gByT1b2QJBAPtL3mSKdvwRu/+40zaZLwvSJRxaj0mcE4BJOS6Oqs/hS1xRlrNk
160PpQ7WJ4yM6ZOLnXzm2mKyxm50Mv64109FtMCQQDOqS2KkjHaLowTGVxwC0DijMfr
161I9Lf8sSQk32J5VWCySWf5gGTfEnpmUa41gKTMJIbqZZLucNuDcOtzUaeWZlZAkA8
162ttXigLnCqR486JDPTi9ZscoZkZ+w7y6e/hH8t6d5Vjt48JVyfjPIaJY+km58LcN3
1636AWSeGAdtRFHVzR7oHjVAkB4hutvxiOeiIVQNBhM6RSI9aBPMI21DoX2JRoxvNW2
164cbvAhow217X9V0dVerEOKxnNYspXRrh36h7k4mQA+sDq
165-----END RSA PRIVATE KEY-----
166"""
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400167
Rick Dean5b7b6372009-04-01 11:34:06 -0500168cleartextCertificateRequestPEM = (
169 "-----BEGIN CERTIFICATE REQUEST-----\n"
170 "MIIBnjCCAQcCAQAwXjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQH\n"
171 "EwdDaGljYWdvMRcwFQYDVQQKEw5NeSBDb21wYW55IEx0ZDEXMBUGA1UEAxMORnJl\n"
172 "ZGVyaWNrIERlYW4wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANp6Y17WzKSw\n"
173 "BsUWkXdqg6tnXy8H8hA1msCMWpc+/2KJ4mbv5NyD6UD+/SqagQqulPbF/DFea9nA\n"
174 "E0zhmHJELcM8gUTIlXv/cgDWnmK4xj8YkjVUiCdqKRAKeuzLG1pGmwwF5lGeJpXN\n"
175 "xQn5ecR0UYSOWj6TTGXB9VyUMQzCClcBAgMBAAGgADANBgkqhkiG9w0BAQUFAAOB\n"
176 "gQAAJGuF/R/GGbeC7FbFW+aJgr9ee0Xbl6nlhu7pTe67k+iiKT2dsl2ti68MVTnu\n"
177 "Vrb3HUNqOkiwsJf6kCtq5oPn3QVYzTa76Dt2y3Rtzv6boRSlmlfrgS92GNma8JfR\n"
178 "oICQk3nAudi6zl1Dix3BCv1pUp5KMtGn3MeDEi6QFGy2rA==\n"
179 "-----END CERTIFICATE REQUEST-----\n")
180
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400181encryptedPrivateKeyPEM = """-----BEGIN RSA PRIVATE KEY-----
182Proc-Type: 4,ENCRYPTED
183DEK-Info: DES-EDE3-CBC,9573604A18579E9E
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400184
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400185SHOho56WxDkT0ht10UTeKc0F5u8cqIa01kzFAmETw0MAs8ezYtK15NPdCXUm3X/2
186a17G7LSF5bkxOgZ7vpXyMzun/owrj7CzvLxyncyEFZWvtvzaAhPhvTJtTIB3kf8B
1878+qRcpTGK7NgXEgYBW5bj1y4qZkD4zCL9o9NQzsKI3Ie8i0239jsDOWR38AxjXBH
188mGwAQ4Z6ZN5dnmM4fhMIWsmFf19sNyAML4gHenQCHhmXbjXeVq47aC2ProInJbrm
189+00TcisbAQ40V9aehVbcDKtS4ZbMVDwncAjpXpcncC54G76N6j7F7wL7L/FuXa3A
190fvSVy9n2VfF/pJ3kYSflLHH2G/DFxjF7dl0GxhKPxJjp3IJi9VtuvmN9R2jZWLQF
191tfC8dXgy/P9CfFQhlinqBTEwgH0oZ/d4k4NVFDSdEMaSdmBAjlHpc+Vfdty3HVnV
192rKXj//wslsFNm9kIwJGIgKUa/n2jsOiydrsk1mgH7SmNCb3YHgZhbbnq0qLat/HC
193gHDt3FHpNQ31QzzL3yrenFB2L9osIsnRsDTPFNi4RX4SpDgNroxOQmyzCCV6H+d4
194o1mcnNiZSdxLZxVKccq0AfRpHqpPAFnJcQHP6xyT9MZp6fBa0XkxDnt9kNU8H3Qw
1957SJWZ69VXjBUzMlQViLuaWMgTnL+ZVyFZf9hTF7U/ef4HMLMAVNdiaGG+G+AjCV/
196MbzjS007Oe4qqBnCWaFPSnJX6uLApeTbqAxAeyCql56ULW5x6vDMNC3dwjvS/CEh
19711n8RkgFIQA0AhuKSIg3CbuartRsJnWOLwgLTzsrKYL4yRog1RJrtw==
198-----END RSA PRIVATE KEY-----
199"""
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400200encryptedPrivateKeyPEMPassphrase = "foobar"
201
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400202# Some PKCS#7 stuff. Generated with the openssl command line:
203#
204# openssl crl2pkcs7 -inform pem -outform pem -certfile s.pem -nocrl
205#
206# with a certificate and key (but the key should be irrelevant) in s.pem
207pkcs7Data = """\
208-----BEGIN PKCS7-----
209MIIDNwYJKoZIhvcNAQcCoIIDKDCCAyQCAQExADALBgkqhkiG9w0BBwGgggMKMIID
210BjCCAm+gAwIBAgIBATANBgkqhkiG9w0BAQQFADB7MQswCQYDVQQGEwJTRzERMA8G
211A1UEChMITTJDcnlwdG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtN
212MkNyeXB0byBDZXJ0aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNA
213cG9zdDEuY29tMB4XDTAwMDkxMDA5NTEzMFoXDTAyMDkxMDA5NTEzMFowUzELMAkG
214A1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwlsb2NhbGhvc3Qx
215HTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tMFwwDQYJKoZIhvcNAQEBBQAD
216SwAwSAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh5kwI
217zOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEAAaOCAQQwggEAMAkGA1UdEwQCMAAw
218LAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0G
219A1UdDgQWBBTPhIKSvnsmYsBVNWjj0m3M2z0qVTCBpQYDVR0jBIGdMIGagBT7hyNp
22065w6kxXlxb8pUU/+7Sg4AaF/pH0wezELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0y
221Q3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlwdG8g
222Q2VydGlmaWNhdGUgTWFzdGVyMR0wGwYJKoZIhvcNAQkBFg5uZ3BzQHBvc3QxLmNv
223bYIBADANBgkqhkiG9w0BAQQFAAOBgQA7/CqT6PoHycTdhEStWNZde7M/2Yc6BoJu
224VwnW8YxGO8Sn6UJ4FeffZNcYZddSDKosw8LtPOeWoK3JINjAk5jiPQ2cww++7QGG
225/g5NDjxFZNDJP1dGiLAxPW6JXwov4v0FmdzfLOZ01jDcgQQZqEpYlgpuI5JEWUQ9
226Ho4EzbYCOaEAMQA=
227-----END PKCS7-----
228"""
229
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -0500230crlData ="""\
231-----BEGIN X509 CRL-----
232MIIBWzCBxTANBgkqhkiG9w0BAQQFADBYMQswCQYDVQQGEwJVUzELMAkGA1UECBMC
233SUwxEDAOBgNVBAcTB0NoaWNhZ28xEDAOBgNVBAoTB1Rlc3RpbmcxGDAWBgNVBAMT
234D1Rlc3RpbmcgUm9vdCBDQRcNMDkwNzI2MDQzNDU2WhcNMTIwOTI3MDI0MTUyWjA8
235MBUCAgOrGA8yMDA5MDcyNTIzMzQ1NlowIwICAQAYDzIwMDkwNzI1MjMzNDU2WjAM
236MAoGA1UdFQQDCgEEMA0GCSqGSIb3DQEBBAUAA4GBAEBt7xTs2htdD3d4ErrcGAw1
2374dKcVnIWTutoI7xxen26Wwvh8VCsT7i/UeP+rBl9rC/kfjWjzQk3/zleaarGTpBT
2380yp4HXRFFoRhhSE/hP+eteaPXRgrsNRLHe9ZDd69wmh7J1wMDb0m81RG7kqcbsid
239vrzEeLDRiiPl92dyyWmu
240-----END X509 CRL-----
241"""
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400242
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400243class X509ExtTests(TestCase):
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400244 """
245 Tests for L{OpenSSL.crypto.X509Extension}.
246 """
247
248 def setUp(self):
249 """
250 Create a new private key and start a certificate request (for a test
251 method to finish in one way or another).
252 """
253 # Basic setup stuff to generate a certificate
254 self.pkey = PKey()
255 self.pkey.generate_key(TYPE_RSA, 384)
256 self.req = X509Req()
257 self.req.set_pubkey(self.pkey)
258 # Authority good you have.
259 self.req.get_subject().commonName = "Yoda root CA"
260 self.x509 = X509()
261 self.subject = self.x509.get_subject()
262 self.subject.commonName = self.req.get_subject().commonName
263 self.x509.set_issuer(self.subject)
264 self.x509.set_pubkey(self.pkey)
265 now = datetime.now().strftime("%Y%m%d%H%M%SZ")
266 expire = (datetime.now() + timedelta(days=100)).strftime("%Y%m%d%H%M%SZ")
267 self.x509.set_notBefore(now)
268 self.x509.set_notAfter(expire)
269
270
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400271 def test_type(self):
272 """
273 L{X509Extension} and L{X509ExtensionType} refer to the same type object
274 and can be used to create instances of that type.
275 """
276 self.assertIdentical(X509Extension, X509ExtensionType)
277 self.assertConsistentType(
278 X509Extension, 'X509Extension', 'basicConstraints', True, 'CA:true')
279
280
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500281 def test_construction(self):
282 """
283 L{X509Extension} accepts an extension type name, a critical flag,
284 and an extension value and returns an L{X509ExtensionType} instance.
285 """
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500286 basic = X509Extension('basicConstraints', True, 'CA:true')
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500287 self.assertTrue(
288 isinstance(basic, X509ExtensionType),
289 "%r is of type %r, should be %r" % (
290 basic, type(basic), X509ExtensionType))
291
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500292 comment = X509Extension('nsComment', False, 'pyOpenSSL unit test')
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500293 self.assertTrue(
294 isinstance(comment, X509ExtensionType),
295 "%r is of type %r, should be %r" % (
296 comment, type(comment), X509ExtensionType))
297
298
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500299 def test_invalid_extension(self):
300 """
301 L{X509Extension} raises something if it is passed a bad extension
302 name or value.
303 """
304 self.assertRaises(
305 Error, X509Extension, 'thisIsMadeUp', False, 'hi')
306 self.assertRaises(
307 Error, X509Extension, 'basicConstraints', False, 'blah blah')
308
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500309 # Exercise a weird one (an extension which uses the r2i method). This
310 # exercises the codepath that requires a non-NULL ctx to be passed to
311 # X509V3_EXT_nconf. It can't work now because we provide no
312 # configuration database. It might be made to work in the future.
313 self.assertRaises(
314 Error, X509Extension, 'proxyCertInfo', True,
315 'language:id-ppl-anyLanguage,pathlen:1,policy:text:AB')
316
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500317
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500318 def test_get_critical(self):
319 """
320 L{X509ExtensionType.get_critical} returns the value of the
321 extension's critical flag.
322 """
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500323 ext = X509Extension('basicConstraints', True, 'CA:true')
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500324 self.assertTrue(ext.get_critical())
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500325 ext = X509Extension('basicConstraints', False, 'CA:true')
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500326 self.assertFalse(ext.get_critical())
327
Jean-Paul Calderone7535dab2008-03-06 18:53:11 -0500328
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -0500329 def test_get_short_name(self):
330 """
331 L{X509ExtensionType.get_short_name} returns a string giving the short
332 type name of the extension.
333 """
334 ext = X509Extension('basicConstraints', True, 'CA:true')
335 self.assertEqual(ext.get_short_name(), 'basicConstraints')
336 ext = X509Extension('nsComment', True, 'foo bar')
337 self.assertEqual(ext.get_short_name(), 'nsComment')
338
339
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400340 def test_unused_subject(self):
Rick Dean47262da2009-07-08 16:17:17 -0500341 """
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400342 The C{subject} parameter to L{X509Extension} may be provided for an
343 extension which does not use it and is ignored in this case.
Rick Dean47262da2009-07-08 16:17:17 -0500344 """
Jean-Paul Calderonef0179c72009-07-17 15:48:22 -0400345 ext1 = X509Extension('basicConstraints', False, 'CA:TRUE', subject=self.x509)
346 self.x509.add_extensions([ext1])
347 self.x509.sign(self.pkey, 'sha1')
348 # This is a little lame. Can we think of a better way?
349 text = dump_certificate(FILETYPE_TEXT, self.x509)
350 self.assertTrue('X509v3 Basic Constraints:' in text)
351 self.assertTrue('CA:TRUE' in text)
352
353
354 def test_subject(self):
355 """
356 If an extension requires a subject, the C{subject} parameter to
357 L{X509Extension} provides its value.
358 """
359 ext3 = X509Extension('subjectKeyIdentifier', False, 'hash', subject=self.x509)
360 self.x509.add_extensions([ext3])
361 self.x509.sign(self.pkey, 'sha1')
362 text = dump_certificate(FILETYPE_TEXT, self.x509)
363 self.assertTrue('X509v3 Subject Key Identifier:' in text)
364
365
366 def test_missing_subject(self):
367 """
368 If an extension requires a subject and the C{subject} parameter is
369 given no value, something happens.
370 """
371 self.assertRaises(
372 Error, X509Extension, 'subjectKeyIdentifier', False, 'hash')
373
374
375 def test_invalid_subject(self):
376 """
377 If the C{subject} parameter is given a value which is not an L{X509}
378 instance, L{TypeError} is raised.
379 """
380 for badObj in [True, object(), "hello", [], self]:
381 self.assertRaises(
382 TypeError,
383 X509Extension,
384 'basicConstraints', False, 'CA:TRUE', subject=badObj)
385
386
387 def test_unused_issuer(self):
388 """
389 The C{issuer} parameter to L{X509Extension} may be provided for an
390 extension which does not use it and is ignored in this case.
391 """
392 ext1 = X509Extension('basicConstraints', False, 'CA:TRUE', issuer=self.x509)
393 self.x509.add_extensions([ext1])
394 self.x509.sign(self.pkey, 'sha1')
395 text = dump_certificate(FILETYPE_TEXT, self.x509)
396 self.assertTrue('X509v3 Basic Constraints:' in text)
397 self.assertTrue('CA:TRUE' in text)
398
399
400 def test_issuer(self):
401 """
402 If an extension requires a issuer, the C{issuer} parameter to
403 L{X509Extension} provides its value.
404 """
405 ext2 = X509Extension(
406 'authorityKeyIdentifier', False, 'issuer:always',
407 issuer=self.x509)
408 self.x509.add_extensions([ext2])
409 self.x509.sign(self.pkey, 'sha1')
410 text = dump_certificate(FILETYPE_TEXT, self.x509)
411 self.assertTrue('X509v3 Authority Key Identifier:' in text)
412 self.assertTrue('DirName:/CN=Yoda root CA' in text)
413
414
415 def test_missing_issuer(self):
416 """
417 If an extension requires an issue and the C{issuer} parameter is given
418 no value, something happens.
419 """
420 self.assertRaises(
421 Error,
422 X509Extension,
423 'authorityKeyIdentifier', False, 'keyid:always,issuer:always')
424
425
426 def test_invalid_issuer(self):
427 """
428 If the C{issuer} parameter is given a value which is not an L{X509}
429 instance, L{TypeError} is raised.
430 """
431 for badObj in [True, object(), "hello", [], self]:
432 self.assertRaises(
433 TypeError,
434 X509Extension,
435 'authorityKeyIdentifier', False, 'keyid:always,issuer:always',
436 issuer=badObj)
Rick Dean47262da2009-07-08 16:17:17 -0500437
438
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500439
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400440class PKeyTests(TestCase):
Jean-Paul Calderoneac930e12008-03-06 18:50:51 -0500441 """
442 Unit tests for L{OpenSSL.crypto.PKey}.
443 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400444 def test_type(self):
445 """
446 L{PKey} and L{PKeyType} refer to the same type object and can be used
447 to create instances of that type.
448 """
449 self.assertIdentical(PKey, PKeyType)
450 self.assertConsistentType(PKey, 'PKey')
451
452
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500453 def test_construction(self):
454 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400455 L{PKey} takes no arguments and returns a new L{PKey} instance.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500456 """
457 self.assertRaises(TypeError, PKey, None)
458 key = PKey()
459 self.assertTrue(
460 isinstance(key, PKeyType),
461 "%r is of type %r, should be %r" % (key, type(key), PKeyType))
462
463
464 def test_pregeneration(self):
465 """
466 L{PKeyType.bits} and L{PKeyType.type} return C{0} before the key is
467 generated.
468 """
469 key = PKey()
470 self.assertEqual(key.type(), 0)
471 self.assertEqual(key.bits(), 0)
472
473
474 def test_failedGeneration(self):
475 """
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500476 L{PKeyType.generate_key} takes two arguments, the first giving the key
477 type as one of L{TYPE_RSA} or L{TYPE_DSA} and the second giving the
478 number of bits to generate. If an invalid type is specified or
479 generation fails, L{Error} is raised. If an invalid number of bits is
480 specified, L{ValueError} or L{Error} is raised.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500481 """
482 key = PKey()
483 self.assertRaises(TypeError, key.generate_key)
484 self.assertRaises(TypeError, key.generate_key, 1, 2, 3)
485 self.assertRaises(TypeError, key.generate_key, "foo", "bar")
486 self.assertRaises(Error, key.generate_key, -1, 0)
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500487
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -0500488 self.assertRaises(ValueError, key.generate_key, TYPE_RSA, -1)
489 self.assertRaises(ValueError, key.generate_key, TYPE_RSA, 0)
Jean-Paul Calderoned71fe982008-03-06 00:31:50 -0500490
491 # XXX RSA generation for small values of bits is fairly buggy in a wide
492 # range of OpenSSL versions. I need to figure out what the safe lower
493 # bound for a reasonable number of OpenSSL versions is and explicitly
494 # check for that in the wrapper. The failure behavior is typically an
495 # infinite loop inside OpenSSL.
496
497 # self.assertRaises(Error, key.generate_key, TYPE_RSA, 2)
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500498
499 # XXX DSA generation seems happy with any number of bits. The DSS
500 # says bits must be between 512 and 1024 inclusive. OpenSSL's DSA
501 # generator doesn't seem to care about the upper limit at all. For
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500502 # the lower limit, it uses 512 if anything smaller is specified.
Jean-Paul Calderoned8782ad2008-03-04 23:39:59 -0500503 # So, it doesn't seem possible to make generate_key fail for
504 # TYPE_DSA with a bits argument which is at least an int.
505
506 # self.assertRaises(Error, key.generate_key, TYPE_DSA, -7)
507
508
509 def test_rsaGeneration(self):
510 """
511 L{PKeyType.generate_key} generates an RSA key when passed
512 L{TYPE_RSA} as a type and a reasonable number of bits.
513 """
514 bits = 128
515 key = PKey()
516 key.generate_key(TYPE_RSA, bits)
517 self.assertEqual(key.type(), TYPE_RSA)
518 self.assertEqual(key.bits(), bits)
519
520
521 def test_dsaGeneration(self):
522 """
523 L{PKeyType.generate_key} generates a DSA key when passed
524 L{TYPE_DSA} as a type and a reasonable number of bits.
525 """
526 # 512 is a magic number. The DSS (Digital Signature Standard)
527 # allows a minimum of 512 bits for DSA. DSA_generate_parameters
528 # will silently promote any value below 512 to 512.
529 bits = 512
530 key = PKey()
531 key.generate_key(TYPE_DSA, bits)
532 self.assertEqual(key.type(), TYPE_DSA)
533 self.assertEqual(key.bits(), bits)
534
535
536 def test_regeneration(self):
537 """
538 L{PKeyType.generate_key} can be called multiple times on the same
539 key to generate new keys.
540 """
541 key = PKey()
542 for type, bits in [(TYPE_RSA, 512), (TYPE_DSA, 576)]:
543 key.generate_key(type, bits)
544 self.assertEqual(key.type(), type)
545 self.assertEqual(key.bits(), bits)
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500546
547
548
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400549class X509NameTests(TestCase):
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500550 """
551 Unit tests for L{OpenSSL.crypto.X509Name}.
552 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500553 def _x509name(self, **attrs):
554 # XXX There's no other way to get a new X509Name yet.
555 name = X509().get_subject()
556 attrs = attrs.items()
557 # Make the order stable - order matters!
558 attrs.sort(lambda (k1, v1), (k2, v2): cmp(v1, v2))
559 for k, v in attrs:
560 setattr(name, k, v)
561 return name
562
563
Rick Deane15b1472009-07-09 15:53:42 -0500564 def test_type(self):
565 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400566 The type of X509Name objects is L{X509NameType}.
Rick Deane15b1472009-07-09 15:53:42 -0500567 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400568 self.assertIdentical(X509Name, X509NameType)
569 self.assertEqual(X509NameType.__name__, 'X509Name')
570 self.assertTrue(isinstance(X509NameType, type))
571
Rick Deane15b1472009-07-09 15:53:42 -0500572 name = self._x509name()
573 self.assertTrue(
574 isinstance(name, X509NameType),
575 "%r is of type %r, should be %r" % (
576 name, type(name), X509NameType))
Rick Deane15b1472009-07-09 15:53:42 -0500577
578
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500579 def test_attributes(self):
580 """
581 L{X509NameType} instances have attributes for each standard (?)
582 X509Name field.
583 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500584 name = self._x509name()
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500585 name.commonName = "foo"
586 self.assertEqual(name.commonName, "foo")
587 self.assertEqual(name.CN, "foo")
588 name.CN = "baz"
589 self.assertEqual(name.commonName, "baz")
590 self.assertEqual(name.CN, "baz")
591 name.commonName = "bar"
592 self.assertEqual(name.commonName, "bar")
593 self.assertEqual(name.CN, "bar")
594 name.CN = "quux"
595 self.assertEqual(name.commonName, "quux")
596 self.assertEqual(name.CN, "quux")
597
598
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500599 def test_copy(self):
600 """
601 L{X509Name} creates a new L{X509NameType} instance with all the same
602 attributes as an existing L{X509NameType} instance when called with
603 one.
604 """
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500605 name = self._x509name(commonName="foo", emailAddress="bar@example.com")
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500606
607 copy = X509Name(name)
608 self.assertEqual(copy.commonName, "foo")
609 self.assertEqual(copy.emailAddress, "bar@example.com")
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500610
611 # Mutate the copy and ensure the original is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500612 copy.commonName = "baz"
613 self.assertEqual(name.commonName, "foo")
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500614
615 # Mutate the original and ensure the copy is unmodified.
Jean-Paul Calderoneeff3cd92008-03-05 22:35:26 -0500616 name.emailAddress = "quux@example.com"
617 self.assertEqual(copy.emailAddress, "bar@example.com")
618
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500619
620 def test_repr(self):
621 """
622 L{repr} passed an L{X509NameType} instance should return a string
623 containing a description of the type and the NIDs which have been set
624 on it.
625 """
626 name = self._x509name(commonName="foo", emailAddress="bar")
627 self.assertEqual(
628 repr(name),
629 "<X509Name object '/emailAddress=bar/CN=foo'>")
630
631
632 def test_comparison(self):
633 """
634 L{X509NameType} instances should compare based on their NIDs.
635 """
636 def _equality(a, b, assertTrue, assertFalse):
637 assertTrue(a == b, "(%r == %r) --> False" % (a, b))
638 assertFalse(a != b)
639 assertTrue(b == a)
640 assertFalse(b != a)
641
642 def assertEqual(a, b):
643 _equality(a, b, self.assertTrue, self.assertFalse)
644
645 # Instances compare equal to themselves.
646 name = self._x509name()
647 assertEqual(name, name)
648
649 # Empty instances should compare equal to each other.
650 assertEqual(self._x509name(), self._x509name())
651
652 # Instances with equal NIDs should compare equal to each other.
653 assertEqual(self._x509name(commonName="foo"),
654 self._x509name(commonName="foo"))
655
656 # Instance with equal NIDs set using different aliases should compare
657 # equal to each other.
658 assertEqual(self._x509name(commonName="foo"),
659 self._x509name(CN="foo"))
660
661 # Instances with more than one NID with the same values should compare
662 # equal to each other.
663 assertEqual(self._x509name(CN="foo", organizationalUnitName="bar"),
664 self._x509name(commonName="foo", OU="bar"))
665
666 def assertNotEqual(a, b):
667 _equality(a, b, self.assertFalse, self.assertTrue)
668
669 # Instances with different values for the same NID should not compare
670 # equal to each other.
671 assertNotEqual(self._x509name(CN="foo"),
672 self._x509name(CN="bar"))
673
674 # Instances with different NIDs should not compare equal to each other.
675 assertNotEqual(self._x509name(CN="foo"),
676 self._x509name(OU="foo"))
677
678 def _inequality(a, b, assertTrue, assertFalse):
679 assertTrue(a < b)
680 assertTrue(a <= b)
681 assertTrue(b > a)
682 assertTrue(b >= a)
683 assertFalse(a > b)
684 assertFalse(a >= b)
685 assertFalse(b < a)
686 assertFalse(b <= a)
687
688 def assertLessThan(a, b):
689 _inequality(a, b, self.assertTrue, self.assertFalse)
690
691 # An X509Name with a NID with a value which sorts less than the value
692 # of the same NID on another X509Name compares less than the other
693 # X509Name.
694 assertLessThan(self._x509name(CN="abc"),
695 self._x509name(CN="def"))
696
697 def assertGreaterThan(a, b):
698 _inequality(a, b, self.assertFalse, self.assertTrue)
699
700 # An X509Name with a NID with a value which sorts greater than the
701 # value of the same NID on another X509Name compares greater than the
702 # other X509Name.
703 assertGreaterThan(self._x509name(CN="def"),
704 self._x509name(CN="abc"))
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -0500705
706
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400707 def test_hash(self):
708 """
709 L{X509Name.hash} returns an integer hash based on the value of the
710 name.
711 """
712 a = self._x509name(CN="foo")
713 b = self._x509name(CN="foo")
714 self.assertEqual(a.hash(), b.hash())
715 a.CN = "bar"
716 self.assertNotEqual(a.hash(), b.hash())
717
718
Jean-Paul Calderonee957a002008-03-25 15:16:51 -0400719 def test_der(self):
720 """
721 L{X509Name.der} returns the DER encoded form of the name.
722 """
723 a = self._x509name(CN="foo", C="US")
724 self.assertEqual(
725 a.der(),
726 '0\x1b1\x0b0\t\x06\x03U\x04\x06\x13\x02US'
727 '1\x0c0\n\x06\x03U\x04\x03\x13\x03foo')
728
729
Jean-Paul Calderonec54cc182008-03-26 21:11:07 -0400730 def test_get_components(self):
731 """
732 L{X509Name.get_components} returns a C{list} of two-tuples of C{str}
733 giving the NIDs and associated values which make up the name.
734 """
735 a = self._x509name()
736 self.assertEqual(a.get_components(), [])
737 a.CN = "foo"
738 self.assertEqual(a.get_components(), [("CN", "foo")])
739 a.organizationalUnitName = "bar"
740 self.assertEqual(
741 a.get_components(),
742 [("CN", "foo"), ("OU", "bar")])
743
Jean-Paul Calderone110cd092008-03-24 17:27:42 -0400744
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400745class _PKeyInteractionTestsMixin:
746 """
747 Tests which involve another thing and a PKey.
748 """
749 def signable(self):
750 """
751 Return something with a C{set_pubkey}, C{set_pubkey}, and C{sign} method.
752 """
753 raise NotImplementedError()
754
755
756 def test_signWithUngenerated(self):
757 """
758 L{X509Req.sign} raises L{ValueError} when pass a L{PKey} with no parts.
759 """
760 request = self.signable()
761 key = PKey()
762 self.assertRaises(ValueError, request.sign, key, 'MD5')
763
764
765 def test_signWithPublicKey(self):
766 """
767 L{X509Req.sign} raises L{ValueError} when pass a L{PKey} with no
768 private part as the signing key.
769 """
770 request = self.signable()
771 key = PKey()
772 key.generate_key(TYPE_RSA, 512)
773 request.set_pubkey(key)
774 pub = request.get_pubkey()
775 self.assertRaises(ValueError, request.sign, pub, 'MD5')
776
777
778
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400779class X509ReqTests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -0500780 """
781 Tests for L{OpenSSL.crypto.X509Req}.
782 """
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400783 def signable(self):
784 """
785 Create and return a new L{X509Req}.
786 """
787 return X509Req()
788
789
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400790 def test_type(self):
791 """
792 L{X509Req} and L{X509ReqType} refer to the same type object and can be
793 used to create instances of that type.
794 """
795 self.assertIdentical(X509Req, X509ReqType)
796 self.assertConsistentType(X509Req, 'X509Req')
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -0500797
798
799 def test_construction(self):
800 """
801 L{X509Req} takes no arguments and returns an L{X509ReqType} instance.
802 """
803 request = X509Req()
804 self.assertTrue(
805 isinstance(request, X509ReqType),
806 "%r is of type %r, should be %r" % (request, type(request), X509ReqType))
807
808
Jean-Paul Calderone8dd19b82008-12-28 20:41:16 -0500809 def test_version(self):
810 """
811 L{X509ReqType.set_version} sets the X.509 version of the certificate
812 request. L{X509ReqType.get_version} returns the X.509 version of
813 the certificate request. The initial value of the version is 0.
814 """
815 request = X509Req()
816 self.assertEqual(request.get_version(), 0)
817 request.set_version(1)
818 self.assertEqual(request.get_version(), 1)
819 request.set_version(3)
820 self.assertEqual(request.get_version(), 3)
821
822
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -0500823 def test_get_subject(self):
824 """
825 L{X509ReqType.get_subject} returns an L{X509Name} for the subject of
826 the request and which is valid even after the request object is
827 otherwise dead.
828 """
829 request = X509Req()
830 subject = request.get_subject()
831 self.assertTrue(
832 isinstance(subject, X509NameType),
833 "%r is of type %r, should be %r" % (subject, type(subject), X509NameType))
834 subject.commonName = "foo"
835 self.assertEqual(request.get_subject().commonName, "foo")
836 del request
837 subject.commonName = "bar"
838 self.assertEqual(subject.commonName, "bar")
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500839
840
841
Jean-Paul Calderone18808652009-07-05 12:54:05 -0400842class X509Tests(TestCase, _PKeyInteractionTestsMixin):
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500843 """
844 Tests for L{OpenSSL.crypto.X509}.
845 """
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400846 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
Jean-Paul Calderone8114b452008-03-25 15:27:59 -0400847
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400848 def signable(self):
849 """
850 Create and return a new L{X509}.
851 """
852 return X509()
853
854
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400855 def test_type(self):
856 """
857 L{X509} and L{X509Type} refer to the same type object and can be used
858 to create instances of that type.
859 """
860 self.assertIdentical(X509, X509Type)
861 self.assertConsistentType(X509, 'X509')
862
863
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500864 def test_construction(self):
865 """
866 L{X509} takes no arguments and returns an instance of L{X509Type}.
867 """
868 certificate = X509()
869 self.assertTrue(
870 isinstance(certificate, X509Type),
871 "%r is of type %r, should be %r" % (certificate,
872 type(certificate),
873 X509Type))
Rick Deane15b1472009-07-09 15:53:42 -0500874 self.assertEqual(type(X509Type).__name__, 'type')
875 self.assertEqual(type(certificate).__name__, 'X509')
876 self.assertEqual(type(certificate), X509Type)
Rick Dean04113e72009-07-16 12:06:35 -0500877 self.assertEqual(type(certificate), X509)
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500878
879
880 def test_serial_number(self):
881 """
882 The serial number of an L{X509Type} can be retrieved and modified with
883 L{X509Type.get_serial_number} and L{X509Type.set_serial_number}.
884 """
885 certificate = X509()
886 self.assertRaises(TypeError, certificate.set_serial_number)
887 self.assertRaises(TypeError, certificate.set_serial_number, 1, 2)
888 self.assertRaises(TypeError, certificate.set_serial_number, "1")
889 self.assertRaises(TypeError, certificate.set_serial_number, 5.5)
890 self.assertEqual(certificate.get_serial_number(), 0)
891 certificate.set_serial_number(1)
892 self.assertEqual(certificate.get_serial_number(), 1)
893 certificate.set_serial_number(2 ** 32 + 1)
894 self.assertEqual(certificate.get_serial_number(), 2 ** 32 + 1)
895 certificate.set_serial_number(2 ** 64 + 1)
896 self.assertEqual(certificate.get_serial_number(), 2 ** 64 + 1)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400897 certificate.set_serial_number(2 ** 128 + 1)
898 self.assertEqual(certificate.get_serial_number(), 2 ** 128 + 1)
899
900
901 def _setBoundTest(self, which):
902 """
903 L{X509Type.set_notBefore} takes a string in the format of an ASN1
904 GENERALIZEDTIME and sets the beginning of the certificate's validity
905 period to it.
906 """
907 certificate = X509()
908 set = getattr(certificate, 'set_not' + which)
909 get = getattr(certificate, 'get_not' + which)
910
Jean-Paul Calderonee0615b52008-03-09 21:44:46 -0400911 # Starts with no value.
912 self.assertEqual(get(), None)
913
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400914 # GMT (Or is it UTC?) -exarkun
915 when = "20040203040506Z"
916 set(when)
917 self.assertEqual(get(), when)
918
919 # A plus two hours and thirty minutes offset
920 when = "20040203040506+0530"
921 set(when)
922 self.assertEqual(get(), when)
923
924 # A minus one hour fifteen minutes offset
925 when = "20040203040506-0115"
926 set(when)
927 self.assertEqual(get(), when)
928
929 # An invalid string results in a ValueError
930 self.assertRaises(ValueError, set, "foo bar")
931
Jean-Paul Calderone31ca2002010-01-30 15:14:43 -0500932 # The wrong number of arguments results in a TypeError.
933 self.assertRaises(TypeError, set)
934 self.assertRaises(TypeError, set, "20040203040506Z", "20040203040506Z")
935 self.assertRaises(TypeError, get, "foo bar")
936
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400937
938 def test_set_notBefore(self):
939 """
940 L{X509Type.set_notBefore} takes a string in the format of an ASN1
941 GENERALIZEDTIME and sets the beginning of the certificate's validity
942 period to it.
943 """
944 self._setBoundTest("Before")
945
946
947 def test_set_notAfter(self):
948 """
949 L{X509Type.set_notAfter} takes a string in the format of an ASN1
950 GENERALIZEDTIME and sets the end of the certificate's validity period
951 to it.
952 """
953 self._setBoundTest("After")
Jean-Paul Calderone76576d52008-03-24 16:04:46 -0400954
955
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -0400956 def test_get_notBefore(self):
957 """
958 L{X509Type.get_notBefore} returns a string in the format of an ASN1
959 GENERALIZEDTIME even for certificates which store it as UTCTIME
960 internally.
961 """
Jean-Paul Calderone8114b452008-03-25 15:27:59 -0400962 cert = load_certificate(FILETYPE_PEM, self.pemData)
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400963 self.assertEqual(cert.get_notBefore(), "20090325123658Z")
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -0400964
Rick Dean38a05c82009-07-18 01:41:30 -0500965
966 def test_get_notAfter(self):
967 """
968 L{X509Type.get_notAfter} returns a string in the format of an ASN1
969 GENERALIZEDTIME even for certificates which store it as UTCTIME
970 internally.
971 """
972 cert = load_certificate(FILETYPE_PEM, self.pemData)
973 self.assertEqual(cert.get_notAfter(), "20170611123658Z")
974
975
976 def test_digest(self):
977 """
978 L{X509.digest} returns a string giving ":"-separated hex-encoded words
979 of the digest of the certificate.
980 """
981 cert = X509()
982 self.assertEqual(
983 cert.digest("md5"),
984 "A8:EB:07:F8:53:25:0A:F2:56:05:C5:A5:C4:C4:C7:15")
985
986
987
Rick Dean623ee362009-07-17 12:22:16 -0500988class PKCS12Tests(TestCase):
989 """
Jean-Paul Calderone9389c922009-07-25 12:24:04 -0400990 Test for L{OpenSSL.crypto.PKCS12} and L{OpenSSL.crypto.load_pkcs12}.
Rick Dean623ee362009-07-17 12:22:16 -0500991 """
992 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
993
Jean-Paul Calderonec3a41f72009-07-25 12:36:02 -0400994 def test_type(self):
995 """
996 L{PKCS12Type} is a type object.
997 """
998 self.assertIdentical(PKCS12, PKCS12Type)
999 self.assertConsistentType(PKCS12, 'PKCS12')
1000
1001
Rick Deanf94096c2009-07-18 14:23:06 -05001002 def test_empty_construction(self):
Rick Dean38a05c82009-07-18 01:41:30 -05001003 """
Jean-Paul Calderonedc857b52009-07-25 12:25:07 -04001004 L{PKCS12} returns a new instance of L{PKCS12} with no certificate,
1005 private key, CA certificates, or friendly name.
Rick Dean38a05c82009-07-18 01:41:30 -05001006 """
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001007 p12 = PKCS12()
Rick Dean623ee362009-07-17 12:22:16 -05001008 self.assertEqual(None, p12.get_certificate())
1009 self.assertEqual(None, p12.get_privatekey())
1010 self.assertEqual(None, p12.get_ca_certificates())
Rick Dean42d69e12009-07-20 11:36:08 -05001011 self.assertEqual(None, p12.get_friendlyname())
Rick Dean623ee362009-07-17 12:22:16 -05001012
Rick Dean38a05c82009-07-18 01:41:30 -05001013
Rick Dean623ee362009-07-17 12:22:16 -05001014 def test_type_errors(self):
Rick Dean38a05c82009-07-18 01:41:30 -05001015 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001016 The L{PKCS12} setter functions (C{set_certificate}, C{set_privatekey},
1017 C{set_ca_certificates}, and C{set_friendlyname}) raise L{TypeError}
1018 when passed objects of types other than those expected.
Rick Dean38a05c82009-07-18 01:41:30 -05001019 """
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001020 p12 = PKCS12()
Rick Dean623ee362009-07-17 12:22:16 -05001021 self.assertRaises(TypeError, p12.set_certificate, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05001022 self.assertRaises(TypeError, p12.set_certificate, PKey())
1023 self.assertRaises(TypeError, p12.set_certificate, X509)
Rick Dean623ee362009-07-17 12:22:16 -05001024 self.assertRaises(TypeError, p12.set_privatekey, 3)
Rick Deanf94096c2009-07-18 14:23:06 -05001025 self.assertRaises(TypeError, p12.set_privatekey, 'legbone')
1026 self.assertRaises(TypeError, p12.set_privatekey, X509())
Rick Dean623ee362009-07-17 12:22:16 -05001027 self.assertRaises(TypeError, p12.set_ca_certificates, 3)
1028 self.assertRaises(TypeError, p12.set_ca_certificates, X509())
1029 self.assertRaises(TypeError, p12.set_ca_certificates, (3, 4))
Rick Deanf94096c2009-07-18 14:23:06 -05001030 self.assertRaises(TypeError, p12.set_ca_certificates, ( PKey(), ))
Rick Dean42d69e12009-07-20 11:36:08 -05001031 self.assertRaises(TypeError, p12.set_friendlyname, 6)
1032 self.assertRaises(TypeError, p12.set_friendlyname, ('foo', 'bar'))
Rick Dean623ee362009-07-17 12:22:16 -05001033
Rick Dean38a05c82009-07-18 01:41:30 -05001034
Rick Dean623ee362009-07-17 12:22:16 -05001035 def test_key_only(self):
1036 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001037 A L{PKCS12} with only a private key can be exported using
1038 L{PKCS12.export} and loaded again using L{load_pkcs12}.
Rick Dean623ee362009-07-17 12:22:16 -05001039 """
1040 passwd = 'blah'
1041 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001042 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001043 p12.set_privatekey(pkey)
Rick Dean623ee362009-07-17 12:22:16 -05001044 self.assertEqual(None, p12.get_certificate())
1045 self.assertEqual(pkey, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05001046 try:
1047 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
1048 except Error:
1049 # Some versions of OpenSSL will throw an exception
1050 # for this nearly useless PKCS12 we tried to generate:
1051 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
1052 return
Rick Dean623ee362009-07-17 12:22:16 -05001053 p12 = load_pkcs12(dumped_p12, passwd)
1054 self.assertEqual(None, p12.get_ca_certificates())
1055 self.assertEqual(None, p12.get_certificate())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001056
1057 # OpenSSL fails to bring the key back to us. So sad. Perhaps in the
1058 # future this will be improved.
1059 self.assertTrue(isinstance(p12.get_privatekey(), (PKey, type(None))))
Rick Dean623ee362009-07-17 12:22:16 -05001060
Rick Dean38a05c82009-07-18 01:41:30 -05001061
Rick Dean623ee362009-07-17 12:22:16 -05001062 def test_cert_only(self):
1063 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001064 A L{PKCS12} with only a certificate can be exported using
1065 L{PKCS12.export} and loaded again using L{load_pkcs12}.
Rick Dean623ee362009-07-17 12:22:16 -05001066 """
1067 passwd = 'blah'
1068 p12 = PKCS12()
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001069 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001070 p12.set_certificate(cert)
Rick Dean623ee362009-07-17 12:22:16 -05001071 self.assertEqual(cert, p12.get_certificate())
1072 self.assertEqual(None, p12.get_privatekey())
Rick Dean321a0512009-08-13 17:21:29 -05001073 try:
1074 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
1075 except Error:
1076 # Some versions of OpenSSL will throw an exception
1077 # for this nearly useless PKCS12 we tried to generate:
1078 # [('PKCS12 routines', 'PKCS12_create', 'invalid null argument')]
1079 return
Rick Dean623ee362009-07-17 12:22:16 -05001080 p12 = load_pkcs12(dumped_p12, passwd)
1081 self.assertEqual(None, p12.get_privatekey())
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001082
1083 # OpenSSL fails to bring the cert back to us. Groany mcgroan.
1084 self.assertTrue(isinstance(p12.get_certificate(), (X509, type(None))))
1085
1086 # Oh ho. It puts the certificate into the ca certificates list, in
1087 # fact. Totally bogus, I would think. Nevertheless, let's exploit
1088 # that to check to see if it reconstructed the certificate we expected
1089 # it to. At some point, hopefully this will change so that
1090 # p12.get_certificate() is actually what returns the loaded
1091 # certificate.
1092 self.assertEqual(
1093 cleartextCertificatePEM,
1094 dump_certificate(FILETYPE_PEM, p12.get_ca_certificates()[0]))
Rick Dean623ee362009-07-17 12:22:16 -05001095
1096
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001097 def gen_pkcs12(self, cert_pem=None, key_pem=None, ca_pem=None, friendly_name=None):
Rick Dean623ee362009-07-17 12:22:16 -05001098 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001099 Generate a PKCS12 object with components from PEM. Verify that the set
1100 functions return None.
Rick Dean623ee362009-07-17 12:22:16 -05001101 """
Rick Deanf94096c2009-07-18 14:23:06 -05001102 p12 = PKCS12()
1103 if cert_pem:
1104 ret = p12.set_certificate(load_certificate(FILETYPE_PEM, cert_pem))
1105 self.assertEqual(ret, None)
1106 if key_pem:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001107 ret = p12.set_privatekey(load_privatekey(FILETYPE_PEM, key_pem))
Rick Deanf94096c2009-07-18 14:23:06 -05001108 self.assertEqual(ret, None)
1109 if ca_pem:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001110 ret = p12.set_ca_certificates((load_certificate(FILETYPE_PEM, ca_pem),))
Rick Deanf94096c2009-07-18 14:23:06 -05001111 self.assertEqual(ret, None)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001112 if friendly_name:
1113 ret = p12.set_friendlyname(friendly_name)
Rick Dean42d69e12009-07-20 11:36:08 -05001114 self.assertEqual(ret, None)
Rick Deanf94096c2009-07-18 14:23:06 -05001115 return p12
1116
1117
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001118 def check_recovery(self, p12_str, key=None, cert=None, ca=None, passwd='',
1119 extra=()):
Rick Deanf94096c2009-07-18 14:23:06 -05001120 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001121 Use openssl program to confirm three components are recoverable from a
1122 PKCS12 string.
Rick Deanf94096c2009-07-18 14:23:06 -05001123 """
1124 if key:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001125 recovered_key = _runopenssl(
1126 p12_str, "pkcs12", '-nocerts', '-nodes', '-passin',
1127 'pass:' + passwd, *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001128 self.assertEqual(recovered_key[-len(key):], key)
1129 if cert:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001130 recovered_cert = _runopenssl(
1131 p12_str, "pkcs12", '-clcerts', '-nodes', '-passin',
1132 'pass:' + passwd, '-nokeys', *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001133 self.assertEqual(recovered_cert[-len(cert):], cert)
1134 if ca:
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001135 recovered_cert = _runopenssl(
1136 p12_str, "pkcs12", '-cacerts', '-nodes', '-passin',
1137 'pass:' + passwd, '-nokeys', *extra)
Rick Deanf94096c2009-07-18 14:23:06 -05001138 self.assertEqual(recovered_cert[-len(ca):], ca)
1139
1140
1141 def test_load_pkcs12(self):
1142 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001143 A PKCS12 string generated using the openssl command line can be loaded
1144 with L{load_pkcs12} and its components extracted and examined.
Rick Deanf94096c2009-07-18 14:23:06 -05001145 """
Rick Dean623ee362009-07-17 12:22:16 -05001146 passwd = 'whatever'
1147 pem = client_key_pem + client_cert_pem
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001148 p12_str = _runopenssl(
1149 pem, "pkcs12", '-export', '-clcerts', '-passout', 'pass:' + passwd)
Rick Dean623ee362009-07-17 12:22:16 -05001150 p12 = load_pkcs12(p12_str, passwd)
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001151 # verify
Rick Deanf94096c2009-07-18 14:23:06 -05001152 self.assertTrue(isinstance(p12, PKCS12))
Rick Dean623ee362009-07-17 12:22:16 -05001153 cert_pem = dump_certificate(FILETYPE_PEM, p12.get_certificate())
1154 self.assertEqual(cert_pem, client_cert_pem)
1155 key_pem = dump_privatekey(FILETYPE_PEM, p12.get_privatekey())
1156 self.assertEqual(key_pem, client_key_pem)
1157 self.assertEqual(None, p12.get_ca_certificates())
Rick Deanf94096c2009-07-18 14:23:06 -05001158
Rick Deanee568302009-07-24 09:56:29 -05001159
1160 def test_load_pkcs12_garbage(self):
1161 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001162 L{load_pkcs12} raises L{OpenSSL.crypto.Error} when passed a string
1163 which is not a PKCS12 dump.
Rick Deanee568302009-07-24 09:56:29 -05001164 """
1165 passwd = 'whatever'
1166 e = self.assertRaises(Error, load_pkcs12, 'fruit loops', passwd)
1167 self.assertEqual( e[0][0][0], 'asn1 encoding routines')
1168 self.assertEqual( len(e[0][0]), 3)
1169
1170
Rick Deanf94096c2009-07-18 14:23:06 -05001171 def test_replace(self):
1172 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001173 L{PKCS12.set_certificate} replaces the certificate in a PKCS12 cluster.
1174 L{PKCS12.set_privatekey} replaces the private key.
1175 L{PKCS12.set_ca_certificates} replaces the CA certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05001176 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001177 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
1178 p12.set_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1179 p12.set_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001180 root_cert = load_certificate(FILETYPE_PEM, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05001181 client_cert = load_certificate(FILETYPE_PEM, client_cert_pem)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001182 p12.set_ca_certificates([root_cert]) # not a tuple
Rick Dean623ee362009-07-17 12:22:16 -05001183 self.assertEqual(1, len(p12.get_ca_certificates()))
1184 self.assertEqual(root_cert, p12.get_ca_certificates()[0])
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001185 p12.set_ca_certificates([client_cert, root_cert])
Rick Deanf94096c2009-07-18 14:23:06 -05001186 self.assertEqual(2, len(p12.get_ca_certificates()))
1187 self.assertEqual(client_cert, p12.get_ca_certificates()[0])
1188 self.assertEqual(root_cert, p12.get_ca_certificates()[1])
1189
1190
1191 def test_friendly_name(self):
1192 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001193 The I{friendlyName} of a PKCS12 can be set and retrieved via
1194 L{PKCS12.get_friendlyname} and L{PKCS12_set_friendlyname}, and a
1195 L{PKCS12} with a friendly name set can be dumped with L{PKCS12.export}.
Rick Deanf94096c2009-07-18 14:23:06 -05001196 """
Rick Deanf94096c2009-07-18 14:23:06 -05001197 passwd = 'Dogmeat[]{}!@#$%^&*()~`?/.,<>-_+=";:'
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001198 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
1199 for friendly_name in ['Serverlicious', None, '###']:
Rick Dean42d69e12009-07-20 11:36:08 -05001200 p12.set_friendlyname(friendly_name)
1201 self.assertEqual(p12.get_friendlyname(), friendly_name)
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001202 dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
Rick Dean42d69e12009-07-20 11:36:08 -05001203 reloaded_p12 = load_pkcs12(dumped_p12, passwd)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001204 self.assertEqual(
1205 p12.get_friendlyname(),reloaded_p12.get_friendlyname())
Jean-Paul Calderonea202edb2009-07-25 12:22:12 -04001206 # We would use the openssl program to confirm the friendly
1207 # name, but it is not possible. The pkcs12 command
1208 # does not store the friendly name in the cert's
Rick Dean42d69e12009-07-20 11:36:08 -05001209 # alias, which we could then extract.
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001210 self.check_recovery(
1211 dumped_p12, key=server_key_pem, cert=server_cert_pem,
1212 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05001213
1214
1215 def test_various_empty_passphrases(self):
1216 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001217 Test that missing, None, and '' passphrases are identical for PKCS12
1218 export.
Rick Deanf94096c2009-07-18 14:23:06 -05001219 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001220 p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
Rick Dean623ee362009-07-17 12:22:16 -05001221 passwd = ''
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001222 dumped_p12_empty = p12.export(iter=2, maciter=0, passphrase=passwd)
1223 dumped_p12_none = p12.export(iter=3, maciter=2, passphrase=None)
1224 dumped_p12_nopw = p12.export(iter=9, maciter=4)
1225 for dumped_p12 in [dumped_p12_empty, dumped_p12_none, dumped_p12_nopw]:
1226 self.check_recovery(
1227 dumped_p12, key=client_key_pem, cert=client_cert_pem,
1228 ca=root_cert_pem, passwd=passwd)
Rick Deanf94096c2009-07-18 14:23:06 -05001229
1230
1231 def test_removing_ca_cert(self):
1232 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001233 Passing C{None} to L{PKCS12.set_ca_certificates} removes all CA
1234 certificates.
Rick Deanf94096c2009-07-18 14:23:06 -05001235 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001236 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
1237 p12.set_ca_certificates(None)
Rick Dean623ee362009-07-17 12:22:16 -05001238 self.assertEqual(None, p12.get_ca_certificates())
Rick Deanf94096c2009-07-18 14:23:06 -05001239
1240
1241 def test_export_without_mac(self):
1242 """
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001243 Exporting a PKCS12 with a C{maciter} of C{-1} excludes the MAC
1244 entirely.
Rick Deanf94096c2009-07-18 14:23:06 -05001245 """
1246 passwd = 'Lake Michigan'
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001247 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Dean623ee362009-07-17 12:22:16 -05001248 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Jean-Paul Calderone7426ed82009-07-25 21:19:23 -04001249 self.check_recovery(
1250 dumped_p12, key=server_key_pem, cert=server_cert_pem,
1251 passwd=passwd, extra=('-nomacver',))
1252
1253
1254 def test_load_without_mac(self):
1255 """
1256 Loading a PKCS12 without a MAC does something other than crash.
1257 """
1258 passwd = 'Lake Michigan'
1259 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
1260 dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
Rick Dean321a0512009-08-13 17:21:29 -05001261 try:
1262 recovered_p12 = load_pkcs12(dumped_p12, passwd)
1263 # The person who generated this PCKS12 should be flogged,
1264 # or better yet we should have a means to determine
1265 # whether a PCKS12 had a MAC that was verified.
1266 # Anyway, libopenssl chooses to allow it, so the
1267 # pyopenssl binding does as well.
1268 self.assertTrue(isinstance(recovered_p12, PKCS12))
1269 except Error:
1270 # Failing here with an exception is preferred as some openssl
1271 # versions do.
1272 pass
Rick Dean623ee362009-07-17 12:22:16 -05001273
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001274
Rick Dean25bcc1f2009-07-20 11:53:13 -05001275 def test_zero_len_list_for_ca(self):
1276 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04001277 A PKCS12 with an empty CA certificates list can be exported.
Rick Dean25bcc1f2009-07-20 11:53:13 -05001278 """
1279 passwd = 'Hobie 18'
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04001280 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem)
1281 p12.set_ca_certificates([])
Rick Dean25bcc1f2009-07-20 11:53:13 -05001282 self.assertEqual((), p12.get_ca_certificates())
1283 dumped_p12 = p12.export(passphrase=passwd, iter=3)
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04001284 self.check_recovery(
1285 dumped_p12, key=server_key_pem, cert=server_cert_pem,
1286 passwd=passwd)
Rick Dean25bcc1f2009-07-20 11:53:13 -05001287
1288
Rick Deanf94096c2009-07-18 14:23:06 -05001289 def test_export_without_args(self):
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001290 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04001291 All the arguments to L{PKCS12.export} are optional.
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -04001292 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04001293 p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
Rick Deanf94096c2009-07-18 14:23:06 -05001294 dumped_p12 = p12.export() # no args
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04001295 self.check_recovery(
1296 dumped_p12, key=server_key_pem, cert=server_cert_pem, passwd='')
Rick Deanf94096c2009-07-18 14:23:06 -05001297
1298
1299 def test_key_cert_mismatch(self):
1300 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04001301 L{PKCS12.export} raises an exception when a key and certificate
1302 mismatch.
Rick Deanf94096c2009-07-18 14:23:06 -05001303 """
Jean-Paul Calderoneda1ffa72009-07-25 21:24:34 -04001304 p12 = self.gen_pkcs12(server_cert_pem, client_key_pem, root_cert_pem)
1305 self.assertRaises(Error, p12.export)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04001306
1307
1308
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04001309# These quoting functions taken directly from Twisted's twisted.python.win32.
1310_cmdLineQuoteRe = re.compile(r'(\\*)"')
1311_cmdLineQuoteRe2 = re.compile(r'(\\+)\Z')
1312def cmdLineQuote(s):
1313 """
1314 Internal method for quoting a single command-line argument.
1315
1316 @type: C{str}
1317 @param s: A single unquoted string to quote for something that is expecting
1318 cmd.exe-style quoting
1319
1320 @rtype: C{str}
1321 @return: A cmd.exe-style quoted string
1322
1323 @see: U{http://www.perlmonks.org/?node_id=764004}
1324 """
1325 s = _cmdLineQuoteRe2.sub(r"\1\1", _cmdLineQuoteRe.sub(r'\1\1\\"', s))
1326 return '"%s"' % s
1327
1328
1329
1330def quoteArguments(arguments):
1331 """
1332 Quote an iterable of command-line arguments for passing to CreateProcess or
1333 a similar API. This allows the list passed to C{reactor.spawnProcess} to
1334 match the child process's C{sys.argv} properly.
1335
1336 @type arguments: C{iterable} of C{str}
1337 @param arguments: An iterable of unquoted arguments to quote
1338
1339 @rtype: C{str}
1340 @return: A space-delimited string containing quoted versions of L{arguments}
1341 """
1342 return ' '.join(map(cmdLineQuote, arguments))
1343
1344
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05001345
Rick Dean4c9ad612009-07-17 15:05:22 -05001346def _runopenssl(pem, *args):
1347 """
1348 Run the command line openssl tool with the given arguments and write
Rick Dean55d1ce62009-08-13 17:40:24 -05001349 the given PEM to its stdin. Not safe for quotes.
Rick Dean4c9ad612009-07-17 15:05:22 -05001350 """
Jean-Paul Calderone038de952009-08-21 12:16:06 -04001351 if os.name == 'posix':
Jean-Paul Calderone7b874db2009-08-27 12:32:47 -04001352 command = "openssl " + " ".join(["'%s'" % (arg.replace("'", "'\\''"),) for arg in args])
Rick Dean55d1ce62009-08-13 17:40:24 -05001353 else:
Jean-Paul Calderone50924502009-08-27 12:47:55 -04001354 command = "openssl " + quoteArguments(args)
Jean-Paul Calderone038de952009-08-21 12:16:06 -04001355 write, read = popen2(command, "b")
Rick Dean4c9ad612009-07-17 15:05:22 -05001356 write.write(pem)
1357 write.close()
1358 return read.read()
1359
1360
1361
Jean-Paul Calderone18808652009-07-05 12:54:05 -04001362class FunctionTests(TestCase):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04001363 """
1364 Tests for free-functions in the L{OpenSSL.crypto} module.
1365 """
1366 def test_load_privatekey_wrongPassphrase(self):
1367 """
1368 L{load_privatekey} raises L{OpenSSL.crypto.Error} when it is passed an
1369 encrypted PEM and an incorrect passphrase.
1370 """
1371 self.assertRaises(
1372 Error,
1373 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, "quack")
1374
1375
1376 def test_load_privatekey_passphrase(self):
1377 """
1378 L{load_privatekey} can create a L{PKey} object from an encrypted PEM
1379 string if given the passphrase.
1380 """
1381 key = load_privatekey(
1382 FILETYPE_PEM, encryptedPrivateKeyPEM,
1383 encryptedPrivateKeyPEMPassphrase)
1384 self.assertTrue(isinstance(key, PKeyType))
1385
1386
1387 def test_load_privatekey_wrongPassphraseCallback(self):
1388 """
1389 L{load_privatekey} raises L{OpenSSL.crypto.Error} when it is passed an
1390 encrypted PEM and a passphrase callback which returns an incorrect
1391 passphrase.
1392 """
1393 called = []
1394 def cb(*a):
1395 called.append(None)
1396 return "quack"
1397 self.assertRaises(
1398 Error,
1399 load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
1400 self.assertTrue(called)
1401
1402 def test_load_privatekey_passphraseCallback(self):
1403 """
1404 L{load_privatekey} can create a L{PKey} object from an encrypted PEM
1405 string if given a passphrase callback which returns the correct
1406 password.
1407 """
1408 called = []
1409 def cb(writing):
1410 called.append(writing)
1411 return encryptedPrivateKeyPEMPassphrase
1412 key = load_privatekey(FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
1413 self.assertTrue(isinstance(key, PKeyType))
1414 self.assertEqual(called, [False])
1415
1416
1417 def test_dump_privatekey_passphrase(self):
1418 """
1419 L{dump_privatekey} writes an encrypted PEM when given a passphrase.
1420 """
1421 passphrase = "foo"
1422 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
1423 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
1424 self.assertTrue(isinstance(pem, str))
1425 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
1426 self.assertTrue(isinstance(loadedKey, PKeyType))
1427 self.assertEqual(loadedKey.type(), key.type())
1428 self.assertEqual(loadedKey.bits(), key.bits())
1429
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04001430
Rick Dean5b7b6372009-04-01 11:34:06 -05001431 def test_dump_certificate(self):
1432 """
1433 L{dump_certificate} writes PEM, DER, and text.
1434 """
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04001435 pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
Rick Dean5b7b6372009-04-01 11:34:06 -05001436 cert = load_certificate(FILETYPE_PEM, pemData)
1437 dumped_pem = dump_certificate(FILETYPE_PEM, cert)
1438 self.assertEqual(dumped_pem, cleartextCertificatePEM)
1439 dumped_der = dump_certificate(FILETYPE_ASN1, cert)
Rick Dean4c9ad612009-07-17 15:05:22 -05001440 good_der = _runopenssl(dumped_pem, "x509", "-outform", "DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05001441 self.assertEqual(dumped_der, good_der)
1442 cert2 = load_certificate(FILETYPE_ASN1, dumped_der)
1443 dumped_pem2 = dump_certificate(FILETYPE_PEM, cert2)
1444 self.assertEqual(dumped_pem2, cleartextCertificatePEM)
1445 dumped_text = dump_certificate(FILETYPE_TEXT, cert)
Rick Dean4c9ad612009-07-17 15:05:22 -05001446 good_text = _runopenssl(dumped_pem, "x509", "-noout", "-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05001447 self.assertEqual(dumped_text, good_text)
1448
1449
1450 def test_dump_privatekey(self):
1451 """
1452 L{dump_privatekey} writes a PEM, DER, and text.
1453 """
1454 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
1455 dumped_pem = dump_privatekey(FILETYPE_PEM, key)
1456 self.assertEqual(dumped_pem, cleartextPrivateKeyPEM)
1457 dumped_der = dump_privatekey(FILETYPE_ASN1, key)
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04001458 # XXX This OpenSSL call writes "writing RSA key" to standard out. Sad.
Rick Dean4c9ad612009-07-17 15:05:22 -05001459 good_der = _runopenssl(dumped_pem, "rsa", "-outform", "DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05001460 self.assertEqual(dumped_der, good_der)
1461 key2 = load_privatekey(FILETYPE_ASN1, dumped_der)
1462 dumped_pem2 = dump_privatekey(FILETYPE_PEM, key2)
1463 self.assertEqual(dumped_pem2, cleartextPrivateKeyPEM)
1464 dumped_text = dump_privatekey(FILETYPE_TEXT, key)
Rick Dean4c9ad612009-07-17 15:05:22 -05001465 good_text = _runopenssl(dumped_pem, "rsa", "-noout", "-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05001466 self.assertEqual(dumped_text, good_text)
1467
Jean-Paul Calderonef17e4212009-04-01 14:21:40 -04001468
Rick Dean5b7b6372009-04-01 11:34:06 -05001469 def test_dump_certificate_request(self):
1470 """
1471 L{dump_certificate_request} writes a PEM, DER, and text.
1472 """
1473 req = load_certificate_request(FILETYPE_PEM, cleartextCertificateRequestPEM)
1474 dumped_pem = dump_certificate_request(FILETYPE_PEM, req)
1475 self.assertEqual(dumped_pem, cleartextCertificateRequestPEM)
1476 dumped_der = dump_certificate_request(FILETYPE_ASN1, req)
Rick Dean4c9ad612009-07-17 15:05:22 -05001477 good_der = _runopenssl(dumped_pem, "req", "-outform", "DER")
Rick Dean5b7b6372009-04-01 11:34:06 -05001478 self.assertEqual(dumped_der, good_der)
1479 req2 = load_certificate_request(FILETYPE_ASN1, dumped_der)
1480 dumped_pem2 = dump_certificate_request(FILETYPE_PEM, req2)
1481 self.assertEqual(dumped_pem2, cleartextCertificateRequestPEM)
1482 dumped_text = dump_certificate_request(FILETYPE_TEXT, req)
Rick Dean4c9ad612009-07-17 15:05:22 -05001483 good_text = _runopenssl(dumped_pem, "req", "-noout", "-text")
Rick Dean5b7b6372009-04-01 11:34:06 -05001484 self.assertEqual(dumped_text, good_text)
1485
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -04001486
1487 def test_dump_privatekey_passphraseCallback(self):
1488 """
1489 L{dump_privatekey} writes an encrypted PEM when given a callback which
1490 returns the correct passphrase.
1491 """
1492 passphrase = "foo"
1493 called = []
1494 def cb(writing):
1495 called.append(writing)
1496 return passphrase
1497 key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
1498 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", cb)
1499 self.assertTrue(isinstance(pem, str))
1500 self.assertEqual(called, [True])
1501 loadedKey = load_privatekey(FILETYPE_PEM, pem, passphrase)
1502 self.assertTrue(isinstance(loadedKey, PKeyType))
1503 self.assertEqual(loadedKey.type(), key.type())
1504 self.assertEqual(loadedKey.bits(), key.bits())
Rick Dean5b7b6372009-04-01 11:34:06 -05001505
1506
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04001507 def test_load_pkcs7_data(self):
1508 """
1509 L{load_pkcs7_data} accepts a PKCS#7 string and returns an instance of
1510 L{PKCS7Type}.
1511 """
1512 pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
1513 self.assertTrue(isinstance(pkcs7, PKCS7Type))
1514
1515
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04001516
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001517class PKCS7Tests(TestCase):
1518 """
1519 Tests for L{PKCS7Type}.
1520 """
1521 def test_type(self):
1522 """
1523 L{PKCS7Type} is a type object.
1524 """
1525 self.assertTrue(isinstance(PKCS7Type, type))
1526 self.assertEqual(PKCS7Type.__name__, 'PKCS7')
1527
1528 # XXX This doesn't currently work.
1529 # self.assertIdentical(PKCS7, PKCS7Type)
1530
1531
1532
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04001533class NetscapeSPKITests(TestCase):
1534 """
1535 Tests for L{OpenSSL.crypto.NetscapeSPKI}.
1536 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001537 def test_type(self):
1538 """
1539 L{NetscapeSPKI} and L{NetscapeSPKIType} refer to the same type object
1540 and can be used to create instances of that type.
1541 """
1542 self.assertIdentical(NetscapeSPKI, NetscapeSPKIType)
1543 self.assertConsistentType(NetscapeSPKI, 'NetscapeSPKI')
1544
1545
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04001546 def test_construction(self):
1547 """
1548 L{NetscapeSPKI} returns an instance of L{NetscapeSPKIType}.
1549 """
1550 nspki = NetscapeSPKI()
1551 self.assertTrue(isinstance(nspki, NetscapeSPKIType))
1552
1553
Rick Dean536ba022009-07-24 23:57:27 -05001554class RevokedTests(TestCase):
1555 """
1556 Tests for L{OpenSSL.crypto.Revoked}
1557 """
1558 def test_construction(self):
1559 """
1560 Confirm we can create L{OpenSSL.crypto.Revoked}. Check
1561 that it is empty.
1562 """
1563 revoked = Revoked()
1564 self.assertTrue( isinstance(revoked, Revoked) )
1565 self.assertEqual( type(revoked), Revoked )
1566 self.assertEqual( revoked.get_serial(), '00' )
1567 self.assertEqual( revoked.get_rev_date(), None )
Rick Dean6385faf2009-07-26 00:07:47 -05001568 self.assertEqual( revoked.get_reason(), None )
Rick Dean536ba022009-07-24 23:57:27 -05001569
1570
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05001571 def test_construction_wrong_args(self):
1572 """
1573 Calling L{OpenSSL.crypto.Revoked} with any arguments results
1574 in a L{TypeError} being raised.
1575 """
1576 self.assertRaises(TypeError, Revoked, None)
1577 self.assertRaises(TypeError, Revoked, 1)
1578 self.assertRaises(TypeError, Revoked, "foo")
1579
1580
Rick Dean536ba022009-07-24 23:57:27 -05001581 def test_serial(self):
1582 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05001583 Confirm we can set and get serial numbers from
Rick Dean536ba022009-07-24 23:57:27 -05001584 L{OpenSSL.crypto.Revoked}. Confirm errors are handled
1585 with grace.
1586 """
1587 revoked = Revoked()
1588 ret = revoked.set_serial('10b')
1589 self.assertEqual( ret, None )
1590 ser = revoked.get_serial()
1591 self.assertEqual( ser, '010B' )
1592
1593 revoked.set_serial('31ppp') # a type error would be nice
1594 ser = revoked.get_serial()
1595 self.assertEqual( ser, '31' )
1596
Rick Dean6385faf2009-07-26 00:07:47 -05001597 self.assertRaises(ValueError, revoked.set_serial, 'pqrst')
Rick Dean536ba022009-07-24 23:57:27 -05001598 self.assertRaises(TypeError, revoked.set_serial, 100)
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05001599 self.assertRaises(TypeError, revoked.get_serial, 1)
1600 self.assertRaises(TypeError, revoked.get_serial, None)
1601 self.assertRaises(TypeError, revoked.get_serial, "")
Rick Dean536ba022009-07-24 23:57:27 -05001602
1603
1604 def test_date(self):
1605 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05001606 Confirm we can set and get revocation dates from
Rick Dean536ba022009-07-24 23:57:27 -05001607 L{OpenSSL.crypto.Revoked}. Confirm errors are handled
1608 with grace.
1609 """
1610 revoked = Revoked()
1611 date = revoked.get_rev_date()
1612 self.assertEqual( date, None )
1613
1614 now = datetime.now().strftime("%Y%m%d%H%M%SZ")
1615 ret = revoked.set_rev_date(now)
1616 self.assertEqual( ret, None )
1617 date = revoked.get_rev_date()
1618 self.assertEqual( date, now )
1619
1620
Rick Dean6385faf2009-07-26 00:07:47 -05001621 def test_reason(self):
1622 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05001623 Confirm we can set and get revocation reasons from
Rick Dean6385faf2009-07-26 00:07:47 -05001624 L{OpenSSL.crypto.Revoked}. The "get" need to work
1625 as "set". Likewise, each reason of all_reasons() must work.
1626 """
1627 revoked = Revoked()
1628 for r in revoked.all_reasons():
1629 for x in xrange(2):
1630 ret = revoked.set_reason(r)
1631 self.assertEqual( ret, None )
1632 reason = revoked.get_reason()
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05001633 self.assertEqual( reason.lower().replace(' ',''),
Rick Dean6385faf2009-07-26 00:07:47 -05001634 r.lower().replace(' ','') )
1635 r = reason # again with the resp of get
1636
1637 revoked.set_reason(None)
1638 self.assertEqual(revoked.get_reason(), None)
1639
1640
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05001641 def test_set_reason_wrong_arguments(self):
Rick Dean6385faf2009-07-26 00:07:47 -05001642 """
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05001643 Calling L{OpenSSL.crypto.Revoked.set_reason} with other than
1644 one argument, or an argument which isn't a valid reason,
1645 results in L{TypeError} or L{ValueError} being raised.
Rick Dean6385faf2009-07-26 00:07:47 -05001646 """
1647 revoked = Revoked()
1648 self.assertRaises(TypeError, revoked.set_reason, 100)
1649 self.assertRaises(ValueError, revoked.set_reason, 'blue')
1650
Rick Dean536ba022009-07-24 23:57:27 -05001651
Jean-Paul Calderone4f74bfe2010-01-30 14:32:49 -05001652 def test_get_reason_wrong_arguments(self):
1653 """
1654 Calling L{OpenSSL.crypto.Revoked.get_reason} with any
1655 arguments results in L{TypeError} being raised.
1656 """
1657 revoked = Revoked()
1658 self.assertRaises(TypeError, revoked.get_reason, None)
1659 self.assertRaises(TypeError, revoked.get_reason, 1)
1660 self.assertRaises(TypeError, revoked.get_reason, "foo")
1661
1662
1663
Rick Dean536ba022009-07-24 23:57:27 -05001664class CRLTests(TestCase):
1665 """
1666 Tests for L{OpenSSL.crypto.CRL}
1667 """
1668 cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
1669 pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
1670
1671 def test_construction(self):
1672 """
1673 Confirm we can create L{OpenSSL.crypto.CRL}. Check
1674 that it is empty
1675 """
1676 crl = CRL()
1677 self.assertTrue( isinstance(crl, CRL) )
1678 self.assertEqual(crl.get_revoked(), None)
1679
1680
Jean-Paul Calderone2efd03e2010-01-30 13:59:55 -05001681 def test_construction_wrong_args(self):
1682 """
1683 Calling L{OpenSSL.crypto.CRL} with any number of arguments
1684 results in a L{TypeError} being raised.
1685 """
1686 self.assertRaises(TypeError, CRL, 1)
1687 self.assertRaises(TypeError, CRL, "")
1688 self.assertRaises(TypeError, CRL, None)
1689
1690
Rick Dean536ba022009-07-24 23:57:27 -05001691 def test_export(self):
1692 """
1693 Use python to create a simple CRL with a revocation, and export
1694 the CRL in formats of PEM, DER and text. Those outputs are verified
1695 with the openssl program.
1696 """
1697 crl = CRL()
1698 revoked = Revoked()
1699 now = datetime.now().strftime("%Y%m%d%H%M%SZ")
1700 revoked.set_rev_date(now)
1701 revoked.set_serial('3ab')
Rick Dean6385faf2009-07-26 00:07:47 -05001702 revoked.set_reason('sUpErSeDEd')
Rick Dean536ba022009-07-24 23:57:27 -05001703 crl.add_revoked(revoked)
1704
1705 # PEM format
1706 dumped_crl = crl.export(self.cert, self.pkey, days=20)
1707 text = _runopenssl(dumped_crl, "crl", "-noout", "-text")
1708 text.index('Serial Number: 03AB')
Rick Dean6385faf2009-07-26 00:07:47 -05001709 text.index('Superseded')
Rick Dean536ba022009-07-24 23:57:27 -05001710 text.index('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA')
1711
1712 # DER format
1713 dumped_crl = crl.export(self.cert, self.pkey, FILETYPE_ASN1)
1714 text = _runopenssl(dumped_crl, "crl", "-noout", "-text", "-inform", "DER")
1715 text.index('Serial Number: 03AB')
Rick Dean6385faf2009-07-26 00:07:47 -05001716 text.index('Superseded')
Rick Dean536ba022009-07-24 23:57:27 -05001717 text.index('Issuer: /C=US/ST=IL/L=Chicago/O=Testing/CN=Testing Root CA')
1718
1719 # text format
1720 dumped_text = crl.export(self.cert, self.pkey, type=FILETYPE_TEXT)
1721 self.assertEqual(text, dumped_text)
1722
1723
Jean-Paul Calderone56515342010-01-30 13:49:38 -05001724 def test_add_revoked_keyword(self):
1725 """
1726 L{OpenSSL.CRL.add_revoked} accepts its single argument as the
1727 I{revoked} keyword argument.
1728 """
1729 crl = CRL()
1730 revoked = Revoked()
1731 crl.add_revoked(revoked=revoked)
1732 self.assertTrue(isinstance(crl.get_revoked()[0], Revoked))
1733
Rick Dean6385faf2009-07-26 00:07:47 -05001734
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05001735 def test_export_wrong_args(self):
1736 """
1737 Calling L{OpenSSL.CRL.export} with fewer than two or more than
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05001738 four arguments, or with arguments other than the certificate,
1739 private key, integer file type, and integer number of days it
1740 expects, results in a L{TypeError} being raised.
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05001741 """
1742 crl = CRL()
1743 self.assertRaises(TypeError, crl.export)
1744 self.assertRaises(TypeError, crl.export, self.cert)
1745 self.assertRaises(TypeError, crl.export, self.cert, self.pkey, FILETYPE_PEM, 10, "foo")
1746
Jean-Paul Calderonef1515862010-01-30 13:57:03 -05001747 self.assertRaises(TypeError, crl.export, None, self.pkey, FILETYPE_PEM, 10)
1748 self.assertRaises(TypeError, crl.export, self.cert, None, FILETYPE_PEM, 10)
1749 self.assertRaises(TypeError, crl.export, self.cert, self.pkey, None, 10)
1750 self.assertRaises(TypeError, crl.export, self.cert, FILETYPE_PEM, None)
1751
Jean-Paul Calderone883ca4b2010-01-30 13:55:13 -05001752
Jean-Paul Calderoneea198422010-01-30 13:58:23 -05001753 def test_export_unknown_filetype(self):
1754 """
1755 Calling L{OpenSSL.CRL.export} with a file type other than
1756 L{FILETYPE_PEM}, L{FILETYPE_ASN1}, or L{FILETYPE_TEXT} results
1757 in a L{ValueError} being raised.
1758 """
1759 crl = CRL()
1760 self.assertRaises(ValueError, crl.export, self.cert, self.pkey, 100, 10)
1761
1762
Rick Dean536ba022009-07-24 23:57:27 -05001763 def test_get_revoked(self):
1764 """
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05001765 Use python to create a simple CRL with two revocations.
1766 Get back the L{Revoked} using L{OpenSSL.CRL.get_revoked} and
Rick Dean536ba022009-07-24 23:57:27 -05001767 verify them.
1768 """
1769 crl = CRL()
1770
1771 revoked = Revoked()
1772 now = datetime.now().strftime("%Y%m%d%H%M%SZ")
1773 revoked.set_rev_date(now)
1774 revoked.set_serial('3ab')
1775 crl.add_revoked(revoked)
1776 revoked.set_serial('100')
Rick Dean6385faf2009-07-26 00:07:47 -05001777 revoked.set_reason('sUpErSeDEd')
Rick Dean536ba022009-07-24 23:57:27 -05001778 crl.add_revoked(revoked)
1779
1780 revs = crl.get_revoked()
1781 self.assertEqual(len(revs), 2)
1782 self.assertEqual(type(revs[0]), Revoked)
1783 self.assertEqual(type(revs[1]), Revoked)
1784 self.assertEqual(revs[0].get_serial(), '03AB')
1785 self.assertEqual(revs[1].get_serial(), '0100')
1786 self.assertEqual(revs[0].get_rev_date(), now)
1787 self.assertEqual(revs[1].get_rev_date(), now)
1788
1789
Jean-Paul Calderone46bdce42010-01-30 13:44:16 -05001790 def test_get_revoked_wrong_args(self):
1791 """
1792 Calling L{OpenSSL.CRL.get_revoked} with any arguments results
1793 in a L{TypeError} being raised.
1794 """
1795 crl = CRL()
1796 self.assertRaises(TypeError, crl.get_revoked, None)
1797 self.assertRaises(TypeError, crl.get_revoked, 1)
1798 self.assertRaises(TypeError, crl.get_revoked, "")
1799 self.assertRaises(TypeError, crl.get_revoked, "", 1, None)
1800
1801
Jean-Paul Calderoneecef6fa2010-01-30 13:47:18 -05001802 def test_add_revoked_wrong_args(self):
1803 """
1804 Calling L{OpenSSL.CRL.add_revoked} with other than one
1805 argument results in a L{TypeError} being raised.
1806 """
1807 crl = CRL()
1808 self.assertRaises(TypeError, crl.add_revoked)
1809 self.assertRaises(TypeError, crl.add_revoked, 1, 2)
1810 self.assertRaises(TypeError, crl.add_revoked, "foo", "bar")
1811
1812
Rick Dean536ba022009-07-24 23:57:27 -05001813 def test_load_crl(self):
1814 """
1815 Load a known CRL and inspect its revocations. Both
1816 PEM and DER formats are loaded.
1817 """
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05001818 crl = load_crl(FILETYPE_PEM, crlData)
Rick Dean536ba022009-07-24 23:57:27 -05001819 revs = crl.get_revoked()
1820 self.assertEqual(len(revs), 2)
1821 self.assertEqual(revs[0].get_serial(), '03AB')
Rick Dean6385faf2009-07-26 00:07:47 -05001822 self.assertEqual(revs[0].get_reason(), None)
Rick Dean536ba022009-07-24 23:57:27 -05001823 self.assertEqual(revs[1].get_serial(), '0100')
Rick Dean6385faf2009-07-26 00:07:47 -05001824 self.assertEqual(revs[1].get_reason(), 'Superseded')
Rick Dean536ba022009-07-24 23:57:27 -05001825
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05001826 der = _runopenssl(crlData, "crl", "-outform", "DER")
Jean-Paul Calderoneb98eae02010-01-30 13:18:04 -05001827 crl = load_crl(FILETYPE_ASN1, der)
Rick Dean536ba022009-07-24 23:57:27 -05001828 revs = crl.get_revoked()
1829 self.assertEqual(len(revs), 2)
1830 self.assertEqual(revs[0].get_serial(), '03AB')
Rick Dean6385faf2009-07-26 00:07:47 -05001831 self.assertEqual(revs[0].get_reason(), None)
Rick Dean536ba022009-07-24 23:57:27 -05001832 self.assertEqual(revs[1].get_serial(), '0100')
Rick Dean6385faf2009-07-26 00:07:47 -05001833 self.assertEqual(revs[1].get_reason(), 'Superseded')
Rick Dean536ba022009-07-24 23:57:27 -05001834
1835
Jean-Paul Calderone3eb5cc72010-01-30 15:24:40 -05001836 def test_load_crl_wrong_args(self):
1837 """
1838 Calling L{OpenSSL.crypto.load_crl} with other than two
1839 arguments results in a L{TypeError} being raised.
1840 """
1841 self.assertRaises(TypeError, load_crl)
1842 self.assertRaises(TypeError, load_crl, FILETYPE_PEM)
1843 self.assertRaises(TypeError, load_crl, FILETYPE_PEM, crlData, None)
1844
1845
1846 def test_load_crl_bad_filetype(self):
1847 """
1848 Calling L{OpenSSL.crypto.load_crl} with an unknown file type
1849 raises a L{ValueError}.
1850 """
1851 self.assertRaises(ValueError, load_crl, 100, crlData)
1852
1853
1854 def test_load_crl_bad_data(self):
1855 """
1856 Calling L{OpenSSL.crypto.load_crl} with file data which can't
1857 be loaded raises a L{OpenSSL.crypto.Error}.
1858 """
1859 self.assertRaises(Error, load_crl, FILETYPE_PEM, "hello, world")
1860
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -04001861
James Yonan7c2e5d32010-02-27 05:45:50 -07001862class SignVerifyTests(TestCase):
1863 """
1864 Tests for L{OpenSSL.crypto.sign} and L{OpenSSL.crypto.verify}.
1865 """
1866 def test_sign_verify(self):
1867 from OpenSSL.crypto import sign, verify
1868
1869 content = "It was a bright cold day in April, and the clocks were striking thirteen. Winston Smith, his chin nuzzled into his breast in an effort to escape the vile wind, slipped quickly through the glass doors of Victory Mansions, though not quickly enough to prevent a swirl of gritty dust from entering along with him."
1870 priv_key = load_privatekey (FILETYPE_PEM, root_key_pem) # sign the content with this private key
1871 good_cert = load_certificate(FILETYPE_PEM, root_cert_pem) # verify the content with this cert
1872 bad_cert = load_certificate(FILETYPE_PEM, server_cert_pem) # certificate unrelated to priv_key, used to trigger an error
1873
1874 for digest in ('md5', 'sha1'):
1875 sig = sign(priv_key, content, digest)
1876
1877 # Verify the signature of content, will throw an exception if error.
1878 verify(good_cert, sig, content, digest)
1879
1880 # This should fail because the certificate doesn't match the
1881 # private key that was used to sign the content.
1882 self.assertRaises(Error, verify, bad_cert, sig, content, digest)
1883
1884 # This should fail because we've "tainted" the content after
1885 # signing it.
1886 self.assertRaises(Error, verify, good_cert, sig, content+"tainted", digest)
1887
1888 # test that unknown digest types fail
1889 self.assertRaises(ValueError, sign, priv_key, content, "strange-digest")
1890 self.assertRaises(ValueError, verify, good_cert, sig, content, "strange-digest")
1891
Rick Dean5b7b6372009-04-01 11:34:06 -05001892if __name__ == '__main__':
1893 main()