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 _add(self, x_1: int, x_2: int, y_1: int, y_2: int) -> Tuple[int, int]:
     compare_x = compare(int_to_bytearray(x_1, self._size),
                         int_to_bytearray(x_2, self._size))
     compare_y = compare(int_to_bytearray(y_1, self._size),
                         int_to_bytearray(y_2, self._size))
     if compare_x and compare_y:
         grad = (3 * x_1 * x_1 + self._a) * self._invert(2 * y_1,
                                                         self._p) % self._p
     else:
         d_x = (x_2 - x_1) % self._p
         d_y = (y_2 - y_1) % self._p
         grad = (d_y * self._invert(d_x, self._p)) % self._p
     x_3 = (grad * grad - x_1 - x_2) % self._p
     y_3 = (grad * (x_1 - x_3) - y_1) % self._p
     return x_3, y_3
    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 _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 #5
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 _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
Exemple #8
0
 def _u_first(self) -> bytearray:
     self._hmac_obj.reset()
     self._hmac_obj.update(self._salt + int_to_bytearray(self._counter, 4))
     return self._hmac_obj.digest()
 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)