grondilu / libbitcoin-perl

bitcoin perl library
19 stars 12 forks source link

How do i get compressed public keys? #2

Open buzztiaan opened 9 years ago

buzztiaan commented 9 years ago

I am making a 'input 64 hexadecimal dice rolls and get two priv/pub keys' program, and was looking for some speedincrease.

Your library seems faster than my current code, but, i fail to be able to get the compressed keys from it. Care to write a small example for that?

This gives me the uncompressed one ;

my $privkey = new EC::DSA::PrivateKey 1; my $key = new Bitcoin::Key $privkey;

print $key; print "\n"; print $key->address; print "\n";

Was messing with EC::DSA::PublicKey::UnCompressed but doesnt seem to even be used to make an address?

grondilu commented 9 years ago

I've just looked at the code (which I haven't done for years btw) and apparently I wrote a "compress" method. So you should be able to do something like:

my $privkey->public_key->compress

and get the compressed version of the public key.

buzztiaan commented 9 years ago

But don't I need it on the EC::DSA::PrivateKey?

The Bitcoin::Key doesnt have a public_key method, nor a compress .. As far as I can see, only EC::DSA::PublicKey::UnCompressed has the compress method, but as far as i can see I can't use it's output to feed into Bitcoin::Key to get a priv/pubkey pair to use for the wallet?

buzztiaan commented 9 years ago

oh, EC::DSA::PrivateKey -does- have public_key method which gets me the following result;

my $privkey = new EC::DSA::PrivateKey 1;

print $privkey->public_key->compress; print "\n";

Output :

point is not on elliptic curve at EC.pm line 46. in add at EC.pm line 59.

grondilu commented 9 years ago

I can't reproduce your error. The following works on my machine:

use EC::DSA qw(secp256k1);
say my $privkey = new EC::DSA::PrivateKey 1;
my $pubkey = bless $privkey->public_key, "EC::DSA::PublicKey::UnCompressed";
say $pubkey->compress;

As you can see I had to bless the public key manually in order to access the compress method, though. That should be automatic.

buzztiaan commented 9 years ago

Ehr, maybe i am missing some step then O_o

use Bitcoin; my $privkey = new EC::DSA::PrivateKey 1; my $pubkey = $privkey->public_key;

print $pubkey; print "\n";

my $pubkey = bless $privkey->public_key, "EC::DSA::PublicKey::UnCompressed";

print $pubkey -> compress; print "\n";

This outputs:


x: 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 y: 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8


x: 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 y: 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8

grondilu commented 9 years ago

The only difference between a compressed public key and an uncompressed one is the "serialize" method, which is not used for pretty print (what you get when you print the object). This is maybe not the best, but apparently that's how I ended up implementing it.

If you want the compressed output to show up on the screen you have to call the serialize method and unpack it (because it's binary).

say unpack "H*", $compressed_public_key->serialize;
buzztiaan commented 9 years ago

Then i still don't seem to be able to feed the compressed key into Bitcoin::Key :(

I think somehow i need to tell Bitcoin::Key to use the other serializer?

grondilu commented 9 years ago

Bitcoin::Key inherits from EC::DSA::PrivateKey. A private key is a secret exponent, and as such it is just a natural integer. There is no compression format for this. Only the public key can be compressed. So you feed Bitcoin::Key with an integer, you get the public key with the public_key method, then you bless it with EC::DSA::PublicKey::Compressed, and then you call the serialize method.

You can also explicitly call the serializer you want indeed:

say EC::DSA::PublicKey::Compressed::serialize($pubKey);
buzztiaan commented 9 years ago

But then how do i turn that back into a Bitcoin::Key so i can create the WIF and address to feed into a wallet?

buzztiaan commented 9 years ago

Or actually, feed to a QR printer ;)

grondilu commented 9 years ago

Trying making the address manually:

my $address =  new Bitcoin::Address bless $priv_key->public_key, "EC::DSA::PublicKey::Compressed";

I can't test this myself as I don't have all required modules anymore.

buzztiaan commented 9 years ago

So,

my $privkey = new EC::DSA::PrivateKey 1; my $address = new Bitcoin::Address bless $privkey->public_key, "EC::DSA::PublicKey::Compressed";

dies in a

point is not on elliptic curve at EC.pm line 46. in add at EC.pm line 59.

And this creates -a- address, but the wrong one;

my $privkey = new EC::DSA::PrivateKey 1;

my $compkey = new Bitcoin::Key $privkey; my $compkey = bless $compkey->public_key, "EC::DSA::PublicKey::Compressed";

my $address = new Bitcoin::Address bless $compkey, "EC::DSA::PublicKey::Compressed";

This outputs the address 12aJDuq56zPqWB31AHL38MUhNmr9xFNo3K but according to bitaddress , for secret exponent 0x1 it should be 1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH