Ejemplo n.º 1
0
    def encrypt(self, data: bytearray) -> bytearray:
        """
        Plaintext encryption in CTR mode.

        Args:
            data: Plaintext data to be encrypted (as a byte object).

        Returns:
            Ciphertext data (as a byte object).

        Raises:
            GOSTCipherError('GOSTCipherError: invalid plaintext data'): In
              case where the plaintext data is not byte object.
        """
        result = bytearray()
        gamma = bytearray()
        data = super().encrypt(data)
        for i in range(self._get_num_block(data)):
            gamma = self._cipher_obj.encrypt(self._counter)
            self._counter = self._inc_ctr(self._counter)
            result = result + add_xor(self._get_block(data, i), gamma)
        if len(data) % self.block_size != 0:
            gamma = self._cipher_obj.encrypt(self._counter)
            self._counter = self._inc_ctr(self._counter)
            result = result + add_xor(
                data[self.block_size * self._get_num_block(data)::], gamma)
        return result
Ejemplo n.º 2
0
    def encrypt(self, data: bytearray) -> bytearray:
        """
        Plaintext encryption in CTR mode.

        Parameters
        - data: plaintext data to be encrypted (as a byte object).

        Return: ciphertext data (as a byte object).

        Exception
        - GOSTCipherError('invalid plaintext data'): in case where the plaintext data
        is not byte object.
        """
        if not isinstance(data, (bytes, bytearray)):
            self.clear()
            raise GOSTCipherError('invalid plaintext data')
        gamma = bytearray()
        result = bytearray()
        for i in range(get_num_block(data, self.block_size)):
            gamma = self._cipher_obj.encrypt(self._counter)
            self._counter = self._inc_ctr(self._counter)
            result = result + add_xor(
                data[self.block_size * i:self.block_size +
                     (self.block_size * i)], gamma)
        if len(data) % self.block_size != 0:
            gamma = self._cipher_obj.encrypt(self._counter)
            self._counter = self._inc_ctr(self._counter)
            result = result + add_xor(
                data[self.block_size * get_num_block(data, self.block_size)::],
                gamma)
        return result
