libbitcoin-perl icon indicating copy to clipboard operation
libbitcoin-perl copied to clipboard

How do i get compressed public keys?

Open buzztiaan opened this issue 9 years ago • 12 comments

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?

buzztiaan avatar Mar 29 '15 14:03 buzztiaan

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.

grondilu avatar Mar 29 '15 15:03 grondilu

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 avatar Mar 29 '15 15:03 buzztiaan

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.

buzztiaan avatar Mar 29 '15 15:03 buzztiaan

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.

grondilu avatar Mar 29 '15 16:03 grondilu

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

buzztiaan avatar Mar 29 '15 16:03 buzztiaan

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;

grondilu avatar Mar 29 '15 16:03 grondilu

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?

buzztiaan avatar Mar 29 '15 17:03 buzztiaan

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);

grondilu avatar Mar 29 '15 17:03 grondilu

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 avatar Mar 29 '15 17:03 buzztiaan

Or actually, feed to a QR printer ;)

buzztiaan avatar Mar 29 '15 17:03 buzztiaan

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.

grondilu avatar Mar 29 '15 17:03 grondilu

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

buzztiaan avatar Mar 29 '15 17:03 buzztiaan