Ejemplo n.º 1
0
    def test_hash_verification(self):
        data = b"Test bytes"

        cyphertext, keys = encrypt_attachment(data)

        with pytest.raises(EncryptionError):
            decrypt_attachment(cyphertext, keys["key"]["k"], "Fake hash",
                               keys["iv"])
Ejemplo n.º 2
0
    def test_invalid_iv(self):
        data = b"Test bytes"

        cyphertext, keys = encrypt_attachment(data)

        with pytest.raises(EncryptionError):
            decrypt_attachment(cyphertext, keys["key"]["k"],
                               keys["hashes"]["sha256"], "Fake iv")
Ejemplo n.º 3
0
    async def test_short_key(self):
        data, cyphertext, keys = await self._get_data_cypher_keys()

        with pytest.raises(EncryptionError):
            decrypt_attachment(
                cyphertext,
                unpaddedbase64.encode_base64(b"Fake key", urlsafe=True),
                keys["hashes"]["sha256"],
                keys["iv"],
            )
Ejemplo n.º 4
0
    async def test_hash_verification(self):
        data, cyphertext, keys = await self._get_data_cypher_keys()

        with pytest.raises(EncryptionError):
            decrypt_attachment(
                cyphertext,
                keys["key"]["k"],
                "Fake hash",
                keys["iv"],
            )
Ejemplo n.º 5
0
    async def test_invalid_iv(self):
        data, cyphertext, keys = await self._get_data_cypher_keys()

        with pytest.raises(EncryptionError):
            decrypt_attachment(
                cyphertext,
                keys["key"]["k"],
                keys["hashes"]["sha256"],
                "Fake iv",
            )
Ejemplo n.º 6
0
    def test_short_key(self):
        data = b"Test bytes"

        cyphertext, keys = encrypt_attachment(data)

        with pytest.raises(EncryptionError):
            decrypt_attachment(
                cyphertext,
                unpaddedbase64.encode_base64(b"Fake key", urlsafe=True),
                keys["hashes"]["sha256"], keys["iv"])
Ejemplo n.º 7
0
def main():
    parser = argparse.ArgumentParser(
        description='Download and decrypt matrix attachments')
    parser.add_argument('url', help='the url of the attachment')
    parser.add_argument('--plumber',
                        help='program that gets called with the '
                        'dowloaded file')

    args = parser.parse_args()
    url = urlparse(args.url)
    query = parse_qs(url.query)

    if not query["key"] or not query["iv"] or not query["hash"]:
        print("Missing decryption argument")
        return -1

    key = query["key"][0]
    iv = query["iv"][0]
    hash = query["hash"][0]

    http_url = "https://{}{}".format(url.netloc, url.path)

    request = requests.get(http_url)

    if not request.ok:
        print("Error downloading file")
        return -2

    plumber = args.plumber or "/usr/bin/rifle"
    plaintext = decrypt_attachment(request.content, key, hash, iv)
    file_name = save_file(plaintext)

    subprocess.run([plumber, "{file}".format(file=file_name)])

    return 0
Ejemplo n.º 8
0
    def test_encrypt(self):
        data = b"Test bytes"

        cyphertext, keys = encrypt_attachment(data)

        plaintext = decrypt_attachment(cyphertext, keys["key"]["k"],
                                       keys["hashes"]["sha256"], keys["iv"])

        assert data == plaintext
Ejemplo n.º 9
0
    async def test_short_iv(self):
        data, cyphertext, keys = await self._get_data_cypher_keys()

        plaintext = decrypt_attachment(
            cyphertext,
            keys["key"]["k"],
            keys["hashes"]["sha256"],
            unpaddedbase64.encode_base64(b"F" + b"\x00" * 8),
        )
        assert plaintext != data
Ejemplo n.º 10
0
    def test_fake_key(self):
        data = b"Test bytes"

        cyphertext, keys = encrypt_attachment(data)

        fake_key = Random.new().read(32)

        plaintext = decrypt_attachment(
            cyphertext, unpaddedbase64.encode_base64(fake_key, urlsafe=True),
            keys["hashes"]["sha256"], keys["iv"])
        assert plaintext != data
Ejemplo n.º 11
0
    async def test_encrypt(self, data=b"Test bytes", large=False):
        _, cyphertext, keys = await self._get_data_cypher_keys(data)

        plaintext = decrypt_attachment(
            cyphertext,
            keys["key"]["k"],
            keys["hashes"]["sha256"],
            keys["iv"],
        )

        assert plaintext == b"Test bytes" * (16384 if large else 1)
Ejemplo n.º 12
0
    def test_short_iv(self):
        data = b"Test bytes"

        cyphertext, keys = encrypt_attachment(data)

        plaintext = decrypt_attachment(
            cyphertext,
            keys["key"]["k"],
            keys["hashes"]["sha256"],
            unpaddedbase64.encode_base64(b"F" + b"\x00" * 8),
        )
        assert plaintext != data
Ejemplo n.º 13
0
    async def test_fake_key(self):
        data, cyphertext, keys = await self._get_data_cypher_keys()

        fake_key = Random.new().read(32)

        plaintext = decrypt_attachment(
            cyphertext,
            unpaddedbase64.encode_base64(fake_key, urlsafe=True),
            keys["hashes"]["sha256"],
            keys["iv"],
        )
        assert plaintext != data
Ejemplo n.º 14
0
 async def _handle_matrix_image(
         self, sender: 'u.User',
         message: MediaMessageEventContent) -> Optional[str]:
     if message.file and decrypt_attachment:
         data = await self.main_intent.download_media(message.file.url)
         data = decrypt_attachment(data, message.file.key.key,
                                   message.file.hashes.get("sha256"),
                                   message.file.iv)
     elif message.url:
         data = await self.main_intent.download_media(message.url)
     else:
         return None
     image = await sender.client.upload_image(io.BytesIO(data),
                                              filename=message.body)
     return await sender.send_image(self.gid, image)
Ejemplo n.º 15
0
 async def _handle_matrix_image(
         self, sender: 'u.User',
         message: MediaMessageEventContent) -> Optional[str]:
     if message.file and decrypt_attachment:
         data = await self.main_intent.download_media(message.file.url)
         data = decrypt_attachment(data, message.file.key.key,
                                   message.file.hashes.get("sha256"),
                                   message.file.iv)
     elif message.url:
         data = await self.main_intent.download_media(message.url)
     else:
         return None
     mime = message.info.mimetype or magic.from_buffer(data, mime=True)
     files = await sender._upload([(message.body, data, mime)])
     return await sender._send_files(files,
                                     thread_id=self.fbid,
                                     thread_type=self.fb_type)
Ejemplo n.º 16
0
def main():
    parser = argparse.ArgumentParser(
        description='Download and decrypt matrix attachments'
    )
    parser.add_argument('url', help='the url of the attachment')
    parser.add_argument('file', nargs='?', help='save attachment to <file>')
    parser.add_argument('--plumber',
                        help='program that gets called with the '
                             'dowloaded file')

    args = parser.parse_args()
    url = urlparse(args.url)
    query = parse_qs(url.query)

    if not query["key"] or not query["iv"] or not query["hash"]:
        print("Missing decryption argument")
        return -1

    key = query["key"][0]
    iv = query["iv"][0]
    hash = query["hash"][0]

    http_url = "https://{}{}".format(url.netloc, url.path)

    request = requests.get(http_url)

    if not request.ok:
        print("Error downloading file")
        return -2

    plumber = args.plumber
    plaintext = decrypt_attachment(request.content, key, hash, iv)

    if args.file is None:
        file_name = save_file(plaintext)
        if plumber is None:
            plumber = "xdg-open"
    else:
        file_name = args.file
        open(file_name, "wb").write(plaintext)

    if plumber is not None:
        subprocess.run([plumber, file_name])

    return 0
Ejemplo n.º 17
0
    async def _handle_matrix_file(self, sender_id: TelegramID, event_id: EventID,
                                  space: TelegramID, client: 'MautrixTelegramClient',
                                  content: MediaMessageEventContent, reply_to: TelegramID,
                                  caption: TextMessageEventContent = None) -> None:
        mime = content.info.mimetype
        w, h = content.info.width, content.info.height
        file_name = content["net.maunium.telegram.internal.filename"]
        max_image_size = config["bridge.image_as_file_size"] * 1000 ** 2

        if config["bridge.parallel_file_transfer"] and content.url:
            file_handle, file_size = await parallel_transfer_to_telegram(client, self.main_intent,
                                                                         content.url, sender_id)
        else:
            if content.file:
                if not decrypt_attachment:
                    self.log.warning(f"Can't bridge encrypted media event {event_id}:"
                                     " matrix-nio not installed")
                    return
                file = await self.main_intent.download_media(content.file.url)
                file = decrypt_attachment(file, content.file.key.key,
                                          content.file.hashes.get("sha256"), content.file.iv)
            else:
                file = await self.main_intent.download_media(content.url)

            if content.msgtype == MessageType.STICKER:
                if mime != "image/gif":
                    mime, file, w, h = util.convert_image(file, source_mime=mime,
                                                          target_type="webp")
                else:
                    # Remove sticker description
                    file_name = "sticker.gif"

            file_handle = await client.upload_file(file)
            file_size = len(file)

        file_handle.name = file_name

        attributes = [DocumentAttributeFilename(file_name=file_name)]
        if w and h:
            attributes.append(DocumentAttributeImageSize(w, h))

        if (mime == "image/png" or mime == "image/jpeg") and file_size < max_image_size:
            media = InputMediaUploadedPhoto(file_handle)
        else:
            media = InputMediaUploadedDocument(file=file_handle, attributes=attributes,
                                               mime_type=mime or "application/octet-stream")

        caption, entities = self._matrix_event_to_entities(caption) if caption else (None, None)

        async with self.send_lock(sender_id):
            if await self._matrix_document_edit(client, content, space, caption, media, event_id):
                return
            try:
                response = await client.send_media(self.peer, media, reply_to=reply_to,
                                                   caption=caption, entities=entities)
            except (PhotoInvalidDimensionsError, PhotoSaveFileInvalidError, PhotoExtInvalidError):
                media = InputMediaUploadedDocument(file=media.file, mime_type=mime,
                                                   attributes=attributes)
                response = await client.send_media(self.peer, media, reply_to=reply_to,
                                                   caption=caption, entities=entities)
            self._add_telegram_message_to_db(event_id, space, 0, response)