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):
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 AttributeTypeAndValue(Sequence):
93 ("type", AttributeType()),
94 ("value", AttributeValue()),
98 class RelativeDistinguishedName(SetOf):
99 schema = AttributeTypeAndValue()
100 bounds = (1, float("+inf"))
103 class RDNSequence(SequenceOf):
104 schema = RelativeDistinguishedName()
109 ("rdnSequence", RDNSequence()),
115 ("utcTime", UTCTime()),
116 ("generalTime", GeneralizedTime()),
120 class Validity(Sequence):
122 ("notBefore", Time()),
123 ("notAfter", Time()),
127 class SubjectPublicKeyInfo(Sequence):
129 ("algorithm", AlgorithmIdentifier()),
130 ("subjectPublicKey", BitString()),
134 class UniqueIdentifier(BitString):
138 class Extension(Sequence):
140 ("extnID", ObjectIdentifier()),
141 ("critical", Boolean(default=False)),
142 ("extnValue", OctetString()),
146 class Extensions(SequenceOf):
148 bounds = (1, float("+inf"))
151 class TBSCertificate(Sequence):
153 ("version", Version(expl=tag_ctxc(0), default="v1")),
154 ("serialNumber", CertificateSerialNumber()),
155 ("signature", AlgorithmIdentifier()),
157 ("validity", Validity()),
159 ("subjectPublicKeyInfo", SubjectPublicKeyInfo()),
160 ("issuerUniqueID", UniqueIdentifier(impl=tag_ctxp(1), optional=True)),
161 ("subjectUniqueID", UniqueIdentifier(impl=tag_ctxp(2), optional=True)),
162 ("extensions", Extensions(expl=tag_ctxc(3), optional=True)),
166 class Certificate(Sequence):
168 ("tbsCertificate", TBSCertificate()),
169 ("signatureAlgorithm", AlgorithmIdentifier()),
170 ("signatureValue", BitString()),
174 class TestGoSelfSignedVector(TestCase):
176 raw = hexdec("".join((
177 "30820218308201c20209008cc3379210ec2c98300d06092a864886f70d0101050",
178 "500308192310b3009060355040613025858311330110603550408130a536f6d65",
179 "2d5374617465310d300b06035504071304436974793121301f060355040a13184",
180 "96e7465726e6574205769646769747320507479204c7464311a30180603550403",
181 "131166616c73652e6578616d706c652e636f6d3120301e06092a864886f70d010",
182 "901161166616c7365406578616d706c652e636f6d301e170d3039313030383030",
183 "323535335a170d3130313030383030323535335a308192310b300906035504061",
184 "3025858311330110603550408130a536f6d652d5374617465310d300b06035504",
185 "071304436974793121301f060355040a1318496e7465726e65742057696467697",
186 "47320507479204c7464311a30180603550403131166616c73652e6578616d706c",
187 "652e636f6d3120301e06092a864886f70d010901161166616c7365406578616d7",
188 "06c652e636f6d305c300d06092a864886f70d0101010500034b003048024100cd",
189 "b7639c3278f006aa277f6eaf42902b592d8cbcbe38a1c92ba4695a331b1deadea",
190 "dd8e9a5c27e8c4c2fd0a8889657722a4f2af7589cf2c77045dc8fdeec357d0203",
191 "010001300d06092a864886f70d0101050500034100a67b06ec5ece92772ca413c",
192 "ba3ca12568fdc6c7b4511cd40a7f659980402df2b998bb9a4a8cbeb34c0f0a78c",
193 "f8d91ede14a5ed76bf116fe360aafa8821490435",
195 crt, tail = Certificate().decode(raw)
196 self.assertSequenceEqual(tail, b"")
197 tbs = crt["tbsCertificate"]
198 self.assertEqual(tbs["version"], 0)
199 self.assertFalse(tbs["version"].decoded)
200 self.assertNotIn("version", tbs)
201 self.assertEqual(tbs["serialNumber"], 10143011886257155224)
203 def assert_raw_equals(obj, expect):
204 self.assertTrue(obj.decoded)
205 self.assertSequenceEqual(
206 raw[obj.offset:obj.offset + obj.tlvlen],
209 assert_raw_equals(tbs["serialNumber"], Integer(10143011886257155224))
210 algo_id = AlgorithmIdentifier()
211 algo_id["algorithm"] = ObjectIdentifier("1.2.840.113549.1.1.5")
212 algo_id["parameters"] = Any(Null())
213 self.assertEqual(tbs["signature"], algo_id)
214 assert_raw_equals(tbs["signature"], algo_id)
216 rdnSeq = RDNSequence()
217 for oid, klass, text in (
218 ("2.5.4.6", PrintableString, "XX"),
219 ("2.5.4.8", PrintableString, "Some-State"),
220 ("2.5.4.7", PrintableString, "City"),
221 ("2.5.4.10", PrintableString, "Internet Widgits Pty Ltd"),
222 ("2.5.4.3", PrintableString, "false.example.com"),
223 ("1.2.840.113549.1.9.1", IA5String, "false@example.com"),
225 attr = AttributeTypeAndValue()
226 attr["type"] = AttributeType(oid)
227 attr["value"] = AttributeValue(klass(text))
228 rdn = RelativeDistinguishedName()
231 issuer["rdnSequence"] = rdnSeq
232 self.assertEqual(tbs["issuer"], issuer)
233 assert_raw_equals(tbs["issuer"], issuer)
234 validity = Validity()
235 validity["notBefore"] = Time(
236 ("utcTime", UTCTime(datetime(2009, 10, 8, 0, 25, 53)))
238 validity["notAfter"] = Time(
239 ("utcTime", UTCTime(datetime(2010, 10, 8, 0, 25, 53)))
241 self.assertEqual(tbs["validity"], validity)
242 assert_raw_equals(tbs["validity"], validity)
243 self.assertEqual(tbs["subject"], issuer)
244 assert_raw_equals(tbs["subject"], issuer)
245 spki = SubjectPublicKeyInfo()
246 algo_id["algorithm"] = ObjectIdentifier("1.2.840.113549.1.1.1")
247 spki["algorithm"] = algo_id
248 spki["subjectPublicKey"] = BitString(hexdec("".join((
249 "3048024100cdb7639c3278f006aa277f6eaf42902b592d8cbcbe38a1c92ba4695",
250 "a331b1deadeadd8e9a5c27e8c4c2fd0a8889657722a4f2af7589cf2c77045dc8f",
251 "deec357d0203010001",
253 self.assertEqual(tbs["subjectPublicKeyInfo"], spki)
254 assert_raw_equals(tbs["subjectPublicKeyInfo"], spki)
255 self.assertNotIn("issuerUniqueID", tbs)
256 self.assertNotIn("subjectUniqueID", tbs)
257 self.assertNotIn("extensions", tbs)
258 algo_id["algorithm"] = ObjectIdentifier("1.2.840.113549.1.1.5")
259 self.assertEqual(crt["signatureAlgorithm"], algo_id)
260 self.assertEqual(crt["signatureValue"], BitString(hexdec("".join((
261 "a67b06ec5ece92772ca413cba3ca12568fdc6c7b4511cd40a7f659980402df2b",
262 "998bb9a4a8cbeb34c0f0a78cf8d91ede14a5ed76bf116fe360aafa8821490435",
264 self.assertSequenceEqual(crt.encode(), raw)
268 tbs = TBSCertificate()
269 tbs["serialNumber"] = CertificateSerialNumber(10143011886257155224)
271 sign_algo_id = AlgorithmIdentifier()
272 sign_algo_id["algorithm"] = ObjectIdentifier("1.2.840.113549.1.1.5")
273 sign_algo_id["parameters"] = Any(Null())
274 tbs["signature"] = sign_algo_id
276 rdnSeq = RDNSequence()
277 for oid, klass, text in (
278 ("2.5.4.6", PrintableString, "XX"),
279 ("2.5.4.8", PrintableString, "Some-State"),
280 ("2.5.4.7", PrintableString, "City"),
281 ("2.5.4.10", PrintableString, "Internet Widgits Pty Ltd"),
282 ("2.5.4.3", PrintableString, "false.example.com"),
283 ("1.2.840.113549.1.9.1", IA5String, "false@example.com"),
285 attr = AttributeTypeAndValue()
286 attr["type"] = AttributeType(oid)
287 attr["value"] = AttributeValue(klass(text))
288 rdn = RelativeDistinguishedName()
292 issuer["rdnSequence"] = rdnSeq
293 tbs["issuer"] = issuer
294 tbs["subject"] = issuer
296 validity = Validity()
297 validity["notBefore"] = Time(("utcTime", UTCTime(datetime(2009, 10, 8, 0, 25, 53))))
298 validity["notAfter"] = Time(("utcTime", UTCTime(datetime(2010, 10, 8, 0, 25, 53))))
299 tbs["validity"] = validity
301 spki = SubjectPublicKeyInfo()
302 spki_algo_id = sign_algo_id.copy()
303 spki_algo_id["algorithm"] = ObjectIdentifier("1.2.840.113549.1.1.1")
304 spki["algorithm"] = spki_algo_id
305 spki["subjectPublicKey"] = BitString(hexdec("".join((
306 "3048024100cdb7639c3278f006aa277f6eaf42902b592d8cbcbe38a1c92ba4695",
307 "a331b1deadeadd8e9a5c27e8c4c2fd0a8889657722a4f2af7589cf2c77045dc8f",
308 "deec357d0203010001",
310 tbs["subjectPublicKeyInfo"] = spki
313 crt["tbsCertificate"] = tbs
314 crt["signatureAlgorithm"] = sign_algo_id
315 crt["signatureValue"] = BitString(hexdec("".join((
316 "a67b06ec5ece92772ca413cba3ca12568fdc6c7b4511cd40a7f659980402df2b",
317 "998bb9a4a8cbeb34c0f0a78cf8d91ede14a5ed76bf116fe360aafa8821490435",
319 self.assertSequenceEqual(crt.encode(), raw)
322 class TestGoPayPalVector(TestCase):
324 raw = hexdec("".join((
325 "30820644308205ada003020102020300f09b300d06092a864886f70d010105050",
326 "030820112310b3009060355040613024553311230100603550408130942617263",
327 "656c6f6e61311230100603550407130942617263656c6f6e61312930270603550",
328 "40a13204950532043657274696669636174696f6e20417574686f726974792073",
329 "2e6c2e312e302c060355040a142567656e6572616c4069707363612e636f6d204",
330 "32e492e462e2020422d423632323130363935312e302c060355040b1325697073",
331 "434120434c41534541312043657274696669636174696f6e20417574686f72697",
332 "479312e302c06035504031325697073434120434c415345413120436572746966",
333 "69636174696f6e20417574686f726974793120301e06092a864886f70d0109011",
334 "61167656e6572616c4069707363612e636f6d301e170d30393032323432333034",
335 "31375a170d3131303232343233303431375a308194310b3009060355040613025",
336 "553311330110603550408130a43616c69666f726e696131163014060355040713",
337 "0d53616e204672616e636973636f3111300f060355040a1308536563757269747",
338 "931143012060355040b130b53656375726520556e6974312f302d060355040313",
339 "267777772e70617970616c2e636f6d0073736c2e736563757265636f6e6e65637",
340 "4696f6e2e636330819f300d06092a864886f70d010101050003818d0030818902",
341 "818100d269fa6f3a00b4211bc8b102d73f19b2c46db454f88b8accdb72c29e3c6",
342 "0b9c6913d82b77d99ffd12984c173539c82ddfc248c77d541f3e81e42a1ad2d9e",
343 "ff5b1026ce9d571773162338c8d6f1baa3965b16674a4f73973a4d14a4f4e23f8",
344 "b058342d1d0dc2f7ae5b610b211c0dc212a90ffae97715a4981ac40f33bb859b2",
345 "4f0203010001a38203213082031d30090603551d1304023000301106096086480",
346 "186f8420101040403020640300b0603551d0f0404030203f830130603551d2504",
347 "0c300a06082b06010505070301301d0603551d0e04160414618f61344355147f2",
348 "709ce4c8bea9b7b1925bc6e301f0603551d230418301680140e0760d439c91b5b",
349 "5d907b23c8d2349d4a9a463930090603551d1104023000301c0603551d1204153",
350 "013811167656e6572616c4069707363612e636f6d307206096086480186f84201",
351 "0d046516634f7267616e697a6174696f6e20496e666f726d6174696f6e204e4f5",
352 "42056414c4944415445442e20434c415345413120536572766572204365727469",
353 "666963617465206973737565642062792068747470733a2f2f7777772e6970736",
354 "3612e636f6d2f302f06096086480186f84201020422162068747470733a2f2f77",
355 "77772e69707363612e636f6d2f6970736361323030322f304306096086480186f",
356 "84201040436163468747470733a2f2f7777772e69707363612e636f6d2f697073",
357 "6361323030322f697073636132303032434c41534541312e63726c30460609608",
358 "6480186f84201030439163768747470733a2f2f7777772e69707363612e636f6d",
359 "2f6970736361323030322f7265766f636174696f6e434c41534541312e68746d6",
360 "c3f304306096086480186f84201070436163468747470733a2f2f7777772e6970",
361 "7363612e636f6d2f6970736361323030322f72656e6577616c434c41534541312",
362 "e68746d6c3f304106096086480186f84201080434163268747470733a2f2f7777",
363 "772e69707363612e636f6d2f6970736361323030322f706f6c696379434c41534",
364 "541312e68746d6c3081830603551d1f047c307a3039a037a0358633687474703a",
365 "2f2f7777772e69707363612e636f6d2f6970736361323030322f6970736361323",
366 "03032434c41534541312e63726c303da03ba0398637687474703a2f2f77777762",
367 "61636b2e69707363612e636f6d2f6970736361323030322f69707363613230303",
368 "2434c41534541312e63726c303206082b0601050507010104263024302206082b",
369 "060105050730018616687474703a2f2f6f6373702e69707363612e636f6d2f300",
370 "d06092a864886f70d01010505000381810068ee799797dd3bef166a06f2149a6e",
371 "cd9e12f7aa8310bdd17c98fac7aed40e2c9e38059d5260a9990a81b498901daeb",
372 "b4ad7b9dc889e3778415bf782a5f2ba41255a901a1e4538a1525875942644fb20",
373 "07ba44cce54a2d723f9847f626dc054605076321ab469b9c78d5545b3d0c1ec86",
374 "48cb55023826fdbb8221c439607a8bb",
376 crt, tail = Certificate().decode(raw)
377 self.assertSequenceEqual(tail, b"")
378 self.assertSequenceEqual(crt.encode(), raw)