Exemplo n.º 1
0
def decrypt(infile, outfile, key):
    iv = infile.read(12)
    if len(iv) != 12:
        raise Exception('IV of incorrect length was read from input.')
    decryptor = Cipher(
            algorithms.AES(key),
            modes.GCM(iv),
            backend=backend,
            ).decryptor()
    buff = b''
    for block in read_blocks(infile):
        block = buff + block
        buff = block[-16:]
        block = block[:-16]
        outfile.write(decryptor.update(block))
    decryptor.finalize_with_tag(buff)
Exemplo n.º 2
0
 def decrypt(self, key, verbose=False):
     assert (isinstance(key, bytes))
     (meta,
      dkey) = self.kdf(self._header["kdf"],
                       key,
                       salt=bytes.fromhex(self._header["kdf"]["salt"]),
                       verbose=verbose)
     if self._header["cipher"]["name"] == "AES256-GCM":
         iv = bytes.fromhex(self._header["cipher"]["iv"])
         decryptor = Cipher(algorithms.AES(dkey),
                            modes.GCM(iv),
                            backend=_backend).decryptor()
         plaintext = decryptor.update(self._encrypted_payload)
         tag = bytes.fromhex(self._header["cipher"]["tag"])
         decryptor.finalize_with_tag(tag)
     else:
         raise NotImplementedError(self._header["cipher"]["name"])
     return plaintext
Exemplo n.º 3
0
def pay():
    token = ast.literal_eval(raw_input("Token: "))
    iv = token["iv"].decode("hex")
    enc = token["enc"].decode("hex")
    tag = token["tag"].decode("hex")

    decryptor = Cipher(
        algorithms.AES(key),
        modes.GCM(iv),
        backend=default_backend()
    ).decryptor()

    account = ast.literal_eval(decryptor.update(enc) + decryptor.finalize_with_tag(tag))
    if account["balance"] != 1000 and account["admin"] == "N":
        print("Huh? you have no money and want the flag? -.-")
    else:
        print(flag)
Exemplo n.º 4
0
    def _decrypt(cls, fobj: io.BufferedIOBase,
                 input_size: typing.Optional[int],
                 privkey: x25519.X25519PrivateKey,
                 chunk_size: int) -> typing.Iterable[bytes]:
        if input_size is None:
            input_size = cls._get_size_till_eof(fobj)

        epubkey = x25519.X25519PublicKey.from_public_bytes(
            cls._read_exact(fobj, cls._PUBKEY_SIZE_BYTES))
        input_size -= cls._PUBKEY_SIZE_BYTES
        shared_secret = privkey.exchange(epubkey)
        iv = cls._read_exact(fobj, cls._IV_SIZE_BYTES)
        input_size -= cls._IV_SIZE_BYTES
        cipher_key = cls._derive_keys(shared_secret, iv)
        cipher_iv = iv[:cls._CIPHER_IV_SIZE_BYTES]
        decryptor = Cipher(algorithm=cls._CIPHER(cipher_key),
                           mode=GCM(cipher_iv),
                           backend=cls._CRYPTO_BACKEND).decryptor()

        if input_size < cls._AUTH_TAG_SIZE_BYTES:
            raise RuntimeError('input_size is too short')
        bufmv = memoryview(bytearray(chunk_size))
        auth_tag = b''
        while input_size > 0:
            bytes_read = fobj.readinto(bufmv)
            if bytes_read == 0:
                break
            input_size -= bytes_read
            if input_size <= cls._AUTH_TAG_SIZE_BYTES:
                auth_tag_part_len = cls._AUTH_TAG_SIZE_BYTES - input_size
                auth_tag += bufmv[bytes_read - auth_tag_part_len:bytes_read]
                auth_tag += fobj.read()
                yield decryptor.update(bufmv[:bytes_read - auth_tag_part_len])
            else:
                yield decryptor.update(bufmv[:bytes_read])
        yield decryptor.finalize_with_tag(auth_tag)
