]> Cypherpunks.ru repositories - pygost.git/blobdiff - pygost/gost3410.py
Reuse _pos method
[pygost.git] / pygost / gost3410.py
index c9b905e225ed06e63fb70c0c55f4f15b96934121..f1baa5834400a4c183efa65bd5d709033d32d6c5 100644 (file)
@@ -1,6 +1,6 @@
 # coding: utf-8
 # PyGOST -- Pure Python GOST cryptographic functions library
 # coding: utf-8
 # PyGOST -- Pure Python GOST cryptographic functions library
-# Copyright (C) 2015-2016 Sergey Matveev <stargrave@stargrave.org>
+# Copyright (C) 2015-2019 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
 #
 # 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
@@ -23,120 +23,38 @@ key, digest and signature lengths.
 
 from os import urandom
 
 
 from os import urandom
 
-from pygost.gost3411_94 import GOST341194
 from pygost.utils import bytes2long
 from pygost.utils import hexdec
 from pygost.utils import long2bytes
 from pygost.utils import modinvert
 
 
 from pygost.utils import bytes2long
 from pygost.utils import hexdec
 from pygost.utils import long2bytes
 from pygost.utils import modinvert
 
 
-SIZE_3410_2001 = 32
-SIZE_3410_2012 = 64
-
-
-DEFAULT_CURVE = "GostR3410_2001_CryptoPro_A_ParamSet"
-# Curve parameters are the following: p, q, a, b, x, y
-CURVE_PARAMS = {
-    "GostR3410_2001_ParamSet_cc": (
-        "C0000000000000000000000000000000000000000000000000000000000003C7",
-        "5fffffffffffffffffffffffffffffff606117a2f4bde428b7458a54b6e87b85",
-        "C0000000000000000000000000000000000000000000000000000000000003c4",
-        "2d06B4265ebc749ff7d0f1f1f88232e81632e9088fd44b7787d5e407e955080c",
-        "0000000000000000000000000000000000000000000000000000000000000002",
-        "a20e034bf8813ef5c18d01105e726a17eb248b264ae9706f440bedc8ccb6b22c",
-    ),
-    "GostR3410_2001_TestParamSet": (
-        "8000000000000000000000000000000000000000000000000000000000000431",
-        "8000000000000000000000000000000150FE8A1892976154C59CFC193ACCF5B3",
-        "0000000000000000000000000000000000000000000000000000000000000007",
-        "5FBFF498AA938CE739B8E022FBAFEF40563F6E6A3472FC2A514C0CE9DAE23B7E",
-        "0000000000000000000000000000000000000000000000000000000000000002",
-        "08E2A8A0E65147D4BD6316030E16D19C85C97F0A9CA267122B96ABBCEA7E8FC8",
-    ),
-    "GostR3410_2001_CryptoPro_A_ParamSet": (
-        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD97",
-        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C611070995AD10045841B09B761B893",
-        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD94",
-        "00000000000000000000000000000000000000000000000000000000000000a6",
-        "0000000000000000000000000000000000000000000000000000000000000001",
-        "8D91E471E0989CDA27DF505A453F2B7635294F2DDF23E3B122ACC99C9E9F1E14",
-    ),
-    "GostR3410_2001_CryptoPro_B_ParamSet": (
-        "8000000000000000000000000000000000000000000000000000000000000C99",
-        "800000000000000000000000000000015F700CFFF1A624E5E497161BCC8A198F",
-        "8000000000000000000000000000000000000000000000000000000000000C96",
-        "3E1AF419A269A5F866A7D3C25C3DF80AE979259373FF2B182F49D4CE7E1BBC8B",
-        "0000000000000000000000000000000000000000000000000000000000000001",
-        "3FA8124359F96680B83D1C3EB2C070E5C545C9858D03ECFB744BF8D717717EFC",
-    ),
-    "GostR3410_2001_CryptoPro_C_ParamSet": (
-        "9B9F605F5A858107AB1EC85E6B41C8AACF846E86789051D37998F7B9022D759B",
-        "9B9F605F5A858107AB1EC85E6B41C8AA582CA3511EDDFB74F02F3A6598980BB9",
-        "9B9F605F5A858107AB1EC85E6B41C8AACF846E86789051D37998F7B9022D7598",
-        "000000000000000000000000000000000000000000000000000000000000805a",
-        "0000000000000000000000000000000000000000000000000000000000000000",
-        "41ECE55743711A8C3CBF3783CD08C0EE4D4DC440D4641A8F366E550DFDB3BB67",
-    ),
-    "GostR3410_2001_CryptoPro_XchA_ParamSet": (
-        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD97",
-        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C611070995AD10045841B09B761B893",
-        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD94",
-        "00000000000000000000000000000000000000000000000000000000000000a6",
-        "0000000000000000000000000000000000000000000000000000000000000001",
-        "8D91E471E0989CDA27DF505A453F2B7635294F2DDF23E3B122ACC99C9E9F1E14",
-    ),
-    "GostR3410_2001_CryptoPro_XchB_ParamSet": (
-        "9B9F605F5A858107AB1EC85E6B41C8AACF846E86789051D37998F7B9022D759B",
-        "9B9F605F5A858107AB1EC85E6B41C8AA582CA3511EDDFB74F02F3A6598980BB9",
-        "9B9F605F5A858107AB1EC85E6B41C8AACF846E86789051D37998F7B9022D7598",
-        "000000000000000000000000000000000000000000000000000000000000805a",
-        "0000000000000000000000000000000000000000000000000000000000000000",
-        "41ECE55743711A8C3CBF3783CD08C0EE4D4DC440D4641A8F366E550DFDB3BB67",
-    ),
-    "GostR3410_2012_TC26_ParamSetA": (
-        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC7",
-        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF27E69532F48D89116FF22B8D4E0560609B4B38ABFAD2B85DCACDB1411F10B275",
-        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC4",
-        "E8C2505DEDFC86DDC1BD0B2B6667F1DA34B82574761CB0E879BD081CFD0B6265EE3CB090F30D27614CB4574010DA90DD862EF9D4EBEE4761503190785A71C760",
-        "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003",
-        "7503CFE87A836AE3A61B8816E25450E6CE5E1C93ACF1ABC1778064FDCBEFA921DF1626BE4FD036E93D75E6A50E3A41E98028FE5FC235F5B889A589CB5215F2A4",
-    ),
-    "GostR3410_2012_TC26_ParamSetB": (
-        "8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006F",
-        "800000000000000000000000000000000000000000000000000000000000000149A1EC142565A545ACFDB77BD9D40CFA8B996712101BEA0EC6346C54374F25BD",
-        "8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006C",
-        "687D1B459DC841457E3E06CF6F5E2517B97C7D614AF138BCBF85DC806C4B289F3E965D2DB1416D217F8B276FAD1AB69C50F78BEE1FA3106EFB8CCBC7C5140116",
-        "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002",
-        "1A8F7EDA389B094C2C071E3647A8940F3C123B697578C213BE6DD9E6C8EC7335DCB228FD1EDF4A39152CBCAAF8C0398828041055F94CEEEC7E21340780FE41BD"
-    ),
+MODE2SIZE = {
+    2001: 32,
+    2012: 64,
 }
 }
