def test_validate_header_invalid(self):
     """Validate that the validate_header function behaves
         as expected for a valid header.
     """
     self.mock_decrypt.side_effect = InvalidTag()
     with six.assertRaisesRegex(self, SerializationError,
                                'Header authorization failed'):
         aws_encryption_sdk.internal.formatting.deserialize.validate_header(
             header=VALUES['deserialized_header_block'],
             header_auth=VALUES['deserialized_header_auth_block'],
             raw_header=VALUES['header'],
             data_key=VALUES['data_key_obj'])
Exemple #2
0
 def test_validate_header_invalid(self):
     """Validate that the validate_header function behaves
         as expected for a valid header.
     """
     self.mock_decrypt.side_effect = InvalidTag()
     with pytest.raises(SerializationError) as excinfo:
         aws_encryption_sdk.internal.formatting.deserialize.validate_header(
             header=VALUES["deserialized_header_block"],
             header_auth=VALUES["deserialized_header_auth_block"],
             raw_header=VALUES["header"],
             data_key=VALUES["data_key_obj"],
         )
     excinfo.match("Header authorization failed")
Exemple #3
0
    def decrypt(self, ciphertext, aad, iv, tag, key):
        """Key Decryption with AES AES_CBC_HMAC_SHA2.

        :param ciphertext: ciphertext in bytes
        :param aad: additional authenticated data in bytes
        :param iv: initialization vector in bytes
        :param tag: authentication tag in bytes
        :param key: encrypted key in bytes
        :return: message
        """
        self.check_iv(iv)
        hkey = key[:self.key_bytes_length]
        dkey = key[self.key_bytes_length:]

        _tag = self._hmac(ciphertext, aad, iv, hkey)
        if not hmac.compare_digest(_tag, tag):
            raise InvalidTag()

        cipher = Cipher(AES(dkey), CBC(iv), backend=default_backend())
        d = cipher.decryptor()
        data = d.update(ciphertext) + d.finalize()
        unpad = PKCS7(AES.block_size).unpadder()
        return unpad.update(data) + unpad.finalize()
Exemple #4
0
    def locker(self, remove=True):
        """Provides file locking/unlocking mechanism
        This function either encrypts or decrypts the file - *file_path*.
        Encryption or decryption depends upon the file's extension.
        The user's encryption or decryption task is almost automated since
        *encryption* or *decryption* is determined by the file's extension.


          Usage
         -------
           
          remove = If set to True, the the file that is being
                   encrypted or decrypted will be removed.
                   (Default: True).
        """

        # The file is being decrypted
        try:
            if not self._flag:
                method = 'decrypt'
                new_file = os.path.splitext(self.file_path)[0]

                # Retrieve the nonce and remove it from the
                # encrypted file

                with open(self.file_path, 'rb+') as f:
                    f.seek(-(self.NONCE_SIZE + self.SALT_LEN), 2)
                    nonce, _ = unpack(
                        '<{}s{}s'.format(self.NONCE_SIZE, self.SALT_LEN),
                        f.read())

                orig_size = os.path.getsize(
                    self.file_path) - (self.NONCE_SIZE + self.SALT_LEN)
                os.truncate(self.file_path, orig_size)

            # The file is being encrypted
            else:
                method = 'encrypt'
                new_file = self.file_path + self.EXT

                nonce = os.urandom(self.NONCE_SIZE)

            # Create a cipher with the required method

            key = self.password_hash
            cipher = getattr(AESGCM(key), method)

            # Create a partial function with default values.

            crp = partial(cipher, nonce=nonce, associated_data=None)

            # Read from *file_path* and write to the *new_file*
            try:
                Locker._writer(
                    self.file_path,
                    new_file,
                    crp,
                    self._flag,
                    nonce=nonce,
                    salt=self._salt,
                )
            except InvalidTag:
                os.remove(new_file)
                raise InvalidTag('Invalid Password or tampered data.')

            if remove:
                os.remove(self.file_path)

            return self
        except Exception as err:
            raise err
