]> Cypherpunks.ru repositories - pyderasn.git/blobdiff - tests/test_crts.py
Raise copyright years
[pyderasn.git] / tests / test_crts.py
index 8de934b019558a9263000a078474b6e2833edeaf..e43b4c22fbd23390c83da7eaec791ea4fca461ff 100644 (file)
@@ -1,11 +1,10 @@
 # coding: utf-8
-# PyDERASN -- Python ASN.1 DER codec with abstract structures
-# Copyright (C) 2017-2019 Sergey Matveev <stargrave@stargrave.org>
+# PyDERASN -- Python ASN.1 DER/CER/BER codec with abstract structures
+# Copyright (C) 2017-2024 Sergey Matveev <stargrave@stargrave.org>
 #
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU Lesser General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
+# published by the Free Software Foundation, version 3 of the License.
 #
 # This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # License along with this program.  If not, see
 # <http://www.gnu.org/licenses/>.
 
+from copy import copy
 from datetime import datetime
+from pickle import dumps as pickle_dumps
+from pickle import HIGHEST_PROTOCOL as pickle_proto
+from pickle import loads as pickle_loads
 from unittest import TestCase
 
 from pyderasn import Any
 from pyderasn import BitString
 from pyderasn import Boolean
 from pyderasn import Choice
+from pyderasn import DecodeError
+from pyderasn import encode_cer
 from pyderasn import GeneralizedTime
 from pyderasn import hexdec
 from pyderasn import IA5String
@@ -39,27 +44,29 @@ from pyderasn import tag_ctxc
 from pyderasn import tag_ctxp
 from pyderasn import TeletexString
 from pyderasn import UTCTime
-
-
-some_oids = {
-    "1.2.840.113549.1.1.1": "id-rsaEncryption",
-    "1.2.840.113549.1.1.5": "id-sha1WithRSAEncryption",
-    "1.2.840.113549.1.9.1": "id-emailAddress",
-    "2.5.29.14": "id-ce-subjectKeyIdentifier",
-    "2.5.29.15": "id-ce-keyUsage",
-    "2.5.29.17": "id-ce-subjectAltName",
-    "2.5.29.18": "id-ce-issuerAltName",
-    "2.5.29.19": "id-ce-basicConstraints",
-    "2.5.29.31": "id-ce-cRLDistributionPoints",
-    "2.5.29.35": "id-ce-authorityKeyIdentifier",
-    "2.5.29.37": "id-ce-extKeyUsage",
-    "2.5.4.3": "id-at-commonName",
-    "2.5.4.6": "id-at-countryName",
-    "2.5.4.7": "id-at-localityName",
-    "2.5.4.8": "id-at-stateOrProvinceName",
-    "2.5.4.10": "id-at-organizationName",
-    "2.5.4.11": "id-at-organizationalUnitName",
+from pyderasn import UTF8String
+
+
+name2oid = {
+    "id-rsaEncryption": ObjectIdentifier("1.2.840.113549.1.1.1"),
+    "id-sha1WithRSAEncryption": ObjectIdentifier("1.2.840.113549.1.1.5"),
+    "id-emailAddress": ObjectIdentifier("1.2.840.113549.1.9.1"),
+    "id-ce-subjectKeyIdentifier": ObjectIdentifier("2.5.29.14"),
+    "id-ce-keyUsage": ObjectIdentifier("2.5.29.15"),
+    "id-ce-subjectAltName": ObjectIdentifier("2.5.29.17"),
+    "id-ce-issuerAltName": ObjectIdentifier("2.5.29.18"),
+    "id-ce-basicConstraints": ObjectIdentifier("2.5.29.19"),
+    "id-ce-cRLDistributionPoints": ObjectIdentifier("2.5.29.31"),
+    "id-ce-authorityKeyIdentifier": ObjectIdentifier("2.5.29.35"),
+    "id-ce-extKeyUsage": ObjectIdentifier("2.5.29.37"),
+    "id-at-commonName": ObjectIdentifier("2.5.4.3"),
+    "id-at-countryName": ObjectIdentifier("2.5.4.6"),
+    "id-at-localityName": ObjectIdentifier("2.5.4.7"),
+    "id-at-stateOrProvinceName": ObjectIdentifier("2.5.4.8"),
+    "id-at-organizationName": ObjectIdentifier("2.5.4.10"),
+    "id-at-organizationalUnitName": ObjectIdentifier("2.5.4.11"),
 }
+stroid2name = {str(oid): name for name, oid in name2oid.items()}
 
 
 class Version(Integer):
@@ -96,14 +103,21 @@ class OrganizationName(Choice):
     )
 
 
