python-bitcoinlib icon indicating copy to clipboard operation
python-bitcoinlib copied to clipboard

Implement low R signing

Open brianddk opened this issue 5 years ago • 5 comments

Bitcoin Core v0.17.0 introduced R-value grinding to ensure that all DER signatures are 71 bytes. In involves looping through nonce values till you produce a smaller sig and deterministically stopping at the first one.

Electrum recently rolled it out so the code could be lifted from there.

  • Core issue: https://github.com/bitcoin/bitcoin/pull/13666
  • Electrum grinding: https://github.com/spesmilo/electrum/blob/4.0.4/electrum/ecc.py#L467
  • Reddit thread: https://www.reddit.com/r/Electrum/comments/jf97pc/
  • Test Script: https://github.com/brianddk/reddit/blob/master/python/compare-btclib-elec.py

brianddk avatar Oct 21 '20 09:10 brianddk

I've implemented for bitcointx: https://github.com/Simplexum/python-bitcointx/pull/54

For bitcoinlib that might be more involved because it still uses openssl by default

dgpv avatar Oct 21 '20 18:10 dgpv

@dgpv Awesome. Is your codebase close enough issue a PR, or are you soliciting others to do a little copypasta to bring the changes upstream?

For bitcoinlib that might be more involved because it still uses openssl by default

Well the OpenSSL libs already have malleable signatures, so you don't even need a sign call that supports nonce, just loop the sig call till you get a small one. Not sure if the OpenSSL sigs get that small though.

But yes... I always call use_libsecp256k1_for_signing(True) to ensure I don't get the OpenSSL lib.

brianddk avatar Oct 21 '20 20:10 brianddk

My codebase in this area is very different now. secp256k1 is used exclusively and not optionally. key.sign() in bitcointx is still descended from _sign_with_libsecp256k1 that I submitted to bitcoinlib long ago, and it is likely that adapting the code from bitcointx that I referenced would be easier than adapting from electrum or writing anew.

to bring the changes upstream?

Note that I do not consider bitcoinlib 'upstream' to bitcointx - it diverged significantly both in code and in overall approach ("swiss army knife" vs "specialized and strict"). But watching PRs and issues in bitcoinlib gives ideas for how to improve bitcointx, and of course anyone is free to get the code from bitcointx and port to bitcoinlib when it makes sense.

dgpv avatar Oct 21 '20 20:10 dgpv

just loop the sig call till you get a small one. Not sure if the OpenSSL sigs get that small though.

The code in Bitcoin Core and electrum is not grinding for smaller size. It specifically grinding for 'low R' value, and the smaller size is the consequence. AFAIU, you could have a signature that is 70 bytes long, but still has high R. If you just grind for size, it is likely that the lib will sometimes produce signatures that are distinguishable from signatures made with Core or electrum. This might have privacy implications.

dgpv avatar Oct 21 '20 21:10 dgpv

anyone is free to get the code from bitcointx and port to bitcoinlib when it makes sense.

@dgpv Thanks... If no one else picks up the change, I'll be happy to draft the PR. Low level object marshaling in Python is a rather new realm for me, so it might be slow going.

If you just grind for size, it is likely that the lib will sometimes produce signatures that are distinguishable from signatures made with Core or electrum. This might have privacy implications.

Yep... I meant to imply "grind till you get a good enough R". At least that is what I would suggest and will try to fold into the PR.

brianddk avatar Oct 21 '20 21:10 brianddk