Bitcoin Forum
June 19, 2024, 07:22:12 AM *
News: Latest Bitcoin Core release: 27.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: [1]
  Print  
Author Topic: Perl Private Key -> Public Address  (Read 1424 times)
ethought (OP)
Legendary
*
Offline Offline

Activity: 1316
Merit: 1000



View Profile
March 19, 2015, 07:09:45 PM
 #1

Does any one have a minimal / basic perl script that can generate a public addresses given a 32 byte private key?

Most of the perl code examples on Github are unmaintained / broken / years old and I am having troubles getting any of them working.

Something similar to this python code:

Code:
import ecdsa

secp256k1curve=ecdsa.ellipticcurve.CurveFp(115792089237316195423570985008687907853269984665640564039457584007908834671663,0,7)
secp256k1point=ecdsa.ellipticcurve.Point(secp256k1curve,0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8,0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141)
secp256k1=ecdsa.curves.Curve('secp256k1',secp256k1curve,secp256k1point,(1,3,132,0,10))

#--------------------------------------

import binascii, hashlib

def addy(pk):
 pko=ecdsa.SigningKey.from_secret_exponent(pk,secp256k1)
 pubkey=binascii.hexlify(pko.get_verifying_key().to_string())
 pubkey2=hashlib.sha256(binascii.unhexlify('04'+pubkey)).hexdigest()
 pubkey3=hashlib.new('ripemd160',binascii.unhexlify(pubkey2)).hexdigest()
 pubkey4=hashlib.sha256(binascii.unhexlify('00'+pubkey3)).hexdigest()
 pubkey5=hashlib.sha256(binascii.unhexlify(pubkey4)).hexdigest()
 pubkey6=pubkey3+pubkey5[:8]
 pubnum=int(pubkey6,16)
 pubnumlist=[]
 while pubnum!=0: pubnumlist.append(pubnum%58); pubnum/=58
 address=''
 for l in ['123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'[x] for x in pubnumlist]:
  address=l+address
 return '1'+address
 
print addy(0x18E14A7B6A307F426A94F8114701E7C8E774E7F9A47E2C2035DB29A206321725)
print addy(int(hashlib.sha256('something small and easy to remember but not easy to guess').hexdigest(),16))


ref: https://bitcointalk.org/index.php?topic=84238.0

Would be happy to provide a small bounty.

thanks



dserrano5
Legendary
*
Offline Offline

Activity: 1974
Merit: 1029



View Profile
March 19, 2015, 07:19:40 PM
 #2

I do have some Perl but in the bit privkey → pubkey I cheat via "use Inline" Wink. C compiler and libssl-dev required.
ethought (OP)
Legendary
*
Offline Offline

Activity: 1316
Merit: 1000



View Profile
March 19, 2015, 07:25:38 PM
 #3

I do have some Perl but in the bit privkey → pubkey I cheat via "use Inline" Wink. C compiler and libssl-dev required.

Interested..  Smiley
dserrano5
Legendary
*
Offline Offline

Activity: 1974
Merit: 1029



View Profile
March 19, 2015, 08:19:49 PM
 #4

Code:
#!/usr/bin/perl

use strict;
use warnings;
use Digest::SHA qw/sha256/;
use Crypt::Digest::RIPEMD160 qw/ripemd160/;
use Encode::Base58::GMP;
use Inline C => Config => LIBS => '-lssl';
use Inline C => <<'END_OF_C_CODE';
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <openssl/ec.h>
#include <openssl/bn.h>

#define NID_secp256k1       714

SV* get_pubkey (char *pk) {
    EC_KEY *k = NULL;
    EC_POINT *pub_key = NULL;
    const EC_GROUP *group = NULL;
    BIGNUM start;
    BIGNUM *priv_key;
    BN_CTX *ctx;

    BN_init(&start);
    ctx = BN_CTX_new();
    assert(ctx);

    priv_key = &start;
    BN_hex2bn(&priv_key,pk);

    k = EC_KEY_new_by_curve_name(NID_secp256k1); assert(k);
    group = EC_KEY_get0_group(k); assert(group);
    pub_key = EC_POINT_new(group); assert(pub_key);
    assert(EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx)); assert(pub_key);

    char *hex = EC_POINT_point2hex(group, pub_key, POINT_CONVERSION_UNCOMPRESSED, ctx);
    SV *hex_copy = newSVpvf("%s", hex);
    OPENSSL_free(hex);

    return hex_copy;
}
END_OF_C_CODE

sub base58_gmp_to_btc {
    my ($base58) = @_;
    $base58 =~ y|0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv|123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz|;
    return $base58;
}

