def random(self) -> bytearray:
        """
        Generate the next value from a pseudo-random sequence.

        Return: new random value.

        Exception
        - GOSTRandomError ('exceeded the limit value of the counter'): when the
        counter limit is exceeded.
        - GOSTRandomError('the seed value is zero'): if the seed value is zero.
        """
        if bytearray_to_int(self._rand_u[:self._size_s]) == 0:
            raise GOSTRandomError('the seed value is zero')
        i = self._q
        result = bytearray(0)
        while i > 0:
            if bytearray_to_int(self._rand_u[self._size_s::]) >= self._limit:
                self._rand_u = zero_fill(self._rand_u)
                raise GOSTRandomError('exceeded the limit value of the counter')
            self._inc_rand_u()
            self._hash_obj.update(self._rand_u)
            rand_c = self._hash_obj.digest()
            self._hash_obj.reset()
            result = result + rand_c
            i = i - 1
        if self._r != 0:
            if bytearray_to_int(self._rand_u[self._size_s::]) >= self._limit:
                self._rand_u = zero_fill(self._rand_u)
                raise GOSTRandomError('exceeded the limit value of the counter')
            self._inc_rand_u()
            self._hash_obj.update(self._rand_u)
            rand_c = self._hash_obj.digest()
            self._hash_obj.reset()
            result = result + rand_c[_SIZE_H - self._r:_SIZE_H:]
        return result
    def sign(
        self,
        private_key: bytearray,
        digest: bytearray,
        rand_k: bytearray = bytearray(b'')) -> bytearray:
        """
        Create a signature.

        Args:
            private_key: Private signature key (as a byte object).
            digest: Digest for which the signature is calculated.  This value
              must be obtained using the 'streebog' algorithm in accordance with
              GOST 34.11-2012.
            rand_k: Random (pseudo-random) number (as a byte object). By
              default, it is generated by the function itself.

        Returns:
            Signature for provided digest (as a byte object).

        Raises:
            GOSTSignatureError('GOSTSignatureError: invalid private key value'):
              If the private key value is incorrect.
            GOSTSignatureError('GOSTSignatureError: invalid digest value'): If
              the digest value is incorrect.
            GOSTSignatureError('GOSTSignatureError: invalid random value'): If
              the random value is incorrect.
        """
        if not check_value(private_key, self._size):
            raise GOSTSignatureError(
                'GOSTSignatureError: invalid private key value')
        if not check_value(digest, self._size):
            raise GOSTSignatureError(
                'GOSTSignatureError: invalid digest value')
        sign_e = self._set_e(digest)
        sign_r = 0
        sign_s = 0
        sign_k = 0
        if rand_k == bytearray(b''):
            rand_k = self._get_rand_k()
        if not isinstance(rand_k, (bytes, bytearray)):
            private_key = zero_fill(private_key)
            raise GOSTSignatureError(
                'GOSTSignatureError: invalid random value')
        if bytearray_to_int(rand_k) >= self._q:
            private_key = zero_fill(private_key)
            raise GOSTSignatureError(
                'GOSTSignatureError: invalid random value')
        while compare_to_zero(int_to_bytearray(sign_s, self._size)):
            while compare_to_zero(int_to_bytearray(sign_r, self._size)):
                sign_k = bytearray_to_int(rand_k)
                sign_c = self._mul_point(sign_k)
                sign_r = sign_c[0] % self._q
            sign_s = (sign_r * bytearray_to_int(private_key) +
                      sign_k * sign_e) % self._q
        result = int_to_bytearray(sign_r, self._size) + int_to_bytearray(
            sign_s, self._size)
        private_key = zero_fill(private_key)
        return result
    def verify(self, public_key: Any, digest: bytearray,
               signature: bytearray) -> bool:
        """
        Verify a signature.

        Args:
            public_key: Public signature key (as a byte object).
            digest: Digest for which to be checked signature (as a byte object).
            signature: Signature of the digest being checked (as a byte object).

        Returns:
            The result of the signature verification ('True' or 'False').

        Raises:
            GOSTSignatureError('GOSTSignatureError: invalid public key value'):
              If the public key value is incorrect.
            GOSTSignatureError('GOSTSignatureError: invalid signature value'):
              If the signature value is incorrect.
            GOSTSignatureError('GOSTSignatureError: invalid digest value'): If
              the digest value is incorrect.
        """
        if not check_value(public_key, self._size * 2):
            raise GOSTSignatureError(
                'GOSTSignatureError: invalid public key value')
        if not check_value(signature, self._size * 2):
            raise GOSTSignatureError(
                'GOSTSignatureError: invalid signature value')
        if not check_value(digest, self._size):
            raise GOSTSignatureError(
                'GOSTSignatureError: invalid digest value')
        public_key = (bytearray_to_int(public_key[:self._size]),
                      bytearray_to_int(public_key[self._size:]))
        sign_r, sign_s = self._get_r_s(signature)
        if not self._verify_step_1(sign_r, sign_s):
            return False
        sign_e = self._set_e(digest)
        sign_v = self._invert(sign_e, self._q)
        sign_z_1 = sign_s * sign_v % self._q
        sign_z_2 = self._q - sign_r * sign_v % self._q
        sign_p = self._mul_point(sign_z_1)
        sign_q = self._mul_point(sign_z_2, public_key[0], public_key[1])
        sign_c = self._add(sign_p[0], sign_q[0], sign_p[1], sign_q[1])
        sign_r_check = sign_c[0] % self._q
        return compare(int_to_bytearray(sign_r_check, self._size),
                       int_to_bytearray(sign_r, self._size))
 def _rand_iter(self) -> bytearray:
     if bytearray_to_int(self._rand_u[self._size_s::]) >= self._limit:
         self._rand_u = zero_fill(self._rand_u)
         raise GOSTRandomError(
             'GOSTRandomError: exceeded the limit value of the counter')
     self._inc_rand_u()
     self._hash_obj.update(self._rand_u)
     result = self._hash_obj.digest()
     self._hash_obj.reset()
     return result
 def _get_mac_key(self, value_r):
     value_b = b''
     if self.block_size == 16:
         value_b = _B_128
     elif self.block_size == 8:
         value_b = _B_64
     if msb(value_r) == 0:
         int_value = bytearray_to_int(value_r) << 1
         key_1 = int_to_bytearray(int_value, self.block_size)
     else:
         int_value = bytearray_to_int(value_r) << 1
         key_1 = add_xor(int_to_bytearray(int_value, self.block_size),
                         value_b)
     if msb(key_1) == 0:
         int_value = bytearray_to_int(key_1) << 1
         key_2 = int_to_bytearray(int_value, self.block_size)
     else:
         int_value = bytearray_to_int(key_1) << 1
         key_2 = add_xor(int_to_bytearray(int_value, self.block_size),
                         value_b)
     return [key_1, key_2]
