-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Add support for message signing/verification with SegWit addresses (BIP 137) #2657
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for message signing/verification with SegWit addresses (BIP 137) #2657
Conversation
|
Thanks for your contribution! A quick glance looks great, especially the large amount of tests. For now my main comment is this: On our master branch, ideally each commit should have one specific goal, and build successfully. This meant the accompanying unit tests should go with the changes that implement the logic to be tested. Do some of your added tests also run on the existing codebase? We could merge them earlier than the rest. |
|
Hi!
Ok, I definitely didn't follow this rule. The first rule adds test which fail because of missing functionality, and then the next commit adds the missing functionality (new range for signature header byte). I will restructure the commits so that each commit only contains only one functionality and its test. And regarding tests and existing codebase: the large set of test I added is in the new test class Of course, theoretically we could reuse the content of some of these tests (at least the signatures not created from SegWit addresses) and include it as new tests in the existing |
8cca9fb to
75aff74
Compare
BIP 137 extended the allowed range of values for the header byte of signatures (for signatures created from SegWit addresses). This commit reflects these changes and adds the newly allowed header byte values to ECKey.signedMessageToKey(...). Also adds test cases verifying signatures created with SegWit addresses.
BIP 137 defined new header byte values for the created signature when the signature was created with a private key from a SwgWit address. This commit extends the "signMessage(..)" with a new ScriptType argument (because the value of the signature header since BIP 137 depends on the address type). This commit keeps the old methods (without the ScriptType argument), but marks them as deprecated (using P2SH as default, if called without ScriptType, thus not changing old behaviour).
Since P2SH-P2WPKH addresses do not contain the public itself – but instead a value derived from a pubkey, namely RIPEMD160(SHA256(0x00 0x14 <20-byte-pubKeyHash>)) - the verification of signed messages got a bit more complicated (and different per address type). To encapsulate this complexity and make it easy to use, this commit introduces a new util class for verifying signed Bitcoin messages. It also adds some test vectors partly from other projects implementing the same functionality to test interoperability, as well as some publicly known messages and signatures.
75aff74 to
55ef43e
Compare
|
Hi! I've restructured my changes now into 3 commits (the change itself stayed the same). Each commit now has now one single goal and should build and test successfully:
As the test cases all use the API of the added utility class for verification, the majority of testcases for now also is included in the 3rd commit. I also tried to use meaningful commit messages. [edit] I also rebased on current master. [/edit] |
|
Thanks again! I just merged this, with my only change being renaming SegWit to segwit. |
Overview
MessageVerifyUtilswhich makes it easier to verify addresses without the need for taking care which address type has been used to produce the signature.Short general background info
(not related to this PR, omit if you 're familiar with the topic)
Bitcoin Signed Message:) and serialisation before hashing (i.e. using VarInt for message length) was never formally specified in a BIP but instead de-facto standardised by the implementation in the Satoshi client (now Bitcoin Core)Rvalue, 32 byteSvalue, prefixed with a single header byte containing meta information about the signature -> details see below), serialised as base64 stringrecIdin bitcoinJ, and can have a range from 0-3 (0=first recovered key with even y,1=first recovered key with odd y,2=second key with even y,3=second key with odd y)P2WPKH(native SegWit) andP2WPKH-wrapped-in-P2SH(legacy SegWit)What was missing in bitcoinJ?
As the possible allowed values for this signature's header byte had been extended in BIP 137 (new range 27-42), it was no longer possible to use
ECKey.signedMessageToKey()with signatures from SegWit addresses as it would fail when checking the signature's header byte for allowed valuesUntil now the
verifyMessage(...)method resides in theECKeyclass, which was ok, as long as all message verification operations consisted of just comparing two pubKeyHashes (the one from the given address and the one recovered from the signature). This is no longer true withP2SH-P2WPKHaddresses, as here we don't have the plain pubKeyHash in the address but insteadRIPEMD160(SHA256(0x00 0x14 <20-byte-pubKeyHash>)). So to verify messages signed with this type of address, we also need to do the same with the recovered pubKey from the signature (before we can compare it with the data contained in the address). So message signature verification is no longer script type agnostic, it needs to know the type of address, which has been used.What I did in this PR:
ECKey.signedMessageToKey (…)to allow the new header byte values added with BIP 137signMessage(...)methods with a new parameterScriptTypewhich set the header byte value according to BIP 137 when creating new signatures in this commit.MessageVerifyUtils.javaOut of scope:
BIP 322 defines a new format for signing messages, which promises to be backwards compatible to the above described legacy message signing format, but additionally will allow more sophisticated proofs (not just proof of key ownership), but this BIP is still a draft and to my knowledge not implemented by any wallet (there is only one open PR against Bitcoin Core). Therefore BIP 322 is out-of-scope of this PR.
I am happy about any feedback. 🙂 If I should structure anything different, please let me know. 🙂