Exemplo n.º 5
0
    def receive(self,
                message_id,
                outfp=None,
                access_method=AccessMethod.view,
                extra_key_hashes=None,
                max_size=None):
        if not self.ok:
            raise NotReady()

        merged_url, headers = self.merge_and_headers(self.url, raw="embed")

        response = self.session.get(merge_get_url(self.url, raw="embed"),
                                    headers=headers)
        response.raise_for_status()
        graph = Graph()
        graph.parse(data=response.content, format="turtle")
        self.retrieve_missing(graph, merged_url)
        result = list(
            graph.query(
                """
                SELECT DISTINCT ?base ?hash_algorithm ?type
                WHERE {
                    ?base a <https://spkcspider.net/static/schemes/spkcgraph#spkc:Content> ;
                                  spkc:type ?type ;
                                  spkc:properties ?propalg , ?propid .
                    ?propid spkc:name ?idname ;
                            spkc:value ?idvalue .
                    ?propalg spkc:name ?algname ;
                             spkc:value ?hash_algorithm .
                }
            """,  # noqa E501
                initNs={"spkc": spkcgraph},
                initBindings={
                    "idvalue": Literal(message_id),
                    "algname": Literal("hash_algorithm", datatype=XSD.string),
                    "idname": Literal("id", datatype=XSD.string),
                }))
        if not result or result[0].type.toPython() not in {
                "WebReference", "MessageContent"
        }:
            raise SrcException("No Message")
        # every object has it's own copy of the hash algorithm, used
        hash_algo = getattr(hashes, result[0].hash_algorithm.upper())()

        if not outfp:
            outfp = tempfile.TempFile()

        if hash_algo == self.hash_algo:
            pub_key_hashalg = "%s=%s" % (hash_algo.name,
                                         self.hash_key_public.hex())
        else:
            digest = hashes.Hash(hash_algo, backend=default_backend())
            digest.update(self.pem_key_public)
            pub_key_hashalg = "%s=%s" % (hash_algo.name,
                                         digest.finalize().hex())

        key_hashes = list()
        if extra_key_hashes:
            extra_key_hashes = set(extra_key_hashes)
            extra_key_hashes.discard(pub_key_hashalg)
            for key in self.client_list:
                if key[0] in extra_key_hashes:
                    if hash_algo == self.hash_algo:
                        key_hashalg = "%s=%s" % (hash_algo.name, key[0])
                    else:
                        digest = hashes.Hash(hash_algo,
                                             backend=default_backend())
                        digest.update(key[1])
                        key_hashalg = "%s=%s" % (hash_algo.name,
                                                 digest.finalize().hex())
                    key_hashes.append(key_hashalg)

        if access_method == AccessMethod.view:
            key_hashes.append(pub_key_hashalg)

        retrieve_url, headers = self.merge_and_headers(
            replace_action(
                result[0].base, "bypass/" if
                (access_method == AccessMethod.bypass) else "message/"))
        data = {}
        if access_method != AccessMethod.bypass:
            data.update({"max_size": max_size or "", "keyhash": key_hashes})
        response = self.session.post(retrieve_url,
                                     stream=True,
                                     headers=headers,
                                     data=data)
        try:
            response.raise_for_status()
        except Exception as exc:
            raise DestException("Message retrieval failed",
                                response.text) from exc
        key_list = json.loads(response.headers["X-KEYLIST"])
        key = key_list.get(pub_key_hashalg, None)
        if not key:
            raise WrongRecipient("message not for me")
        decrypted_key = self.priv_key.decrypt(
            base64.b64decode(key),
            padding.OAEP(mgf=padding.MGF1(algorithm=hash_algo),
                         algorithm=hash_algo,
                         label=None))

        headblock = b""
        fdecryptor = None
        eparser = emailparser.BytesFeedParser(policy=policy.default)
        headers = None
        for chunk in response.iter_content(chunk_size=256):
            blob = None
            if not fdecryptor:
                headblock = b"%b%b" % (headblock, chunk)
                if b"\0" in headblock:
                    nonce, headblock = headblock.split(b"\0", 1)
                    nonce = base64.b64decode(nonce)
                    fdecryptor = Cipher(algorithms.AES(decrypted_key),
                                        modes.GCM(nonce),
                                        backend=default_backend()).decryptor()
                    blob = fdecryptor.update(headblock[:-16])
                    headblock = headblock[-16:]
                else:
                    continue
            else:
                blob = fdecryptor.update(b"%b%b" % (headblock, chunk[:-16]))
                headblock = chunk[-16:]
            if not headers:
                if b"\n\n" not in blob:
                    eparser.feed(blob)
                    continue
                headersrest, blob = blob.split(b"\n\n", 1)
                eparser.feed(headersrest)
                headers = eparser.close()
                # check  what to do
                t = headers.get("SPKC-Type", MessageType.email)
                if t == MessageType.email:
                    outfp.write(
                        headers.as_bytes(unixfrom=True, policy=policy.SMTP))
            outfp.write(blob)
        outfp.write(fdecryptor.finalize_with_tag(headblock))
        return outfp, headers, decrypted_key