Exemple #6
0
    def public_key_generate(self, private_key: Any) -> bytearray:
        """
        Generate a public key.

        Parameters
        - private_key: private signature key (as a byte object).

        Return: public key (as a byte object).

        Exception
        - GOSTSignatureError('invalid private key') - if the private key value
        is incorrect.
        """
        if not check_value(private_key, self._size):
            raise GOSTSignatureError('invalid private key')
        private_key = bytearray_to_int(private_key)
        public_key = self._mul_point(private_key)
        public_key_x = int_to_bytearray(public_key[0], self._size)
        public_key_y = int_to_bytearray(public_key[1], self._size)
        private_key = 0
        return public_key_x + public_key_y
    def public_key_generate(self, private_key: Any) -> bytearray:
        """
        Generate a public key.

        Args:
            private_key: Private signature key (as a byte object).

        Returns:
            Public key (as a byte object).

        Raises:
            GOSTSignatureError('GOSTSignatureError: invalid private key'): If
              the private key value is incorrect.
        """
        if not check_value(private_key, self._size):
            raise GOSTSignatureError('GOSTSignatureError: invalid private key')
        private_key = bytearray_to_int(private_key)
        public_key = self._mul_point(private_key)
        public_key_x = int_to_bytearray(public_key[0], self._size)
        public_key_y = int_to_bytearray(public_key[1], self._size)
        private_key = 0
        return public_key_x + public_key_y
    def random(self) -> bytearray:
        """
        Generate the next value from a pseudo-random sequence.

        Returns:
            New random value.

        Raises:
            GOSTRandomError ('GOSTRandomError: exceeded the limit value of the
              counter'): When the counter limit is exceeded.
            GOSTRandomError('GOSTRandomError: the seed value is zero'): If the
              seed value is zero.
        """
        if bytearray_to_int(self._rand_u[:self._size_s]) == 0:
            raise GOSTRandomError('GOSTRandomError: the seed value is zero')
        i = self._q
        result = bytearray(0)
        while i > 0:
            result = result + self._rand_iter()
            i = i - 1
        if self._r != 0:
            result = result + self._rand_iter()[_SIZE_H - self._r:_SIZE_H:]
        return result
