]> Cypherpunks.ru repositories - pygost.git/commitdiff
More test vectors and ASN.1 related structures 4.4
authorSergey Matveev <stargrave@stargrave.org>
Tue, 4 Feb 2020 13:44:56 +0000 (16:44 +0300)
committerSergey Matveev <stargrave@stargrave.org>
Tue, 4 Feb 2020 13:58:12 +0000 (16:58 +0300)
VERSION
install.texi
news.texi
pygost/__init__.py
pygost/asn1schemas/cert-selfsigned-example.py
pygost/asn1schemas/oids.py
pygost/asn1schemas/pkcs10.py [new file with mode: 0644]
pygost/asn1schemas/x509.py
pygost/gost3410.py
pygost/test_x509.py

diff --git a/VERSION b/VERSION
index 69df05f33b7e980f3528fbee240360b759b79dfa..515be8f918de9d7addeeccda132a1db7b29afc14 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-4.3
+4.4
index c022ba13ea23c794bcfe428e49fcecd0ccf87a5a..01a6873a1413addcb2d8f2c83e1322086498cc0a 100644 (file)
@@ -1,7 +1,7 @@
 @node Download
 @unnumbered Download
 
-@set VERSION 4.3
+@set VERSION 4.4
 
 No additional dependencies except Python 2.7/3.x interpreter are required.
 
index 384258a3513f3db3effd33fe53d57efd056ef624..9d173f994b1bf657bfea9931f222d3cf383bd003 100644 (file)
--- a/news.texi
+++ b/news.texi
@@ -3,6 +3,15 @@
 
 @table @strong
 
+@anchor{Release 4.4}
+@item 4.4
+    @itemize
+    @item @code{id-tc26-gost-3410-2012-512-paramSetTest} curve
+    @item Simple FAQ
+    @item More test vectors for 34.10-2012
+    @item More X.509, PKCS #10 and corresponding ASN.1 helper structures
+    @end itemize
+
 @anchor{Release 4.3}
 @item 4.3
 Dummy release with fixed @code{pygost.__version__}.
