2 # PyDERASN -- Python ASN.1 DER codec with abstract structures
3 # Copyright (C) 2017-2019 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, version 3 of the License.
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.
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/>.
18 from datetime import datetime
19 from unittest import TestCase
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
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):
72 class CertificateSerialNumber(Integer):
76 class AlgorithmIdentifier(Sequence):
78 ("algorithm", ObjectIdentifier()),
79 ("parameters", Any(optional=True)),
83 class AttributeType(ObjectIdentifier):
87 class AttributeValue(Any):
91 class OrganizationName(Choice):
93 ("printableString", PrintableString()),
94 ("teletexString", TeletexString()),
98 class AttributeTypeAndValue(Sequence):
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(),
107 ("value", AttributeValue()),
111 class RelativeDistinguishedName(SetOf):
112 schema = AttributeTypeAndValue()
113 bounds = (1, float("+inf"))
116 class RDNSequence(SequenceOf):
117 schema = RelativeDistinguishedName()
122 ("rdnSequence", RDNSequence()),
128 ("utcTime", UTCTime()),
129 ("generalTime", GeneralizedTime()),
133 class Validity(Sequence):
135 ("notBefore", Time()),
136 ("notAfter", Time()),
140 class SubjectPublicKeyInfo(Sequence):
142 ("algorithm", AlgorithmIdentifier()),
143 ("subjectPublicKey", BitString()),
147 class UniqueIdentifier(BitString):
151 class Extension(Sequence):
153 ("extnID", ObjectIdentifier()),
154 ("critical", Boolean(default=False)),
155 ("extnValue", OctetString()),
159 class Extensions(SequenceOf):
161 bounds = (1, float("+inf"))
164 class TBSCertificate(Sequence):
166 ("version", Version(expl=tag_ctxc(0), default="v1")),
167 ("serialNumber", CertificateSerialNumber()),
168 ("signature", AlgorithmIdentifier()),
170 ("validity", Validity()),
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)),
179 class Certificate(Sequence):
181 ("tbsCertificate", TBSCertificate()),
182 ("signatureAlgorithm", AlgorithmIdentifier()),
183 ("signatureValue", BitString()),
187 class TestGoSelfSignedVector(TestCase):
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",
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)
216 def assert_raw_equals(obj, expect):
217 self.assertTrue(obj.decoded)
218 self.assertSequenceEqual(
219 raw[obj.offset:obj.offset + obj.tlvlen],
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())),
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"),
239 RelativeDistinguishedName((
240 AttributeTypeAndValue((
241 ("type", AttributeType(oid)),
242 ("value", AttributeValue(klass(text))),
246 issuer = Name(("rdnSequence", rdnSeq))
247 self.assertEqual(tbs["issuer"], issuer)
248 assert_raw_equals(tbs["issuer"], issuer)
249 validity = Validity((
251 ("utcTime", UTCTime(datetime(2009, 10, 8, 0, 25, 53)))
254 ("utcTime", UTCTime(datetime(2010, 10, 8, 0, 25, 53)))
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",
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",
280 self.assertSequenceEqual(crt.encode(), raw)
284 tbs = TBSCertificate()
285 tbs["serialNumber"] = CertificateSerialNumber(10143011886257155224)
287 sign_algo_id = AlgorithmIdentifier((
288 ("algorithm", ObjectIdentifier("1.2.840.113549.1.1.5")),
289 ("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"),
303 RelativeDistinguishedName((
304 AttributeTypeAndValue((
305 ("type", AttributeType(oid)),
306 ("value", AttributeValue(klass(text))),
311 issuer["rdnSequence"] = rdnSeq
312 tbs["issuer"] = issuer
313 tbs["subject"] = issuer
315 validity = Validity((
317 ("utcTime", UTCTime(datetime(2009, 10, 8, 0, 25, 53)),),
320 ("utcTime", UTCTime(datetime(2010, 10, 8, 0, 25, 53)),),
323 tbs["validity"] = validity
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",
334 tbs["subjectPublicKeyInfo"] = spki
337 crt["tbsCertificate"] = tbs
338 crt["signatureAlgorithm"] = sign_algo_id
339 crt["signatureValue"] = BitString(hexdec("".join((
340 "a67b06ec5ece92772ca413cba3ca12568fdc6c7b4511cd40a7f659980402df2b",
341 "998bb9a4a8cbeb34c0f0a78cf8d91ede14a5ed76bf116fe360aafa8821490435",
343 self.assertSequenceEqual(crt.encode(), raw)
346 class TestGoPayPalVector(TestCase):
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",
400 crt, tail = Certificate().decode(raw)
401 self.assertSequenceEqual(tail, b"")
402 self.assertSequenceEqual(crt.encode(), raw)