Example #1
0
    def __init__(self, algorithm: str, key: bytearray) -> None:
        """
        Initialize the ciphering object.

        Args:
            algorithm: The string with the name of the ciphering algorithm.
            key: The encryption key.

        Raises:
            GOSTCipherError('GOSTCipherError: unsupported cipher algorithm'): In
              case of unsupported cipher algorithm (is not 'kuznechik' or
              'magma').
            GOSTCipherError('GOSTCipherError: invalid key value'): In case of
              invalid 'key' value (the key value is not a byte object
              ('bytearray' or 'bytes') or its length is not 256 bits).
        """
        if algorithm not in ('magma', 'kuznechik'):
            key = zero_fill(key)
            raise GOSTCipherError(
                'GOSTCipherError: unsupported cipher algorithm')
        if not check_value(key, _KEY_SIZE):
            key = zero_fill(key)
            raise GOSTCipherError('GOSTCipherError: invalid key value')
        if algorithm == 'kuznechik':
            self._cipher_obj: CipherObjType = GOST34122015Kuznechik(key)
        elif algorithm == 'magma':
            self._cipher_obj = GOST34122015Magma(key)
        self.oid = self._cipher_obj.oid
    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
Example #3
0
 def _expand_iter_key_final(self, key: bytearray) -> None:
     for j in range(8):
         iter_key = bytearray(4)
         for i in range(4):
             iter_key[i] = key[28 - (j * 4) + i]
         self._cipher_iter_key.append(iter_key)
     iter_key = zero_fill(iter_key)
     key = zero_fill(key)
Example #4
0
    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 __init__(self, algorithm: str, key: bytearray) -> None:
     """Initialize the ciphering object."""
     if algorithm not in ('magma', 'kuznechik'):
         key = zero_fill(key)
         raise GOSTCipherError('unsupported cipher algorithm')
     if not check_value(key, _KEY_SIZE):
         key = zero_fill(key)
         raise GOSTCipherError('invalid key value')
     if algorithm == 'kuznechik':
         self._cipher_obj = GOST34122015Kuznechik(key)
     elif algorithm == 'magma':
         self._cipher_obj = GOST34122015Magma(key)
Example #6
0
 def __init__(self, password: bytearray, salt: bytearray,
              iterations: int) -> None:
     """Initialize the PBKDF object."""
     if not isinstance(password, (bytes, bytearray)):
         raise GOSTPBKDFError('invalid password value')
     self._password = bytearray(password)
     self._salt = salt
     if self._salt == bytearray(b''):
         self._salt = bytearray(os.urandom(32))
     if not isinstance(self._salt, (bytes, bytearray)):
         password = zero_fill(password)
         self._password = zero_fill(self._password)
         raise GOSTPBKDFError('invalid salt value')
     self._salt = bytearray(self._salt)
     self._iterations = iterations
     self._num_block = 0
     self._counter = 0
     self._hmac_obj = R5011132016('HMAC_GOSTR3411_2012_512', self._password)
     password = zero_fill(password)
 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
Example #8
0
    def __init__(self, key: bytearray):
        """
        Initialize the ciphering object.

        Args:
            key: Encryption key.
        """
        self.oid = ObjectIdentifier('1.2.643.7.1.1.5.1')
        self._cipher_iter_key: List[bytearray] = []
        self._expand_iter_key(key)
        self._expand_iter_key(key)
        self._expand_iter_key(key)
        self._expand_iter_key_final(key)
        key = zero_fill(key)
Example #9
0
 def clear(self) -> None:
     """Сlear the key value."""
     self._hasher_obj.reset()
     self._key = zero_fill(self._key)
Example #10
0
 def clear(self):
     """Сlear the password value."""
     self._password = zero_fill(self._password)
 def clear(self) -> None:
     """Clear the counter value."""
     if hasattr(self, '_rand_u'):
         self._rand_u = zero_fill(self._rand_u)
