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