2 # PyDERASN -- Python ASN.1 DER codec with abstract structures
3 # Copyright (C) 2017-2018 Sergey Matveev <stargrave@stargrave.org>
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.
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.
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/>.
19 from datetime import datetime
20 from unittest import TestCase
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
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",
65 class Version(Integer):
73 class CertificateSerialNumber(Integer):
77 class AlgorithmIdentifier(Sequence):
79 ("algorithm", ObjectIdentifier()),
80 ("parameters", Any(optional=True)),
84 class AttributeType(ObjectIdentifier):
88 class AttributeValue(Any):
92 class OrganizationName(Choice):
94 ("printableString", PrintableString()),
95 ("teletexString", TeletexString()),
99 class AttributeTypeAndValue(Sequence):
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(),
108 ("value", AttributeValue()),
112 class RelativeDistinguishedName(SetOf):
113 schema = AttributeTypeAndValue()
114 bounds = (1, float("+inf"))
117 class RDNSequence(SequenceOf):
118 schema = RelativeDistinguishedName()
123 ("rdnSequence", RDNSequence()),
129 ("utcTime", UTCTime()),
130 ("generalTime", GeneralizedTime()),
134 class Validity(Sequence):
136 ("notBefore", Time()),
137 ("notAfter", Time()),
141 class SubjectPublicKeyInfo(Sequence):
143 ("algorithm", AlgorithmIdentifier()),
144 ("subjectPublicKey", BitString()),
148 class UniqueIdentifier(BitString):
152 class Extension(Sequence):
154 ("extnID", ObjectIdentifier()),
155 ("critical", Boolean(default=False)),
156 ("extnValue", OctetString()),
160 class Extensions(SequenceOf):
162 bounds = (1, float("+inf"))
165 class TBSCertificate(Sequence):
167 ("version", Version(expl=tag_ctxc(0), default="v1")),
168 ("serialNumber", CertificateSerialNumber()),
169 ("signature", AlgorithmIdentifier()),
171 ("validity", Validity()),
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)),
180 class Certificate(Sequence):
182 ("tbsCertificate", TBSCertificate()),
183 ("signatureAlgorithm", AlgorithmIdentifier()),
184 ("signatureValue", BitString()),
188 class TestGoSelfSignedVector(TestCase):
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",
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)
217 def assert_raw_equals(obj, expect):
218 self.assertTrue(obj.decoded)
219 self.assertSequenceEqual(
220 raw[obj.offset:obj.offset + obj.tlvlen],
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())),
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"),
240 RelativeDistinguishedName((
241 AttributeTypeAndValue((
242 ("type", AttributeType(oid)),
243 ("value", AttributeValue(klass(text))),
247 issuer = Name(("rdnSequence", rdnSeq))
248 self.assertEqual(tbs["issuer"], issuer)
249 assert_raw_equals(tbs["issuer"], issuer)
250 validity = Validity((
252 ("utcTime", UTCTime(datetime(2009, 10, 8, 0, 25, 53)))
255 ("utcTime", UTCTime(datetime(2010, 10, 8, 0, 25, 53)))
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",
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",
281 self.assertSequenceEqual(crt.encode(), raw)
285 tbs = TBSCertificate()
286 tbs["serialNumber"] = CertificateSerialNumber(10143011886257155224)
288 sign_algo_id = AlgorithmIdentifier((
289 ("algorithm", ObjectIdentifier("1.2.840.113549.1.1.5")),
290 ("parameters", Any(Null())),
292 tbs["signature"] = sign_algo_id
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"),
304 RelativeDistinguishedName((
305 AttributeTypeAndValue((
306 ("type", AttributeType(oid)),
307 ("value", AttributeValue(klass(text))),
312 issuer["rdnSequence"] = rdnSeq
313 tbs["issuer"] = issuer
314 tbs["subject"] = issuer
316 validity = Validity((
318 ("utcTime", UTCTime(datetime(2009, 10, 8, 0, 25, 53)),),
321 ("utcTime", UTCTime(datetime(2010, 10, 8, 0, 25, 53)),),
324 tbs["validity"] = validity
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",
335 tbs["subjectPublicKeyInfo"] = spki
338 crt["tbsCertificate"] = tbs
339 crt["signatureAlgorithm"] = sign_algo_id
340 crt["signatureValue"] = BitString(hexdec("".join((
341 "a67b06ec5ece92772ca413cba3ca12568fdc6c7b4511cd40a7f659980402df2b",
342 "998bb9a4a8cbeb34c0f0a78cf8d91ede14a5ed76bf116fe360aafa8821490435",
344 self.assertSequenceEqual(crt.encode(), raw)
347 class TestGoPayPalVector(TestCase):
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",
401 crt, tail = Certificate().decode(raw)
402 self.assertSequenceEqual(tail, b"")
403 self.assertSequenceEqual(crt.encode(), raw)