예제 #1
0
파일: auth.py 프로젝트: qkcww/pyquarkchain
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
예제 #2
0
    def create_auth_message(self, nonce: bytes) -> bytes:
        ecdh_shared_secret = ecies.ecdh_agree(self.privkey, self.remote.pubkey)
        secret_xor_nonce = sxor(ecdh_shared_secret, nonce)
        S = self.ephemeral_privkey.sign_msg_hash(secret_xor_nonce).to_bytes()

        if self.use_eip8:
            data = rlp.encode(
                [S, self.pubkey.to_bytes(), nonce, SUPPORTED_RLPX_VERSION],
                sedes=eip8_auth_sedes,
            )
            return _pad_eip8_data(data)
        else:
            # S || H(ephemeral-pubk) || pubk || nonce || 0x0
            return (S + keccak(self.ephemeral_pubkey.to_bytes()) +
                    self.pubkey.to_bytes() + nonce + b"\x00")
예제 #3
0
    def derive_secrets(
        self,
        initiator_nonce: bytes,
        responder_nonce: bytes,
        remote_ephemeral_pubkey: datatypes.PublicKey,
        auth_init_ciphertext: bytes,
        auth_ack_ciphertext: bytes,
    ) -> Tuple[bytes, bytes, BasePreImage, BasePreImage]:
        """Derive base secrets from ephemeral key agreement."""
        # ecdhe-shared-secret = ecdh.agree(ephemeral-privkey, remote-ephemeral-pubk)
        ecdhe_shared_secret = ecies.ecdh_agree(
            self.ephemeral_privkey, remote_ephemeral_pubkey
        )

        # shared-secret = keccak(ecdhe-shared-secret || keccak(nonce || initiator-nonce))
        shared_secret = keccak(
            ecdhe_shared_secret + keccak(responder_nonce + initiator_nonce)
        )

        # aes-secret = keccak(ecdhe-shared-secret || shared-secret)
        aes_secret = keccak(ecdhe_shared_secret + shared_secret)

        # mac-secret = keccak(ecdhe-shared-secret || aes-secret)
        mac_secret = keccak(ecdhe_shared_secret + aes_secret)

        # setup keccak instances for the MACs
        # egress-mac = sha3.keccak_256(mac-secret ^ recipient-nonce || auth-sent-init)
        mac1 = keccaklib.new(
            data=sxor(mac_secret, responder_nonce) + auth_init_ciphertext,
            digest_bits=256,
            update_after_digest=True,
        )
        # ingress-mac = sha3.keccak_256(mac-secret ^ initiator-nonce || auth-recvd-ack)
        mac2 = keccaklib.new(
            data=sxor(mac_secret, initiator_nonce) + auth_ack_ciphertext,
            digest_bits=256,
            update_after_digest=True,
        )

        if self._is_initiator:
            egress_mac, ingress_mac = mac1, mac2
        else:
            egress_mac, ingress_mac = mac2, mac1

        return aes_secret, mac_secret, egress_mac, ingress_mac
예제 #4
0
def test_ecdh(privkey_hex, pubkey_hex, ecdh_expected):
    privkey = keys.PrivateKey(decode_hex(privkey_hex))
    pubkey = keys.PublicKey(decode_hex(pubkey_hex))
    assert ecdh_expected == encode_hex(ecies.ecdh_agree(privkey, pubkey))