Exemplo n.º 6
0
def __decrypt(input: Union[str, Iterable[bytes]],
              cipher: str = "AES-256-GCM",
              kdf: str = "PBKDF2",
              hashfunc: str = "SHA3_512",
              iterations: int = 100000,
              buf_size: int = 65536) -> Iterable[bytes]:
    with BufferedReader(input) as istream:

        cipher, key_len, mode, kdf, hashfunc = __get_meta(
            cipher, kdf, hashfunc)

        salt_len = int.from_bytes(istream.read(2), byteorder="little")
        salt = istream.read(salt_len)
        if len(salt) != salt_len:
            raise ValueError(
                f"Expected a salt of length {salt_len} but the file is not long enough. Most likely the file is corrupted or not encrypted using this cipher."
            )

        key = __make_key(salt, kdf["algorithm"], hashfunc["algorithm"],
                         key_len, iterations)

        if mode:
            iv = istream.read(cipher["block_size"])
        else:
            iv = None

        decryptor = Cipher(cipher["algorithm"](key),
                           mode["algorithm"](iv) if mode else None,
                           backend=__backend).decryptor()

        unpadder = PKCS7(cipher["block_size"] * 8).unpadder()

        buf = None
        while len(buf2 := istream.read(buf_size)) != 0:
            if buf:
                if mode["padded"]:
                    yield unpadder.update(decryptor.update(buf))
                else:
                    yield decryptor.update(buf)
            buf = buf2
        if mode["auth_tag"]:
            try:
                if mode["padded"]:
                    yield unpadder.update(
                        decryptor.update(buf[:-mode["auth_tag"]]))
                    yield unpadder.update(
                        decryptor.finalize_with_tag(buf[-mode["auth_tag"]:]))
                    yield unpadder.finalize()
                else:
                    yield decryptor.update(buf[:-mode["auth_tag"]])
                    yield decryptor.finalize_with_tag(buf[-mode["auth_tag"]:])
            except InvalidTag as e:
                raise ValueError(
                    "\nThe authentication token could not be verified. Most likely the data is corrupt or was not encrypted using the given cipher."
                ) from e
        else:
            if mode["padded"]:
                yield unpadder.update(decryptor.update(buf))
                yield unpadder.update(decryptor.finalize())
                try:
                    yield unpadder.finalize()
                except ValueError as e:
                    raise ValueError(
                        "Could not finalize padding. Most likely the file is corrupt or was not encrypted using the given cipher."
                    ) from e
            else:
                yield decryptor.update(buf)
                yield decryptor.finalize()
