2 # PyDERASN -- Python ASN.1 DER codec with abstract structures
3 # Copyright (C) 2017 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 UTCTime
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",
64 class Version(Integer):
73 class CertificateSerialNumber(Integer):
78 class AlgorithmIdentifier(Sequence):
81 ("algorithm", ObjectIdentifier()),
82 ("parameters", Any(optional=True)),
86 class AttributeType(ObjectIdentifier):
91 class AttributeValue(Any):
96 class AttributeTypeAndValue(Sequence):
99 ("type", AttributeType()),
100 ("value", AttributeValue()),
104 class RelativeDistinguishedName(SetOf):
106 schema = AttributeTypeAndValue()
107 bounds = (1, float("+inf"))
110 class RDNSequence(SequenceOf):
112 schema = RelativeDistinguishedName()
118 ("rdnSequence", RDNSequence()),
125 ("utcTime", UTCTime()),
126 ("generalTime", GeneralizedTime()),
130 class Validity(Sequence):
133 ("notBefore", Time()),
134 ("notAfter", Time()),
138 class SubjectPublicKeyInfo(Sequence):
141 ("algorithm", AlgorithmIdentifier()),
142 ("subjectPublicKey", BitString()),
146 class UniqueIdentifier(BitString):
151 class Extension(Sequence):
154 ("extnID", ObjectIdentifier()),
155 ("critical", Boolean(default=False)),
156 ("extnValue", OctetString()),
160 class Extensions(SequenceOf):
163 bounds = (1, float("+inf"))
166 class TBSCertificate(Sequence):
169 ("version", Version(expl=tag_ctxc(0), default="v1")),
170 ("serialNumber", CertificateSerialNumber()),
171 ("signature", AlgorithmIdentifier()),
173 ("validity", Validity()),
175 ("subjectPublicKeyInfo", SubjectPublicKeyInfo()),
176 ("issuerUniqueID", UniqueIdentifier(impl=tag_ctxp(1), optional=True)),
177 ("subjectUniqueID", UniqueIdentifier(impl=tag_ctxp(2), optional=True)),
178 ("extensions", Extensions(expl=tag_ctxc(3), optional=True)),
182 class Certificate(Sequence):
185 ("tbsCertificate", TBSCertificate()),
186 ("signatureAlgorithm", AlgorithmIdentifier()),
187 ("signatureValue", BitString()),
191 class TestGoSelfSignedVector(TestCase):
193 raw = hexdec("".join((
194 "30820218308201c20209008cc3379210ec2c98300d06092a864886f70d0101050",
195 "500308192310b3009060355040613025858311330110603550408130a536f6d65",
196 "2d5374617465310d300b06035504071304436974793121301f060355040a13184",
197 "96e7465726e6574205769646769747320507479204c7464311a30180603550403",
198 "131166616c73652e6578616d706c652e636f6d3120301e06092a864886f70d010",
199 "901161166616c7365406578616d706c652e636f6d301e170d3039313030383030",
200 "323535335a170d3130313030383030323535335a308192310b300906035504061",
201 "3025858311330110603550408130a536f6d652d5374617465310d300b06035504",
202 "071304436974793121301f060355040a1318496e7465726e65742057696467697",
203 "47320507479204c7464311a30180603550403131166616c73652e6578616d706c",
204 "652e636f6d3120301e06092a864886f70d010901161166616c7365406578616d7",
205 "06c652e636f6d305c300d06092a864886f70d0101010500034b003048024100cd",
206 "b7639c3278f006aa277f6eaf42902b592d8cbcbe38a1c92ba4695a331b1deadea",
207 "dd8e9a5c27e8c4c2fd0a8889657722a4f2af7589cf2c77045dc8fdeec357d0203",
208 "010001300d06092a864886f70d0101050500034100a67b06ec5ece92772ca413c",
209 "ba3ca12568fdc6c7b4511cd40a7f659980402df2b998bb9a4a8cbeb34c0f0a78c",
210 "f8d91ede14a5ed76bf116fe360aafa8821490435",
212 crt, tail = Certificate().decode(raw)
213 self.assertSequenceEqual(tail, b"")
214 tbs = crt["tbsCertificate"]
215 self.assertEqual(tbs["version"], 0)
216 self.assertFalse(tbs["version"].decoded)
217 self.assertNotIn("version", tbs)
218 self.assertEqual(tbs["serialNumber"], 10143011886257155224)
220 def assert_raw_equals(obj, expect):
221 self.assertTrue(obj.decoded)
222 self.assertSequenceEqual(
223 raw[obj.offset:obj.offset + obj.tlvlen],
226 assert_raw_equals(tbs["serialNumber"], Integer(10143011886257155224))
227 algo_id = AlgorithmIdentifier()
228 algo_id["algorithm"] = ObjectIdentifier("1.2.840.113549.1.1.5")
229 algo_id["parameters"] = Any(Null())
230 self.assertEqual(tbs["signature"], algo_id)
231 assert_raw_equals(tbs["signature"], algo_id)
233 rdnSeq = RDNSequence()
234 for oid, klass, text in (
235 ("2.5.4.6", PrintableString, "XX"),
236 ("2.5.4.8", PrintableString, "Some-State"),
237 ("2.5.4.7", PrintableString, "City"),
238 ("2.5.4.10", PrintableString, "Internet Widgits Pty Ltd"),
239 ("2.5.4.3", PrintableString, "false.example.com"),
240 ("1.2.840.113549.1.9.1", IA5String, "false@example.com"),
242 attr = AttributeTypeAndValue()
243 attr["type"] = AttributeType(oid)
244 attr["value"] = AttributeValue(klass(text))
245 rdn = RelativeDistinguishedName()
248 issuer["rdnSequence"] = rdnSeq
249 self.assertEqual(tbs["issuer"], issuer)
250 assert_raw_equals(tbs["issuer"], issuer)
251 validity = Validity()
252 validity["notBefore"] = Time(
253 ("utcTime", UTCTime(datetime(2009, 10, 8, 0, 25, 53)))
255 validity["notAfter"] = Time(
256 ("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 sign_algo_id["algorithm"] = ObjectIdentifier("1.2.840.113549.1.1.5")
290 sign_algo_id["parameters"] = Any(Null())
291 tbs["signature"] = sign_algo_id
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"),
302 attr = AttributeTypeAndValue()
303 attr["type"] = AttributeType(oid)
304 attr["value"] = AttributeValue(klass(text))
305 rdn = RelativeDistinguishedName()
309 issuer["rdnSequence"] = rdnSeq
310 tbs["issuer"] = issuer
311 tbs["subject"] = issuer
313 validity = Validity()
314 validity["notBefore"] = Time(("utcTime", UTCTime(datetime(2009, 10, 8, 0, 25, 53))))
315 validity["notAfter"] = Time(("utcTime", UTCTime(datetime(2010, 10, 8, 0, 25, 53))))
316 tbs["validity"] = validity
318 spki = SubjectPublicKeyInfo()
319 spki_algo_id = sign_algo_id.copy()
320 spki_algo_id["algorithm"] = ObjectIdentifier("1.2.840.113549.1.1.1")
321 spki["algorithm"] = spki_algo_id
322 spki["subjectPublicKey"] = BitString(hexdec("".join((
323 "3048024100cdb7639c3278f006aa277f6eaf42902b592d8cbcbe38a1c92ba4695",
324 "a331b1deadeadd8e9a5c27e8c4c2fd0a8889657722a4f2af7589cf2c77045dc8f",
325 "deec357d0203010001",
327 tbs["subjectPublicKeyInfo"] = spki
330 crt["tbsCertificate"] = tbs
331 crt["signatureAlgorithm"] = sign_algo_id
332 crt["signatureValue"] = BitString(hexdec("".join((
333 "a67b06ec5ece92772ca413cba3ca12568fdc6c7b4511cd40a7f659980402df2b",
334 "998bb9a4a8cbeb34c0f0a78cf8d91ede14a5ed76bf116fe360aafa8821490435",
336 self.assertSequenceEqual(crt.encode(), raw)
339 class TestGoPayPalVector(TestCase):
341 raw = hexdec("".join((
342 "30820644308205ada003020102020300f09b300d06092a864886f70d010105050",
343 "030820112310b3009060355040613024553311230100603550408130942617263",
344 "656c6f6e61311230100603550407130942617263656c6f6e61312930270603550",
345 "40a13204950532043657274696669636174696f6e20417574686f726974792073",
346 "2e6c2e312e302c060355040a142567656e6572616c4069707363612e636f6d204",
347 "32e492e462e2020422d423632323130363935312e302c060355040b1325697073",
348 "434120434c41534541312043657274696669636174696f6e20417574686f72697",
349 "479312e302c06035504031325697073434120434c415345413120436572746966",
350 "69636174696f6e20417574686f726974793120301e06092a864886f70d0109011",
351 "61167656e6572616c4069707363612e636f6d301e170d30393032323432333034",
352 "31375a170d3131303232343233303431375a308194310b3009060355040613025",
353 "553311330110603550408130a43616c69666f726e696131163014060355040713",
354 "0d53616e204672616e636973636f3111300f060355040a1308536563757269747",
355 "931143012060355040b130b53656375726520556e6974312f302d060355040313",
356 "267777772e70617970616c2e636f6d0073736c2e736563757265636f6e6e65637",
357 "4696f6e2e636330819f300d06092a864886f70d010101050003818d0030818902",
358 "818100d269fa6f3a00b4211bc8b102d73f19b2c46db454f88b8accdb72c29e3c6",
359 "0b9c6913d82b77d99ffd12984c173539c82ddfc248c77d541f3e81e42a1ad2d9e",
360 "ff5b1026ce9d571773162338c8d6f1baa3965b16674a4f73973a4d14a4f4e23f8",
361 "b058342d1d0dc2f7ae5b610b211c0dc212a90ffae97715a4981ac40f33bb859b2",
362 "4f0203010001a38203213082031d30090603551d1304023000301106096086480",
363 "186f8420101040403020640300b0603551d0f0404030203f830130603551d2504",
364 "0c300a06082b06010505070301301d0603551d0e04160414618f61344355147f2",
365 "709ce4c8bea9b7b1925bc6e301f0603551d230418301680140e0760d439c91b5b",
366 "5d907b23c8d2349d4a9a463930090603551d1104023000301c0603551d1204153",
367 "013811167656e6572616c4069707363612e636f6d307206096086480186f84201",
368 "0d046516634f7267616e697a6174696f6e20496e666f726d6174696f6e204e4f5",
369 "42056414c4944415445442e20434c415345413120536572766572204365727469",
370 "666963617465206973737565642062792068747470733a2f2f7777772e6970736",
371 "3612e636f6d2f302f06096086480186f84201020422162068747470733a2f2f77",
372 "77772e69707363612e636f6d2f6970736361323030322f304306096086480186f",
373 "84201040436163468747470733a2f2f7777772e69707363612e636f6d2f697073",
374 "6361323030322f697073636132303032434c41534541312e63726c30460609608",
375 "6480186f84201030439163768747470733a2f2f7777772e69707363612e636f6d",
376 "2f6970736361323030322f7265766f636174696f6e434c41534541312e68746d6",
377 "c3f304306096086480186f84201070436163468747470733a2f2f7777772e6970",
378 "7363612e636f6d2f6970736361323030322f72656e6577616c434c41534541312",
379 "e68746d6c3f304106096086480186f84201080434163268747470733a2f2f7777",
380 "772e69707363612e636f6d2f6970736361323030322f706f6c696379434c41534",
381 "541312e68746d6c3081830603551d1f047c307a3039a037a0358633687474703a",
382 "2f2f7777772e69707363612e636f6d2f6970736361323030322f6970736361323",
383 "03032434c41534541312e63726c303da03ba0398637687474703a2f2f77777762",
384 "61636b2e69707363612e636f6d2f6970736361323030322f69707363613230303",
385 "2434c41534541312e63726c303206082b0601050507010104263024302206082b",
386 "060105050730018616687474703a2f2f6f6373702e69707363612e636f6d2f300",
387 "d06092a864886f70d01010505000381810068ee799797dd3bef166a06f2149a6e",
388 "cd9e12f7aa8310bdd17c98fac7aed40e2c9e38059d5260a9990a81b498901daeb",
389 "b4ad7b9dc889e3778415bf782a5f2ba41255a901a1e4538a1525875942644fb20",
390 "07ba44cce54a2d723f9847f626dc054605076321ab469b9c78d5545b3d0c1ec86",
391 "48cb55023826fdbb8221c439607a8bb",
393 crt, tail = Certificate().decode(raw)
394 self.assertSequenceEqual(tail, b"")
395 self.assertSequenceEqual(crt.encode(), raw)