2 # PyDERASN -- Python ASN.1 DER codec with abstract structures
3 # Copyright (C) 2017-2020 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 = Certificate().decod(raw)
209 tbs = crt["tbsCertificate"]
210 self.assertEqual(tbs["version"], 0)
211 self.assertFalse(tbs["version"].decoded)
212 self.assertNotIn("version", tbs)
213 self.assertEqual(tbs["serialNumber"], 10143011886257155224)
215 def assert_raw_equals(obj, expect):
216 self.assertTrue(obj.decoded)
217 self.assertSequenceEqual(
218 raw[obj.offset:obj.offset + obj.tlvlen],
221 assert_raw_equals(tbs["serialNumber"], Integer(10143011886257155224))
222 algo_id = AlgorithmIdentifier((
223 ("algorithm", ObjectIdentifier("1.2.840.113549.1.1.5")),
224 ("parameters", Any(Null())),
226 self.assertEqual(tbs["signature"], algo_id)
227 assert_raw_equals(tbs["signature"], algo_id)
228 rdnSeq = RDNSequence()
229 for oid, klass, text in (
230 ("2.5.4.6", PrintableString, "XX"),
231 ("2.5.4.8", PrintableString, "Some-State"),
232 ("2.5.4.7", PrintableString, "City"),
233 ("2.5.4.10", PrintableString, "Internet Widgits Pty Ltd"),
234 ("2.5.4.3", PrintableString, "false.example.com"),
235 ("1.2.840.113549.1.9.1", IA5String, "false@example.com"),
238 RelativeDistinguishedName((
239 AttributeTypeAndValue((
240 ("type", AttributeType(oid)),
241 ("value", AttributeValue(klass(text))),
245 issuer = Name(("rdnSequence", rdnSeq))
246 self.assertEqual(tbs["issuer"], issuer)
247 assert_raw_equals(tbs["issuer"], issuer)
248 validity = Validity((
250 ("utcTime", UTCTime(datetime(2009, 10, 8, 0, 25, 53)))
253 ("utcTime", UTCTime(datetime(2010, 10, 8, 0, 25, 53)))
256 self.assertEqual(tbs["validity"], validity)
257 assert_raw_equals(tbs["validity"], validity)
258 self.assertEqual(tbs["subject"], issuer)
259 assert_raw_equals(tbs["subject"], issuer)
260 spki = SubjectPublicKeyInfo()
261 algo_id["algorithm"] = ObjectIdentifier("1.2.840.113549.1.1.1")
262 spki["algorithm"] = algo_id
263 spki["subjectPublicKey"] = BitString(hexdec("".join((
264 "3048024100cdb7639c3278f006aa277f6eaf42902b592d8cbcbe38a1c92ba4695",
265 "a331b1deadeadd8e9a5c27e8c4c2fd0a8889657722a4f2af7589cf2c77045dc8f",
266 "deec357d0203010001",
268 self.assertEqual(tbs["subjectPublicKeyInfo"], spki)
269 assert_raw_equals(tbs["subjectPublicKeyInfo"], spki)
270 self.assertNotIn("issuerUniqueID", tbs)
271 self.assertNotIn("subjectUniqueID", tbs)
272 self.assertNotIn("extensions", tbs)
273 algo_id["algorithm"] = ObjectIdentifier("1.2.840.113549.1.1.5")
274 self.assertEqual(crt["signatureAlgorithm"], algo_id)
275 self.assertEqual(crt["signatureValue"], BitString(hexdec("".join((
276 "a67b06ec5ece92772ca413cba3ca12568fdc6c7b4511cd40a7f659980402df2b",
277 "998bb9a4a8cbeb34c0f0a78cf8d91ede14a5ed76bf116fe360aafa8821490435",
279 self.assertSequenceEqual(crt.encode(), raw)
283 tbs = TBSCertificate()
284 tbs["serialNumber"] = CertificateSerialNumber(10143011886257155224)
286 sign_algo_id = AlgorithmIdentifier((
287 ("algorithm", ObjectIdentifier("1.2.840.113549.1.1.5")),
288 ("parameters", Any(Null())),
290 tbs["signature"] = sign_algo_id
292 rdnSeq = RDNSequence()
293 for oid, klass, text in (
294 ("2.5.4.6", PrintableString, "XX"),
295 ("2.5.4.8", PrintableString, "Some-State"),
296 ("2.5.4.7", PrintableString, "City"),
297 ("2.5.4.10", PrintableString, "Internet Widgits Pty Ltd"),
298 ("2.5.4.3", PrintableString, "false.example.com"),
299 ("1.2.840.113549.1.9.1", IA5String, "false@example.com"),
302 RelativeDistinguishedName((
303 AttributeTypeAndValue((
304 ("type", AttributeType(oid)),
305 ("value", AttributeValue(klass(text))),
310 issuer["rdnSequence"] = rdnSeq
311 tbs["issuer"] = issuer
312 tbs["subject"] = issuer
314 validity = Validity((
316 ("utcTime", UTCTime(datetime(2009, 10, 8, 0, 25, 53)),),
319 ("utcTime", UTCTime(datetime(2010, 10, 8, 0, 25, 53)),),
322 tbs["validity"] = validity
324 spki = SubjectPublicKeyInfo()
325 spki_algo_id = sign_algo_id.copy()
326 spki_algo_id["algorithm"] = ObjectIdentifier("1.2.840.113549.1.1.1")
327 spki["algorithm"] = spki_algo_id
328 spki["subjectPublicKey"] = BitString(hexdec("".join((
329 "3048024100cdb7639c3278f006aa277f6eaf42902b592d8cbcbe38a1c92ba4695",
330 "a331b1deadeadd8e9a5c27e8c4c2fd0a8889657722a4f2af7589cf2c77045dc8f",
331 "deec357d0203010001",
333 tbs["subjectPublicKeyInfo"] = spki
336 crt["tbsCertificate"] = tbs
337 crt["signatureAlgorithm"] = sign_algo_id
338 crt["signatureValue"] = BitString(hexdec("".join((
339 "a67b06ec5ece92772ca413cba3ca12568fdc6c7b4511cd40a7f659980402df2b",
340 "998bb9a4a8cbeb34c0f0a78cf8d91ede14a5ed76bf116fe360aafa8821490435",
342 self.assertSequenceEqual(crt.encode(), raw)
345 class TestGoPayPalVector(TestCase):
347 raw = hexdec("".join((
348 "30820644308205ada003020102020300f09b300d06092a864886f70d010105050",
349 "030820112310b3009060355040613024553311230100603550408130942617263",
350 "656c6f6e61311230100603550407130942617263656c6f6e61312930270603550",
351 "40a13204950532043657274696669636174696f6e20417574686f726974792073",
352 "2e6c2e312e302c060355040a142567656e6572616c4069707363612e636f6d204",
353 "32e492e462e2020422d423632323130363935312e302c060355040b1325697073",
354 "434120434c41534541312043657274696669636174696f6e20417574686f72697",
355 "479312e302c06035504031325697073434120434c415345413120436572746966",
356 "69636174696f6e20417574686f726974793120301e06092a864886f70d0109011",
357 "61167656e6572616c4069707363612e636f6d301e170d30393032323432333034",
358 "31375a170d3131303232343233303431375a308194310b3009060355040613025",
359 "553311330110603550408130a43616c69666f726e696131163014060355040713",
360 "0d53616e204672616e636973636f3111300f060355040a1308536563757269747",
361 "931143012060355040b130b53656375726520556e6974312f302d060355040313",
362 "267777772e70617970616c2e636f6d0073736c2e736563757265636f6e6e65637",
363 "4696f6e2e636330819f300d06092a864886f70d010101050003818d0030818902",
364 "818100d269fa6f3a00b4211bc8b102d73f19b2c46db454f88b8accdb72c29e3c6",
365 "0b9c6913d82b77d99ffd12984c173539c82ddfc248c77d541f3e81e42a1ad2d9e",
366 "ff5b1026ce9d571773162338c8d6f1baa3965b16674a4f73973a4d14a4f4e23f8",
367 "b058342d1d0dc2f7ae5b610b211c0dc212a90ffae97715a4981ac40f33bb859b2",
368 "4f0203010001a38203213082031d30090603551d1304023000301106096086480",
369 "186f8420101040403020640300b0603551d0f0404030203f830130603551d2504",
370 "0c300a06082b06010505070301301d0603551d0e04160414618f61344355147f2",
371 "709ce4c8bea9b7b1925bc6e301f0603551d230418301680140e0760d439c91b5b",
372 "5d907b23c8d2349d4a9a463930090603551d1104023000301c0603551d1204153",
373 "013811167656e6572616c4069707363612e636f6d307206096086480186f84201",
374 "0d046516634f7267616e697a6174696f6e20496e666f726d6174696f6e204e4f5",
375 "42056414c4944415445442e20434c415345413120536572766572204365727469",
376 "666963617465206973737565642062792068747470733a2f2f7777772e6970736",
377 "3612e636f6d2f302f06096086480186f84201020422162068747470733a2f2f77",
378 "77772e69707363612e636f6d2f6970736361323030322f304306096086480186f",
379 "84201040436163468747470733a2f2f7777772e69707363612e636f6d2f697073",
380 "6361323030322f697073636132303032434c41534541312e63726c30460609608",
381 "6480186f84201030439163768747470733a2f2f7777772e69707363612e636f6d",
382 "2f6970736361323030322f7265766f636174696f6e434c41534541312e68746d6",
383 "c3f304306096086480186f84201070436163468747470733a2f2f7777772e6970",
384 "7363612e636f6d2f6970736361323030322f72656e6577616c434c41534541312",
385 "e68746d6c3f304106096086480186f84201080434163268747470733a2f2f7777",
386 "772e69707363612e636f6d2f6970736361323030322f706f6c696379434c41534",
387 "541312e68746d6c3081830603551d1f047c307a3039a037a0358633687474703a",
388 "2f2f7777772e69707363612e636f6d2f6970736361323030322f6970736361323",
389 "03032434c41534541312e63726c303da03ba0398637687474703a2f2f77777762",
390 "61636b2e69707363612e636f6d2f6970736361323030322f69707363613230303",
391 "2434c41534541312e63726c303206082b0601050507010104263024302206082b",
392 "060105050730018616687474703a2f2f6f6373702e69707363612e636f6d2f300",
393 "d06092a864886f70d01010505000381810068ee799797dd3bef166a06f2149a6e",
394 "cd9e12f7aa8310bdd17c98fac7aed40e2c9e38059d5260a9990a81b498901daeb",
395 "b4ad7b9dc889e3778415bf782a5f2ba41255a901a1e4538a1525875942644fb20",
396 "07ba44cce54a2d723f9847f626dc054605076321ab469b9c78d5545b3d0c1ec86",
397 "48cb55023826fdbb8221c439607a8bb",
399 crt = Certificate().decod(raw)
400 self.assertSequenceEqual(crt.encode(), raw)