Exemple #9
0
import unittest
import os
import pytest
from unittest import mock

import gostcrypto
from gostcrypto.utils import bytearray_to_int
from gostcrypto.utils import int_to_bytearray
from gostcrypto.gostsignature import GOSTSignatureError

TEST_CURVE = {
    'id-tc26-gost-3410-2012-256-paramSetTest':dict(
        p=bytearray_to_int(bytearray.fromhex('8000000000000000000000000000000000000000000000000000000000000431')),
        a=0x07,
        b=bytearray_to_int(bytearray.fromhex('5fbff498aa938ce739b8e022fbafef40563f6e6a3472fc2a514c0ce9dae23b7e')),
        m=bytearray_to_int(bytearray.fromhex('8000000000000000000000000000000150fe8a1892976154c59cfc193accf5b3')),
        q=bytearray_to_int(bytearray.fromhex('8000000000000000000000000000000150fe8a1892976154c59cfc193accf5b3')),
        x=0x02,
        y=bytearray_to_int(bytearray.fromhex('08e2a8a0e65147d4bd6316030e16d19c85c97f0a9ca267122b96abbcea7e8fc8'))
    ),
        'id-tc26-gost-3410-2012-256-paramSetTest_raises_1':dict(
        p=bytearray_to_int(bytearray.fromhex('8000000000000000000000000000000150fe8a1892976154c59cfc193accf5b3')),
        a=0x07,
        b=bytearray_to_int(bytearray.fromhex('5fbff498aa938ce739b8e022fbafef40563f6e6a3472fc2a514c0ce9dae23b7e')),
        m=bytearray_to_int(bytearray.fromhex('8000000000000000000000000000000150fe8a1892976154c59cfc193accf5b3')),
        q=bytearray_to_int(bytearray.fromhex('8000000000000000000000000000000150fe8a1892976154c59cfc193accf5b3')),
        x=0x02,
        y=bytearray_to_int(bytearray.fromhex('08e2a8a0e65147d4bd6316030e16d19c85c97f0a9ca267122b96abbcea7e8fc8'))
    ),
    'id-tc26-gost-3410-2012-256-paramSetTest_raises_2':dict(
        p=bytearray_to_int(bytearray.fromhex('8000000000000000000000000000000000000000000000000000000000000431')),
 def _get_r_s(self, signature: bytearray) -> Tuple[int, int]:
     sign_r = bytearray_to_int(signature[:self._size])
     sign_s = bytearray_to_int(signature[self._size:])
     return sign_r, sign_s
 def _set_e(self, digest: bytearray) -> int:
     result = bytearray_to_int(digest) % self._q
     if compare_to_zero(int_to_bytearray(result, self._size)):
         result = 1
     return result
 def _get_rand_k(self) -> bytearray:
     rand_k = bytearray(os.urandom(self._size))
     while bytearray_to_int(rand_k) >= self._q:
         rand_k = bytearray(os.urandom(self._size))
     return rand_k
from gostcrypto.utils import bytearray_to_int
from gostcrypto.utils import int_to_bytearray
from gostcrypto.utils import compare
from gostcrypto.utils import compare_to_zero
from gostcrypto.utils import check_value
from gostcrypto.gostoid import ObjectIdentifier

MODE_256: int = 0x01
MODE_512: int = 0x02

# pylint: disable=R0801
CURVES_R_1323565_1_024_2019: dict = {
    'id-tc26-gost-3410-2012-256-paramSetB':
    dict(p=bytearray_to_int(
        bytearray([
            0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
            0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
            0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x97
        ])),
         a=bytearray_to_int(
             bytearray([
                 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                 0xff, 0xfd, 0x94
             ])),
         b=0xa6,
         m=bytearray_to_int(
             bytearray([
                 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6c, 0x61, 0x10,
                 0x70, 0x99, 0x5a, 0xd1, 0x00, 0x45, 0x84, 0x1b, 0x09, 0xb7,
 def _inc_rand_u(self) -> None:
     int_rand_u = bytearray_to_int(self._rand_u) + 1 % (2**(_SIZE_M - 1))
     self._rand_u = int_to_bytearray(int_rand_u, _SIZE_M - 1)