+class CommonName(Choice):
+    schema = (
+        ("printableString", PrintableString()),
+        ("utf8String", UTF8String()),
+    )
+
+
 class AttributeTypeAndValue(Sequence):
     schema = (
-        ("type", AttributeType(defines=(((".", "value"), {
-            ObjectIdentifier("2.5.4.6"): PrintableString(),
-            ObjectIdentifier("2.5.4.8"): PrintableString(),
-            ObjectIdentifier("2.5.4.7"): PrintableString(),
-            ObjectIdentifier("2.5.4.10"): OrganizationName(),
-            ObjectIdentifier("2.5.4.3"): PrintableString(),
+        ("type", AttributeType(defines=((("value",), {
+            name2oid["id-at-countryName"]: PrintableString(),
+            name2oid["id-at-localityName"]: PrintableString(),
+            name2oid["id-at-stateOrProvinceName"]: PrintableString(),
+            name2oid["id-at-organizationName"]: OrganizationName(),
+            name2oid["id-at-commonName"]: CommonName(),
         }),))),
         ("value", AttributeValue()),
     )
@@ -149,6 +163,14 @@ class UniqueIdentifier(BitString):
     pass
 
 
+class KeyIdentifier(OctetString):
+    pass
+
+
+class SubjectKeyIdentifier(KeyIdentifier):
+    pass
+
+
 class Extension(Sequence):
     schema = (
         ("extnID", ObjectIdentifier()),
@@ -183,6 +205,7 @@ class Certificate(Sequence):
         ("signatureAlgorithm", AlgorithmIdentifier()),
         ("signatureValue", BitString()),
     )
+    der_forced = True
 
 
 class TestGoSelfSignedVector(TestCase):
@@ -206,8 +229,7 @@ class TestGoSelfSignedVector(TestCase):
             "ba3ca12568fdc6c7b4511cd40a7f659980402df2b998bb9a4a8cbeb34c0f0a78c",
             "f8d91ede14a5ed76bf116fe360aafa8821490435",
         )))
-        crt, tail = Certificate().decode(raw)
-        self.assertSequenceEqual(tail, b"")
+        crt = Certificate().decod(raw, ctx={"keep_memoryview": True})
         tbs = crt["tbsCertificate"]
         self.assertEqual(tbs["version"], 0)
         self.assertFalse(tbs["version"].decoded)
@@ -222,7 +244,7 @@ class TestGoSelfSignedVector(TestCase):
             )
         assert_raw_equals(tbs["serialNumber"], Integer(10143011886257155224))
         algo_id = AlgorithmIdentifier((
-            ("algorithm", ObjectIdentifier("1.2.840.113549.1.1.5")),
+            ("algorithm", name2oid["id-sha1WithRSAEncryption"]),
             ("parameters", Any(Null())),
         ))
         self.assertEqual(tbs["signature"], algo_id)
@@ -260,7 +282,7 @@ class TestGoSelfSignedVector(TestCase):
         self.assertEqual(tbs["subject"], issuer)
         assert_raw_equals(tbs["subject"], issuer)
         spki = SubjectPublicKeyInfo()
-        algo_id["algorithm"] = ObjectIdentifier("1.2.840.113549.1.1.1")
+        algo_id["algorithm"] = name2oid["id-rsaEncryption"]
         spki["algorithm"] = algo_id
         spki["subjectPublicKey"] = BitString(hexdec("".join((
             "3048024100cdb7639c3278f006aa277f6eaf42902b592d8cbcbe38a1c92ba4695",
@@ -272,21 +294,23 @@ class TestGoSelfSignedVector(TestCase):
         self.assertNotIn("issuerUniqueID", tbs)
         self.assertNotIn("subjectUniqueID", tbs)
         self.assertNotIn("extensions", tbs)
-        algo_id["algorithm"] = ObjectIdentifier("1.2.840.113549.1.1.5")
+        algo_id["algorithm"] = name2oid["id-sha1WithRSAEncryption"]
         self.assertEqual(crt["signatureAlgorithm"], algo_id)
         self.assertEqual(crt["signatureValue"], BitString(hexdec("".join((
             "a67b06ec5ece92772ca413cba3ca12568fdc6c7b4511cd40a7f659980402df2b",
             "998bb9a4a8cbeb34c0f0a78cf8d91ede14a5ed76bf116fe360aafa8821490435",
         )))))
         self.assertSequenceEqual(crt.encode(), raw)
+        crt = Certificate().decod(raw)
         pprint(crt)
         repr(crt)
+        pickle_loads(pickle_dumps(crt, pickle_proto))
 
         tbs = TBSCertificate()
         tbs["serialNumber"] = CertificateSerialNumber(10143011886257155224)
 
         sign_algo_id = AlgorithmIdentifier((
-            ("algorithm", ObjectIdentifier("1.2.840.113549.1.1.5")),
+            ("algorithm", name2oid["id-sha1WithRSAEncryption"]),
             ("parameters", Any(Null())),
         ))
         tbs["signature"] = sign_algo_id
@@ -324,8 +348,8 @@ class TestGoSelfSignedVector(TestCase):
         tbs["validity"] = validity
 
         spki = SubjectPublicKeyInfo()
-        spki_algo_id = sign_algo_id.copy()
-        spki_algo_id["algorithm"] = ObjectIdentifier("1.2.840.113549.1.1.1")
+        spki_algo_id = copy(sign_algo_id)
+        spki_algo_id["algorithm"] = name2oid["id-rsaEncryption"]
         spki["algorithm"] = spki_algo_id
         spki["subjectPublicKey"] = BitString(hexdec("".join((
             "3048024100cdb7639c3278f006aa277f6eaf42902b592d8cbcbe38a1c92ba4695",
@@ -342,9 +366,15 @@ class TestGoSelfSignedVector(TestCase):
             "998bb9a4a8cbeb34c0f0a78cf8d91ede14a5ed76bf116fe360aafa8821490435",
         ))))
         self.assertSequenceEqual(crt.encode(), raw)
+        self.assertEqual(
+            Certificate().decod(encode_cer(crt), ctx={"bered": True}),
+            crt,
+        )
 
 
 class TestGoPayPalVector(TestCase):
+    """PayPal certificate with "www.paypal.com\x00ssl.secureconnection.cc" name
+    """
     def runTest(self):
         raw = hexdec("".join((
             "30820644308205ada003020102020300f09b300d06092a864886f70d010105050",
@@ -398,8 +428,5 @@ class TestGoPayPalVector(TestCase):
             "07ba44cce54a2d723f9847f626dc054605076321ab469b9c78d5545b3d0c1ec86",
             "48cb55023826fdbb8221c439607a8bb",
         )))
-        crt, tail = Certificate().decode(raw)
-        self.assertSequenceEqual(tail, b"")
-        self.assertSequenceEqual(crt.encode(), raw)
-        pprint(crt)
-        repr(crt)
+        with self.assertRaisesRegex(DecodeError, "alphabet value"):
+            crt = Certificate().decod(raw)