index 306746ec75fff13d9e141eb61f06f8769c6b95d2..17c35b67ddacb107b62450bd6e3b031f28c7f496 100644 (file)
@@ -3,4 +3,4 @@
 PyGOST is free software: see the file COPYING for copying conditions.
 """
 
-__version__ = "4.3"
+__version__ = "4.4"
index 5cdca8f5cfa4c961e67af56a623259d81cf4a522..10ec5d29de3eeb8c620d39786336dd22b9875e2c 100644 (file)
@@ -7,17 +7,16 @@ from datetime import timedelta
 from os import urandom
 from sys import argv
 from sys import exit as sys_exit
-from sys import stderr
 from textwrap import fill
 
 from pyderasn import Any
 from pyderasn import BitString
 from pyderasn import Integer
-from pyderasn import ObjectIdentifier
 from pyderasn import OctetString
 from pyderasn import PrintableString
 from pyderasn import UTCTime
 
+from pygost.asn1schemas.oids import id_at_commonName
 from pygost.asn1schemas.oids import id_ce_subjectKeyIdentifier
 from pygost.asn1schemas.oids import id_tc26_gost3410_2012_512
 from pygost.asn1schemas.oids import id_tc26_gost3410_2012_512_paramSetA
@@ -52,12 +51,13 @@ from pygost.gost3410 import sign
 from pygost.gost34112012512 import GOST34112012512
 
 if len(argv) != 2:
-    print("Usage: cert-selfsigned-example.py COMMON-NAME", file=stderr)
-    sys_exit(1)
+    sys_exit("Usage: cert-selfsigned-example.py COMMON-NAME")
+
 
 def pem(obj):
     return fill(standard_b64encode(obj.encode()).decode('ascii'), 64)
 
+
 key_params = GostR34102012PublicKeyParameters((
     ("publicKeyParamSet", id_tc26_gost3410_2012_512_paramSetA),
     ("digestParamSet", id_tc26_gost3411_2012_512),
@@ -78,7 +78,6 @@ print("-----END PRIVATE KEY-----")
 prv = prv_unmarshal(prv_raw)
 curve = CURVES["id-tc26-gost-3410-12-512-paramSetA"]
 pub_raw = pub_marshal(public_key(curve, prv), mode=2012)
-id_at_commonName = ObjectIdentifier("2.5.4.3")
 subj = Name(("rdnSequence", RDNSequence([
     RelativeDistinguishedName((
         AttributeTypeAndValue((
index eff060d891eba5ad07b45e48d096bd6eb009c255..0cb3b8dca41e6da7e74457d1e353df29261005db 100644 (file)
@@ -2,12 +2,12 @@ from pyderasn import ObjectIdentifier
 
 
 id_pkcs7 = ObjectIdentifier("1.2.840.113549.1.7")
+id_data = id_pkcs7 + (1,)
 id_signedData = id_pkcs7 + (2,)
 id_envelopedData = id_pkcs7 + (3,)
 id_digestedData = id_pkcs7 + (5,)
 id_encryptedData = id_pkcs7 + (6,)
 
-id_data = ObjectIdentifier("1.2.840.113549.1.7.1")
 id_tc26_gost3410_2012_256 = ObjectIdentifier("1.2.643.7.1.1.1.1")
 id_tc26_gost3410_2012_512 = ObjectIdentifier("1.2.643.7.1.1.1.2")
 id_tc26_gost3411_2012_256 = ObjectIdentifier("1.2.643.7.1.1.2.2")
@@ -16,14 +16,19 @@ id_tc26_gost3410_2012_256_paramSetA = ObjectIdentifier("1.2.643.7.1.2.1.1.1")
 id_tc26_gost3410_2012_256_paramSetB = ObjectIdentifier("1.2.643.7.1.2.1.1.2")
 id_tc26_gost3410_2012_256_paramSetC = ObjectIdentifier("1.2.643.7.1.2.1.1.3")
 id_tc26_gost3410_2012_256_paramSetD = ObjectIdentifier("1.2.643.7.1.2.1.1.4")
+id_tc26_gost3410_2012_512_paramSetTest = ObjectIdentifier("1.2.643.7.1.2.1.2.0")
 id_tc26_gost3410_2012_512_paramSetA = ObjectIdentifier("1.2.643.7.1.2.1.2.1")
 id_tc26_gost3410_2012_512_paramSetB = ObjectIdentifier("1.2.643.7.1.2.1.2.2")
 id_tc26_gost3410_2012_512_paramSetC = ObjectIdentifier("1.2.643.7.1.2.1.2.3")
 id_tc26_signwithdigest_gost3410_2012_256 = ObjectIdentifier("1.2.643.7.1.1.3.2")
 id_tc26_signwithdigest_gost3410_2012_512 = ObjectIdentifier("1.2.643.7.1.1.3.3")
+id_tc26_gost_28147_param_Z = ObjectIdentifier("1.2.643.7.1.2.5.1.1")
 id_Gost28147_89 = ObjectIdentifier("1.2.643.2.2.21")
+id_GostR3410_2001_TestParamSet = ObjectIdentifier("1.2.643.2.2.35.0")
 
 id_pbes2 = ObjectIdentifier("1.2.840.113549.1.5.13")
 id_pbkdf2 = ObjectIdentifier("1.2.840.113549.1.5.12")
 
+id_at_commonName = ObjectIdentifier("2.5.4.3")
+id_ce_basicConstraints = ObjectIdentifier("2.5.29.19")
 id_ce_subjectKeyIdentifier = ObjectIdentifier("2.5.29.14")
diff --git a/pygost/asn1schemas/pkcs10.py b/pygost/asn1schemas/pkcs10.py
new file mode 100644 (file)
index 0000000..f1f684a
--- /dev/null
@@ -0,0 +1,65 @@
+# coding: utf-8
+# PyGOST -- Pure Python GOST cryptographic functions library
+# Copyright (C) 2015-2020 Sergey Matveev <stargrave@stargrave.org>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as 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
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""PKCS #10 related structures (**NOT COMPLETE**)
+"""
+
+from pyderasn import Any
+from pyderasn import BitString
+from pyderasn import Integer
+from pyderasn import ObjectIdentifier
+from pyderasn import Sequence
+from pyderasn import SetOf
+from pyderasn import tag_ctxc
+
+from pygost.asn1schemas.x509 import AlgorithmIdentifier
+from pygost.asn1schemas.x509 import Name
+from pygost.asn1schemas.x509 import SubjectPublicKeyInfo
+
+
+class AttributeValue(Any):
+    pass
+
+
+class AttributeValues(SetOf):
+    schema = AttributeValue()
+
+
+class Attribute(Sequence):
+    schema = (
+        ("type", ObjectIdentifier()),
+        ("values", AttributeValues()),
+    )
+
+
+class Attributes(SetOf):
+    schema = Attribute()
+
+
+class CertificationRequestInfo(Sequence):
+    schema = (
+        ("version", Integer(0)),
+        ("subject", Name()),
+        ("subjectPKInfo", SubjectPublicKeyInfo()),
+        ("attributes", Attributes(impl=tag_ctxc(0))),
+    )
+
+
+class CertificationRequest(Sequence):
+    schema = (
+        ("certificationRequestInfo", CertificationRequestInfo()),
+        ("signatureAlgorithm", AlgorithmIdentifier()),
+        ("signature", BitString()),
+    )
index bbeca669c5f5f3412a1ddfa0135c6fb62a1a912a..831f9abc2f248275c22b5e96578886994098fb19 100644 (file)
@@ -112,16 +112,10 @@ class Validity(Sequence):
     )
 
 
