Although the same private key (in byte form) was used, the resulting bitcoin address is now different than the one calculated earlier:
1BNLp3roCQws6SvC53QuYStShFJNWyh7FG (bitcoin address for compressed form)
1Pq3SXz94SCnQVGxNUqUe7g2sqxjH8g72E (bitcoin address for uncompressed form)
I am too
lazy busy (yeah that is it) to copy the private key from the screenshot but if you include it in another post I will verify I am getting the same outputs.
This is how it should be. The wording is unclear so I am not sure if you are just walking through the process or if it seemed unexpected to you. The Address is the encoded pubKeyHash and the pubkeyhash is different because the pubkeys formats are "different" (although they represent the same value). As a side note I don't think any wallet supports this but if you have a wallet which has 1,000 uncompressed pubkeys (and thus 1,0000 addresses) with the same raw private key you can generate 1,000 new compressed addresses.
The answer is that this bit of information gets encoded in the first byte of the signature. (I should write a more detailed post describing how to manually sign bitcoin messages, as it does not appear to be nearly as well documented as for signing bitcoin transactions themselves.) It seems that the rule is:
if bitcoin address corresponds to an uncompressed key
then first_byte_of_sig = 27 + (y%2)
else first_byte_of_sig = 31 + (y%2)
where y is the y-coordinate of the curve point k*G found part way through the ECDSA signing operation.
I didn't read this documented anywhere, however. I got the "27" from pybtctool and I got the 31 by inspecting the binary data of signatures produced by brainwallet.org for compressed pubkeys.
Agreed it is rather poorly documented. My understand is the 27 is just a "magic number" designed to prevent collision with other prefixes. It could have just as easily been:
1 = uncompressed & odd
2 = uncompressed & even
3 = compressed & odd
4 = compressed & even
I think I have some notes I saved when I reverse engineered it a while back. I will see what I can find.
As a side note the distinction of compressed vs uncompressed is a bitcoin specific requirement. By the ECDSA standard there is only one pubkey for a private key it just can have multiple forms. The reason why the Bitcoin message signature needs to encode if the key is compressed is because Bitcoin addresses (which are what will be recognized by the user) are the hash of the pubkey not the pubkey. Also secp256k1 makes it pretty easy there are only two possible y values for a given x value. Some curves have more (4 or even
. For this reason it really isn't necessary for the even/odd to be encoded. It can be determined by brute force (if you can call a check even and then check odd to be "brute force"). The encoding of even/odd saves on average 0.5 verifications per signature (at the cost of a marginally larger signature).
Here's what pybtctool says about the same input:
Notices that it recovers the same uncompressed public key for the bitcoin message signed by the key to 1Pq3SXz94SCnQVGxNUqUe7g2sqxjH8g72E as it does for the message signed by the key to 1BNLp3roCQws6SvC53QuYStShFJNWyh7FG. In my opinion, it should recover the compressed public key in the second case.
That may be a bug in the implementation. I would point out however the message signing protocol is rather loosely defined (especially the output). If you take a look at Bitcoin-core for example you must provide the address in the verification screen and it separates out the address, signature, and message.
I also noticed that the popular web services:
- bitaddress.og
- brainwallet.org
- blockchain.info
all default to using uncompressed pubkeys. Now that I understand the issue more clearly, I think that by default developers should have their software use compressed pubkeys. I think the reason this is not done now is that it's simply not on many people's radar.
You're right there is no reason to default to uncompressed keys certainly not in 2014. I wouldn't say it is something not on their radar, pointed it out to bc.i more than two years ago. I just don't think they care enough to make the change. Obviously uncompressed keys need to still be supported for backwards compatibility but not only should uncompressed keys not be the default it shouldn't even be possible for users to create them (baring some advanced options). Case in point if you call getnewaddress in Bitcoin core it will always return an address produced from a compressed key. The only way to add "new" uncompressed keys is to import a private key in WIF format which lacks the IsCompressed flag. I can't see a reason other than apathy which has prevented developers from switching over.
A good chance to get on my soapbox, developers make it easier for other developers to adopt good practices. If you are writing a library or tool it should default to compressed keys.
Example (C# - NBitcoin)
public Key() : this(true)
{
}
public Key(bool fCompressedIn)
{
...
SetBytes(data, data.Length, fCompressedIn);
...
}
"var k = new Key()" produces a compressed key, to create an uncompressed one requires an explicit declaration "var k = new Key(false)".