>>> data_for_signing = b"some data"
>>> dgst = gost34112012256.new(data_for_signing).digest()
>>> from pygost.gost3410 import sign
- >>> signature = sign(curve, prv, dgst, mode=2012)
+ >>> signature = sign(curve, prv, dgst)
>>> from pygost.gost3410 import verify
- >>> verify(curve, pub, dgst, signature, mode=2012)
+ >>> verify(curve, pub, dgst, signature)
True
Other examples can be found in docstrings and unittests.
@node Download
@unnumbered Download
-@set VERSION 4.9
+@set VERSION 5.0
No additional dependencies except Python 2.7/3.x interpreter are required.
@table @strong
+@anchor{Release 5.0}
+@item 5.0
+Backward incompatible removing of misleading and excess @option{mode}
+keyword argument from all @code{gost3410*} related functions. Point/key
+sizes are determined by looking at curve's parameters size.
+
@anchor{Release 4.9}
@item 4.9
@itemize
PyGOST is free software: see the file COPYING for copying conditions.
"""
-__version__ = "4.9"
+__version__ = "5.0"
prv = prv_unmarshal(prv_raw)
curve = CURVES["id-tc26-gost-3410-12-512-paramSetA"]
-pub_raw = pub_marshal(public_key(curve, prv), mode=2012)
+pub_raw = pub_marshal(public_key(curve, prv))
subj = Name(("rdnSequence", RDNSequence([
RelativeDistinguishedName((
AttributeTypeAndValue((
curve,
prv,
GOST34112012512(tbs.encode()).digest()[::-1],
- mode=2012,
))),
))
print("-----BEGIN CERTIFICATE-----")
from pygost.utils import modinvert
-MODE2SIZE = {
- 2001: 32,
- 2012: 64,
-}
+def point_size(point):
+ """Determine is it either 256 or 512 bit point
+ """
+ return (512 // 8) if point.bit_length() > 256 else (256 // 8)
class GOST3410Curve(object):
raise ValueError("Invalid parameters")
self._st = None
+ @property
+ def point_size(self):
+ return point_size(self.p)
+
def pos(self, v):
"""Make positive number
"""
return curve.exp(prv)
-def sign(curve, prv, digest, rand=None, mode=2001):
+def sign(curve, prv, digest, rand=None):
""" Calculate signature for provided digest
:param GOST3410Curve curve: curve to use
:returns: signature, BE(S) || BE(R)
:rtype: bytes, 64 or 128 bytes
"""
- size = MODE2SIZE[mode]
+ size = curve.point_size
q = curve.q
e = bytes2long(digest) % q
if e == 0:
return long2bytes(s, size) + long2bytes(r, size)
-def verify(curve, pub, digest, signature, mode=2001):
+def verify(curve, pub, digest, signature):
""" Verify provided digest with the signature
:param GOST3410Curve curve: curve to use
:type signature: bytes, 64 or 128 bytes
:rtype: bool
"""
- size = MODE2SIZE[mode]
+ size = curve.point_size
if len(signature) != size * 2:
raise ValueError("Invalid signature length")
q = curve.q
return bytes2long(prv[::-1])
-def pub_marshal(pub, mode=2001):
+def pub_marshal(pub):
"""Marshal public key
:type pub: (long, long)
:rtype: bytes
:returns: LE(X) || LE(Y)
"""
- size = MODE2SIZE[mode]
+ size = point_size(pub[0])
return (long2bytes(pub[1], size) + long2bytes(pub[0], size))[::-1]
-def pub_unmarshal(pub, mode=2001):
+def pub_unmarshal(pub):
"""Unmarshal public key
:param pub: LE(X) || LE(Y)
:type pub: bytes
:rtype: (long, long)
"""
- size = MODE2SIZE[mode]
+ size = len(pub) // 2
pub = pub[::-1]
return (bytes2long(pub[size:]), bytes2long(pub[:size]))
return bytes2long(ukm[::-1])
-def kek(curve, prv, pub, ukm, mode):
+def kek(curve, prv, pub, ukm):
key = curve.exp(prv, pub[0], pub[1])
key = curve.exp(curve.cofactor * ukm, key[0], key[1])
- return pub_marshal(key, mode)
+ return pub_marshal(key)
def kek_34102001(curve, prv, pub, ukm):
hash output.
"""
return GOST341194(
- kek(curve, prv, pub, ukm, mode=2001),
+ kek(curve, prv, pub, ukm),
sbox="id-GostR3411-94-CryptoProParamSet",
).digest()
-def kek_34102012256(curve, prv, pub, ukm=1, mode=2012):
+def kek_34102012256(curve, prv, pub, ukm=1):
""" Key agreement (34.10-2012, 34.11-2012 256 bit)
:param GOST3410Curve curve: curve to use
Shared Key Encryption Key computation is based on
:rfc:`7836` VKO GOST R 34.10-2012.
"""
- return GOST34112012256(kek(curve, prv, pub, ukm, mode=mode)).digest()
+ return GOST34112012256(kek(curve, prv, pub, ukm)).digest()
def kek_34102012512(curve, prv, pub, ukm=1):
Shared Key Encryption Key computation is based on
:rfc:`7836` VKO GOST R 34.10-2012.
"""
- return GOST34112012512(kek(curve, prv, pub, ukm, mode=2012)).digest()
+ return GOST34112012512(kek(curve, prv, pub, ukm)).digest()
return keymat
-def keg(curve, prv, pub, h, mode=2001):
+def keg(curve, prv, pub, h):
"""Export key generation (Р 1323565.1.020-2018)
:param GOST3410Curve curve: curve to use
ukm = bytes2long(h[:16])
if ukm == 0:
ukm = 1
- if mode == 2012:
+ if curve.point_size == 64:
return kek_34102012512(curve, prv, pub, ukm)
- k_exp = kek_34102012256(curve, prv, pub, ukm, mode=2001)
+ k_exp = kek_34102012256(curve, prv, pub, ukm)
return b"".join(kdf_tree_gostr3411_2012_256(k_exp, b"kdf tree", h[16:24], 2))
def public_key(curve: GOST3410Curve, prv: int) -> PublicKey: ...
-def sign(
- curve: GOST3410Curve,
- prv: int,
- digest: bytes,
- rand: bytes=None,
- mode: int=...,
-) -> bytes: ...
+def sign(curve: GOST3410Curve, prv: int, digest: bytes, rand: bytes=None) -> bytes: ...
-def verify(
- curve: GOST3410Curve,
- pub: PublicKey,
- digest: bytes,
- signature: bytes,
- mode: int=...,
-) -> bool: ...
+def verify(curve: GOST3410Curve, pub: PublicKey, digest: bytes, signature: bytes) -> bool: ...
def prv_unmarshal(prv: bytes) -> int: ...
-def pub_marshal(pub: PublicKey, mode: int=...) -> bytes: ...
+def pub_marshal(pub: PublicKey) -> bytes: ...
-def pub_unmarshal(pub: bytes, mode: int=...) -> PublicKey: ...
+def pub_unmarshal(pub: bytes) -> PublicKey: ...
def uv2xy(curve: GOST3410Curve, u: int, v: int) -> Tuple[int, int]: ...
def kek_34102001(curve: GOST3410Curve, prv: int, pub: PublicKey, ukm: int) -> bytes: ...
-def kek_34102012256(curve: GOST3410Curve, prv: int, pub: PublicKey, ukm: int=..., mode: int=...) -> bytes: ...
+def kek_34102012256(curve: GOST3410Curve, prv: int, pub: PublicKey, ukm: int=...) -> bytes: ...
def kek_34102012512(curve: GOST3410Curve, prv: int, pub: PublicKey, ukm: int=...) -> bytes: ...
) -> Sequence[bytes]: ...
-def keg(curve: GOST3410Curve, prv: int, pub: PublicKey, h: bytes, mode=2001) -> bytes: ...
+def keg(curve: GOST3410Curve, prv: int, pub: PublicKey, h: bytes) -> bytes: ...
prv_key_raw,
curve_name,
hasher,
- mode,
):
content_info, tail = ContentInfo().decode(content_info_raw)
self.assertSequenceEqual(tail, b"")
public_key(curve, prv_unmarshal(prv_key_raw)),
hasher(bytes(signed_data["encapContentInfo"]["eContent"])).digest()[::-1],
bytes(signed_data["signerInfos"][0]["signature"]),
- mode=mode,
))
def test_256(self):
prv_key_raw,
"id-GostR3410-2001-CryptoPro-XchA-ParamSet",
GOST34112012256,
- 2001,
)
def test_512(self):
prv_key_raw,
"id-tc26-gost-3410-12-512-paramSetB",
GOST34112012512,
- 2012,
)
prv_unmarshal(prv),
pub_unmarshal(pub),
ukm_unmarshal(ukm),
- mode=2001,
)
self.process_cms(
return kek_34102012256(
curve,
prv_unmarshal(prv),
- pub_unmarshal(pub, mode=2012),
+ pub_unmarshal(pub),
ukm_unmarshal(ukm),
)
prv_unmarshal(prv),
pub_unmarshal(pub),
ukm_unmarshal(ukm),
- mode=2001,
)
self.process_cms(
return kek_34102012256(
curve,
prv_unmarshal(prv),
- pub_unmarshal(pub, mode=2012),
+ pub_unmarshal(pub),
ukm_unmarshal(ukm),
)
def test_certs(self):
"""Certificates signatures
"""
- for prv, pub, curve, mode, cert in (
- (self.ca_prv, self.ca_pub, self.curve256, 2001, self.ca_cert),
- (self.sender256_prv, self.sender256_pub, self.curve256, 2001, self.sender256_cert),
- (self.recipient256_prv, self.recipient256_pub, self.curve256, 2001, self.recipient256_cert),
- (self.sender512_prv, self.sender512_pub, self.curve512, 2012, self.sender512_cert),
- (self.recipient512_prv, self.recipient512_pub, self.curve512, 2012, self.recipient512_cert),
+ for prv, pub, curve, cert in (
+ (self.ca_prv, self.ca_pub, self.curve256, self.ca_cert),
+ (self.sender256_prv, self.sender256_pub, self.curve256, self.sender256_cert),
+ (self.recipient256_prv, self.recipient256_pub, self.curve256, self.recipient256_cert),
+ (self.sender512_prv, self.sender512_pub, self.curve512, self.sender512_cert),
+ (self.recipient512_prv, self.recipient512_pub, self.curve512, self.recipient512_cert),
):
pub_our = public_key(curve, prv)
self.assertEqual(pub_our, pub)
self.assertSequenceEqual(
- pub_marshal(pub_our, mode=mode),
+ pub_marshal(pub_our),
bytes(OctetString().decod(bytes(
cert["tbsCertificate"]["subjectPublicKeyInfo"]["subjectPublicKey"]
))),
self.ca_pub,
GOST34112012256(cert["tbsCertificate"].encode()).digest()[::-1],
bytes(cert["signatureValue"]),
- mode=2001,
))
def test_signed_with_attrs(self):
SignedAttributes(si["signedAttrs"]).encode()
).digest()[::-1],
bytes(si["signature"]),
- mode=2012,
))
def test_signed_without_attrs(self):
self.sender256_pub,
GOST34112012256(content).digest()[::-1],
bytes(si["signature"]),
- mode=2001,
))
def test_kari_ephemeral(self):
)
orig_pub = pub_unmarshal(
bytes(OctetString().decod(bytes(orig_key["publicKey"]))),
- mode=2012,
)
ukm = bytes(kari["ukm"])
self.assertEqual(
id_tc26_agreement_gost3410_2012_512,
)
kexp = bytes(kari["recipientEncryptedKeys"][0]["encryptedKey"])
- keymat = keg(self.curve512, self.recipient512_prv, orig_pub, ukm, mode=2012)
+ keymat = keg(self.curve512, self.recipient512_prv, orig_pub, ukm)
kim, kek = keymat[:KEYSIZE], keymat[KEYSIZE:]
cek = kimp15(
GOST3412Kuznechik(kek).encrypt,
self.recipient256_prv,
self.sender256_pub,
ukm,
- mode=2001,
)
kim, kek = keymat[:KEYSIZE], keymat[KEYSIZE:]
cek = kimp15(
)
pub = pub_unmarshal(bytes(OctetString().decod(
bytes(encrypted_key["ephemeralPublicKey"]["subjectPublicKey"])
- )), mode=2001)
+ )))
ukm = bytes(encrypted_key["ukm"])
kexp = bytes(encrypted_key["encryptedKey"])
- keymat = keg(self.curve256, self.recipient256_prv, pub, ukm, mode=2001)
+ keymat = keg(self.curve256, self.recipient256_prv, pub, ukm)
kim, kek = keymat[:KEYSIZE], keymat[KEYSIZE:]
cek = kimp15(
GOST3412Kuznechik(kek).encrypt,
bytes(OctetString().decod(
bytes(encrypted_key["ephemeralPublicKey"]["subjectPublicKey"])
)),
- mode=2012,
)
ukm = bytes(encrypted_key["ukm"])
kexp = bytes(encrypted_key["encryptedKey"])
- keymat = keg(self.curve512, self.recipient512_prv, pub, ukm, mode=2012)
+ keymat = keg(self.curve512, self.recipient512_prv, pub, ukm)
kim, kek = keymat[:KEYSIZE], keymat[KEYSIZE:]
cek = kimp15(
GOST3412Magma(kek).encrypt,
pubX, pubY = public_key(c, prv)
for _ in range(20):
digest = urandom(32)
- s = sign(c, prv, digest, mode=2001)
- self.assertTrue(verify(c, (pubX, pubY), digest, s, mode=2001))
+ s = sign(c, prv, digest)
+ self.assertTrue(verify(c, (pubX, pubY), digest, s))
class Test34102012(TestCase):
prv = bytes2long(hexdec("0BA6048AADAE241BA40936D47756D7C93091A0E8514669700EE7508E508B102072E8123B2200A0563322DAD2827E2714A2636B7BFD18AADFC62967821FA18DD4"))
digest = hexdec("3754F3CFACC9E0615C4F4A7C4D8DAB531B09B6F9C170C533A71D147035B0C5917184EE536593F4414339976C647C5D5A407ADEDB1D560C4FC6777D2972075B8C")
rand = hexdec("0359E7F4B1410FEACC570456C6801496946312120B39D019D455986E364F365886748ED7A44B3E794434006011842286212273A6D14CF70EA3AF71BB1AE679F1")
- signature = sign(curve, prv, digest, rand, mode=2012)
+ signature = sign(curve, prv, digest, rand)
r = "2f86fa60a081091a23dd795e1e3c689ee512a3c82ee0dcc2643c78eea8fcacd35492558486b20f1c9ec197c90699850260c93bcbcd9c5c3317e19344e173ae36"
s = "1081b394696ffe8e6585e7a9362d26b6325f56778aadbc081c0bfbe933d52ff5823ce288e8c4f362526080df7f70ce406a6eeb1f56919cb92a9853bde73e5b4a"
self.assertSequenceEqual(hexenc(signature), s + r)
pubX, pubY = public_key(c, prv)
self.assertSequenceEqual(long2bytes(pubX), pub_x)
self.assertSequenceEqual(long2bytes(pubY), pub_y)
- s = sign(c, prv, digest, mode=2012)
- self.assertTrue(verify(c, (pubX, pubY), digest, s, mode=2012))
- self.assertTrue(verify(c, (pubX, pubY), digest, signature, mode=2012))
+ s = sign(c, prv, digest)
+ self.assertTrue(verify(c, (pubX, pubY), digest, s))
+ self.assertTrue(verify(c, (pubX, pubY), digest, signature))
def test_sequence(self):
c = CURVES["id-tc26-gost-3410-12-512-paramSetA"]
pubX, pubY = public_key(c, prv)
for _ in range(20):
digest = urandom(64)
- s = sign(c, prv, digest, mode=2012)
- self.assertTrue(verify(c, (pubX, pubY), digest, s, mode=2012))
+ s = sign(c, prv, digest)
+ self.assertTrue(verify(c, (pubX, pubY), digest, s))
self.assertNotIn(b"\x00" * 8, s)
curve = CURVES["id-tc26-gost-3410-12-512-paramSetA"]
ukm = ukm_unmarshal(hexdec("1d80603c8544c727"))
prvA = prv_unmarshal(hexdec("c990ecd972fce84ec4db022778f50fcac726f46708384b8d458304962d7147f8c2db41cef22c90b102f2968404f9b9be6d47c79692d81826b32b8daca43cb667"))
- pubA = pub_unmarshal(hexdec("aab0eda4abff21208d18799fb9a8556654ba783070eba10cb9abb253ec56dcf5d3ccba6192e464e6e5bcb6dea137792f2431f6c897eb1b3c0cc14327b1adc0a7914613a3074e363aedb204d38d3563971bd8758e878c9db11403721b48002d38461f92472d40ea92f9958c0ffa4c93756401b97f89fdbe0b5e46e4a4631cdb5a"), mode=2012)
+ pubA = pub_unmarshal(hexdec("aab0eda4abff21208d18799fb9a8556654ba783070eba10cb9abb253ec56dcf5d3ccba6192e464e6e5bcb6dea137792f2431f6c897eb1b3c0cc14327b1adc0a7914613a3074e363aedb204d38d3563971bd8758e878c9db11403721b48002d38461f92472d40ea92f9958c0ffa4c93756401b97f89fdbe0b5e46e4a4631cdb5a"))
prvB = prv_unmarshal(hexdec("48c859f7b6f11585887cc05ec6ef1390cfea739b1a18c0d4662293ef63b79e3b8014070b44918590b4b996acfea4edfbbbcccc8c06edd8bf5bda92a51392d0db"))
- pubB = pub_unmarshal(hexdec("192fe183b9713a077253c72c8735de2ea42a3dbc66ea317838b65fa32523cd5efca974eda7c863f4954d1147f1f2b25c395fce1c129175e876d132e94ed5a65104883b414c9b592ec4dc84826f07d0b6d9006dda176ce48c391e3f97d102e03bb598bf132a228a45f7201aba08fc524a2d77e43a362ab022ad4028f75bde3b79"), mode=2012)
+ pubB = pub_unmarshal(hexdec("192fe183b9713a077253c72c8735de2ea42a3dbc66ea317838b65fa32523cd5efca974eda7c863f4954d1147f1f2b25c395fce1c129175e876d132e94ed5a65104883b414c9b592ec4dc84826f07d0b6d9006dda176ce48c391e3f97d102e03bb598bf132a228a45f7201aba08fc524a2d77e43a362ab022ad4028f75bde3b79"))
vko = hexdec("c9a9a77320e2cc559ed72dce6f47e2192ccea95fa648670582c054c0ef36c221")
self.assertSequenceEqual(kek_34102012256(curve, prvA, pubB, ukm), vko)
self.assertSequenceEqual(kek_34102012256(curve, prvB, pubA, ukm), vko)
curve = CURVES["id-tc26-gost-3410-12-512-paramSetA"]
ukm = ukm_unmarshal(hexdec("1d80603c8544c727"))
prvA = prv_unmarshal(hexdec("c990ecd972fce84ec4db022778f50fcac726f46708384b8d458304962d7147f8c2db41cef22c90b102f2968404f9b9be6d47c79692d81826b32b8daca43cb667"))
- pubA = pub_unmarshal(hexdec("aab0eda4abff21208d18799fb9a8556654ba783070eba10cb9abb253ec56dcf5d3ccba6192e464e6e5bcb6dea137792f2431f6c897eb1b3c0cc14327b1adc0a7914613a3074e363aedb204d38d3563971bd8758e878c9db11403721b48002d38461f92472d40ea92f9958c0ffa4c93756401b97f89fdbe0b5e46e4a4631cdb5a"), mode=2012)
+ pubA = pub_unmarshal(hexdec("aab0eda4abff21208d18799fb9a8556654ba783070eba10cb9abb253ec56dcf5d3ccba6192e464e6e5bcb6dea137792f2431f6c897eb1b3c0cc14327b1adc0a7914613a3074e363aedb204d38d3563971bd8758e878c9db11403721b48002d38461f92472d40ea92f9958c0ffa4c93756401b97f89fdbe0b5e46e4a4631cdb5a"))
prvB = prv_unmarshal(hexdec("48c859f7b6f11585887cc05ec6ef1390cfea739b1a18c0d4662293ef63b79e3b8014070b44918590b4b996acfea4edfbbbcccc8c06edd8bf5bda92a51392d0db"))
- pubB = pub_unmarshal(hexdec("192fe183b9713a077253c72c8735de2ea42a3dbc66ea317838b65fa32523cd5efca974eda7c863f4954d1147f1f2b25c395fce1c129175e876d132e94ed5a65104883b414c9b592ec4dc84826f07d0b6d9006dda176ce48c391e3f97d102e03bb598bf132a228a45f7201aba08fc524a2d77e43a362ab022ad4028f75bde3b79"), mode=2012)
+ pubB = pub_unmarshal(hexdec("192fe183b9713a077253c72c8735de2ea42a3dbc66ea317838b65fa32523cd5efca974eda7c863f4954d1147f1f2b25c395fce1c129175e876d132e94ed5a65104883b414c9b592ec4dc84826f07d0b6d9006dda176ce48c391e3f97d102e03bb598bf132a228a45f7201aba08fc524a2d77e43a362ab022ad4028f75bde3b79"))
vko = hexdec("79f002a96940ce7bde3259a52e015297adaad84597a0d205b50e3e1719f97bfa7ee1d2661fa9979a5aa235b558a7e6d9f88f982dd63fc35a8ec0dd5e242d3bdf")
self.assertSequenceEqual(kek_34102012512(curve, prvA, pubB, ukm), vko)
self.assertSequenceEqual(kek_34102012512(curve, prvB, pubA, ukm), vko)
(TK26IOK.pdf)
"""
- def process_cert(self, curve_name, mode, hasher, prv_key_raw, cert_raw):
+ def process_cert(self, curve_name, hasher, prv_key_raw, cert_raw):
cert, tail = Certificate().decode(cert_raw, ctx={
"defines_by_path": (
(
spk = cert["tbsCertificate"]["subjectPublicKeyInfo"]["subjectPublicKey"]
self.assertIsNotNone(spk.defined)
_, pub_key_raw = spk.defined
- pub_key = pub_unmarshal(bytes(pub_key_raw), mode=mode)
+ pub_key = pub_unmarshal(bytes(pub_key_raw))
self.assertSequenceEqual(pub_key, public_key(curve, prv_key))
self.assertTrue(verify(
curve,
pub_key,
hasher(cert["tbsCertificate"].encode()).digest()[::-1],
bytes(cert["signatureValue"]),
- mode=mode,
))
def test_256(self):
prv_key_raw = hexdec("BFCF1D623E5CDD3032A7C6EABB4A923C46E43D640FFEAAF2C3ED39A8FA399924")[::-1]
self.process_cert(
"id-GostR3410-2001-CryptoPro-XchA-ParamSet",
- 2001,
GOST34112012256,
prv_key_raw,
cert_raw,
prv_key_raw = hexdec("3FC01CDCD4EC5F972EB482774C41E66DB7F380528DFE9E67992BA05AEE462435757530E641077CE587B976C8EEB48C48FD33FD175F0C7DE6A44E014E6BCB074B")[::-1]
self.process_cert(
"id-tc26-gost-3410-12-512-paramSetB",
- 2012,
GOST34112012512,
prv_key_raw,
cert_raw,
def _test_vector(
self,
curve_name,
- mode,
hsh,
ai_spki,
ai_sign,
prv = prv_unmarshal(prv_raw)
curve = CURVES[curve_name]
pub = public_key(curve, prv)
- pub_raw = pub_marshal(pub, mode=mode)
+ pub_raw = pub_marshal(pub)
subj = Name(("rdnSequence", RDNSequence([
RelativeDistinguishedName((
AttributeTypeAndValue((
pub,
hsh(cri.encode()).digest()[::-1],
sign,
- mode=mode,
))
cr = CertificationRequest((
("certificationRequestInfo", cri),
pub,
hsh(tbs.encode()).digest()[::-1],
sign,
- mode=mode,
))
cert = Certificate((
("tbsCertificate", tbs),
pub,
hsh(tbs.encode()).digest()[::-1],
sign,
- mode=mode,
))
crl = CertificateList((
("tbsCertList", tbs),
def test_256_test_paramset(self):
self._test_vector(
"id-GostR3410-2001-TestParamSet",
- 2001,
GOST34112012256,
AlgorithmIdentifier((
("algorithm", id_tc26_gost3410_2012_256),
def test_256a_paramset(self):
self._test_vector(
"id-tc26-gost-3410-2012-256-paramSetA",
- 2001,
GOST34112012256,
AlgorithmIdentifier((
("algorithm", id_tc26_gost3410_2012_256),
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),
>>> data_for_signing = b"some data"
>>> dgst = gost34112012256.new(data_for_signing).digest()[::-1]
>>> from pygost.gost3410 import sign
->>> signature = sign(curve, prv, dgst, mode=2012)
+>>> signature = sign(curve, prv, dgst)
>>> from pygost.gost3410 import verify
->>> verify(curve, pub, dgst, signature, mode=2012)
+>>> verify(curve, pub, dgst, signature)
True
@end example