]> Cypherpunks.ru repositories - pyderasn.git/blob - tests/test_crts.py
Auto add __slots__ to all inherited classes
[pyderasn.git] / tests / test_crts.py
1 # coding: utf-8
2 # PyDERASN -- Python ASN.1 DER codec with abstract structures
3 # Copyright (C) 2017 Sergey Matveev <stargrave@stargrave.org>
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Lesser General Public License as
7 # published by the Free Software Foundation, either version 3 of the
8 # License, or (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU Lesser General Public License for more details.
14 #
15 # You should have received a copy of the GNU Lesser General Public
16 # License along with this program.  If not, see
17 # <http://www.gnu.org/licenses/>.
18
19 from datetime import datetime
20 from unittest import TestCase
21
22 from pyderasn import Any
23 from pyderasn import BitString
24 from pyderasn import Boolean
25 from pyderasn import Choice
26 from pyderasn import GeneralizedTime
27 from pyderasn import hexdec
28 from pyderasn import IA5String
29 from pyderasn import Integer
30 from pyderasn import Null
31 from pyderasn import ObjectIdentifier
32 from pyderasn import OctetString
33 from pyderasn import pprint
34 from pyderasn import PrintableString
35 from pyderasn import Sequence
36 from pyderasn import SequenceOf
37 from pyderasn import SetOf
38 from pyderasn import tag_ctxc
39 from pyderasn import tag_ctxp
40 from pyderasn import UTCTime
41
42
43 some_oids = {
44     "1.2.840.113549.1.1.1": "id-rsaEncryption",
45     "1.2.840.113549.1.1.5": "id-sha1WithRSAEncryption",
46     "1.2.840.113549.1.9.1": "id-emailAddress",
47     "2.5.29.14": "id-ce-subjectKeyIdentifier",
48     "2.5.29.15": "id-ce-keyUsage",
49     "2.5.29.17": "id-ce-subjectAltName",
50     "2.5.29.18": "id-ce-issuerAltName",
51     "2.5.29.19": "id-ce-basicConstraints",
52     "2.5.29.31": "id-ce-cRLDistributionPoints",
53     "2.5.29.35": "id-ce-authorityKeyIdentifier",
54     "2.5.29.37": "id-ce-extKeyUsage",
55     "2.5.4.3": "id-at-commonName",
56     "2.5.4.6": "id-at-countryName",
57     "2.5.4.7": "id-at-localityName",
58     "2.5.4.8": "id-at-stateOrProvinceName",
59     "2.5.4.10": "id-at-organizationName",
60     "2.5.4.11": "id-at-organizationalUnitName",
61 }
62
63
64 class Version(Integer):
65     schema = (
66         ("v1", 0),
67         ("v2", 1),
68         ("v3", 2),
69     )
70
71
72 class CertificateSerialNumber(Integer):
73     pass
74
75
76 class AlgorithmIdentifier(Sequence):
77     schema = (
78         ("algorithm", ObjectIdentifier()),
79         ("parameters", Any(optional=True)),
80     )
81
82
83 class AttributeType(ObjectIdentifier):
84     pass
85
86
87 class AttributeValue(Any):
88     pass
89
90
91 class AttributeTypeAndValue(Sequence):
92     schema = (
93         ("type", AttributeType()),
94         ("value", AttributeValue()),
95     )
96
97
98 class RelativeDistinguishedName(SetOf):
99     schema = AttributeTypeAndValue()
100     bounds = (1, float("+inf"))
101
102
103 class RDNSequence(SequenceOf):
104     schema = RelativeDistinguishedName()
105
106
107 class Name(Choice):
108     schema = (
109         ("rdnSequence", RDNSequence()),
110     )
111
112
113 class Time(Choice):
114     schema = (
115         ("utcTime", UTCTime()),
116         ("generalTime", GeneralizedTime()),
117     )
118
119
120 class Validity(Sequence):
121     schema = (
122         ("notBefore", Time()),
123         ("notAfter", Time()),
124     )
125
126
127 class SubjectPublicKeyInfo(Sequence):
128     schema = (
129         ("algorithm", AlgorithmIdentifier()),
130         ("subjectPublicKey", BitString()),
131     )
132
133
134 class UniqueIdentifier(BitString):
135     pass
136
137
138 class Extension(Sequence):
139     schema = (
140         ("extnID", ObjectIdentifier()),
141         ("critical", Boolean(default=False)),
142         ("extnValue", OctetString()),
143     )
144
145
146 class Extensions(SequenceOf):
147     schema = Extension()
148     bounds = (1, float("+inf"))
149
150
151 class TBSCertificate(Sequence):
152     schema = (
153         ("version", Version(expl=tag_ctxc(0), default="v1")),
154         ("serialNumber", CertificateSerialNumber()),
155         ("signature", AlgorithmIdentifier()),
156         ("issuer", Name()),
157         ("validity", Validity()),
158         ("subject", Name()),
159         ("subjectPublicKeyInfo", SubjectPublicKeyInfo()),
160         ("issuerUniqueID", UniqueIdentifier(impl=tag_ctxp(1), optional=True)),
161         ("subjectUniqueID", UniqueIdentifier(impl=tag_ctxp(2), optional=True)),
162         ("extensions", Extensions(expl=tag_ctxc(3), optional=True)),
163     )
164
165
166 class Certificate(Sequence):
167     schema = (
168         ("tbsCertificate", TBSCertificate()),
169         ("signatureAlgorithm", AlgorithmIdentifier()),
170         ("signatureValue", BitString()),
171     )
172
173
174 class TestGoSelfSignedVector(TestCase):
175     def runTest(self):
176         raw = hexdec("".join((
177             "30820218308201c20209008cc3379210ec2c98300d06092a864886f70d0101050",
178             "500308192310b3009060355040613025858311330110603550408130a536f6d65",
179             "2d5374617465310d300b06035504071304436974793121301f060355040a13184",
180             "96e7465726e6574205769646769747320507479204c7464311a30180603550403",
181             "131166616c73652e6578616d706c652e636f6d3120301e06092a864886f70d010",
182             "901161166616c7365406578616d706c652e636f6d301e170d3039313030383030",
183             "323535335a170d3130313030383030323535335a308192310b300906035504061",
184             "3025858311330110603550408130a536f6d652d5374617465310d300b06035504",
185             "071304436974793121301f060355040a1318496e7465726e65742057696467697",
186             "47320507479204c7464311a30180603550403131166616c73652e6578616d706c",
187             "652e636f6d3120301e06092a864886f70d010901161166616c7365406578616d7",
188             "06c652e636f6d305c300d06092a864886f70d0101010500034b003048024100cd",
189             "b7639c3278f006aa277f6eaf42902b592d8cbcbe38a1c92ba4695a331b1deadea",
190             "dd8e9a5c27e8c4c2fd0a8889657722a4f2af7589cf2c77045dc8fdeec357d0203",
191             "010001300d06092a864886f70d0101050500034100a67b06ec5ece92772ca413c",
192             "ba3ca12568fdc6c7b4511cd40a7f659980402df2b998bb9a4a8cbeb34c0f0a78c",
193             "f8d91ede14a5ed76bf116fe360aafa8821490435",
194         )))
195         crt, tail = Certificate().decode(raw)
196         self.assertSequenceEqual(tail, b"")
197         tbs = crt["tbsCertificate"]
198         self.assertEqual(tbs["version"], 0)
199         self.assertFalse(tbs["version"].decoded)
200         self.assertNotIn("version", tbs)
201         self.assertEqual(tbs["serialNumber"], 10143011886257155224)
202
203         def assert_raw_equals(obj, expect):
204             self.assertTrue(obj.decoded)
205             self.assertSequenceEqual(
206                 raw[obj.offset:obj.offset + obj.tlvlen],
207                 expect.encode(),
208             )
209         assert_raw_equals(tbs["serialNumber"], Integer(10143011886257155224))
210         algo_id = AlgorithmIdentifier()
211         algo_id["algorithm"] = ObjectIdentifier("1.2.840.113549.1.1.5")
212         algo_id["parameters"] = Any(Null())
213         self.assertEqual(tbs["signature"], algo_id)
214         assert_raw_equals(tbs["signature"], algo_id)
215         issuer = Name()
216         rdnSeq = RDNSequence()
217         for oid, klass, text in (
218                 ("2.5.4.6", PrintableString, "XX"),
219                 ("2.5.4.8", PrintableString, "Some-State"),
220                 ("2.5.4.7", PrintableString, "City"),
221                 ("2.5.4.10", PrintableString, "Internet Widgits Pty Ltd"),
222                 ("2.5.4.3", PrintableString, "false.example.com"),
223                 ("1.2.840.113549.1.9.1", IA5String, "false@example.com"),
224         ):
225             attr = AttributeTypeAndValue()
226             attr["type"] = AttributeType(oid)
227             attr["value"] = AttributeValue(klass(text))
228             rdn = RelativeDistinguishedName()
229             rdn.append(attr)
230             rdnSeq.append(rdn)
231         issuer["rdnSequence"] = rdnSeq
232         self.assertEqual(tbs["issuer"], issuer)
233         assert_raw_equals(tbs["issuer"], issuer)
234         validity = Validity()
235         validity["notBefore"] = Time(
236             ("utcTime", UTCTime(datetime(2009, 10, 8, 0, 25, 53)))
237         )
238         validity["notAfter"] = Time(
239             ("utcTime", UTCTime(datetime(2010, 10, 8, 0, 25, 53)))
240         )
241         self.assertEqual(tbs["validity"], validity)
242         assert_raw_equals(tbs["validity"], validity)
243         self.assertEqual(tbs["subject"], issuer)
244         assert_raw_equals(tbs["subject"], issuer)
245         spki = SubjectPublicKeyInfo()
246         algo_id["algorithm"] = ObjectIdentifier("1.2.840.113549.1.1.1")
247         spki["algorithm"] = algo_id
248         spki["subjectPublicKey"] = BitString(hexdec("".join((
249             "3048024100cdb7639c3278f006aa277f6eaf42902b592d8cbcbe38a1c92ba4695",
250             "a331b1deadeadd8e9a5c27e8c4c2fd0a8889657722a4f2af7589cf2c77045dc8f",
251             "deec357d0203010001",
252         ))))
253         self.assertEqual(tbs["subjectPublicKeyInfo"], spki)
254         assert_raw_equals(tbs["subjectPublicKeyInfo"], spki)
255         self.assertNotIn("issuerUniqueID", tbs)
256         self.assertNotIn("subjectUniqueID", tbs)
257         self.assertNotIn("extensions", tbs)
258         algo_id["algorithm"] = ObjectIdentifier("1.2.840.113549.1.1.5")
259         self.assertEqual(crt["signatureAlgorithm"], algo_id)
260         self.assertEqual(crt["signatureValue"], BitString(hexdec("".join((
261             "a67b06ec5ece92772ca413cba3ca12568fdc6c7b4511cd40a7f659980402df2b",
262             "998bb9a4a8cbeb34c0f0a78cf8d91ede14a5ed76bf116fe360aafa8821490435",
263         )))))
264         self.assertSequenceEqual(crt.encode(), raw)
265         pprint(crt)
266         repr(crt)
267
268         tbs = TBSCertificate()
269         tbs["serialNumber"] = CertificateSerialNumber(10143011886257155224)
270
271         sign_algo_id = AlgorithmIdentifier()
272         sign_algo_id["algorithm"] = ObjectIdentifier("1.2.840.113549.1.1.5")
273         sign_algo_id["parameters"] = Any(Null())
274         tbs["signature"] = sign_algo_id
275
276         rdnSeq = RDNSequence()
277         for oid, klass, text in (
278                 ("2.5.4.6", PrintableString, "XX"),
279                 ("2.5.4.8", PrintableString, "Some-State"),
280                 ("2.5.4.7", PrintableString, "City"),
281                 ("2.5.4.10", PrintableString, "Internet Widgits Pty Ltd"),
282                 ("2.5.4.3", PrintableString, "false.example.com"),
283                 ("1.2.840.113549.1.9.1", IA5String, "false@example.com"),
284         ):
285             attr = AttributeTypeAndValue()
286             attr["type"] = AttributeType(oid)
287             attr["value"] = AttributeValue(klass(text))
288             rdn = RelativeDistinguishedName()
289             rdn.append(attr)
290             rdnSeq.append(rdn)
291         issuer = Name()
292         issuer["rdnSequence"] = rdnSeq
293         tbs["issuer"] = issuer
294         tbs["subject"] = issuer
295
296         validity = Validity()
297         validity["notBefore"] = Time(("utcTime", UTCTime(datetime(2009, 10, 8, 0, 25, 53))))
298         validity["notAfter"] = Time(("utcTime", UTCTime(datetime(2010, 10, 8, 0, 25, 53))))
299         tbs["validity"] = validity
300
301         spki = SubjectPublicKeyInfo()
302         spki_algo_id = sign_algo_id.copy()
303         spki_algo_id["algorithm"] = ObjectIdentifier("1.2.840.113549.1.1.1")
304         spki["algorithm"] = spki_algo_id
305         spki["subjectPublicKey"] = BitString(hexdec("".join((
306             "3048024100cdb7639c3278f006aa277f6eaf42902b592d8cbcbe38a1c92ba4695",
307             "a331b1deadeadd8e9a5c27e8c4c2fd0a8889657722a4f2af7589cf2c77045dc8f",
308             "deec357d0203010001",
309         ))))
310         tbs["subjectPublicKeyInfo"] = spki
311
312         crt = Certificate()
313         crt["tbsCertificate"] = tbs
314         crt["signatureAlgorithm"] = sign_algo_id
315         crt["signatureValue"] = BitString(hexdec("".join((
316             "a67b06ec5ece92772ca413cba3ca12568fdc6c7b4511cd40a7f659980402df2b",
317             "998bb9a4a8cbeb34c0f0a78cf8d91ede14a5ed76bf116fe360aafa8821490435",
318         ))))
319         self.assertSequenceEqual(crt.encode(), raw)
320
321
322 class TestGoPayPalVector(TestCase):
323     def runTest(self):
324         raw = hexdec("".join((
325             "30820644308205ada003020102020300f09b300d06092a864886f70d010105050",
326             "030820112310b3009060355040613024553311230100603550408130942617263",
327             "656c6f6e61311230100603550407130942617263656c6f6e61312930270603550",
328             "40a13204950532043657274696669636174696f6e20417574686f726974792073",
329             "2e6c2e312e302c060355040a142567656e6572616c4069707363612e636f6d204",
330             "32e492e462e2020422d423632323130363935312e302c060355040b1325697073",
331             "434120434c41534541312043657274696669636174696f6e20417574686f72697",
332             "479312e302c06035504031325697073434120434c415345413120436572746966",
333             "69636174696f6e20417574686f726974793120301e06092a864886f70d0109011",
334             "61167656e6572616c4069707363612e636f6d301e170d30393032323432333034",
335             "31375a170d3131303232343233303431375a308194310b3009060355040613025",
336             "553311330110603550408130a43616c69666f726e696131163014060355040713",
337             "0d53616e204672616e636973636f3111300f060355040a1308536563757269747",
338             "931143012060355040b130b53656375726520556e6974312f302d060355040313",
339             "267777772e70617970616c2e636f6d0073736c2e736563757265636f6e6e65637",
340             "4696f6e2e636330819f300d06092a864886f70d010101050003818d0030818902",
341             "818100d269fa6f3a00b4211bc8b102d73f19b2c46db454f88b8accdb72c29e3c6",
342             "0b9c6913d82b77d99ffd12984c173539c82ddfc248c77d541f3e81e42a1ad2d9e",
343             "ff5b1026ce9d571773162338c8d6f1baa3965b16674a4f73973a4d14a4f4e23f8",
344             "b058342d1d0dc2f7ae5b610b211c0dc212a90ffae97715a4981ac40f33bb859b2",
345             "4f0203010001a38203213082031d30090603551d1304023000301106096086480",
346             "186f8420101040403020640300b0603551d0f0404030203f830130603551d2504",
347             "0c300a06082b06010505070301301d0603551d0e04160414618f61344355147f2",
348             "709ce4c8bea9b7b1925bc6e301f0603551d230418301680140e0760d439c91b5b",
349             "5d907b23c8d2349d4a9a463930090603551d1104023000301c0603551d1204153",
350             "013811167656e6572616c4069707363612e636f6d307206096086480186f84201",
351             "0d046516634f7267616e697a6174696f6e20496e666f726d6174696f6e204e4f5",
352             "42056414c4944415445442e20434c415345413120536572766572204365727469",
353             "666963617465206973737565642062792068747470733a2f2f7777772e6970736",
354             "3612e636f6d2f302f06096086480186f84201020422162068747470733a2f2f77",
355             "77772e69707363612e636f6d2f6970736361323030322f304306096086480186f",
356             "84201040436163468747470733a2f2f7777772e69707363612e636f6d2f697073",
357             "6361323030322f697073636132303032434c41534541312e63726c30460609608",
358             "6480186f84201030439163768747470733a2f2f7777772e69707363612e636f6d",
359             "2f6970736361323030322f7265766f636174696f6e434c41534541312e68746d6",
360             "c3f304306096086480186f84201070436163468747470733a2f2f7777772e6970",
361             "7363612e636f6d2f6970736361323030322f72656e6577616c434c41534541312",
362             "e68746d6c3f304106096086480186f84201080434163268747470733a2f2f7777",
363             "772e69707363612e636f6d2f6970736361323030322f706f6c696379434c41534",
364             "541312e68746d6c3081830603551d1f047c307a3039a037a0358633687474703a",
365             "2f2f7777772e69707363612e636f6d2f6970736361323030322f6970736361323",
366             "03032434c41534541312e63726c303da03ba0398637687474703a2f2f77777762",
367             "61636b2e69707363612e636f6d2f6970736361323030322f69707363613230303",
368             "2434c41534541312e63726c303206082b0601050507010104263024302206082b",
369             "060105050730018616687474703a2f2f6f6373702e69707363612e636f6d2f300",
370             "d06092a864886f70d01010505000381810068ee799797dd3bef166a06f2149a6e",
371             "cd9e12f7aa8310bdd17c98fac7aed40e2c9e38059d5260a9990a81b498901daeb",
372             "b4ad7b9dc889e3778415bf782a5f2ba41255a901a1e4538a1525875942644fb20",
373             "07ba44cce54a2d723f9847f626dc054605076321ab469b9c78d5545b3d0c1ec86",
374             "48cb55023826fdbb8221c439607a8bb",
375         )))
376         crt, tail = Certificate().decode(raw)
377         self.assertSequenceEqual(tail, b"")
378         self.assertSequenceEqual(crt.encode(), raw)
379         pprint(crt)
380         repr(crt)