-id_tc26_gost_28147_param_Z = ObjectIdentifier("1.2.643.7.1.2.5.1.1")
-
-
 class GostR34102012PublicKeyParameters(Sequence):
     schema = (
         ("publicKeyParamSet", ObjectIdentifier()),
-        ("digestParamSet", ObjectIdentifier()),
-        ("encryptionParamSet", ObjectIdentifier(
-            default=id_tc26_gost_28147_param_Z,
-        )),
+        ("digestParamSet", ObjectIdentifier(optional=True)),
     )
 
 
@@ -144,6 +138,13 @@ class SubjectKeyIdentifier(KeyIdentifier):
     pass
 
 
+class BasicConstraints(Sequence):
+    schema = (
+        ('cA', Boolean(default=False)),
+        # ('pathLenConstraint', PathLenConstraint(optional=True)),
+    )
+
+
 class Extension(Sequence):
     schema = (
         ("extnID", ObjectIdentifier()),
@@ -178,3 +179,28 @@ class Certificate(Sequence):
         ("signatureAlgorithm", AlgorithmIdentifier()),
         ("signatureValue", BitString()),
     )
+
+
+class RevokedCertificates(SequenceOf):
+    # schema = RevokedCertificate()
+    schema = OctetString()  # dummy
+
+
+class TBSCertList(Sequence):
+    schema = (
+        ("version", Version(optional=True)),
+        ("signature", AlgorithmIdentifier()),
+        ("issuer", Name()),
+        ("thisUpdate", Time()),
+        ("nextUpdate", Time(optional=True)),
+        ("revokedCertificates", RevokedCertificates(optional=True)),
+        ("crlExtensions", Extensions(expl=tag_ctxc(0), optional=True)),
+    )
+
+
+class CertificateList(Sequence):
+    schema = (
+        ("tbsCertList", TBSCertList()),
+        ("signatureAlgorithm", AlgorithmIdentifier()),
+        ("signatureValue", BitString()),
+    )
index 1848ef56653d21460f1ccf247d6c22ea8c770e9d..7e92e3422c29b0b5ae569257143196a945836a04 100644 (file)
@@ -168,6 +168,14 @@ CURVES = {
         e=0x01,
         d=bytes2long(hexdec("0605F6B7C183FA81578BC39CFAD518132B9DF62897009AF7E522C32D6DC7BFFB")),
     ),
