Exemple #1
0
    def pack(self,
             command: Union[str, bytes, bytearray],
             data: Union[str, bytes, bytearray],
             encrypt: bool,
             type_: int = 0,
             *,
             key: RSA.RsaKey = None) -> Packet:
        if not (isinstance(type_, int) and -1 < type_ < 256):
            raise ValueError('Unsupported type')

        if isinstance(command, (str, bytes, bytearray)):
            if isinstance(command, str):
                command = command.encode('utf8')
            elif isinstance(command, bytearray):
                command = bytes(command)
        else:
            raise ValueError('Unsupported command type')

        if isinstance(data, (str, bytes, bytearray)):
            if isinstance(data, str):
                data = data.encode('utf8')
            if isinstance(data, bytes):
                data = bytearray(data)

            if len(data) > 4294967295:
                raise ValueError('data max length is 4294967295 bytes')
        else:
            raise TypeError('Unsupported data type')

        if not key:
            pass
        elif key and not isinstance(key, RSA.RsaKey):
            raise TypeError('key must be RSA key')
        else:
            if not key.can_encrypt():
                raise KeyError('key can not encrypt data')

        if encrypt:
            cipher: PKCS1_OAEP.PKCS1OAEP_Cipher = PKCS1_OAEP.new(
                key if key else self.key, SHA3_256, randfunc=Random.new().read)
            chunk: int = 65535 if ((key.size_in_bytes() if key else self.key.size_in_bytes()) - 66) > 65535 else \
                (key.size_in_bytes() if key else self.key.size_in_bytes()) - 66
            encrypted = bytearray()

            for i in (data[i:i + chunk]
                      for i in range(0, data.__len__(), chunk)):
                encrypted.extend(cipher.encrypt(i))

        return Packet(
            Header(
                Flags(
                    type_, encrypt,
                    key.size_in_bytes()
                    if key else self.key.size_in_bytes() if encrypt else 0,
                    len(encrypted) if encrypt else len(data)), command,
                b'\x00' * 32), encrypted if encrypt else data)
Exemple #2
0
def decrypt_message(message: bytes, receiver_private_key: RsaKey) -> bytes:
    """
    Decrypts message, using the specified key to decrypt symmetric key firs
    :param message: message with the following structure: IV + encrypted symmetric key + encrypted message
    :param receiver_private_key: RsaKey to decrypt symmetric key
    :return: decrypted message
    """
    iv = message[:IV_LEN]
    enc_aes_key = message[IV_LEN:IV_LEN + receiver_private_key.size_in_bytes()]  # Assume encryption has been done with same key size
    enc_message = message[IV_LEN + receiver_private_key.size_in_bytes():]

    cipher_rsa = PKCS1_OAEP.new(receiver_private_key)
    aes_key = cipher_rsa.decrypt(enc_aes_key)

    cipher_aes = AES.new(aes_key, AES.MODE_CBC, iv)
    return unpad(cipher_aes.decrypt(enc_message), AES.block_size)  # Padding have to be removed
Exemple #3
0
def verify_signature(message: bytes, sender_public_key: RsaKey) -> bytes:
    """
    Verifies if the message has a valid signature, raising SignatureNotAuthentic if not
    :param message: message to be verified
    :param sender_public_key: public key of the pretended sender
    :return: original message without signature if it is valid
    :raise: SignatureNotAuthentic if signature is not valid
    """
    signature = message[:sender_public_key.size_in_bytes()]  # Assume encryption has been done with same key size
    original_message = message[sender_public_key.size_in_bytes():]
    h = SHA256.new(original_message)
    verifier = pkcs1_15.new(sender_public_key)
    try:
        verifier.verify(h, signature)
        return original_message
    except ValueError:
        raise SignatureNotAuthentic
Exemple #4
0
def decrypt(data: bytes, mode: EncryptionMode,
            rec_privkey: RSA.RsaKey) -> bytes:
    """Decrypt given bytes using a specified encryption mode and."""

    key_len = rec_privkey.size_in_bytes()
    enc_session_key = data[:key_len]
    cipher_rsa = PKCS1_OAEP.new(rec_privkey)

    if mode == EncryptionMode.ECB:
        iv = None
        ciphertext = data[key_len:]
    else:
        iv_end = key_len + AES.block_size
        iv = data[key_len:iv_end]
        ciphertext = data[iv_end:]

    try:
        session_key = cipher_rsa.decrypt(enc_session_key)
    except ValueError:
        session_key = os.urandom(16)

    cipher_aes = {
        EncryptionMode.ECB: AES.new(session_key, AES.MODE_ECB),
        EncryptionMode.CBC: AES.new(session_key, AES.MODE_CBC, cast(bytes,
                                                                    iv)),
        EncryptionMode.CFB: AES.new(session_key, AES.MODE_CFB, cast(bytes,
                                                                    iv)),
        EncryptionMode.OFB: AES.new(session_key, AES.MODE_OFB, cast(bytes,
                                                                    iv)),
    }[mode]

    try:
        data = unpad(cipher_aes.decrypt(ciphertext), AES.block_size)
    except ValueError:
        data = ("".join(
            random.SystemRandom().choice(string.printable)
            for _ in range(random.randint(5, 100)))).encode("utf-8")

    return data