Bitcoin Forum
April 26, 2024, 07:58:51 AM *
News: Latest Bitcoin Core release: 27.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: [1]
  Print  
Author Topic: Private key to Public key  (Read 18472 times)
qqq123 (OP)
Newbie
*
Offline Offline

Activity: 11
Merit: 0


View Profile
April 26, 2012, 04:52:46 AM
 #1

Hello,

I am here looking for an understanding of the math behind converting a Bitcoin private key to a Bitcoin public key for a website I am creating.  The website will be capable of dynamically creating a private key and the corresponding public key and Bitcoin address (much like bitaddress.org).

If anyone can help with this understanding, I'd appreciate it.

Thanks.
1714118331
Hero Member
*
Offline Offline

Posts: 1714118331

View Profile Personal Message (Offline)

Ignore
1714118331
Reply with quote  #2

1714118331
Report to moderator
1714118331
Hero Member
*
Offline Offline

Posts: 1714118331

View Profile Personal Message (Offline)

Ignore
1714118331
Reply with quote  #2

1714118331
Report to moderator
Every time a block is mined, a certain amount of BTC (called the subsidy) is created out of thin air and given to the miner. The subsidy halves every four years and will reach 0 in about 130 years.
Advertised sites are not endorsed by the Bitcoin Forum. They may be unsafe, untrustworthy, or illegal in your jurisdiction.
1714118331
Hero Member
*
Offline Offline

Posts: 1714118331

View Profile Personal Message (Offline)

Ignore
1714118331
Reply with quote  #2

1714118331
Report to moderator
1714118331
Hero Member
*
Offline Offline

Posts: 1714118331

View Profile Personal Message (Offline)

Ignore
1714118331
Reply with quote  #2

1714118331
Report to moderator
1714118331
Hero Member
*
Offline Offline

Posts: 1714118331

View Profile Personal Message (Offline)

Ignore
1714118331
Reply with quote  #2

1714118331
Report to moderator
Red Emerald
Hero Member
*****
Offline Offline

Activity: 742
Merit: 500



View Profile WWW
April 26, 2012, 05:11:46 AM
 #2

The wiki is an amazing resource.

https://en.bitcoin.it/wiki/Technical_background_of_Bitcoin_addresses

qqq123 (OP)
Newbie
*
Offline Offline

Activity: 11
Merit: 0


View Profile
April 26, 2012, 01:44:10 PM
 #3

I've read that article more times than I can count.  It still doesn't explain the equation(s) used to go from the private key to the public key.  It just says "1) Have a private ECDSA key. 2) Take the public key generated with it (65 bytes, 1 byte 0x04, 32 bytes corresponding to X coordinate, 32 bytes corresponding to Y coordinate)."  I do not understand how that public key is generated, despite reading several articles on elliptic curve cryptography.
payb.tc
Hero Member
*****
Offline Offline

Activity: 812
Merit: 1000



View Profile
April 26, 2012, 01:51:30 PM
 #4

if the private key is a hex string, try following the below functions.