+    "id-tc26-gost-3410-2012-512-paramSetTest": GOST3410Curve(
+        p=bytes2long(hexdec("4531ACD1FE0023C7550D267B6B2FEE80922B14B2FFB90F04D4EB7C09B5D2D15DF1D852741AF4704A0458047E80E4546D35B8336FAC224DD81664BBF528BE6373")),
+        q=bytes2long(hexdec("4531ACD1FE0023C7550D267B6B2FEE80922B14B2FFB90F04D4EB7C09B5D2D15DA82F2D7ECB1DBAC719905C5EECC423F1D86E25EDBE23C595D644AAF187E6E6DF")),
+        a=7,
+        b=bytes2long(hexdec("1CFF0806A31116DA29D8CFA54E57EB748BC5F377E49400FDD788B649ECA1AC4361834013B2AD7322480A89CA58E0CF74BC9E540C2ADD6897FAD0A3084F302ADC")),
+        x=bytes2long(hexdec("24D19CC64572EE30F396BF6EBBFD7A6C5213B3B3D7057CC825F91093A68CD762FD60611262CD838DC6B60AA7EEE804E28BC849977FAC33B4B530F1B120248A9A")),
+        y=bytes2long(hexdec("2BB312A43BD2CE6E0D020613C857ACDDCFBF061E91E5F2C3F32447C259F39B2C83AB156D77F1496BF7EB3351E1EE4E43DC1A18B91B24640B6DBB92CB1ADD371E")),
+    ),
     "id-tc26-gost-3410-12-512-paramSetA": GOST3410Curve(
         p=bytes2long(hexdec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC7")),
         q=bytes2long(hexdec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF27E69532F48D89116FF22B8D4E0560609B4B38ABFAD2B85DCACDB1411F10B275")),
index a892ad4d67dc8e904acd894b12c8f22fad6e7acc..5e6c74d87fd45af602fa30abb6f63f36bc42f6cf 100644 (file)
@@ -20,6 +20,7 @@ from unittest import TestCase
 
 from pygost.gost3410 import CURVES
 from pygost.gost3410 import prv_unmarshal
+from pygost.gost3410 import pub_marshal
 from pygost.gost3410 import pub_unmarshal
 from pygost.gost3410 import public_key
 from pygost.gost3410 import verify
@@ -28,11 +29,50 @@ from pygost.gost34112012512 import GOST34112012512
 from pygost.utils import hexdec
 
 try:
+
+    from pyderasn import Any
+    from pyderasn import BitString
+    from pyderasn import Boolean
+    from pyderasn import GeneralizedTime
+    from pyderasn import Integer
     from pyderasn import OctetString
+    from pyderasn import PrintableString
+    from pyderasn import UTCTime
 
+    from pygost.asn1schemas.oids import id_at_commonName
+    from pygost.asn1schemas.oids import id_ce_basicConstraints
+    from pygost.asn1schemas.oids import id_GostR3410_2001_TestParamSet
     from pygost.asn1schemas.oids import id_tc26_gost3410_2012_256
+    from pygost.asn1schemas.oids import id_tc26_gost3410_2012_256_paramSetA
     from pygost.asn1schemas.oids import id_tc26_gost3410_2012_512
+    from pygost.asn1schemas.oids import id_tc26_gost3410_2012_512_paramSetTest
+    from pygost.asn1schemas.oids import id_tc26_gost3411_2012_256
+    from pygost.asn1schemas.oids import id_tc26_signwithdigest_gost3410_2012_256
+    from pygost.asn1schemas.oids import id_tc26_signwithdigest_gost3410_2012_512
+    from pygost.asn1schemas.pkcs10 import Attributes
+    from pygost.asn1schemas.pkcs10 import CertificationRequest
+    from pygost.asn1schemas.pkcs10 import CertificationRequestInfo
+    from pygost.asn1schemas.x509 import AlgorithmIdentifier
+    from pygost.asn1schemas.x509 import AttributeType
+    from pygost.asn1schemas.x509 import AttributeTypeAndValue
+    from pygost.asn1schemas.x509 import AttributeValue
+    from pygost.asn1schemas.x509 import BasicConstraints
     from pygost.asn1schemas.x509 import Certificate
+    from pygost.asn1schemas.x509 import CertificateList
+    from pygost.asn1schemas.x509 import CertificateSerialNumber
+    from pygost.asn1schemas.x509 import Extension
+    from pygost.asn1schemas.x509 import Extensions
+    from pygost.asn1schemas.x509 import GostR34102012PublicKeyParameters
+    from pygost.asn1schemas.x509 import Name
+    from pygost.asn1schemas.x509 import RDNSequence
+    from pygost.asn1schemas.x509 import RelativeDistinguishedName
+    from pygost.asn1schemas.x509 import SubjectPublicKeyInfo
+    from pygost.asn1schemas.x509 import TBSCertificate
+    from pygost.asn1schemas.x509 import TBSCertList
+    from pygost.asn1schemas.x509 import Time
+    from pygost.asn1schemas.x509 import Validity
+    from pygost.asn1schemas.x509 import Version
+
 except ImportError:
     pyderasn_exists = False
 else:
@@ -137,3 +177,268 @@ o3eUNFkNyHJwQCk2WoOlO16zwGk2tdKH4KmD5w==
             prv_key_raw,
             cert_raw,
         )
+
+
+@skipIf(not pyderasn_exists, "PyDERASN dependency is required")
+class TestRFC4491bis(TestCase):
+    """Test vectors from https://tools.ietf.org/html/draft-deremin-rfc4491-bis-02
+    """
+
+    def _test_vector(
+            self,
+            curve_name,
+            mode,
+            hsh,
+            ai_spki,
+            ai_sign,
+            cert_serial,
+            prv_hex,
+            cr_sign_hex,
+            cr_b64,
+            c_sign_hex,
+            c_b64,
+            crl_sign_hex,
+            crl_b64,
+    ):
+        prv_raw = hexdec(prv_hex)[::-1]
+        prv = prv_unmarshal(prv_raw)
+        curve = CURVES[curve_name]
+        pub = public_key(curve, prv)
+        pub_raw = pub_marshal(pub, mode=mode)
+        subj = Name(("rdnSequence", RDNSequence([
+            RelativeDistinguishedName((
+                AttributeTypeAndValue((
+                    ("type", AttributeType(id_at_commonName)),
+                    ("value", AttributeValue(PrintableString("Example"))),
+                )),
+            ))
+        ])))
+        spki = SubjectPublicKeyInfo((
+            ("algorithm", ai_spki),
+            ("subjectPublicKey", BitString(OctetString(pub_raw).encode())),
+        ))
+
+        # Certification request
+        cri = CertificationRequestInfo((
+            ("version", Integer(0)),
+            ("subject", subj),
+            ("subjectPKInfo", spki),
+            ("attributes", Attributes()),
+        ))
+        sign = hexdec(cr_sign_hex)
+        self.assertTrue(verify(
+            curve,
+            pub,
+            hsh(cri.encode()).digest()[::-1],
+            sign,
+            mode=mode,
+        ))
+        cr = CertificationRequest((
+            ("certificationRequestInfo", cri),
+            ("signatureAlgorithm", ai_sign),
+            ("signature", BitString(sign)),
+        ))
+        self.assertSequenceEqual(cr.encode(), b64decode(cr_b64))
+
+        # Certificate
+        tbs = TBSCertificate((
+            ("version", Version("v3")),
+            ("serialNumber", CertificateSerialNumber(cert_serial)),
+            ("signature", ai_sign),
+            ("issuer", subj),
+            ("validity", Validity((
+                ("notBefore", Time(("utcTime", UTCTime(b"010101000000Z")))),
+                ("notAfter", Time(("generalTime", GeneralizedTime(b"20501231000000Z")))),
+            ))),
+            ("subject", subj),
+            ("subjectPublicKeyInfo", spki),
+            ("extensions", Extensions((
+                Extension((
+                    ("extnID", id_ce_basicConstraints),
+                    ("critical", Boolean(True)),
+                    ("extnValue", OctetString(
+                        BasicConstraints((("cA", Boolean(True)),)).encode()
+                    )),
+                )),
+            ))),
+        ))
+        sign = hexdec(c_sign_hex)
+        self.assertTrue(verify(
+            curve,
+            pub,
+            hsh(tbs.encode()).digest()[::-1],
+            sign,
+            mode=mode,
+        ))
+        cert = Certificate((
+            ("tbsCertificate", tbs),
+            ("signatureAlgorithm", ai_sign),
+            ("signatureValue", BitString(sign)),
+        ))
+        open("/tmp/1", "wb").write(cert.encode())
+        self.assertSequenceEqual(cert.encode(), b64decode(c_b64))
+
+        # CRL
+        tbs = TBSCertList((
+            ("version", Version("v2")),
+            ("signature", ai_sign),
+            ("issuer", subj),
+            ("thisUpdate", Time(("utcTime", UTCTime(b"140101000000Z")))),
+            ("nextUpdate", Time(("utcTime", UTCTime(b"140102000000Z")))),
+        ))
+        sign = hexdec(crl_sign_hex)
+        self.assertTrue(verify(
+            curve,
+            pub,
+            hsh(tbs.encode()).digest()[::-1],
+            sign,
+            mode=mode,
+        ))
+        crl = CertificateList((
+            ("tbsCertList", tbs),
+            ("signatureAlgorithm", ai_sign),
+            ("signatureValue", BitString(sign)),
+        ))
+        self.assertSequenceEqual(crl.encode(), b64decode(crl_b64))
+
+    def test_256_test_paramset(self):
+        self._test_vector(
+            "id-GostR3410-2001-TestParamSet",
+            2001,
+            GOST34112012256,
+            AlgorithmIdentifier((
+                ("algorithm", id_tc26_gost3410_2012_256),
+                ("parameters", Any(
+                    GostR34102012PublicKeyParameters((
+                        ("publicKeyParamSet", id_GostR3410_2001_TestParamSet),
+                        ("digestParamSet", id_tc26_gost3411_2012_256),
+                    ))
+                )),
+            )),
+            AlgorithmIdentifier((
+                ("algorithm", id_tc26_signwithdigest_gost3410_2012_256),
+            )),
+            10,
+            "7A929ADE789BB9BE10ED359DD39A72C11B60961F49397EEE1D19CE9891EC3B28",
+            "6AAAB38E35D4AAA517940301799122D855484F579F4CBB96D63CDFDF3ACC432A41AA28D2F1AB148280CD9ED56FEDA41974053554A42767B83AD043FD39DC0493",
+            """
+MIHTMIGBAgEAMBIxEDAOBgNVBAMTB0V4YW1wbGUwZjAfBggqhQMHAQEBATATBgcq
+hQMCAiMABggqhQMHAQECAgNDAARAC9hv5djbiWaPeJtOHbqFhcVQi0XsW1nYkG3b
+cOJJK3/ad/+HGhD73ydm0pPF0WSvuzx7lzpByIXRHXDWibTxJqAAMAoGCCqFAwcB
+AQMCA0EAaqqzjjXUqqUXlAMBeZEi2FVIT1efTLuW1jzf3zrMQypBqijS8asUgoDN
+ntVv7aQZdAU1VKQnZ7g60EP9OdwEkw==
+            """,
+            "4D53F012FE081776507D4D9BB81F00EFDB4EEFD4AB83BAC4BACF735173CFA81C41AA28D2F1AB148280CD9ED56FEDA41974053554A42767B83AD043FD39DC0493",
+            """
+MIIBLTCB26ADAgECAgEKMAoGCCqFAwcBAQMCMBIxEDAOBgNVBAMTB0V4YW1wbGUw
+IBcNMDEwMTAxMDAwMDAwWhgPMjA1MDEyMzEwMDAwMDBaMBIxEDAOBgNVBAMTB0V4
+YW1wbGUwZjAfBggqhQMHAQEBATATBgcqhQMCAiMABggqhQMHAQECAgNDAARAC9hv
+5djbiWaPeJtOHbqFhcVQi0XsW1nYkG3bcOJJK3/ad/+HGhD73ydm0pPF0WSvuzx7
+lzpByIXRHXDWibTxJqMTMBEwDwYDVR0TAQH/BAUwAwEB/zAKBggqhQMHAQEDAgNB
+AE1T8BL+CBd2UH1Nm7gfAO/bTu/Uq4O6xLrPc1Fzz6gcQaoo0vGrFIKAzZ7Vb+2k
+GXQFNVSkJ2e4OtBD/TncBJM=
+            """,
+            "42BF392A14D3EBE957AF3E46CB50BF5F4221A003AD3D172753C94A9C37A31D2041AA28D2F1AB148280CD9ED56FEDA41974053554A42767B83AD043FD39DC0493",
+            """
+MIGSMEECAQEwCgYIKoUDBwEBAwIwEjEQMA4GA1UEAxMHRXhhbXBsZRcNMTQwMTAx
+MDAwMDAwWhcNMTQwMTAyMDAwMDAwWjAKBggqhQMHAQEDAgNBAEK/OSoU0+vpV68+
+RstQv19CIaADrT0XJ1PJSpw3ox0gQaoo0vGrFIKAzZ7Vb+2kGXQFNVSkJ2e4OtBD
+/TncBJM=
+            """,
+        )
+
+    def test_256a_paramset(self):
+        self._test_vector(
+            "id-tc26-gost-3410-2012-256-paramSetA",
+            2001,
+            GOST34112012256,
+            AlgorithmIdentifier((
+                ("algorithm", id_tc26_gost3410_2012_256),
+                ("parameters", Any(
+                    GostR34102012PublicKeyParameters((
+                        ("publicKeyParamSet", id_tc26_gost3410_2012_256_paramSetA),
+                    ))
+                )),
+            )),
+            AlgorithmIdentifier((
+                ("algorithm", id_tc26_signwithdigest_gost3410_2012_256),
+            )),
+            10,
+            "7A929ADE789BB9BE10ED359DD39A72C11B60961F49397EEE1D19CE9891EC3B28",
+            "1BDC2A1317679B66232F63EA16FF7C64CCAAB9AD855FC6E18091661DB79D48121D0E1DA5BE347C6F1B5256C7AEAC200AD64AC77A6F5B3A0E097318E7AE6EE769",
+            """
+MIHKMHkCAQAwEjEQMA4GA1UEAxMHRXhhbXBsZTBeMBcGCCqFAwcBAQEBMAsGCSqF
+AwcBAgEBAQNDAARAdCeV1L7ohN3yhQ/sA+o/rxhE4B2dpgtkUJOlXibfw5l49ZbP
+TU0MbPHRiUPZRJPRa57AoW1RLS4SfMRpGmMY4qAAMAoGCCqFAwcBAQMCA0EAG9wq
+Exdnm2YjL2PqFv98ZMyqua2FX8bhgJFmHbedSBIdDh2lvjR8bxtSVseurCAK1krH
+em9bOg4Jcxjnrm7naQ==
+            """,
+            "140B4DA9124B09CB0D5CE928EE874273A310129492EC0E29369E3B791248578C1D0E1DA5BE347C6F1B5256C7AEAC200AD64AC77A6F5B3A0E097318E7AE6EE769",
+            """
+MIIBJTCB06ADAgECAgEKMAoGCCqFAwcBAQMCMBIxEDAOBgNVBAMTB0V4YW1wbGUw
+IBcNMDEwMTAxMDAwMDAwWhgPMjA1MDEyMzEwMDAwMDBaMBIxEDAOBgNVBAMTB0V4
+YW1wbGUwXjAXBggqhQMHAQEBATALBgkqhQMHAQIBAQEDQwAEQHQnldS+6ITd8oUP
+7APqP68YROAdnaYLZFCTpV4m38OZePWWz01NDGzx0YlD2UST0WuewKFtUS0uEnzE
+aRpjGOKjEzARMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoUDBwEBAwIDQQAUC02pEksJ
+yw1c6Sjuh0JzoxASlJLsDik2njt5EkhXjB0OHaW+NHxvG1JWx66sIArWSsd6b1s6
+DglzGOeubudp
+            """,
+            "14BD68087C3B903C7AA28B07FEB2E7BD6FE0963F563267359F5CD8EAB45059AD1D0E1DA5BE347C6F1B5256C7AEAC200AD64AC77A6F5B3A0E097318E7AE6EE769",
+            """
+MIGSMEECAQEwCgYIKoUDBwEBAwIwEjEQMA4GA1UEAxMHRXhhbXBsZRcNMTQwMTAx
+MDAwMDAwWhcNMTQwMTAyMDAwMDAwWjAKBggqhQMHAQEDAgNBABS9aAh8O5A8eqKL
+B/6y571v4JY/VjJnNZ9c2Oq0UFmtHQ4dpb40fG8bUlbHrqwgCtZKx3pvWzoOCXMY
+565u52k=
+            """,
+        )
+
+    def test_512_test_paramset(self):
+        self._test_vector(
+            "id-tc26-gost-3410-2012-512-paramSetTest",
+            2012,
+            GOST34112012512,
+            AlgorithmIdentifier((
+                ("algorithm", id_tc26_gost3410_2012_512),
+                ("parameters", Any(
+                    GostR34102012PublicKeyParameters((
+                        ("publicKeyParamSet", id_tc26_gost3410_2012_512_paramSetTest),
+                    ))
+                )),
+            )),
+            AlgorithmIdentifier((
+                ("algorithm", id_tc26_signwithdigest_gost3410_2012_512),
+            )),
+            11,
+            "0BA6048AADAE241BA40936D47756D7C93091A0E8514669700EE7508E508B102072E8123B2200A0563322DAD2827E2714A2636B7BFD18AADFC62967821FA18DD4",
+            "433B1D6CE40A51F1E5737EB16AA2C683829A405B9D9127E21260FC9D6AC05D87BF24E26C45278A5C2192A75BA94993ABD6074E7FF1BF03FD2F5397AFA1D945582F86FA60A081091A23DD795E1E3C689EE512A3C82EE0DCC2643C78EEA8FCACD35492558486B20F1C9EC197C90699850260C93BCBCD9C5C3317E19344E173AE36",
+            """
+MIIBTzCBvAIBADASMRAwDgYDVQQDEwdFeGFtcGxlMIGgMBcGCCqFAwcBAQECMAsG
+CSqFAwcBAgECAAOBhAAEgYDh7zDVLGEz3dmdHVxBRVz3302LTJJbvGmvFDPRVlhR
+Wt0hRoUMMlxbgcEzvmVaqMTUQOe5io1ZSHsMdpa8xV0R7L53NqnsNX/y/TmTH04R
+TLjNo1knCsfw5/9D2UGUGeph/Sq3f12fY1I9O1CgT2PioM9Rt8E63CFWDwvUDMnH
+N6AAMAoGCCqFAwcBAQMDA4GBAEM7HWzkClHx5XN+sWqixoOCmkBbnZEn4hJg/J1q
+wF2HvyTibEUnilwhkqdbqUmTq9YHTn/xvwP9L1OXr6HZRVgvhvpgoIEJGiPdeV4e
+PGie5RKjyC7g3MJkPHjuqPys01SSVYSGsg8cnsGXyQaZhQJgyTvLzZxcMxfhk0Th
+c642
+            """,
+            "415703D892F1A5F3F68C4353189A7EE207B80B5631EF9D49529A4D6B542C2CFA15AA2EACF11F470FDE7D954856903C35FD8F955EF300D95C77534A724A0EEE702F86FA60A081091A23DD795E1E3C689EE512A3C82EE0DCC2643C78EEA8FCACD35492558486B20F1C9EC197C90699850260C93BCBCD9C5C3317E19344E173AE36",
+            """
+MIIBqjCCARagAwIBAgIBCzAKBggqhQMHAQEDAzASMRAwDgYDVQQDEwdFeGFtcGxl
+MCAXDTAxMDEwMTAwMDAwMFoYDzIwNTAxMjMxMDAwMDAwWjASMRAwDgYDVQQDEwdF
+eGFtcGxlMIGgMBcGCCqFAwcBAQECMAsGCSqFAwcBAgECAAOBhAAEgYDh7zDVLGEz
+3dmdHVxBRVz3302LTJJbvGmvFDPRVlhRWt0hRoUMMlxbgcEzvmVaqMTUQOe5io1Z
+SHsMdpa8xV0R7L53NqnsNX/y/TmTH04RTLjNo1knCsfw5/9D2UGUGeph/Sq3f12f
+Y1I9O1CgT2PioM9Rt8E63CFWDwvUDMnHN6MTMBEwDwYDVR0TAQH/BAUwAwEB/zAK
+BggqhQMHAQEDAwOBgQBBVwPYkvGl8/aMQ1MYmn7iB7gLVjHvnUlSmk1rVCws+hWq
+LqzxH0cP3n2VSFaQPDX9j5Ve8wDZXHdTSnJKDu5wL4b6YKCBCRoj3XleHjxonuUS
+o8gu4NzCZDx47qj8rNNUklWEhrIPHJ7Bl8kGmYUCYMk7y82cXDMX4ZNE4XOuNg==
+            """,
+            "3A13FB7AECDB5560EEF6137CFC5DD64691732EBFB3690A1FC0C7E8A4EEEA08307D648D4DC0986C46A87B3FBE4C7AF42EA34359C795954CA39FF3ABBED9051F4D2F86FA60A081091A23DD795E1E3C689EE512A3C82EE0DCC2643C78EEA8FCACD35492558486B20F1C9EC197C90699850260C93BCBCD9C5C3317E19344E173AE36",
+            """
+MIHTMEECAQEwCgYIKoUDBwEBAwMwEjEQMA4GA1UEAxMHRXhhbXBsZRcNMTQwMTAx
+MDAwMDAwWhcNMTQwMTAyMDAwMDAwWjAKBggqhQMHAQEDAwOBgQA6E/t67NtVYO72
+E3z8XdZGkXMuv7NpCh/Ax+ik7uoIMH1kjU3AmGxGqHs/vkx69C6jQ1nHlZVMo5/z
+q77ZBR9NL4b6YKCBCRoj3XleHjxonuUSo8gu4NzCZDx47qj8rNNUklWEhrIPHJ7B
+l8kGmYUCYMk7y82cXDMX4ZNE4XOuNg==
+            """,
+        )