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