sub b58_gmp {
    my ($str) = @_;
    return base58_gmp_to_btc encode_base58 "0x$str", 'gmp';
}

sub checksum { return uc unpack 'H8', sha256 sha256 pack 'H*', shift }

sub hash160 { return unpack 'H*', ripemd160 sha256 pack 'H*', shift; }

my @leaders; @leaders[0,5] = (1, 3);
sub b58ck {
    my ($ver, $str) = @_;
    my $cksum = checksum "$ver$str";

    "$ver$str$cksum" =~ /^(0*)/;
    my $num_leading_0s = int +(length $1)/2;

    my $b58c = sprintf "%34s", b58_gmp  "$ver$str$cksum";

    my $b58 = $b58c;
    $b58 =~ s/ //g;
    $b58 = sprintf "%s$b58", $leaders[$ver]x$num_leading_0s;

    return $b58;
}

my $privkey = '1900966ca8703f337ad2c191718af367a04a1929685fe17e4b7fa3e1b9dd6d2d';  ## change me!
my $pubkey = get_pubkey $privkey;
my $h160 = hash160 $pubkey;
my $addr = b58ck '00', $h160;
print <<"EOF";
privkey $privkey
pubkey $pubkey
h160 $h160
addr $addr
EOF
ethought (OP)
Legendary
*
Offline Offline

Activity: 1316
Merit: 1000



View Profile
March 20, 2015, 11:36:33 AM
 #5

Thanks very much. Looks great but cannot get it working unfortunately.

I have /usr/include/openssl/bn.h but am getting the following error:

Quote
undefined symbol: BN_init

Looking in bn.h 'BN_init' does not seem to exist...

Will keep trying though.



dserrano5
Legendary
*
Offline Offline

Activity: 1974
Merit: 1029



View Profile
March 20, 2015, 07:10:45 PM
 #6

Looking in bn.h 'BN_init' does not seem to exist...

In my case:

Code:
$ grep -r BN_init /usr/include/openssl/
/usr/include/openssl/bn.h:void BN_init(BIGNUM *);

Code:
$ dpkg -l |grep ssl.*dev
ii  libssl-dev                        1.0.1e-2+deb7u15      amd64                 SSL development libraries, header files and documentation
ii  libssl-doc                        1.0.1e-2+deb7u15      all                   SSL development documentation documentation
DryPalms
Newbie
*
Offline Offline

Activity: 7
Merit: 0


View Profile
July 08, 2018, 12:48:12 AM
Last edit: July 08, 2018, 09:53:51 PM by DryPalms
 #7

dserrano5, great piece of code, works like a charm. The inline C code based on openssl you provided generates over 1500 pubkeys per second which is 5+ times more than any native Perl implementation of secp256k1 curve.

But it seems there might be significant improvement in speed if the code written using inline C based on libsecp256k1 (#include <secp256k1.h>) library. Unfortunately, I am not familiar with C enough to do that. Can anyone rewrite dserrano5's code to use libsecp256k1 lib to generate compressed/uncompressed pubkeys from private key? It should be working many times faster.

Thanks in advance! Would be glad to donate Smiley

PS: This is kind of an old thread but I think it not worth opening a new one so I decided posting here as here is all the pre-history present. Sorry if I am wrong.

UPD: The code seems to have a memory leak because after running it for 24 hours it takes 37% of memory on my server with 48Gb RAM.
DryPalms
Newbie
*
Offline Offline

Activity: 7
Merit: 0


View Profile
June 04, 2021, 12:32:32 PM
 #8

Anyone? I am sitting here waiting for a reply for the last three years  Grin
pooya87
Legendary
*
Offline Offline

Activity: 3486
Merit: 10665



View Profile
June 04, 2021, 12:48:05 PM
 #9

Anyone? I am sitting here waiting for a reply for the last three years  Grin
How about finding a way to call C functions from Perl, I'm not familiar with Perl so here is a link: https://stackoverflow.com/questions/4048557/calling-c-function-from-perl-within-embedded-c-application
Then you can use the library that bitcoin core uses known as libsec256k1: https://github.com/bitcoin-core/secp256k1
That way you don't have to worry about the library not being complete or having any bugs.

.
.BLACKJACK ♠ FUN.
█████████
██████████████
████████████
█████████████████
████████████████▄▄
░█████████████▀░▀▀
██████████████████
░██████████████
████████████████
░██████████████
████████████
███████████████░██
██████████
CRYPTO CASINO &
SPORTS BETTING
▄▄███████▄▄
▄███████████████▄
███████████████████
█████████████████████
███████████████████████
█████████████████████████
█████████████████████████
█████████████████████████
███████████████████████
█████████████████████
███████████████████
▀███████████████▀
█████████
.
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!