Exemple #5
0
def locker(file_path, password, remove=True):
    """Provides file locking/unlocking mechanism
    This function either encrypts or decrypts the file - *file_path*.
    Encryption or decryption depends upon the file's extension.
    The user's encryption or decryption task is almost automated since
    *encryption* or *decryption* is determined by the file's extension.


      Usage
     -------
     file_path = File to be written on.

     password = Key to be used for encryption/decryption.

       remove = If set to True, the the file that is being
                encrypted or decrypted will be removed.
                (Default: True).
    """

    # The file is being decrypted
    try:
        if file_path.endswith(EXT):
            method = 'decrypt'
            flag = False
            new_file = os.path.splitext(file_path)[0]

            # Retrieve the nonce and remove it from the
            # encrypted file

            with open(file_path, 'rb+') as f:
                f.seek(-(NONCE_SIZE + SALT_LEN), 2)
                nonce, salt = unpack('<{}s{}s'.format(NONCE_SIZE, SALT_LEN),
                                     f.read())

            orig_size = os.path.getsize(file_path) - (NONCE_SIZE + SALT_LEN)
            os.truncate(file_path, orig_size)

        # The file is being encrypted
        else:
            method = 'encrypt'
            flag = True
            new_file = file_path + EXT

            salt = os.urandom(SALT_LEN)
            nonce = os.urandom(NONCE_SIZE)

        # Create a cipher with the required method

        key = hashlib.pbkdf2_hmac('sha3-256', password, salt, 10000, 32)
        cipher = getattr(AESGCM(key), method)

        # Create a partial function with default values.

        crp = partial(cipher, nonce=nonce, associated_data=None)

        # Read from *file_path* and write to the *new_file*
        try:
            _writer(
                file_path,
                new_file,
                crp,
                flag,
                nonce=nonce,
                salt=salt,
            )
        except InvalidTag as err:
            os.remove(new_file)
            raise InvalidTag('Invalid Password or tampered data.')

        if remove:
            os.remove(file_path)

    except Exception as err:
        raise err
Exemple #6
0
    def test_verify_finish(self, mock_chacha20_poly1305, mock_tlv_parser, mock_ed25519):
        config = Mock()
        config.get_pairing.return_value = None, 'test_ios_device_ltpk', None
        context = {
            'session_key': 'test_session_key',
            'accessory_curve25519_public_key': b'test_accessory_curve25519_public_key',
            'ios_device_curve25519_public_key': b'test_ios_device_curve25519_public_key',
            'shared_secret': b'shared_secret',
        }
        encrypted_input = b'test_encrypted_input'
        mock_tlv_parser.decode.return_value = [{
            TlvCode.identifier: 'test_identifier',
            TlvCode.signature: b'test_signature',
        }]

        result = pair.verify_finish(config, context, encrypted_input)
        self.assertEqual(result, [{
            TlvCode.state: TlvState.m4,
        }])

        # handle 'verify_finished call before successful verify_start'
        context['session_key'] = None
        result = pair.verify_finish(config, context, encrypted_input)
        self.assertEqual(result, [{
            TlvCode.state: TlvState.m4,
            TlvCode.error: TlvError.authentication,
        }])
        context['session_key'] = 'test_session_key'

        # handle 'invalid auth tag during chacha decryption'
        mock_chacha20_poly1305().decrypt.side_effect = InvalidTag()
        result = pair.verify_finish(config, context, encrypted_input)
        self.assertEqual(result, [{
            TlvCode.state: TlvState.m4,
            TlvCode.error: TlvError.authentication,
        }])
        mock_chacha20_poly1305().decrypt.side_effect = None

        # handle 'unable to decode decrypted tlv data'
        mock_tlv_parser.decode.side_effect = ValueError()
        result = pair.verify_finish(config, context, encrypted_input)
        self.assertEqual(result, [{
            TlvCode.state: TlvState.m4,
            TlvCode.error: TlvError.authentication,
        }])
        mock_tlv_parser.decode.side_effect = None

        # handle 'unable to find requested ios device in config file'
        config.get_pairing.return_value = None, None, None
        result = pair.verify_finish(config, context, encrypted_input)
        self.assertEqual(result, [{
            TlvCode.state: TlvState.m4,
            TlvCode.error: TlvError.authentication,
        }])
        config.get_pairing.return_value = None, 'test_ios_device_ltpk', None

        # handle 'ios_device_info ed25519 signature verification is failed'
        mock_ed25519.BadSignatureError = BadSignatureError
        mock_ed25519.VerifyingKey().verify.side_effect = BadSignatureError()
        result = pair.verify_finish(config, context, encrypted_input)
        self.assertEqual(result, [{
            TlvCode.state: TlvState.m4,
            TlvCode.error: TlvError.authentication,
        }])
        mock_ed25519.VerifyingKey().verify.side_effect = None
