Bitcoin Public and Private Keys Explained
At its core, a Bitcoin address starts with just a number, albiet an extermely large number. So lets take a number. 31. As a lot of Bitcoin math uses base 16 or hex numbers, we choose 31 so we can also show the conversion process.
31 in hexadecimal becomes 1F.
We convert this number into a base58 and put it in “wallet import format” or WIF.
5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreE85b5kg. You can check this is correct at brainwallet.org
Now, heres the trick. The Bitcoin protocol uses Elliptic Curve cryptography (y^2 = x^3 + ax + b), and the named curve secp256k1.
We set D = the private key 31. Then apply the multiply function to D, such that it yields a point on the curve x,y which are 32bit numbers.
The ESDCA public key (not to be confused with your bitcoin address) is then 04 concatinated with x and y
We then Double SHA256 and RipeMD160 hash 04 & x & y and convert to base 58 to give us our Bitcoin address 1KWj99Jwd9LGGC2Y1c9c4cmvWvYTQrLFVc which you can again verify at brainwallet.org. The initial primary key, in this case 31, will always create the same Bitcoin address, and only that Bitcoin address.
The code to generate is very simple, see the c# example below,
private static void CreateAddress()
Org.BouncyCastle.Math.BigInteger d = new Org.BouncyCastle.Math.BigInteger("31");
String wifofBrainWallet = CreateWif("000000000000000000000000000000000000000000000000000000000000001f");
Debug.Assert(wifofBrainWallet == "5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreE85b5kg");
Org.BouncyCastle.Asn1.X9.X9ECParameters ecp = Org.BouncyCastle.Asn1.Sec.SecNamedCurves.GetByName(CURVE_NAME);
ECDomainParameters ecDomainParams = new ECDomainParameters(ecp.Curve, ecp.G, ecp.N, ecp.H);
ECPoint publicKey = ecp.G.Multiply(d);
Byte keyArray = publicKey.GetEncoded();
Debug.Assert(keyArray.Length == 65);
String final = CreateAddress(keyArray);
Debug.Assert(final == "1KWj99Jwd9LGGC2Y1c9c4cmvWvYTQrLFVc");