]> www.wagner.pp.ru Git - oss/ctypescrypto.git/blob - tests/testx509.py
Generate new certificates for X509 tests, because old ones no more validate since...
[oss/ctypescrypto.git] / tests / testx509.py
1 #!/usr/bin/env python
2 # -*- encoding: utf-8 -*-
3
4 from ctypescrypto.x509 import X509,X509Store,utc,StackOfX509
5 from ctypescrypto.oid import Oid
6 from tempfile import NamedTemporaryFile
7 import datetime
8 import unittest
9 import os
10
11
12
13 class TestCertInfo(unittest.TestCase):
14     ca_cert="""-----BEGIN CERTIFICATE-----
15 MIIDxzCCAq+gAwIBAgIJAJ3NNJJNENcOMA0GCSqGSIb3DQEBCwUAMHoxMDAuBgNV
16 BAoMJ9Cj0LTQvtGB0YLQvtCy0LXRgNGP0Y7RidC40Lkg0YbQtdC90YLRgDEiMCAG
17 A1UEAwwZ0JLQuNC60YLQvtGAINCS0LDQs9C90LXRgDELMAkGA1UEBhMCUlUxFTAT
18 BgNVBAgMDNCc0L7RgdC60LLQsDAeFw0xODA0MjkxMjA3NTBaFw0xODA1MjkxMjA3
19 NTBaMHoxMDAuBgNVBAoMJ9Cj0LTQvtGB0YLQvtCy0LXRgNGP0Y7RidC40Lkg0YbQ
20 tdC90YLRgDEiMCAGA1UEAwwZ0JLQuNC60YLQvtGAINCS0LDQs9C90LXRgDELMAkG
21 A1UEBhMCUlUxFTATBgNVBAgMDNCc0L7RgdC60LLQsDCCASIwDQYJKoZIhvcNAQEB
22 BQADggEPADCCAQoCggEBALUXej45EASSw0LRzBQdrktr17KrCaPuVePvdMZYLv6R
23 bN14WwLAAMhk2YfKRSsiv6Vv+n6waWXLKxSKcbS+GU0aHJ/0o85ay7lbZCxvk1Fq
24 pIZeEeILLYOkS+HhFzVXZ4OarO/eZl+tbB1aR/locA5xCHiMqo6pwWRoHMHNriWw
25 DAH3bUxe3DBi3wjQRBq6V6SolDUjjX1CHDH6zaCoe2cQAPsqti6vOG2q08MzEYuC
26 6yDQhjNgXaziUtMo/wpmOsHReTGd44TyMG0FSu8Rs4kVueVBIHjKQpHYMpcb4PI/
27 lhbQgI6495KRU7d5o0FoEsdmcr7ZJ+tFTIUkudBeSA8CAwEAAaNQME4wHQYDVR0O
28 BBYEFCqBD8LZD/Gr4TMy1YyzqzCFt/BEMB8GA1UdIwQYMBaAFCqBD8LZD/Gr4TMy
29 1YyzqzCFt/BEMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAJ3tJjXO
30 c3zUvVQLmUN9J1UcDx9HTNvarOrUXqOiO8ZZIsWdk9+wWXq6oSktdM/ksLL2XyOB
31 rDbFFgVZnniTJufutWUsyQxpSe5eEhqBCqeAPVKEj1AulPgMs8zM6s/uOnTw1W35
32 RzCewrHAnrbQo/hSmzYR101C6k8lUr3jyr69LxIzcqURKdEoatxHH2pFkY1uSkIi
33 qzJrUJeJQrHq1yub2cuNvB/WDmjwdLtPHADtwWRaU65/9yVr5/f54aztuodGM4iX
34 hfB1qdrCFhaN3ku6/VUIpMdnuxcYTx7b2M4KDwG6t5wNCOdfHoMzYYJ6wJbk8pdH
35 9oCVJRRUrpqSB8k=
36 -----END CERTIFICATE-----
37 """
38     cert1="""-----BEGIN CERTIFICATE-----
39 MIIEVDCCAzygAwIBAgIJAPlBrd9jYtl5MA0GCSqGSIb3DQEBCwUAMHoxMDAuBgNV
40 BAoMJ9Cj0LTQvtGB0YLQvtCy0LXRgNGP0Y7RidC40Lkg0YbQtdC90YLRgDEiMCAG
41 A1UEAwwZ0JLQuNC60YLQvtGAINCS0LDQs9C90LXRgDELMAkGA1UEBhMCUlUxFTAT
42 BgNVBAgMDNCc0L7RgdC60LLQsDAeFw0xODA0MjkxMjM4MDZaFw0yODA0MjYxMjM4
43 MDZaMIGBMQswCQYDVQQGEwJSVTEVMBMGA1UECAwM0JzQvtGB0LrQstCwMRUwEwYD
44 VQQHDAzQnNC+0YHQutCy0LAxIDAeBgNVBAoMF9Cn0LDRgdGC0L3QvtC1INC70LjR
45 htC+MSIwIAYDVQQDDBnQktC40LrRgtC+0YAg0JLQsNCz0L3QtdGAMIIBIjANBgkq
46 hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArvwAU7NxWPzy1zmrQRACzWiIRB15bRRg
47 bMoBjdalivIUPrmOBHcWGl16tFZHikDBoTNUPcExyzqeLaAARGG4SIc/mv3tdQyA
48 5Mt02UciW6GIMDMvpz97EY1Zr7fTzYKDPAeF0vaYM5e98Rf0J5OB9NVMxaeylc81
49 u4WBCLy4H3lwixB2cPbs0UCC/Pt/hXKlWukkFjGFm0xspu62IRDvuyEkJXhcryrB
50 VN1WEXNCRwfFEqO+Og4/L+hh9ZyNchbfIJdjenytA1HS9jHpB/C0x32eHCunC2Uf
51 7/rSWHtRAaKf67wNcM3TO25cnoWYfitZ8dj0LgMVCpZQMbwk8qYWgwIDAQABo4HU
52 MIHRMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgXgMBMGA1UdJQQMMAoGCCsGAQUFBwMB
53 MB0GA1UdDgQWBBSvfzRZ/IT2OHoNscl5MuifIqOstzAfBgNVHSMEGDAWgBQqgQ/C
54 2Q/xq+EzMtWMs6swhbfwRDBDBggrBgEFBQcBAQQ3MDUwMwYIKwYBBQUHMAKGJ2h0
55 dHA6Ly93d3cud2FnbmVyLnBwLnJ1LzQ1LmZyZWUubmV0LmRlcjAdBgNVHREEFjAU
56 gRJ2aXR1c0B3YWduZXIucHAucnUwDQYJKoZIhvcNAQELBQADggEBAFq3Xle9+pwE
57 zBhXXCYJZh4b0KGXYp/Ru7kOqNXKWz6rIcxfqozrKZo8qSkxK/g2KOSXM4jXCy1p
58 vfl3qproieewQmHTNvuVSnOjGNSkpsj2fkx7ew5mKb/rrH97a8JU1BhESOR2D32h
59 0d6l3eROs+nSPxQ8i1FIudbVMp6kg2cY7WEZRgijGlOar3M4SdYUYT5GJvO7cPm/
60 B9JpzGu20rEegXftdjyjUj4k0PuIw/fYN9lHrYh/+TK8IMHAZ4nhsqwZH1IWjTsk
61 iJW/uZYOIYhHMieEEoVcgAEKL5uiYB95O690Qtm6Q0hKbIzCClQSuaCSKWQRVBfz
62 mBDJd6+znkw=
63 -----END CERTIFICATE-----
64 """
65     pubkey1="""-----BEGIN PUBLIC KEY-----
66 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArvwAU7NxWPzy1zmrQRAC
67 zWiIRB15bRRgbMoBjdalivIUPrmOBHcWGl16tFZHikDBoTNUPcExyzqeLaAARGG4
68 SIc/mv3tdQyA5Mt02UciW6GIMDMvpz97EY1Zr7fTzYKDPAeF0vaYM5e98Rf0J5OB
69 9NVMxaeylc81u4WBCLy4H3lwixB2cPbs0UCC/Pt/hXKlWukkFjGFm0xspu62IRDv
70 uyEkJXhcryrBVN1WEXNCRwfFEqO+Og4/L+hh9ZyNchbfIJdjenytA1HS9jHpB/C0
71 x32eHCunC2Uf7/rSWHtRAaKf67wNcM3TO25cnoWYfitZ8dj0LgMVCpZQMbwk8qYW
72 gwIDAQAB
73 -----END PUBLIC KEY-----
74 """
75     digicert_cert="""digicert.crt
76 -----BEGIN CERTIFICATE-----
77 MIIG5jCCBc6gAwIBAgIQAze5KDR8YKauxa2xIX84YDANBgkqhkiG9w0BAQUFADBs
78 MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
79 d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
80 ZSBFViBSb290IENBMB4XDTA3MTEwOTEyMDAwMFoXDTIxMTExMDAwMDAwMFowaTEL
81 MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
82 LmRpZ2ljZXJ0LmNvbTEoMCYGA1UEAxMfRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
83 RVYgQ0EtMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPOWYth1bhn/
84 PzR8SU8xfg0ETpmB4rOFVZEwscCvcLssqOcYqj9495BoUoYBiJfiOwZlkKq9ZXbC
85 7L4QWzd4g2B1Rca9dKq2n6Q6AVAXxDlpufFP74LByvNK28yeUE9NQKM6kOeGZrzw
86 PnYoTNF1gJ5qNRQ1A57bDIzCKK1Qss72kaPDpQpYSfZ1RGy6+c7pqzoC4E3zrOJ6
87 4GAiBTyC01Li85xH+DvYskuTVkq/cKs+6WjIHY9YHSpNXic9rQpZL1oRIEDZaARo
88 LfTAhAsKG3jf7RpY3PtBWm1r8u0c7lwytlzs16YDMqbo3rcoJ1mIgP97rYlY1R4U
89 pPKwcNSgPqcCAwEAAaOCA4UwggOBMA4GA1UdDwEB/wQEAwIBhjA7BgNVHSUENDAy
90 BggrBgEFBQcDAQYIKwYBBQUHAwIGCCsGAQUFBwMDBggrBgEFBQcDBAYIKwYBBQUH
91 AwgwggHEBgNVHSAEggG7MIIBtzCCAbMGCWCGSAGG/WwCATCCAaQwOgYIKwYBBQUH
92 AgEWLmh0dHA6Ly93d3cuZGlnaWNlcnQuY29tL3NzbC1jcHMtcmVwb3NpdG9yeS5o
93 dG0wggFkBggrBgEFBQcCAjCCAVYeggFSAEEAbgB5ACAAdQBzAGUAIABvAGYAIAB0
94 AGgAaQBzACAAQwBlAHIAdABpAGYAaQBjAGEAdABlACAAYwBvAG4AcwB0AGkAdAB1
95 AHQAZQBzACAAYQBjAGMAZQBwAHQAYQBuAGMAZQAgAG8AZgAgAHQAaABlACAARABp
96 AGcAaQBDAGUAcgB0ACAARQBWACAAQwBQAFMAIABhAG4AZAAgAHQAaABlACAAUgBl
97 AGwAeQBpAG4AZwAgAFAAYQByAHQAeQAgAEEAZwByAGUAZQBtAGUAbgB0ACAAdwBo
98 AGkAYwBoACAAbABpAG0AaQB0ACAAbABpAGEAYgBpAGwAaQB0AHkAIABhAG4AZAAg
99 AGEAcgBlACAAaQBuAGMAbwByAHAAbwByAGEAdABlAGQAIABoAGUAcgBlAGkAbgAg
100 AGIAeQAgAHIAZQBmAGUAcgBlAG4AYwBlAC4wEgYDVR0TAQH/BAgwBgEB/wIBADCB
101 gwYIKwYBBQUHAQEEdzB1MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2Vy
102 dC5jb20wTQYIKwYBBQUHMAKGQWh0dHA6Ly93d3cuZGlnaWNlcnQuY29tL0NBQ2Vy
103 dHMvRGlnaUNlcnRIaWdoQXNzdXJhbmNlRVZSb290Q0EuY3J0MIGPBgNVHR8EgYcw
104 gYQwQKA+oDyGOmh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEhpZ2hB
105 c3N1cmFuY2VFVlJvb3RDQS5jcmwwQKA+oDyGOmh0dHA6Ly9jcmw0LmRpZ2ljZXJ0
106 LmNvbS9EaWdpQ2VydEhpZ2hBc3N1cmFuY2VFVlJvb3RDQS5jcmwwHQYDVR0OBBYE
107 FExYyyXwQU9S9CjIgUObpqig5pLlMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSYJhoI
108 Au9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQBMeheHKF0XvLIyc7/NLvVYMR3wsXFU
109 nNabZ5PbLwM+Fm8eA8lThKNWYB54lBuiqG+jpItSkdfdXJW777UWSemlQk808kf/
110 roF/E1S3IMRwFcuBCoHLdFfcnN8kpCkMGPAc5K4HM+zxST5Vz25PDVR708noFUjU
111 xbvcNRx3RQdIRYW9135TuMAW2ZXNi419yWBP0aKb49Aw1rRzNubS+QOy46T15bg+
112 BEkAui6mSnKDcp33C4ypieez12Qf1uNgywPE3IjpnSUBAHHLA7QpYCWP+UbRe3Gu
113 zVMSW4SOwg/H7ZMZ2cn6j1g0djIvruFQFGHUqFijyDATI+/GJYw2jxyA
114 -----END CERTIFICATE-----
115 """
116     def test_readpubkey(self):
117         c=X509(self.cert1)
118         p=c.pubkey
119         self.assertEqual(p.exportpub(),self.pubkey1)
120     def test_pem(self):
121         c=X509(self.cert1)
122         self.assertEqual(c.pem(),self.cert1)
123     def test_subject(self):
124         c=X509(self.cert1)
125         self.assertEqual(unicode(c.subject),u'C=RU,ST=Москва,L=Москва,O=Частное лицо,CN=Виктор Вагнер')
126     def test_subject_str(self):
127         c=X509(self.cert1)
128         self.assertEqual(str(c.subject),b'C=RU,ST=\\D0\\9C\\D0\\BE\\D1\\81\\D0\\BA\\D0\\B2\\D0\\B0,L=\\D0\\9C\\D0\\BE\\D1\\81\\D0\\BA\\D0\\B2\\D0\\B0,O=\\D0\\A7\\D0\\B0\\D1\\81\\D1\\82\\D0\\BD\\D0\\BE\\D0\\B5 \\D0\\BB\\D0\\B8\\D1\\86\\D0\\BE,CN=\\D0\\92\\D0\\B8\\D0\\BA\\D1\\82\\D0\\BE\\D1\\80 \\D0\\92\\D0\\B0\\D0\\B3\\D0\\BD\\D0\\B5\\D1\\80')
129     def test_subject_len(self):
130         c=X509(self.cert1)
131         self.assertEqual(len(c.subject),5)
132     def test_issuer(self):
133         c=X509(self.cert1)
134         self.assertEqual(unicode(c.issuer),u'O=Удостоверяющий центр,CN=Виктор Вагнер,C=RU,ST=Москва')
135     def test_subjectfields(self):
136         c=X509(self.cert1)
137         self.assertEqual(c.subject[Oid("C")],"RU")
138         with self.assertRaises(TypeError):
139             x=c.subject["CN"]
140         self.assertEqual(c.subject[Oid("L")],u'\u041c\u043e\u0441\u043a\u0432\u0430')
141     def test_subjectmodify(self):
142         c=X509(self.cert1)
143         with self.assertRaises(ValueError):
144             c.subject[Oid("CN")]=u'Foo'
145         with self.assertRaises(ValueError):
146             del c.subject[Oid('CN')]
147     def test_subjectbadsubfield(self):
148         c=X509(self.cert1)
149         with self.assertRaises(KeyError):
150             x=c.subject[Oid("streetAddress")]
151     def test_subjectfieldindex(self):
152         c=X509(self.cert1)
153         self.assertEqual(repr(c.subject[0]),repr((Oid('C'),u'RU')))
154     def test_subjectbadindex(self):
155         c=X509(self.cert1)
156         with self.assertRaises(IndexError):
157             x=c.subject[11]
158         with self.assertRaises(IndexError):
159             x=c.subject[-1]
160     def test_notBefore(self):
161         c=X509(self.cert1)
162         self.assertEqual(c.startDate,datetime.datetime(2018,4,29,12,38,6,0,utc))
163     def test_notAfter(self):
164         c=X509(self.cert1)
165         self.assertEqual(c.endDate,datetime.datetime(2028,4,26,12,38,6,0,utc))
166     def test_subjectHash(self):
167         c=X509(self.cert1)
168         self.assertEqual(hash(c.subject),0x1f3ed722)
169     def test_issuerHash(self):
170         c=X509(self.cert1)
171         self.assertEqual(hash(c.issuer),0x55224769)
172     def test_namecomp(self):
173         c=X509(self.cert1)
174         ca=X509(self.ca_cert)
175         self.assertEqual(c.issuer,ca.subject)
176         self.assertNotEqual(c.subject,c.issuer)
177         self.assertEqual(ca.issuer,ca.subject)
178     def test_serial(self):
179         c=X509(self.cert1)
180         self.assertEqual(c.serial,0xf941addf6362d979L)
181     def test_version(self):
182         c=X509(self.cert1)
183         self.assertEqual(c.version,3)
184     def test_ca_cert(self):
185         ca=X509(self.ca_cert)
186         self.assertTrue(ca.check_ca())
187         notca=X509(self.cert1)
188         self.assertFalse(notca.check_ca())
189     def test_extension_count(self):
190         cert=X509(self.cert1)
191         self.assertTrue(len(cert.extensions),4)
192         ca_cert=X509(self.ca_cert)
193         self.assertEqual(len(ca_cert.extensions),3)
194     def test_extension_outofrange(self):
195         cert=X509(self.cert1)
196         with self.assertRaises(IndexError):
197             cert.extensions[8]
198         with self.assertRaises(IndexError):
199             cert.extensions[-1]
200     def test_extension_oid(self):
201         cert=X509(self.cert1)
202         ext=cert.extensions[0]
203         ext_id=ext.oid
204         self.assertTrue(isinstance(ext_id,Oid))
205         self.assertEqual(ext_id,Oid('basicConstraints'))
206     def test_extension_text(self):
207         cert=X509(self.cert1)
208         ext=cert.extensions[0]
209         self.assertEqual(str(ext),'CA:FALSE')
210         self.assertEqual(unicode(ext),u'CA:FALSE')
211     def test_extenson_find(self):
212         cert=X509(self.cert1)
213         exts=cert.extensions.find(Oid('subjectAltName'))
214         self.assertEqual(len(exts),1)
215         self.assertEqual(exts[0].oid,Oid('subjectAltName'))
216     def test_extension_bad_find(self):
217         cert=X509(self.cert1)
218         with self.assertRaises(TypeError):
219             exts=cert.extensions.find('subjectAltName')
220     def test_extenson_critical(self):
221         cert=X509(self.digicert_cert)
222         crit_exts=cert.extensions.find_critical()
223         self.assertEqual(len(crit_exts),2)
224         other_exts=cert.extensions.find_critical(False)
225         self.assertEqual(len(crit_exts)+len(other_exts),len(cert.extensions))
226         self.assertEqual(crit_exts[0].critical,True)
227         self.assertEqual(other_exts[0].critical,False)
228     def test_verify_by_key(self):
229         ca=X509(self.ca_cert)
230         pubkey=ca.pubkey
231         self.assertTrue(ca.verify(key=pubkey))
232         c=X509(self.cert1)
233         pk2=c.pubkey
234         self.assertFalse(c.verify(key=pk2))
235         self.assertTrue(c.verify(key=pubkey))
236     def test_verify_self_singed(self):
237         ca=X509(self.ca_cert)
238         self.assertTrue(ca.verify())
239     def test_default_filestore(self):
240         store=X509Store(default=True)
241         c1=X509(self.cert1)
242         # Cert signed by our CA shouldn't be successfully verified
243         # by default CA store
244         self.assertFalse(c1.verify(store))
245         # but cert, downloaded from some commercial CA - should.
246         c2=X509(self.digicert_cert)
247         self.assertTrue(c2.verify(store))
248     def test_verify_by_filestore(self):
249         trusted=NamedTemporaryFile(delete=False)
250         trusted.write(self.ca_cert)
251         trusted.close()
252         goodcert=X509(self.cert1)
253         badcert=X509(self.cert1[0:-30]+"GG"+self.cert1[-28:])
254         gitcert=X509(self.digicert_cert)
255         store=X509Store(file=trusted.name)
256         os.unlink(trusted.name)
257         # We should successfuly verify certificate signed by our CA cert
258         self.assertTrue(goodcert.verify(store))
259         # We should reject corrupted certificate
260         self.assertFalse(badcert.verify(store))
261         # And if we specify explicitely certificate file, certificate,
262         # signed by some commercial CA should be rejected too
263         self.assertFalse(gitcert.verify(store))
264         trusted.close()
265     def test_verify_by_dirstore(self):
266         pass
267     def test_certstack1(self):
268         l=[]
269         l.append(X509(self.cert1))
270         self.assertEqual(unicode(l[0].subject[Oid('CN')]),u'Виктор Вагнер')
271         l.append(X509(self.ca_cert))
272         l.append(X509(self.digicert_cert))
273         stack=StackOfX509(certs=l)
274         self.assertEqual(len(stack),3)
275         self.assertTrue(isinstance(stack[1],X509))
276         self.assertEqual(unicode(stack[0].subject[Oid('CN')]),u'Виктор Вагнер')
277         with self.assertRaises(IndexError):
278             c=stack[-1]
279         with self.assertRaises(IndexError):
280             c=stack[3]
281         del stack[1]
282         self.assertEqual(len(stack),2)
283         self.assertEqual(unicode(stack[0].subject[Oid('CN')]),u'Виктор Вагнер')
284         self.assertEqual(unicode(stack[1].subject[Oid('CN')]),u'DigiCert High Assurance EV CA-1')
285     def test_certstack2(self):
286         stack=StackOfX509()
287         stack.append(X509(self.cert1))
288         stack.append(X509(self.ca_cert))
289         c=stack[1]
290         stack[1]=X509(self.digicert_cert)
291         self.assertEqual(len(stack),2)
292         self.assertEqual(unicode(stack[1].subject[Oid('CN')]),u'DigiCert High Assurance EV CA-1')
293         with self.assertRaises(IndexError):
294             stack[-1]=c
295         with self.assertRaises(IndexError):
296             stack[3]=c
297         with self.assertRaises(TypeError):
298             stack[0]=self.cert1
299         with self.assertRaises(TypeError):
300             stack.append(self.cert1)
301     def test_certstack3(self):
302         l=[]
303         l.append(X509(self.cert1))
304         self.assertEqual(unicode(l[0].subject[Oid('CN')]),u'Виктор Вагнер')
305         l.append(X509(self.ca_cert))
306         l.append(X509(self.digicert_cert))
307         stack=StackOfX509(certs=l)
308         stack2=StackOfX509(ptr=stack.ptr,disposable=False)
309         with self.assertRaises(ValueError):
310             stack3=StackOfX509(ptr=stack.ptr,certs=l)
311         with self.assertRaises(ValueError):
312             stack2[1]=l[0]
313         with self.assertRaises(ValueError):
314             stack2.append(l[0])
315 if __name__ == '__main__':
316     unittest.main()