Example #12
0
def new(algorithm: str, key: bytearray, mode: int, **kwargs) -> CipherType:
    """
    Create a new ciphering object and returns it.

    Args:
        algorithm: The string with the name of the ciphering algorithm of the
          GOST R 34.12-2015 ('kuznechik' with block size 128 bit or 'magma' with
          block size 64 bit).
        key: Byte object with 256-bit encryption key.
        mode: Mode of operation of the block encryption algorithm (valid value:
          MODE_CBC, MODE_CFB, MODE_CTR, MODE_ECB,MODE_OFB or MODE_MAC).
        **init_vect: Byte object with initialization vector.  Used in MODE_CTR,
          MODE_OFB, MODE_CBC and MODE_CFB modes.  For MODE_CTR mode, the
          initialization vector length is equal to half the block size (default
          value iz '_DEFAULT_IV_CTR').  For MODE_CBC, MODE_OFB and MODE_CFB
          modes, it is a multiple of the block size (default value is
          '_DEFAULT_IV').
        **data: The data from which to get the MAC (as a byte object).  For
          MODE_MAC mode only.  If this argument is passed to a function, you
          can immediately use the 'digest' (or 'hexdigest') method to calculate
          the MAC value after calling 'new'.  If the argument is not passed to
          the function, then you must use the 'update(data)' method before the
          'digest' (or 'hexdigest') method.
        **pad_mode: Padding mode for ECB or CBC (the default value is
          PAD_MODE_1).

    Returns:
        New ciphering object.

    Raises:
        GOSTCipherError('GOSTCipherError: unsupported cipher mode'): In case
          of unsupported cipher mode (is not MODE_ECB, MODE_CBC, MODE_CFB,
          MODE_OFB, MODE_CTR or MODE_MAC).
        GOSTCipherError('GOSTCipherError: unsupported cipher algorithm'): In
          case of invalid value 'algorithm'.
        GOSTCipherError('GOSTCipherError: invalid key value'): In case of
          invalid 'key' value (the key value is not a byte object ('bytearray'
          or 'bytes') or its length is not 256 bits).
        GOSTCipherError('GOSTCipherError: invalid padding mode'): In case
          padding mode is incorrect (for MODE_ECB and MODE_CBC modes).
        GOSTCipherError('GOSTCipherError: invalid initialization vector
          value'): In case initialization vector value is incorrect (for all
          modes except ECB mode).
        GOSTCipherError('GOSTCipherError: invalid text data'): In case where
          the text data is not byte object (for MODE_MAC mode).
    """
    result: Any = None
    if mode == MODE_ECB:
        pad_mode = kwargs.get('pad_mode', PAD_MODE_1)
        result = GOST34132015ecb(algorithm, key, pad_mode)
    elif mode == MODE_CBC:
        init_vect = kwargs.get('init_vect', _DEFAULT_IV_KUZNECHIK)
        if algorithm == 'magma':
            init_vect = kwargs.get('init_vect', _DEFAULT_IV_CBC_MAGMA)
        pad_mode = kwargs.get('pad_mode', PAD_MODE_1)
        result = GOST34132015cbc(algorithm, key, init_vect, pad_mode)
    elif mode == MODE_CFB:
        init_vect = kwargs.get('init_vect', _DEFAULT_IV_KUZNECHIK)
        if algorithm == 'magma':
            init_vect = kwargs.get('init_vect', _DEFAULT_IV_MAGMA)
        result = GOST34132015cfb(algorithm, key, init_vect)
    elif mode == MODE_OFB:
        init_vect = kwargs.get('init_vect', _DEFAULT_IV_KUZNECHIK)
        if algorithm == 'magma':
            init_vect = kwargs.get('init_vect', _DEFAULT_IV_MAGMA)
        result = GOST34132015ofb(algorithm, key, init_vect)
    elif mode == MODE_CTR:
        init_vect = kwargs.get('init_vect', _DEFAULT_IV_CTR_KUZNECHIK)
        if algorithm == 'magma':
            init_vect = kwargs.get('init_vect', _DEFAULT_IV_CTR_MAGMA)
        result = GOST34132015ctr(algorithm, key, init_vect)
    elif mode == MODE_MAC:
        data = kwargs.get('data', bytearray(b''))
        result = GOST34132015mac(algorithm, key, data)
    else:
        key = zero_fill(key)
        raise GOSTCipherError('GOSTCipherError: unsupported cipher mode')
    return result
Example #13
0
 def clear(self) -> None:
     """Сlearing the values of iterative encryption keys."""
     for i in range(32):
         self._cipher_iter_key[i] = zero_fill(self._cipher_iter_key[i])
 def clear(self):
     """Clear the counter value."""
     self._rand_u = zero_fill(self._rand_u)