Exemplo n.º 7
0
def action_view(argv, priv_key, pem_public, own_url, session, g_message):
    if argv.message_id is not None:
        assert isinstance(argv.message_id, int)
        result = list(g_message.query(
            """
                SELECT DISTINCT ?base ?hash_algorithm ?type
                WHERE {
                    ?base a <https://spkcspider.net/static/schemes/spkcgraph#spkc:Content> ;
                                  spkc:type ?type ;
                                  spkc:properties ?propalg , ?propid .
                    ?propid spkc:name ?idname ;
                            spkc:value ?idvalue .
                    ?propalg spkc:name ?algname ;
                             spkc:value ?hash_algorithm .
                }
            """,  # noqa E501
            initNs={"spkc": spkcgraph},
            initBindings={
                "idvalue": Literal(argv.message_id),
                "algname": Literal(
                    "hash_algorithm", datatype=XSD.string
                ),
                "idname": Literal(
                    "id", datatype=XSD.string
                ),

            }
        ))
        if not result or result[0].type.toPython() not in {
            "WebReference", "MessageContent"
        }:
            parser.exit(0, "message not found\n")
        pub_key_hasher = getattr(
            hashes, result[0].hash_algorithm.upper()
        )()

        digest = hashes.Hash(pub_key_hasher, backend=default_backend())
        digest.update(pem_public)
        pub_key_hashalg = "%s=%s" % (
            pub_key_hasher.name,
            digest.finalize().hex()
        )
        retrieve_url = merge_get_url(
            replace_action(
                result[0].base, "message/"
            )
        )
        data = {
            "max_size": argv.max
        }
        if argv.action == "view":
            data["keyhash"] = pub_key_hashalg
        response = session.post(
            retrieve_url, stream=True, headers={
                "X-TOKEN": argv.token
            }, data=data
        )
        if not response.ok:
            logger.info("Message retrieval failed: %s", response.text)
            parser.exit(0, "message could not be fetched\n")
        key_list = json.loads(response.headers["X-KEYLIST"])
        key = key_list.get(pub_key_hashalg, None)
        if not key:
            parser.exit(0, "message not for me\n")
        decrypted_key = priv_key.decrypt(
            base64.b64decode(key),
            padding.OAEP(
                mgf=padding.MGF1(algorithm=argv.src_hash_algo),
                algorithm=argv.src_hash_algo,
                label=None
            )
        )

        headblock = b""
        fdecryptor = None
        eparser = emailparser.BytesFeedParser(policy=policy.default)
        headers = None
        for chunk in response.iter_content(chunk_size=256):
            blob = None
            if not fdecryptor:
                headblock = b"%b%b" % (headblock, chunk)
                if b"\0" in headblock:
                    nonce, headblock = headblock.split(b"\0", 1)
                    nonce = base64.b64decode(nonce)
                    fdecryptor = Cipher(
                        algorithms.AES(decrypted_key),
                        modes.GCM(nonce),
                        backend=default_backend()
                    ).decryptor()
                    blob = fdecryptor.update(headblock[:-16])
                    headblock = headblock[-16:]
                else:
                    continue
            else:
                blob = fdecryptor.update(
                    b"%b%b" % (headblock, chunk[:-16])
                )
                headblock = chunk[-16:]
            if not headers:
                if b"\n\n" not in blob:
                    eparser.feed(blob)
                    continue
                headersrest, blob = blob.split(b"\n\n", 1)
                eparser.feed(headersrest)
                headers = eparser.close()
                # check  what to do
                t = headers.get("SPKC-Type", MessageType.email)
                if t == MessageType.email:
                    argv.file.write(headers.as_bytes(
                        unixfrom=True,
                        policy=policy.SMTP
                    ))
            argv.file.write(blob)
        argv.file.write(fdecryptor.finalize_with_tag(headblock))
    else:
        queried_webrefs = {}
        queried_messages = {}
        for i in g_message.query(
            """
            SELECT DISTINCT ?base ?idvalue ?namevalue ?type
            WHERE {
                ?base a <https://spkcspider.net/static/schemes/spkcgraph#spkc:Content> ;
                   spkc:type ?type ;
                   spkc:properties ?propname , ?propid .
                ?propid spkc:name ?idname ;
                        spkc:value ?idvalue .
                ?propname spkc:name ?namename ;
                          spkc:value ?namevalue .
            }
        """,  # noqa E501
            initNs={"spkc": spkcgraph},
            initBindings={
                "idname": Literal(
                    "id", datatype=XSD.string
                ),
                "namename": Literal(
                    "name", datatype=XSD.string
                ),

            }
        ):
            if i.type.toPython() == "WebReference":
                queried = queried_webrefs
            elif i.type.toPython() == "MessageContent":
                queried = queried_messages
            else:
                continue
            queried.setdefault(str(i.base), {})
            queried[str(i.base)]["id"] = i.idvalue
            queried[str(i.base)]["name"] = i.namevalue
        print("Received Messages:")
        for i in sorted(queried_webrefs.values(), key=lambda x: x["id"]):
            print(i["id"], i["name"])

        print("Own Messages:")
        for i in sorted(queried_messages.values(), key=lambda x: x["id"]):
            print(i["id"], i["name"])