Ejemplo n.º 3
0
    def __init__(self, key: bytearray):
        """
        Initialize the ciphering object.

        Args:
            key: Encryption key.
        """
        self._cipher_c: List[bytearray] = []
        self._cipher_iter_key = []
        self._cipher_get_c()
        self.oid = ObjectIdentifier('1.2.643.7.1.1.5.2')
        key_1 = key[:_KEY_SIZE // 2]
        key_2 = key[_KEY_SIZE // 2:]
        internal = bytearray(_KEY_SIZE // 2)
        self._cipher_iter_key.append(key_1)
        self._cipher_iter_key.append(key_2)
        for i in range(4):
            for j in range(8):
                internal = add_xor(key_1, self._cipher_c[i * 8 + j])
                internal = GOST34122015Kuznechik._cipher_s(internal)
                internal = GOST34122015Kuznechik._cipher_l(internal)
                key_1, key_2 = [add_xor(internal, key_2), key_1]
            self._cipher_iter_key.append(key_1)
            self._cipher_iter_key.append(key_2)
        key_1 = bytearray(self.key_size // 2)
        key_2 = bytearray(self.key_size // 2)
        key = bytearray(self.key_size)
Ejemplo n.º 4
0
    def update(self, data: bytearray) -> None:
        """
        Update the MAC object with the bytes-like object.

        Parameters
        - data: The data from which to get the MAC (as a byte object).  Repeated
        calls are equivalent to a single call with the concatenation of all the
        arguments: 'm.update(a)'; 'm.update(b)' is equivalent to 'm.update(a+b)'.

        Exception
        - GOSTCipherError('invalid text data'): in case where the text data
        is not byte object.
        """
        if not isinstance(data, (bytes, bytearray)):
            self.clear()
            raise GOSTCipherError('invalid text data')
        data = set_pad_mode_3(data, self.block_size)
        block = bytearray()
        prev_block = self._cur_mac
        for i in range(0, get_num_block(data, self.block_size) - 1):
            block = (self._cipher_obj.encrypt(
                add_xor(
                    prev_block, data[self.block_size * i:self.block_size +
                                     (self.block_size * i)])))
            prev_block = block
        block = (self._cipher_obj.encrypt(
            add_xor(prev_block, data[len(data) - self.block_size:len(data)])))
        self._cur_mac = block
        self._prev_mac = prev_block
        self._buff = data[self.block_size *
                          (get_num_block(data, self.block_size) - 1):]
Ejemplo n.º 5
0
 def _hash_e(self, k: bytearray, data: bytearray) -> bytearray:
     internal = add_xor(k, data)
     for i in range(12):
         internal = self._hash_s(internal)
         internal = self._hash_p(internal)
         internal = self._hash_l(internal)
         k = self._hash_get_key(k, i)
         internal = add_xor(internal, k)
     return internal
Ejemplo n.º 6
0
 def _hash_g(self, hash_h: bytearray, hash_n: bytearray,
             data: bytearray) -> bytearray:
     k = add_xor(hash_n, hash_h)
     k = self._hash_s(k)
     k = self._hash_p(k)
     k = self._hash_l(k)
     internal = self._hash_e(k, data)
     internal = add_xor(internal, hash_h)
     result = add_xor(internal, data)
     return result
Ejemplo n.º 7
0
 def mac_final(self) -> bytearray:
     """Return the final value of the MAC."""
     if get_pad_size(self._buff, self.block_size) == 0:
         final_key = self._key_1
     else:
         final_key = self._key_2
     self._buff = set_pad_mode_3(self._buff, self.block_size)
     result = bytearray()
     result = self._cipher_obj.encrypt(
         add_xor(add_xor(self._prev_mac, self._buff), final_key))
     return result
Ejemplo n.º 8
0
 def _f(self) -> bytearray:
     _t = self._u_first()
     internal = self._u_first()
     for _ in range(1, self._iterations):
         internal = self._u_iter(internal)
         _t = add_xor(_t, internal)
     return _t
Ejemplo n.º 9
0
    def decrypt(self, data: bytearray) -> bytearray:
        """
        Ciphertext decryption in CBC mode.

        Parameters
        - data: ciphertext data to be decrypted (as a byte object).

        Return: plaintext data (as a byte object).

        Exception
        - GOSTCipherError('invalid ciphertext data'): in case where the
        ciphertext data is not byte object.
        """
        if not isinstance(data, (bytes, bytearray)):
            self.clear()
            raise GOSTCipherError('invalid ciphertext data')
        result = bytearray()
        for i in range(get_num_block(data, self.block_size)):
            cipher_blk = (add_xor(
                self._init_vect[0:self.block_size],
                self._cipher_obj.decrypt(
                    data[self.block_size * i:self.block_size +
                         (self.block_size * i)])))
            result = result + cipher_blk
            self._init_vect[0:len(self._init_vect) - self.block_size] = (
                self._init_vect[self.block_size:len(self._init_vect)])
            self._init_vect[len(self._init_vect) -
                            self.block_size:len(self._init_vect)] = (
                                data[self.block_size * i:self.block_size +
                                     (self.block_size * i)])
        return result
Ejemplo n.º 10
0
    def encrypt(self, data: bytearray) -> bytearray:
        """
        Plaintext encryption in OFB mode.

        Args:
            data: Plaintext data to be encrypted (as a byte object).

        Returns:
            Ciphertext data (as a byte object).

        Raises:
            GOSTCipherError('GOSTCipherError: invalid plaintext data'): In
              case where the plaintext data is not byte object.
        """
        result = bytearray()
        gamma = bytearray()
        data = super().encrypt(data)
        for i in range(self._get_num_block(data)):
            gamma = self._get_gamma()
            cipher_block = self._get_block(data, i)
            result = result + add_xor(gamma, cipher_block)
            self._set_init_vect(gamma[0:self.block_size])
        if len(data) % self.block_size != 0:
            result = result + self._final_cipher(data)
        return result
Ejemplo n.º 11
0
 def _hash_get_key(self, k: bytearray, i: int) -> bytearray:
     key = bytearray(_BLOCK_SIZE)
     key = add_xor(k, _C[i])
     key = self._hash_s(key)
     key = self._hash_p(key)
     key = self._hash_l(key)
     return key
Ejemplo n.º 12
0
    def encrypt(self, block: bytearray) -> bytearray:
        """
        Encrypting a block of plaintext.

        Args:
            block: The block of plaintext to be encrypted (the block size is
              16 bytes).

        Returns:
            The block of ciphertext.
        """
        block = bytearray(block)
        for i in range(9):
            block = add_xor(self._cipher_iter_key[i], block)
            block = GOST34122015Kuznechik._cipher_s(block)
            block = GOST34122015Kuznechik._cipher_l(block)
        block = add_xor(self._cipher_iter_key[9], block)
        return block
Ejemplo n.º 13
0
    def update(self, data: bytearray) -> None:
        """
        Update the MAC object with the bytes-like object.

        Args:
            data: The data from which to get the MAC (as a byte object).
              Repeated calls are equivalent to a single call with the
              concatenation of all the arguments: 'm.update(a)'; 'm.update(b)'
              is equivalent to 'm.update(a+b)'.

        Raises:
            GOSTCipherError('GOSTCipherError: invalid text data'): In case
              where the text data is not byte object.
        """
        if not isinstance(data, (bytes, bytearray)):
            self.clear()
            raise GOSTCipherError('GOSTCipherError: invalid text data')
        data = self._iter_buf + data
        block = bytearray()
        prev_block = self._cur_mac
        for i in range(0, self._get_num_block(data) - 1):
            block = self._cipher_obj.encrypt(
                add_xor(prev_block, self._get_block(data, i)))
            prev_block = block
        if self._get_pad_size(data) == 0:
            block = (self._cipher_obj.encrypt(
                add_xor(prev_block,
                        data[len(data) - self.block_size:len(data)])))
            self._cur_mac = block
            self._prev_mac = prev_block
            self._iter_buf = bytearray(b'')
        else:
            begin_data = len(data) - 2 * self.block_size + self._get_pad_size(
                data)
            end_data = len(data) - self.block_size + self._get_pad_size(data)
            block = (self._cipher_obj.encrypt(
                add_xor(prev_block, data[begin_data:end_data])))
            self._cur_mac = block
            self._prev_mac = block
            self._iter_buf = data[len(data) - self.block_size +
                                  self._get_pad_size(data):]
        self._fin_buff = data[self.block_size *
                              (self._get_num_block(data) - 1):]
Ejemplo n.º 14
0
 def _cipher_g_iter(cipher_k: bytearray, cipher_a: bytearray) -> tuple:
     cipher_k = bytearray(cipher_k)
     cipher_a = bytearray(cipher_a)
     a_0 = bytearray(4)
     a_1 = bytearray(4)
     cipher_g = bytearray(4)
     a_1 = cipher_a[0:4]
     a_0 = cipher_a[4:_BLOCK_SIZE_MAGMA]
     cipher_g = GOST34122015Magma._cipher_g(cipher_k, a_0)
     cipher_g = add_xor(a_1, cipher_g)
     return a_0, a_1, cipher_g
Ejemplo n.º 15
0
 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]
Ejemplo n.º 16
0
    def encrypt(self, data: bytearray) -> bytearray:
        """
        Plaintext encryption in OFB mode.

        Parameters
        :data: Plaintext data to be encrypted (as a byte object).

        Return:
        ciphertext data (as a byte object).

        Exception:
        - GOSTCipherError('invalid plaintext data') - in case where the plaintext data
        is not byte object.
        """
        if not isinstance(data, (bytes, bytearray)):
            self.clear()
            raise GOSTCipherError('invalid plaintext data')
        gamma = bytearray()
        result = bytearray()
        for i in range(get_num_block(data, self.block_size)):
            gamma = self._cipher_obj.encrypt(
                self._init_vect[0:self.block_size])
            cipher_blk = add_xor(
                gamma, data[self.block_size * i:self.block_size +
                            (self.block_size * i)])
            result = result + cipher_blk
            self._init_vect[0:len(self._init_vect) - self.block_size] = (
                self._init_vect[self.block_size:len(self._init_vect)])
            self._init_vect[len(self._init_vect) -
                            self.block_size:len(self._init_vect)] = (
                                gamma[0:self.block_size])
        if len(data) % self.block_size != 0:
            gamma = self._cipher_obj.encrypt(
                self._init_vect[0:self.block_size])
            cipher_blk = add_xor(
                gamma,
                data[self.block_size * get_num_block(data, self.block_size)::])
            result = result + cipher_blk
        return result
Ejemplo n.º 17
0
    def digest(self) -> bytearray:
        """
        Return the HMAC message authentication code.

        This method is called after calling the 'update ()' method.

        Return: HMAC message authentication code as a byte object.
        """
        fin_hasher_obj = GOST34112012(self._hasher_obj.name, data=b'')
        fin_hasher_obj.update(
            add_xor(self._key, _O_PAD) + self._hasher_obj.digest())
        result = fin_hasher_obj.digest()
        fin_hasher_obj.reset()
        return result
Ejemplo n.º 18
0
    def update(self, data: bytearray) -> None:
        """
        Update the HMAC object with the bytes-like object.

        Parameters
        - data: the message for which want to calculate the authentication code.
        Repeated calls are equivalent to a single call with the concatenation
        of all the arguments: 'm.update(a)'; 'm.update(b)' is equivalent to
        'm.update(a+b)'.

        Exception
        - GOSTHMACError('invalid data value'): in case where the data is not
        byte object.
        """
        if not isinstance(data, (bytes, bytearray)):
            raise GOSTHMACError('invalid data value')
        self._counter = self._counter + 1
        if self._counter == 1:
            self._hasher_obj.update(add_xor(self._key, _I_PAD) + data)
        elif self._counter != 1:
            self._hasher_obj.update(data)
Ejemplo n.º 19
0
    def decrypt(self, data: bytearray) -> bytearray:
        """
        Ciphertext decryption in CBC mode.

        Args:
            data: Ciphertext data to be decrypted (as a byte object).

        Returns:
            Plaintext data (as a byte object).

        Raises:
            GOSTCipherError('GOSTCipherError: invalid ciphertext data'): In
              case where the ciphertext data is not byte object.
        """
        result = bytearray()
        data = GOST34132015CipherPadding.decrypt(self, data)
        for i in range(self._get_num_block(data)):
            internal = self._cipher_obj.decrypt(self._get_block(data, i))
            cipher_block = add_xor(self._init_vect[0:self.block_size],
                                   internal)
            result = result + cipher_block
            self._set_init_vect(self._get_block(data, i))
        return result
Ejemplo n.º 20
0
 def _final_cipher(self, data):
     gamma = self._get_gamma()
     cipher_block = self._get_final_block(data)
     return add_xor(gamma, cipher_block)