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