Anti-Exfil Protocol

The following walkthrough demonstrates how to use libwally to implement the ECDSA Anti-Exfil Protocol to prevent a signing device from exfiltrating the secret signing keys through biased signature nonces. For the full details, see here.

The example code here is written in python using the generated python swig wrappers.

Step 1

The host draws randomness rho and computes a commitment to it:

host_commitment = wally.ae_host_commit_from_bytes(rho, wally.EC_FLAG_ECDSA)

Host sends host_commitment to the signer.

Step 2

The signing device computes the original nonce R, i.e. signer commitment:

signer_commitment = wally.ae_signer_commit_from_bytes(priv_key, message_hash, host_commitment, wally.EC_FLAG_ECDSA)

Signing device sends signer_commitment to the host.

Warning

If, at any point from this step onward, the hardware device fails, it is okay to restart the protocol using exactly the same rho and checking that the hardware device proposes exactly the same R. Otherwise, the hardware device may be selectively aborting and thereby biasing the set of nonces that are used in actual signatures.

It takes many (>100) such aborts before there is a plausible attack, given current knowledge in 2020. However such aborts accumulate even across a total replacement of all relevant devices (but not across replacement of the actual signing keys with new independently random ones).

In case the hardware device cannot be made to sign with the given rho, R pair, wallet authors should alert the user and present a very scary message implying that if this happens more than even a few times, say 20 or more times EVER, they should change hardware vendors and perhaps sweep their coins.

Step 3

The host replies with rho generated at Step 1.

Step 4

The signing device signs and provide the signature to the host:

signature = wally.ae_sig_from_bytes(priv_key, message_hash, rho, wally.EC_FLAG_ECDSA)

Step 5

The host verifies that the signature’s public nonce matches the signer commitment R from Step 2 and its original randomness rho:

wally.ae_verify(pub_key, message_hash, rho, signer_commitment, wally.EC_FLAG_ECDSA, signature)