]> www.wagner.pp.ru Git - oss/ctypescrypto.git/blob - tests/testx509.py
fb6e054231e10170c00925b40d8978e068889f06
[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 MIIEDzCCAvegAwIBAgIJAN9Ejmna3JJ7MA0GCSqGSIb3DQEBBQUAMIGdMQswCQYD
16 VQQGEwJSVTEVMBMGA1UECAwM0JzQvtGB0LrQstCwMTAwLgYDVQQKDCfQo9C00L7R
17 gdGC0L7QstC10YDRj9GO0YnQuNC5INGG0LXQvdGC0YAxIjAgBgNVBAMMGdCS0LjQ
18 utGC0L7RgCDQktCw0LPQvdC10YAxITAfBgkqhkiG9w0BCQEWEnZpdHVzQHdhZ25l
19 ci5wcC5ydTAeFw0xNDEwMjYxNDQ2MzJaFw0xNzEwMjUxNDQ2MzJaMIGdMQswCQYD
20 VQQGEwJSVTEVMBMGA1UECAwM0JzQvtGB0LrQstCwMTAwLgYDVQQKDCfQo9C00L7R
21 gdGC0L7QstC10YDRj9GO0YnQuNC5INGG0LXQvdGC0YAxIjAgBgNVBAMMGdCS0LjQ
22 utGC0L7RgCDQktCw0LPQvdC10YAxITAfBgkqhkiG9w0BCQEWEnZpdHVzQHdhZ25l
23 ci5wcC5ydTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJn+nL8CDaM0
24 KNafGYdEDuFuCKHFxCcbaT7ecGbwjPKtnqZLOnYpa2iLFY+n7zAYw1MRkFkaR8b+
25 +AeFPWS9T60ygeWysT9XTS77Fdl69Tmr8HChRk0BuLB3vFCy34vBHSG6Frdm8PtS
26 PLEleldiwUCHLS+EckrnJylQK13X3HofSbIGzKK53MsuQOtp2dJw3b7MILM/+XBm
27 RgZlEbTEPYMOH8CE3mu9/LqXfIRQM7+nmzcNZI3RAwxEVHOSHEbgFZaksTj8rMIa
28 SrJwknmxHntI3P5PSNNbs0SO3TW8ePDIIpbVcjNsMX4qGX8b+8quZuzciKOto8S0
29 0A6eOBd8Vi0CAwEAAaNQME4wHQYDVR0OBBYEFKzcbd6+N1TKfBjvmyTvw8+DnzAZ
30 MB8GA1UdIwQYMBaAFKzcbd6+N1TKfBjvmyTvw8+DnzAZMAwGA1UdEwQFMAMBAf8w
31 DQYJKoZIhvcNAQEFBQADggEBAAa1PpkpL842hh8jLXIpA/nK8aVDDcu5p3pA72/b
32 noFnZuKcuaSUOz1rrLqxDK2JB3lmChQaVx3pZwqJgA0h0XBScar+8wM2TfeyW+oU
33 Gr5tOAxoHVRpgn6oCoJkKo0HS2/NA12T/gYsXhXJXn4tuvDjaUzY+K+hhAWh64oL
34 /c61eKfCZKp50t9Eoua0xHII2Mveb27Ps46j/CZ1r0ts7sGieOqjQo3GZOOikG6F
35 vFY/2KV16/FdBovTFWMyKrzlYHm0Wgt28IWqhocq/golLfvkz3VAkLQvOF2i6hNc
36 4feBv69SRTsTCFN9PtJCtxPX/K9LZKeccBKgGjrHQpAF+JU=
37 -----END CERTIFICATE-----
38 """
39     cert1="""-----BEGIN CERTIFICATE-----
40 MIIEDzCCAvegAwIBAgIJAN9Ejmna3JJ8MA0GCSqGSIb3DQEBBQUAMIGdMQswCQYD
41 VQQGEwJSVTEVMBMGA1UECAwM0JzQvtGB0LrQstCwMTAwLgYDVQQKDCfQo9C00L7R
42 gdGC0L7QstC10YDRj9GO0YnQuNC5INGG0LXQvdGC0YAxIjAgBgNVBAMMGdCS0LjQ
43 utGC0L7RgCDQktCw0LPQvdC10YAxITAfBgkqhkiG9w0BCQEWEnZpdHVzQHdhZ25l
44 ci5wcC5ydTAeFw0xNDEwMjYxOTA3MTdaFw0yNDEwMjMxOTA3MTdaMIGBMQswCQYD
45 VQQGEwJSVTEVMBMGA1UECAwM0JzQvtGB0LrQstCwMRUwEwYDVQQHDAzQnNC+0YHQ
46 utCy0LAxIDAeBgNVBAoMF9Cn0LDRgdGC0L3QvtC1INC70LjRhtC+MSIwIAYDVQQD
47 DBnQktC40LrRgtC+0YAg0JLQsNCz0L3QtdGAMIIBIjANBgkqhkiG9w0BAQEFAAOC
48 AQ8AMIIBCgKCAQEArQSfrrxNROyzNEz60G2EHBP+E4BL0b1QytGAZZiQp2XIhhQe
49 b7mx+c4mpwgvD7/IdAcK+YVGx78nfY723T3wG48U7HzFNbLvNDycxyXecXbvCmRs
50 xPy8TxkwPf6TIT3UcixtwMMqZFqlAtSTDmOOWSaUuftL/+yFk729xDoYkOZhFwUS
51 UM5SbEZ0JpufWFjDi3Qwj3ZOTXliHC3e4C7187Me0Nne59dttyKpq1YAThn4Srar
52 vZYU6Ykk/LUae0FCvfeiKLShWY05XnPVmvPiiFTXJP8/Au8kfezlA4b+eS81zWq2
53 BFvNlBQsgf04S88oew0CuBBgtjUIIw7XZkS03QIDAQABo2wwajAJBgNVHRMEAjAA
54 MB0GA1UdDgQWBBRflZBerCFYheRQne/sWL3zY7GiAzAfBgNVHSMEGDAWgBSs3G3e
55 vjdUynwY75sk78PPg58wGTAdBgNVHREEFjAUgRJ2aXR1c0B3YWduZXIucHAucnUw
56 DQYJKoZIhvcNAQEFBQADggEBAGx1z0ylq90hP3x/2DmfVUYBA46CiGnV4NSiaOWE
57 Y18jCuG3W8FcI7JP4uEEjKyz3XbuhTFW2GsZ2L3FGgpA5eXBikgCn5kRpOHgb45r
58 SxE8u3TwVlYlaF+7RHPYLqmgb25d/O/28McemMmTGecPC9edbtDqLv03aJ0t4gXn
59 BD+xTJOP74Yhu5IPIV92J6pSBpIoy+qiyOA1iRpOWzrVHVR504vAaFxlfZs3VJhP
60 uo291iEXyooazJdbWwZwcwk7WrNNKhqktPTg0X1ZHNnGwOAGPzwNJFGPeFj71r0t
61 aFWU5EMRKaZK75keXq/RdaOAenl+nKF6xA2XHDhGgdndFfY=
62 -----END CERTIFICATE-----
63 """
64     pubkey1="""-----BEGIN PUBLIC KEY-----
65 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArQSfrrxNROyzNEz60G2E
66 HBP+E4BL0b1QytGAZZiQp2XIhhQeb7mx+c4mpwgvD7/IdAcK+YVGx78nfY723T3w
67 G48U7HzFNbLvNDycxyXecXbvCmRsxPy8TxkwPf6TIT3UcixtwMMqZFqlAtSTDmOO
68 WSaUuftL/+yFk729xDoYkOZhFwUSUM5SbEZ0JpufWFjDi3Qwj3ZOTXliHC3e4C71
69 87Me0Nne59dttyKpq1YAThn4SrarvZYU6Ykk/LUae0FCvfeiKLShWY05XnPVmvPi
70 iFTXJP8/Au8kfezlA4b+eS81zWq2BFvNlBQsgf04S88oew0CuBBgtjUIIw7XZkS0
71 3QIDAQAB
72 -----END PUBLIC KEY-----
73 """
74     digicert_cert="""digicert.crt
75 -----BEGIN CERTIFICATE-----
76 MIIG5jCCBc6gAwIBAgIQAze5KDR8YKauxa2xIX84YDANBgkqhkiG9w0BAQUFADBs
77 MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
78 d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
79 ZSBFViBSb290IENBMB4XDTA3MTEwOTEyMDAwMFoXDTIxMTExMDAwMDAwMFowaTEL
80 MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
81 LmRpZ2ljZXJ0LmNvbTEoMCYGA1UEAxMfRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
82 RVYgQ0EtMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPOWYth1bhn/
83 PzR8SU8xfg0ETpmB4rOFVZEwscCvcLssqOcYqj9495BoUoYBiJfiOwZlkKq9ZXbC
84 7L4QWzd4g2B1Rca9dKq2n6Q6AVAXxDlpufFP74LByvNK28yeUE9NQKM6kOeGZrzw
85 PnYoTNF1gJ5qNRQ1A57bDIzCKK1Qss72kaPDpQpYSfZ1RGy6+c7pqzoC4E3zrOJ6
86 4GAiBTyC01Li85xH+DvYskuTVkq/cKs+6WjIHY9YHSpNXic9rQpZL1oRIEDZaARo
87 LfTAhAsKG3jf7RpY3PtBWm1r8u0c7lwytlzs16YDMqbo3rcoJ1mIgP97rYlY1R4U
88 pPKwcNSgPqcCAwEAAaOCA4UwggOBMA4GA1UdDwEB/wQEAwIBhjA7BgNVHSUENDAy
89 BggrBgEFBQcDAQYIKwYBBQUHAwIGCCsGAQUFBwMDBggrBgEFBQcDBAYIKwYBBQUH
90 AwgwggHEBgNVHSAEggG7MIIBtzCCAbMGCWCGSAGG/WwCATCCAaQwOgYIKwYBBQUH
91 AgEWLmh0dHA6Ly93d3cuZGlnaWNlcnQuY29tL3NzbC1jcHMtcmVwb3NpdG9yeS5o
92 dG0wggFkBggrBgEFBQcCAjCCAVYeggFSAEEAbgB5ACAAdQBzAGUAIABvAGYAIAB0
93 AGgAaQBzACAAQwBlAHIAdABpAGYAaQBjAGEAdABlACAAYwBvAG4AcwB0AGkAdAB1
94 AHQAZQBzACAAYQBjAGMAZQBwAHQAYQBuAGMAZQAgAG8AZgAgAHQAaABlACAARABp
95 AGcAaQBDAGUAcgB0ACAARQBWACAAQwBQAFMAIABhAG4AZAAgAHQAaABlACAAUgBl
96 AGwAeQBpAG4AZwAgAFAAYQByAHQAeQAgAEEAZwByAGUAZQBtAGUAbgB0ACAAdwBo
97 AGkAYwBoACAAbABpAG0AaQB0ACAAbABpAGEAYgBpAGwAaQB0AHkAIABhAG4AZAAg
98 AGEAcgBlACAAaQBuAGMAbwByAHAAbwByAGEAdABlAGQAIABoAGUAcgBlAGkAbgAg
99 AGIAeQAgAHIAZQBmAGUAcgBlAG4AYwBlAC4wEgYDVR0TAQH/BAgwBgEB/wIBADCB
100 gwYIKwYBBQUHAQEEdzB1MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2Vy
101 dC5jb20wTQYIKwYBBQUHMAKGQWh0dHA6Ly93d3cuZGlnaWNlcnQuY29tL0NBQ2Vy
102 dHMvRGlnaUNlcnRIaWdoQXNzdXJhbmNlRVZSb290Q0EuY3J0MIGPBgNVHR8EgYcw
103 gYQwQKA+oDyGOmh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEhpZ2hB
104 c3N1cmFuY2VFVlJvb3RDQS5jcmwwQKA+oDyGOmh0dHA6Ly9jcmw0LmRpZ2ljZXJ0
105 LmNvbS9EaWdpQ2VydEhpZ2hBc3N1cmFuY2VFVlJvb3RDQS5jcmwwHQYDVR0OBBYE
106 FExYyyXwQU9S9CjIgUObpqig5pLlMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSYJhoI
107 Au9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQBMeheHKF0XvLIyc7/NLvVYMR3wsXFU
108 nNabZ5PbLwM+Fm8eA8lThKNWYB54lBuiqG+jpItSkdfdXJW777UWSemlQk808kf/
109 roF/E1S3IMRwFcuBCoHLdFfcnN8kpCkMGPAc5K4HM+zxST5Vz25PDVR708noFUjU
110 xbvcNRx3RQdIRYW9135TuMAW2ZXNi419yWBP0aKb49Aw1rRzNubS+QOy46T15bg+
111 BEkAui6mSnKDcp33C4ypieez12Qf1uNgywPE3IjpnSUBAHHLA7QpYCWP+UbRe3Gu
112 zVMSW4SOwg/H7ZMZ2cn6j1g0djIvruFQFGHUqFijyDATI+/GJYw2jxyA
113 -----END CERTIFICATE-----
114 """
115     def test_readpubkey(self):
116         c=X509(self.cert1)
117         p=c.pubkey
118         self.assertEqual(p.exportpub(),self.pubkey1)
119     def test_pem(self):
120         c=X509(self.cert1)
121         self.assertEqual(c.pem(),self.cert1)
122     def test_subject(self):
123         c=X509(self.cert1)
124         self.assertEqual(unicode(c.subject),u'C=RU,ST=Москва,L=Москва,O=Частное лицо,CN=Виктор Вагнер')
125     def test_subject_str(self):
126         c=X509(self.cert1)
127         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')
128     def test_subject_len(self):
129         c=X509(self.cert1)
130         self.assertEqual(len(c.subject),5)
131     def test_issuer(self):
132         c=X509(self.cert1)
133         self.assertEqual(unicode(c.issuer),u'C=RU,ST=Москва,O=Удостоверяющий центр,CN=Виктор Вагнер,emailAddress=vitus@wagner.pp.ru')
134     def test_subjectfields(self):
135         c=X509(self.cert1)
136         self.assertEqual(c.subject[Oid("C")],"RU")
137         with self.assertRaises(TypeError):
138             x=c.subject["CN"]
139         self.assertEqual(c.subject[Oid("L")],u'\u041c\u043e\u0441\u043a\u0432\u0430')
140     def test_subjectmodify(self):
141         c=X509(self.cert1)
142         with self.assertRaises(ValueError):
143             c.subject[Oid("CN")]=u'Foo'
144         with self.assertRaises(ValueError):
145             del c.subject[Oid('CN')]
146     def test_subjectbadsubfield(self):
147         c=X509(self.cert1)
148         with self.assertRaises(KeyError):
149             x=c.subject[Oid("streetAddress")]
150     def test_subjectfieldindex(self):
151         c=X509(self.cert1)
152         self.assertEqual(repr(c.subject[0]),repr((Oid('C'),u'RU')))
153     def test_subjectbadindex(self):
154         c=X509(self.cert1)
155         with self.assertRaises(IndexError):
156             x=c.subject[11]
157         with self.assertRaises(IndexError):
158             x=c.subject[-1]
159     def test_notBefore(self):
160         c=X509(self.cert1)
161         self.assertEqual(c.startDate,datetime.datetime(2014,10,26,19,07,17,0,utc))
162     def test_notAfter(self):
163         c=X509(self.cert1)
164         self.assertEqual(c.endDate,datetime.datetime(2024,10,23,19,7,17,0,utc))
165     def test_subjectHash(self):
166         c=X509(self.cert1)
167         self.assertEqual(hash(c.subject),0x1f3ed722)
168     def test_issuerHash(self):
169         c=X509(self.cert1)
170         self.assertEqual(hash(c.issuer),0x7d3ea8c3)
171     def test_namecomp(self):
172         c=X509(self.cert1)
173         ca=X509(self.ca_cert)
174         self.assertEqual(c.issuer,ca.subject)
175         self.assertNotEqual(c.subject,c.issuer)
176         self.assertEqual(ca.issuer,ca.subject)
177     def test_serial(self):
178         c=X509(self.cert1)
179         self.assertEqual(c.serial,0xDF448E69DADC927CL)
180     def test_version(self):
181         c=X509(self.cert1)
182         self.assertEqual(c.version,3)
183     def test_ca_cert(self):
184         ca=X509(self.ca_cert)
185         self.assertTrue(ca.check_ca())
186         notca=X509(self.cert1)
187         self.assertFalse(notca.check_ca())
188     def test_extension_count(self):
189         cert=X509(self.cert1)
190         self.assertTrue(len(cert.extensions),4)
191         ca_cert=X509(self.ca_cert)
192         self.assertEqual(len(ca_cert.extensions),3)
193     def test_extension_outofrange(self):
194         cert=X509(self.cert1)
195         with self.assertRaises(IndexError):
196             cert.extensions[4]
197         with self.assertRaises(IndexError):
198             cert.extensions[-1]
199     def test_extension_oid(self):
200         cert=X509(self.cert1)
201         ext=cert.extensions[0]
202         ext_id=ext.oid
203         self.assertTrue(isinstance(ext_id,Oid))
204         self.assertEqual(ext_id,Oid('basicConstraints'))
205     def test_extension_text(self):
206         cert=X509(self.cert1)
207         ext=cert.extensions[0]
208         self.assertEqual(str(ext),'CA:FALSE')
209         self.assertEqual(unicode(ext),u'CA:FALSE')
210     def test_extenson_find(self):
211         cert=X509(self.cert1)
212         exts=cert.extensions.find(Oid('subjectAltName'))
213         self.assertEqual(len(exts),1)
214         self.assertEqual(exts[0].oid,Oid('subjectAltName'))
215     def test_extension_bad_find(self):
216         cert=X509(self.cert1)
217         with self.assertRaises(TypeError):
218             exts=cert.extensions.find('subjectAltName')
219     def test_extenson_critical(self):
220         cert=X509(self.digicert_cert)
221         crit_exts=cert.extensions.find_critical()
222         self.assertEqual(len(crit_exts),2)
223         other_exts=cert.extensions.find_critical(False)
224         self.assertEqual(len(crit_exts)+len(other_exts),len(cert.extensions))
225         self.assertEqual(crit_exts[0].critical,True)
226         self.assertEqual(other_exts[0].critical,False)
227     def test_verify_by_key(self):
228         ca=X509(self.ca_cert)
229         pubkey=ca.pubkey
230         self.assertTrue(ca.verify(key=pubkey))
231         c=X509(self.cert1)
232         pk2=c.pubkey
233         self.assertFalse(c.verify(key=pk2))
234         self.assertTrue(c.verify(key=pubkey))
235     def test_verify_self_singed(self):
236         ca=X509(self.ca_cert)
237         self.assertTrue(ca.verify())
238     def test_default_filestore(self):
239         store=X509Store(default=True)
240         c1=X509(self.cert1)
241         # Cert signed by our CA shouldn't be successfully verified
242         # by default CA store
243         self.assertFalse(c1.verify(store))
244         # but cert, downloaded from some commercial CA - should.
245         c2=X509(self.digicert_cert)
246         self.assertTrue(c2.verify(store))
247     def test_verify_by_filestore(self):
248         trusted=NamedTemporaryFile(delete=False)
249         trusted.write(self.ca_cert)
250         trusted.close()
251         goodcert=X509(self.cert1)
252         badcert=X509(self.cert1[0:-30]+"GG"+self.cert1[-28:])
253         gitcert=X509(self.digicert_cert)
254         store=X509Store(file=trusted.name)
255         os.unlink(trusted.name)
256         # We should successfuly verify certificate signed by our CA cert
257         self.assertTrue(goodcert.verify(store))
258         # We should reject corrupted certificate
259         self.assertFalse(badcert.verify(store))
260         # And if we specify explicitely certificate file, certificate,
261         # signed by some commercial CA should be rejected too
262         self.assertFalse(gitcert.verify(store))
263         trusted.close()
264     def test_verify_by_dirstore(self):
265         pass
266     def test_certstack1(self):
267         l=[]
268         l.append(X509(self.cert1))
269         self.assertEqual(unicode(l[0].subject[Oid('CN')]),u'Виктор Вагнер')
270         l.append(X509(self.ca_cert))
271         l.append(X509(self.digicert_cert))
272         stack=StackOfX509(certs=l)
273         self.assertEqual(len(stack),3)
274         self.assertTrue(isinstance(stack[1],X509))
275         self.assertEqual(unicode(stack[0].subject[Oid('CN')]),u'Виктор Вагнер')
276         with self.assertRaises(IndexError):
277             c=stack[-1]
278         with self.assertRaises(IndexError):
279             c=stack[3]
280         del stack[1]
281         self.assertEqual(len(stack),2)
282         self.assertEqual(unicode(stack[0].subject[Oid('CN')]),u'Виктор Вагнер')
283         self.assertEqual(unicode(stack[1].subject[Oid('CN')]),u'DigiCert High Assurance EV CA-1')
284     def test_certstack2(self):
285         stack=StackOfX509()
286         stack.append(X509(self.cert1))
287         stack.append(X509(self.ca_cert))
288         c=stack[1]
289         stack[1]=X509(self.digicert_cert)
290         self.assertEqual(len(stack),2)
291         self.assertEqual(unicode(stack[1].subject[Oid('CN')]),u'DigiCert High Assurance EV CA-1')
292         with self.assertRaises(IndexError):
293             stack[-1]=c
294         with self.assertRaises(IndexError):
295             stack[3]=c
296         with self.assertRaises(TypeError):
297             stack[0]=self.cert1
298         with self.assertRaises(TypeError):
299             stack.append(self.cert1)
300     def test_certstack3(self):
301         l=[]
302         l.append(X509(self.cert1))
303         self.assertEqual(unicode(l[0].subject[Oid('CN')]),u'Виктор Вагнер')
304         l.append(X509(self.ca_cert))
305         l.append(X509(self.digicert_cert))
306         stack=StackOfX509(certs=l)
307         stack2=StackOfX509(ptr=stack.ptr,disposable=False)
308         with self.assertRaises(ValueError):
309             stack3=StackOfX509(ptr=stack.ptr,certs=l)
310         with self.assertRaises(ValueError):
311             stack2[1]=l[0]
312         with self.assertRaises(ValueError):
313             stack2.append(l[0])
314 if __name__ == '__main__':
315     unittest.main()