(apologies to the author, i don't remember where i found this code)

Code:
define("ADDRESSVERSION","00"); //this is a hex byte
 
function decodeHex($hex)
{
        $hex=strtoupper($hex);
        $chars="0123456789ABCDEF";
        $return="0";
        for($i=0;$i<strlen($hex);$i++)
        {
                $current=(string)strpos($chars,$hex[$i]);
                $return=(string)bcmul($return,"16",0);
                $return=(string)bcadd($return,$current,0);
        }
        return $return;
}
 
function encodeHex($dec)
{
        $chars="0123456789ABCDEF";
        $return="";
        while (bccomp($dec,0)==1)
        {
                $dv=(string)bcdiv($dec,"16",0);
                $rem=(integer)bcmod($dec,"16");
                $dec=$dv;
                $return=$return.$chars[$rem];
        }
        return strrev($return);
}
 
function decodeBase58($base58)
{
        $origbase58=$base58;
       
        $chars="123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
        $return="0";
        for($i=0;$i<strlen($base58);$i++)
        {
                $current=(string)strpos($chars,$base58[$i]);
                $return=(string)bcmul($return,"58",0);
                $return=(string)bcadd($return,$current,0);
        }
       
        $return=encodeHex($return);
       
        //leading zeros
        for($i=0;$i<strlen($origbase58)&&$origbase58[$i]=="1";$i++)
        {
                $return="00".$return;
        }
       
        if(strlen($return)%2!=0)
        {
                $return="0".$return;
        }
       
        return $return;
}
 
function encodeBase58($hex)
{
        if(strlen($hex)%2!=0)
        {
                die("encodeBase58: uneven number of hex characters");
        }
        $orighex=$hex;
       
        $chars="123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
        $hex=decodeHex($hex);
        $return="";
        while (bccomp($hex,0)==1)
        {
                $dv=(string)bcdiv($hex,"58",0);
                $rem=(integer)bcmod($hex,"58");
                $hex=$dv;
                $return=$return.$chars[$rem];
        }
        $return=strrev($return);
       
        //leading zeros
        for($i=0;$i<strlen($orighex)&&substr($orighex,$i,2)=="00";$i+=2)
        {
                $return="1".$return;
        }
       
        return $return;
}
 
function hash160ToAddress($hash160,$addressversion=ADDRESSVERSION)
{
        $hash160=$addressversion.$hash160;
        $check=pack("H*" , $hash160);
        $check=hash("sha256",hash("sha256",$check,true));
        $check=substr($check,0,8);
        $hash160=strtoupper($hash160.$check);
        return encodeBase58($hash160);
}
 
function addressToHash160($addr)
{
        $addr=decodeBase58($addr);
        $addr=substr($addr,2,strlen($addr)-10);
        return $addr;
}
 
function checkAddress($addr,$addressversion=ADDRESSVERSION)
{
        $addr=decodeBase58($addr);
        if(strlen($addr)!=50)
        {
                return false;
        }
        $version=substr($addr,0,2);
        if(hexdec($version)>hexdec($addressversion))
        {
                return false;
        }
        $check=substr($addr,0,strlen($addr)-8);
        $check=pack("H*" , $check);
        $check=strtoupper(hash("sha256",hash("sha256",$check,true)));
        $check=substr($check,0,8);
        return $check==substr($addr,strlen($addr)-8);
}
 
function hash160($data)
{
        $data=pack("H*" , $data);
        return strtoupper(hash("ripemd160",hash("sha256",$data,true)));
}
 
function pubKeyToAddress($pubkey)
{
        return hash160ToAddress(hash160($pubkey));
}
 
function remove0x($string)
{
        if(substr($string,0,2)=="0x"||substr($string,0,2)=="0X")
        {
                $string=substr($string,2);
        }
        return $string;
}
qqq123 (OP)
Newbie
*
Offline Offline

Activity: 11
Merit: 0


View Profile
April 26, 2012, 02:06:57 PM
 #5

That's from here, and I don't think it can be used to go from a private key to a public key.
Red Emerald
Hero Member
*****
Offline Offline

Activity: 742
Merit: 500



View Profile WWW
April 26, 2012, 05:56:04 PM
 #6

So you want to know how the initial private and public key are created with ECDSA?  "Complex Math" is as far as I've gone into that one personally.

http://en.wikipedia.org/wiki/Elliptic_Curve_DSA

Stephen Gornick
Legendary
*
Offline Offline

Activity: 2506
Merit: 1010


View Profile
April 27, 2012, 02:29:33 AM
Last edit: April 27, 2012, 03:06:22 AM by Stephen Gornick
 #7

The website will be capable of dynamically creating a private key and the corresponding public key and Bitcoin address (much like bitaddress.org)

Doesn't explain the math behind it, but an example of it is in the Javascript from the HTML source here:
 - http://BitAddress.org

[Update: More info here?
 - http://bitcointalk.org/index.php?topic=3238.0
 - http://bitcointalk.org/index.php?topic=53177.0
 - https://bitcointalk.org/index.php?topic=74136.0 ]

Unichange.me

            █
            █
            █
            █
            █
            █
            █
            █
            █
            █
            █
            █
            █
            █
            █
            █


payb.tc
Hero Member
*****
Offline Offline

Activity: 812
Merit: 1000



View Profile
April 27, 2012, 02:49:26 AM
 #8

That's from here, and I don't think it can be used to go from a private key to a public key.

Quote
* @author theymos (functionality)

ah yeah, from before mike put it in a class.
qqq123 (OP)
Newbie
*
Offline Offline

Activity: 11
Merit: 0


View Profile
April 27, 2012, 07:09:55 PM
Last edit: April 27, 2012, 07:25:58 PM by qqq123
 #9

Thanks for the replies.  From what I've read I've gathered that:

PuK = G * PrK

where PuK is the public key, G is the set of (x, y) coordinates for the secp256k1 elliptic curve, which are, in hex, (x = 79BE667E F9DCBBAC 55A06295 CE870B07 029BFCDB 2DCE28D9 59F2815B 16F81798, y = 483ADA77 26A3C465 5DA4FBFC 0E1108A8 FD17B448 A6855419 9C47D08F FB10D4B8), PrK is the private key, and * stands for point multiplication.

I am, however, having trouble implementing point multiplication.  I've read the wiki article here, and understand that it's basically doubling and adding the point, but I can't quite wrap my head around the pseudocode they give.  Can anyone help with that?  I'm working in php, but anything would help really.

Thanks.
qqq123 (OP)
Newbie
*
Offline Offline

Activity: 11
Merit: 0


View Profile
April 28, 2012, 03:04:44 AM
 #10

If anyone has any test problems I can run for point multiplication on the secp256k1 curve that would be great.  I think I have the implementation down, but the fact that everything is in hex is giving me fits.  I would love to be able to verify that the point multiplication works in decimal before moving on the tackling hex.

Doing the math by hand, I know that 2 * (4, 3) = (56, -419).
But doing large multiplications by hand is impossible.
For example, 100 * (4, 3) = Huh

And for actually doing the point multiplication required by bitcoin...

Let's say privatekey (in hex) = 059E2BF5E2C7A4098C164B29A91CF70508D2FD1A256A60656FD2593BDB980FAA
so privatekey in dec = 2541029483313867478679144795827841690699430215057902992954466247848698056618
Gx (in hex) = 79BE667E F9DCBBAC 55A06295 CE870B07 029BFCDB 2DCE28D9 59F2815B 16F81798
so Gx in dec = 55066263022277343669578718895168534326250603453777594175500187360389116729240
Gy (in hex) = 483ADA77 26A3C465 5DA4FBFC 0E1108A8 FD17B448 A6855419 9C47D08F FB10D4B8
so Gy in dec = 32670510020758816978083085130507043184471273380659243275938904335757337482424

so, given that privatekey * (Gx, Gy) = publickey
the math is (in dec): 2541029483313867478679144795827841690699430215057902992954466247848698056618 * (55066263022277343669578718895168534326250603453777594175500187360389116729240, 32670510020758816978083085130507043184471273380659243275938904335757337482424).

Having a real hard time seeing if my function works with numbers that big...
dansmith
Full Member
***
Offline Offline

Activity: 202
Merit: 100


View Profile
June 23, 2013, 11:12:53 PM
 #11

Since this thread comes up on top when searching for priv key to pub key conversion, here is a link to a self-contained python file where you can see all the background mechanics.

https://bitcointalk.org/index.php?topic=23241.0

https://tlsnotary.org
Transferable webpage content notarization.
thedrs
Newbie
*
Offline Offline

Activity: 40
Merit: 0



View Profile
April 04, 2016, 10:59:22 PM
 #12

This is an old thread.
But just for people who land here and actually want to understand how to code the calculation from private to public key
See here:
http://procbits.com/2013/08/27/generating-a-bitcoin-address-with-javascript
bitdumper
Sr. Member
****
Offline Offline

Activity: 266
Merit: 250

One world One currency, Bitcoin.


View Profile
April 05, 2016, 04:20:02 AM
 #13

If your backend is python
https://github.com/weex/addrgen

If it's php
https://github.com/RobKohr/PHP-Bitcoin-Address-Creator

If it's nodejs
Then
This is an old thread.
But just for people who land here and actually want to understand how to code the calculation from private to public key
See here:
http://procbits.com/2013/08/27/generating-a-bitcoin-address-with-javascript


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!