Example #1
0
def decode_authentication(
    ciphertext: bytes, privkey: datatypes.PrivateKey
) -> Tuple[datatypes.PublicKey, bytes, datatypes.PublicKey]:
    """
    Decrypts and decodes the ciphertext msg.
    Returns the initiator's ephemeral pubkey, nonce, and pubkey.
    """
    if len(ciphertext) < ENCRYPTED_AUTH_MSG_LEN:
        raise DecryptionError(f"Auth msg too short: {len(ciphertext)}")
    elif len(ciphertext) == ENCRYPTED_AUTH_MSG_LEN:
        sig, initiator_pubkey, initiator_nonce, _ = decode_auth_plain(
            ciphertext, privkey
        )
    else:
        sig, initiator_pubkey, initiator_nonce, _ = decode_auth_eip8(
            ciphertext, privkey
        )

    # recover initiator ephemeral pubkey from sig
    #   S(ephemeral-privk, ecdh-shared-secret ^ nonce)
    shared_secret = ecies.ecdh_agree(privkey, initiator_pubkey)

    ephem_pubkey = sig.recover_public_key_from_msg_hash(
        sxor(shared_secret, initiator_nonce)
    )

    return ephem_pubkey, initiator_nonce, initiator_pubkey
Example #2
0
    def decrypt_raw_bytes(self, data: bytes, size: int) -> bytes:
        """
        same as decrypt_body() but no roundup
        """
        if len(data) < size + MAC_LEN:
            raise ValueError(
                "Insufficient body length; Got {}, wanted {} + {}".format(
                    len(data), size, MAC_LEN
                )
            )

        frame_ciphertext = data[:size]
        frame_mac = data[size : size + MAC_LEN]

        self.ingress_mac.update(frame_ciphertext)
        fmac_seed = self.ingress_mac.digest()[:MAC_LEN]
        self.ingress_mac.update(sxor(self.mac_enc(fmac_seed), fmac_seed))
        expected_frame_mac = self.ingress_mac.digest()[:MAC_LEN]
        if not bytes_eq(expected_frame_mac, frame_mac):
            raise DecryptionError(
                "Invalid frame mac: expected {}, got {}".format(
                    expected_frame_mac, frame_mac
                )
            )
        return self.aes_dec.update(frame_ciphertext)[:size]
Example #3
0
def decrypt(data: bytes,
            privkey: datatypes.PrivateKey,
            shared_mac_data: bytes = b"") -> bytes:
    """Decrypt data with ECIES method using the given private key

    1) generate shared-secret = kdf( ecdhAgree(myPrivKey, msg[1:65]) )
    2) verify tag
    3) decrypt

    ecdhAgree(r, recipientPublic) == ecdhAgree(recipientPrivate, R)
    [where R = r*G, and recipientPublic = recipientPrivate*G]

    """
    if data[:1] != b"\x04":
        raise DecryptionError("wrong ecies header")

    #  1) generate shared-secret = kdf( ecdhAgree(myPrivKey, msg[1:65]) )
    shared = data[1:1 + PUBKEY_LEN]
    key_material = ecdh_agree(privkey, keys.PublicKey(shared))
    key = kdf(key_material)
    key_enc, key_mac = key[:KEY_LEN // 2], key[KEY_LEN // 2:]
    key_mac = sha256(key_mac).digest()
    tag = data[-KEY_LEN:]

    # 2) Verify tag
    expected_tag = hmac_sha256(key_mac,
                               data[1 + PUBKEY_LEN:-KEY_LEN] + shared_mac_data)
    if not bytes_eq(expected_tag, tag):
        raise DecryptionError("Failed to verify tag")

    # 3) Decrypt
    algo = CIPHER(key_enc)
    blocksize = algo.block_size // 8
    iv = data[1 + PUBKEY_LEN:1 + PUBKEY_LEN + blocksize]
    ciphertext = data[1 + PUBKEY_LEN + blocksize:-KEY_LEN]
    ctx = Cipher(algo, MODE(iv), default_backend()).decryptor()
    return ctx.update(ciphertext) + ctx.finalize()
Example #4
0
    def decrypt_header(self, data: bytes) -> bytes:
        if len(data) != HEADER_LEN + MAC_LEN:
            raise ValueError(
                f"Unexpected header length: {len(data)}, expected {HEADER_LEN} + {MAC_LEN}"
            )

        header_ciphertext = data[:HEADER_LEN]
        header_mac = data[HEADER_LEN:]
        mac_secret = self.ingress_mac.digest()[:HEADER_LEN]
        aes = self.mac_enc(mac_secret)[:HEADER_LEN]
        self.ingress_mac.update(sxor(aes, header_ciphertext))
        expected_header_mac = self.ingress_mac.digest()[:HEADER_LEN]
        if not bytes_eq(expected_header_mac, header_mac):
            raise DecryptionError(
                f"Invalid header mac: expected {expected_header_mac}, got {header_mac}"
            )
        return self.aes_dec.update(header_ciphertext)
Example #5
0
    def decrypt_body(self, data: bytes, body_size: int) -> bytes:
        read_size = roundup_16(body_size)
        if len(data) < read_size + MAC_LEN:
            raise ValueError(
                f"Insufficient body length; Got {len(data)}, wanted {read_size} + {MAC_LEN}"
            )

        frame_ciphertext = data[:read_size]
        frame_mac = data[read_size:read_size + MAC_LEN]

        self.ingress_mac.update(frame_ciphertext)
        fmac_seed = self.ingress_mac.digest()[:MAC_LEN]
        self.ingress_mac.update(sxor(self.mac_enc(fmac_seed), fmac_seed))
        expected_frame_mac = self.ingress_mac.digest()[:MAC_LEN]
        if not bytes_eq(expected_frame_mac, frame_mac):
            raise DecryptionError(
                f"Invalid frame mac: expected {expected_frame_mac}, got {frame_mac}"
            )
        return self.aes_dec.update(frame_ciphertext)[:body_size]