-for c, params in CURVE_PARAMS.items():
-    CURVE_PARAMS[c] = [hexdec(param) for param in params]
 
 
 class GOST3410Curve(object):
     """ GOST 34.10 validated curve
 
 
 
 class GOST3410Curve(object):
     """ GOST 34.10 validated curve
 
-    >>> p, q, a, b, x, y = CURVE_PARAMS["GostR3410_2001_TestParamSet"]
-    >>> curve = GOST3410Curve(p, q, a, b, x, y)
-    >>> priv = bytes2long(urandom(32))
-    >>> signature = sign(curve, priv, GOST341194(data).digest())
-    >>> pubX, pubY = public_key(curve, priv)
-    >>> verify(curve, pubX, pubY, GOST341194(data).digest(), signature)
+    >>> curve = CURVES["id-GostR3410-2001-TestParamSet"]
+    >>> prv = prv_unmarshal(urandom(32))
+    >>> signature = sign(curve, prv, GOST341194(data).digest())
+    >>> pub = public_key(curve, prv)
+    >>> verify(curve, pub, GOST341194(data).digest(), signature)
     True
     """
     def __init__(self, p, q, a, b, x, y):
     True
     """
     def __init__(self, p, q, a, b, x, y):
-        self.p = bytes2long(p)
-        self.q = bytes2long(q)
-        self.a = bytes2long(a)
-        self.b = bytes2long(b)
-        self.x = bytes2long(x)
-        self.y = bytes2long(y)
+        self.p = p
+        self.q = q
+        self.a = a
+        self.b = b
+        self.x = x
+        self.y = y
         r1 = self.y * self.y % self.p
         r2 = ((self.x * self.x + self.a) * self.x + self.b) % self.p
         r1 = self.y * self.y % self.p
         r2 = ((self.x * self.x + self.a) * self.x + self.b) % self.p