Exemple #7
0
    def test_exchange(self, mock_chacha20_poly1305, mock_hkdf, mock_sha512, mocker_default_backend, mock_tlv_parser,
                      mock_ed25519):
        config = Mock()
        config.get_pairing.return_value = None, None, None
        context = {'srp': Mock()}
        expected_tlv_state = TlvState.m5
        encrypted_input = b'test_encrypted_input'
        encrypted_output = b'test_encrypted_output'
        mock_chacha20_poly1305().encrypt.return_value = encrypted_output
        mock_tlv_parser.decode.return_value = [{
            TlvCode.identifier: 'test_identifier',
            TlvCode.public_key: b'test_public_key',
            TlvCode.signature: b'test_signature',
        }]

        result = pair.exchange(config, context, expected_tlv_state, encrypted_input)
        mock_hkdf.assert_called_with(algorithm=mock_sha512(), length=32, salt=b'Pair-Setup-Accessory-Sign-Salt',
                                     info=b'Pair-Setup-Accessory-Sign-Info', backend=mocker_default_backend())
        mock_hkdf().derive.assert_called_with(context['srp'].session_key)
        mock_chacha20_poly1305.assert_called_with(mock_hkdf().derive())
        mock_chacha20_poly1305().decrypt.assert_called_with(b'\x00\x00\x00\x00PS-Msg05', encrypted_input, None)
        mock_tlv_parser.decode.assert_called_with(mock_chacha20_poly1305().decrypt())
        self.assertEqual(result, [{
            TlvCode.state: TlvState.m6,
            TlvCode.encrypted_data: encrypted_output,
        }])

        # handle 'Unexpected pair_setup state'
        expected_tlv_state = TlvState.m1
        result = pair.exchange(config, context, expected_tlv_state, encrypted_input)
        self.assertEqual(result, [{
            TlvCode.state: TlvState.m6,
            TlvCode.error: TlvError.unknown,
        }])
        expected_tlv_state = TlvState.m5

        # handle 'pair_setup M5: invalid auth tag during chacha decryption'
        mock_chacha20_poly1305().decrypt.side_effect = InvalidTag()
        result = pair.exchange(config, context, expected_tlv_state, encrypted_input)
        self.assertEqual(result, [{
            TlvCode.state: TlvState.m6,
            TlvCode.error: TlvError.authentication,
        }])
        mock_chacha20_poly1305().decrypt.side_effect = None

        # handle 'unable to decode decrypted tlv data'
        mock_tlv_parser.decode.side_effect = ValueError()
        result = pair.exchange(config, context, expected_tlv_state, encrypted_input)
        self.assertEqual(result, [{
            TlvCode.state: TlvState.m6,
            TlvCode.error: TlvError.authentication,
        }])
        mock_tlv_parser.decode.side_effect = None

        # handle 'ios_device_info ed25519 signature verification is failed'
        mock_ed25519.BadSignatureError = BadSignatureError
        mock_ed25519.VerifyingKey().verify.side_effect = BadSignatureError()
        result = pair.exchange(config, context, expected_tlv_state, encrypted_input)
        self.assertEqual(result, [{
            TlvCode.state: TlvState.m6,
            TlvCode.error: TlvError.authentication,
        }])
        mock_ed25519.VerifyingKey().verify.side_effect = None