-        if r2 < 0:
-            r2 += self.p
-        if r1 != r2:
+        if r1 != self._pos(r2):
             raise ValueError("Invalid parameters")
 
     def _pos(self, v):
             raise ValueError("Invalid parameters")
 
     def _pos(self, v):
@@ -161,9 +79,9 @@ class GOST3410Curve(object):
         y = y or self.y
         tx = x
         ty = y
         y = y or self.y
         tx = x
         ty = y
-        degree -= 1
         if degree == 0:
             raise ValueError("Bad degree value")
         if degree == 0:
             raise ValueError("Bad degree value")
+        degree -= 1
         while degree != 0:
             if degree & 1 == 1:
                 tx, ty = self._add(tx, ty, x, y)
         while degree != 0:
             if degree & 1 == 1:
                 tx, ty = self._add(tx, ty, x, y)
@@ -172,55 +90,121 @@ class GOST3410Curve(object):
         return tx, ty
 
 
         return tx, ty
 
 
-def public_key(curve, private_key):
-    """ Generate public key from the private one
-
-    :param GOST3410Curve curve: curve to use
-    :param long private_key: private key
-    :return: public key's parts, X and Y
-    :rtype: (long, long)
-    """
-    return curve.exp(private_key)
+CURVES = {
+    "GostR3410_2001_ParamSet_cc": GOST3410Curve(
+        p=bytes2long(hexdec("C0000000000000000000000000000000000000000000000000000000000003C7")),
+        q=bytes2long(hexdec("5fffffffffffffffffffffffffffffff606117a2f4bde428b7458a54b6e87b85")),
+        a=bytes2long(hexdec("C0000000000000000000000000000000000000000000000000000000000003c4")),
+        b=bytes2long(hexdec("2d06B4265ebc749ff7d0f1f1f88232e81632e9088fd44b7787d5e407e955080c")),
+        x=bytes2long(hexdec("0000000000000000000000000000000000000000000000000000000000000002")),
+        y=bytes2long(hexdec("a20e034bf8813ef5c18d01105e726a17eb248b264ae9706f440bedc8ccb6b22c")),
+    ),
+    "id-GostR3410-2001-TestParamSet": GOST3410Curve(
+        p=bytes2long(hexdec("8000000000000000000000000000000000000000000000000000000000000431")),
+        q=bytes2long(hexdec("8000000000000000000000000000000150FE8A1892976154C59CFC193ACCF5B3")),
+        a=bytes2long(hexdec("0000000000000000000000000000000000000000000000000000000000000007")),
+        b=bytes2long(hexdec("5FBFF498AA938CE739B8E022FBAFEF40563F6E6A3472FC2A514C0CE9DAE23B7E")),
+        x=bytes2long(hexdec("0000000000000000000000000000000000000000000000000000000000000002")),
+        y=bytes2long(hexdec("08E2A8A0E65147D4BD6316030E16D19C85C97F0A9CA267122B96ABBCEA7E8FC8")),
+    ),
+    "id-GostR3410-2001-CryptoPro-A-ParamSet": GOST3410Curve(
+        p=bytes2long(hexdec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD97")),
+        q=bytes2long(hexdec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C611070995AD10045841B09B761B893")),
+        a=bytes2long(hexdec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD94")),
+        b=bytes2long(hexdec("00000000000000000000000000000000000000000000000000000000000000a6")),
+        x=bytes2long(hexdec("0000000000000000000000000000000000000000000000000000000000000001")),
+        y=bytes2long(hexdec("8D91E471E0989CDA27DF505A453F2B7635294F2DDF23E3B122ACC99C9E9F1E14")),
+    ),
+    "id-GostR3410-2001-CryptoPro-B-ParamSet": GOST3410Curve(
+        p=bytes2long(hexdec("8000000000000000000000000000000000000000000000000000000000000C99")),
+        q=bytes2long(hexdec("800000000000000000000000000000015F700CFFF1A624E5E497161BCC8A198F")),
+        a=bytes2long(hexdec("8000000000000000000000000000000000000000000000000000000000000C96")),
+        b=bytes2long(hexdec("3E1AF419A269A5F866A7D3C25C3DF80AE979259373FF2B182F49D4CE7E1BBC8B")),
+        x=bytes2long(hexdec("0000000000000000000000000000000000000000000000000000000000000001")),
+        y=bytes2long(hexdec("3FA8124359F96680B83D1C3EB2C070E5C545C9858D03ECFB744BF8D717717EFC")),
+    ),
+    "id-GostR3410-2001-CryptoPro-C-ParamSet": GOST3410Curve(
+        p=bytes2long(hexdec("9B9F605F5A858107AB1EC85E6B41C8AACF846E86789051D37998F7B9022D759B")),
+        q=bytes2long(hexdec("9B9F605F5A858107AB1EC85E6B41C8AA582CA3511EDDFB74F02F3A6598980BB9")),
+        a=bytes2long(hexdec("9B9F605F5A858107AB1EC85E6B41C8AACF846E86789051D37998F7B9022D7598")),
+        b=bytes2long(hexdec("000000000000000000000000000000000000000000000000000000000000805a")),
+        x=bytes2long(hexdec("0000000000000000000000000000000000000000000000000000000000000000")),
+        y=bytes2long(hexdec("41ECE55743711A8C3CBF3783CD08C0EE4D4DC440D4641A8F366E550DFDB3BB67")),
+    ),
+    "id-GostR3410-2001-CryptoPro-XchA-ParamSet": GOST3410Curve(
+        p=bytes2long(hexdec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD97")),
+        q=bytes2long(hexdec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C611070995AD10045841B09B761B893")),
+        a=bytes2long(hexdec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD94")),
+        b=bytes2long(hexdec("00000000000000000000000000000000000000000000000000000000000000a6")),
+        x=bytes2long(hexdec("0000000000000000000000000000000000000000000000000000000000000001")),
+        y=bytes2long(hexdec("8D91E471E0989CDA27DF505A453F2B7635294F2DDF23E3B122ACC99C9E9F1E14")),
+    ),
+    "id-GostR3410-2001-CryptoPro-XchB-ParamSet": GOST3410Curve(
+        p=bytes2long(hexdec("9B9F605F5A858107AB1EC85E6B41C8AACF846E86789051D37998F7B9022D759B")),
+        q=bytes2long(hexdec("9B9F605F5A858107AB1EC85E6B41C8AA582CA3511EDDFB74F02F3A6598980BB9")),
+        a=bytes2long(hexdec("9B9F605F5A858107AB1EC85E6B41C8AACF846E86789051D37998F7B9022D7598")),
+        b=bytes2long(hexdec("000000000000000000000000000000000000000000000000000000000000805a")),
+        x=bytes2long(hexdec("0000000000000000000000000000000000000000000000000000000000000000")),
+        y=bytes2long(hexdec("41ECE55743711A8C3CBF3783CD08C0EE4D4DC440D4641A8F366E550DFDB3BB67")),
+    ),
+    "id-tc26-gost-3410-2012-256-paramSetA": GOST3410Curve(
+        p=bytes2long(hexdec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD97")),
+        q=bytes2long(hexdec("400000000000000000000000000000000FD8CDDFC87B6635C115AF556C360C67")),
+        a=bytes2long(hexdec("C2173F1513981673AF4892C23035A27CE25E2013BF95AA33B22C656F277E7335")),
+        b=bytes2long(hexdec("295F9BAE7428ED9CCC20E7C359A9D41A22FCCD9108E17BF7BA9337A6F8AE9513")),
+        x=bytes2long(hexdec("91E38443A5E82C0D880923425712B2BB658B9196932E02C78B2582FE742DAA28")),
+        y=bytes2long(hexdec("32879423AB1A0375895786C4BB46E9565FDE0B5344766740AF268ADB32322E5C")),
+    ),
+    "id-tc26-gost-3410-12-512-paramSetA": GOST3410Curve(
+        p=bytes2long(hexdec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC7")),
+        q=bytes2long(hexdec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF27E69532F48D89116FF22B8D4E0560609B4B38ABFAD2B85DCACDB1411F10B275")),
+        a=bytes2long(hexdec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC4")),
+        b=bytes2long(hexdec("E8C2505DEDFC86DDC1BD0B2B6667F1DA34B82574761CB0E879BD081CFD0B6265EE3CB090F30D27614CB4574010DA90DD862EF9D4EBEE4761503190785A71C760")),
+        x=bytes2long(hexdec("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003")),
+        y=bytes2long(hexdec("7503CFE87A836AE3A61B8816E25450E6CE5E1C93ACF1ABC1778064FDCBEFA921DF1626BE4FD036E93D75E6A50E3A41E98028FE5FC235F5B889A589CB5215F2A4")),
+    ),
+    "id-tc26-gost-3410-12-512-paramSetB": GOST3410Curve(
+        p=bytes2long(hexdec("8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006F")),
+        q=bytes2long(hexdec("800000000000000000000000000000000000000000000000000000000000000149A1EC142565A545ACFDB77BD9D40CFA8B996712101BEA0EC6346C54374F25BD")),
+        a=bytes2long(hexdec("8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006C")),
+        b=bytes2long(hexdec("687D1B459DC841457E3E06CF6F5E2517B97C7D614AF138BCBF85DC806C4B289F3E965D2DB1416D217F8B276FAD1AB69C50F78BEE1FA3106EFB8CCBC7C5140116")),
+        x=bytes2long(hexdec("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002")),
+        y=bytes2long(hexdec("1A8F7EDA389B094C2C071E3647A8940F3C123B697578C213BE6DD9E6C8EC7335DCB228FD1EDF4A39152CBCAAF8C0398828041055F94CEEEC7E21340780FE41BD")),
+    ),
+    "id-tc26-gost-3410-2012-512-paramSetC": GOST3410Curve(
+        p=bytes2long(hexdec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC7")),
+        q=bytes2long(hexdec("3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC98CDBA46506AB004C33A9FF5147502CC8EDA9E7A769A12694623CEF47F023ED")),
+        a=bytes2long(hexdec("DC9203E514A721875485A529D2C722FB187BC8980EB866644DE41C68E143064546E861C0E2C9EDD92ADE71F46FCF50FF2AD97F951FDA9F2A2EB6546F39689BD3")),
+        b=bytes2long(hexdec("B4C4EE28CEBC6C2C8AC12952CF37F16AC7EFB6A9F69F4B57FFDA2E4F0DE5ADE038CBC2FFF719D2C18DE0284B8BFEF3B52B8CC7A5F5BF0A3C8D2319A5312557E1")),
+        x=bytes2long(hexdec("E2E31EDFC23DE7BDEBE241CE593EF5DE2295B7A9CBAEF021D385F7074CEA043AA27272A7AE602BF2A7B9033DB9ED3610C6FB85487EAE97AAC5BC7928C1950148")),
+        y=bytes2long(hexdec("F5CE40D95B5EB899ABBCCFF5911CB8577939804D6527378B8C108C3D2090FF9BE18E2D33E3021ED2EF32D85822423B6304F726AA854BAE07D0396E9A9ADDC40F")),
+    ),
+}
+DEFAULT_CURVE = CURVES["id-GostR3410-2001-CryptoPro-A-ParamSet"]
 
 
 
 
-def kek(curve, private_key, ukm, pubkey):
-    """ Make Diffie-Hellman computation
+def public_key(curve, prv):
+    """ Generate public key from the private one
 
     :param GOST3410Curve curve: curve to use
 
     :param GOST3410Curve curve: curve to use
-    :param long private_key: private key
-    :param ukm: UKM value (VKO-factor)
-    :type ukm: bytes, 8 bytes
-    :param pubkey: public key's part
-    :type pubkey: (long, long)
-    :return: Key Encryption Key (shared key)
-    :rtype: bytes, 32 bytes
-
-    Shared Key Encryption Key computation is based on
-    :rfc:`4357` VKO GOST 34.10-2001 with little-endian
-    hash output.
+    :param long prv: private key
+    :returns: public key's parts, X and Y
+    :rtype: (long, long)
     """
     """
-    key = curve.exp(private_key, pubkey[0], pubkey[1])
-    key = curve.exp(bytes2long(24 * b"\x00" + ukm), key[0], key[1])
-    return GOST341194(
-        (long2bytes(key[1]) + long2bytes(key[0]))[::-1],
-        "GostR3411_94_CryptoProParamSet"
-    ).digest()[::-1]
+    return curve.exp(prv)
 
 
 
 
-def sign(curve, private_key, digest, size=SIZE_3410_2001):
+def sign(curve, prv, digest, mode=2001):
     """ Calculate signature for provided digest
 
     :param GOST3410Curve curve: curve to use
     """ Calculate signature for provided digest
 
     :param GOST3410Curve curve: curve to use
-    :param long private_key: private key
+    :param long prv: private key
     :param digest: digest for signing
     :param digest: digest for signing
-    :type digest: bytes, 32 bytes
-    :param size: signature size
-    :type size: 32 (for 34.10-2001) or 64 (for 34.10-2012)
-    :return: signature
-    :rtype: bytes, 64 bytes
+    :type digest: bytes, 32 or 64 bytes
+    :returns: signature
+    :rtype: bytes, 64 or 128 bytes
     """
     """
-    if len(digest) != size:
-        raise ValueError("Invalid digest length")
+    size = MODE2SIZE[mode]
     q = curve.q
     e = bytes2long(digest) % q
     if e == 0:
     q = curve.q
     e = bytes2long(digest) % q
     if e == 0:
@@ -233,7 +217,7 @@ def sign(curve, private_key, digest, size=SIZE_3410_2001):
         r %= q
         if r == 0:
             continue
         r %= q
         if r == 0:
             continue
-        d = private_key * r
+        d = prv * r
         k *= e
         s = (d + k) % q
         if s == 0:
         k *= e
         s = (d + k) % q
         if s == 0:
@@ -242,22 +226,18 @@ def sign(curve, private_key, digest, size=SIZE_3410_2001):
     return long2bytes(s, size) + long2bytes(r, size)
 
 
     return long2bytes(s, size) + long2bytes(r, size)
 
 
-def verify(curve, pubkeyX, pubkeyY, digest, signature, size=SIZE_3410_2001):
+def verify(curve, pub, digest, signature, mode=2001):
     """ Verify provided digest with the signature
 
     :param GOST3410Curve curve: curve to use
     """ Verify provided digest with the signature
 
     :param GOST3410Curve curve: curve to use
-    :param long pubkeyX: public key's X
-    :param long pubkeyY: public key's Y
+    :type pub: (long, long)
     :param digest: digest needed to check
     :param digest: digest needed to check
-    :type digest: bytes, 32 bytes
+    :type digest: bytes, 32 or 64 bytes
     :param signature: signature to verify with
     :param signature: signature to verify with
-    :type signature: bytes, 64 bytes
-    :param size: signature size
-    :type size: 32 (for 34.10-2001) or 64 (for 34.10-2012)
+    :type signature: bytes, 64 or 128 bytes
     :rtype: bool
     """
     :rtype: bool
     """
-    if len(digest) != size:
-        raise ValueError("Invalid digest length")
+    size = MODE2SIZE[mode]
     if len(signature) != size * 2:
         raise ValueError("Invalid signature length")
     q = curve.q
     if len(signature) != size * 2:
         raise ValueError("Invalid signature length")
     q = curve.q
@@ -273,7 +253,7 @@ def verify(curve, pubkeyX, pubkeyY, digest, signature, size=SIZE_3410_2001):
     z1 = s * v % q
     z2 = q - r * v % q
     p1x, p1y = curve.exp(z1)
     z1 = s * v % q
     z2 = q - r * v % q
     p1x, p1y = curve.exp(z1)
-    q1x, q1y = curve.exp(z2, pubkeyX, pubkeyY)
+    q1x, q1y = curve.exp(z2, pub[0], pub[1])
     lm = q1x - p1x
     if lm < 0:
         lm += p
     lm = q1x - p1x
     if lm < 0:
         lm += p
@@ -288,3 +268,33 @@ def verify(curve, pubkeyX, pubkeyY, digest, signature, size=SIZE_3410_2001):
     lm %= q
     # This is not constant time comparison!
     return lm == r
     lm %= q
     # This is not constant time comparison!
     return lm == r
+
+
+def prv_unmarshal(prv):
+    """Unmarshal private key
+
+    :param bytes prv: serialized private key
+    :rtype: long
+    """
+    return bytes2long(prv[::-1])
+
+
+def pub_marshal(pub, mode=2001):
+    """Marshal public key
+
+    :type pub: (long, long)
+    :rtype: bytes
+    """
+    size = MODE2SIZE[mode]
+    return (long2bytes(pub[1], size) + long2bytes(pub[0], size))[::-1]
+
+
+def pub_unmarshal(pub, mode=2001):
+    """Unmarshal public key
+
+    :type pub: bytes
+    :rtype: (long, long)
+    """
+    size = MODE2SIZE[mode]
+    pub = pub[::-1]
+    return (bytes2long(pub[size:]), bytes2long(pub[:size]))