Bitcoin Generate Private Key C++

I’ve been wondering how Bitcoin addresses are generated. This post and the ones following will explore, step by step, how to transform a Bitcoin private key to a public address.

Key

I know that Bitcoin public and private keys are Elliptic Curve DSA (ECDSA) key pairs, and I’ve seen the Q = dG explanation on a few sites, but they leave out some details. I want to experiment for myself, so this post describes how to derive a public key from a private key with runnable code.

  1. Public Key Cryptography, or Asymmetric Cryptography, is a cryptographic system that uses pairs of keys: Public Key and Private Key. It is one of the most important (if not the most important) part of cryptocurrency protocols, and it is used in sev.
  2. Apr 29, 2018  Bitcoin Private Key Generator 2019 Bitcoin Private Key Scanner Marcene Kolb. Unsubscribe from Marcene Kolb? Cancel Unsubscribe. Subscribe Subscribed Unsubscribe 161.
  3. Question: How many public keys per private key / address? I'm curious about the structure of the relationship(s) between Bitcoin addresses, public keys, and private keys. My previous assumption was that from each private key would derive only one public key, and one address via nested RIPEMD160 and SHA256 one-way hash functions.

This is the first post in a four-part series titled “Computing a Bitcoin Address”. Here are all the articles in the series:

  • Part 1: Private to Public Key (this post)
  • Part 2: Public Key to (Hex) Address
  • Part 3: Base58Check Encoding
  • Part 4: Wallet Import Format (WIF)

The accepted Stack Overflow answer from the linked elliptic curve question above says that in the Q = dG equation, Q is the public key and d is the private key, but does not explain G, the group parameter. Luckily, some Googling quickly finds that Bitcoin uses the secp256k1 ECDSA curve.

Jul 16, 2018 We’ll use this private key throughout the article to derive both a public key and the address for the Bitcoin wallet. What we want to do is to apply a series of conversions to the private key to get a public key and then a wallet address. Most of these conversions are called hash functions. Generate a Bitcoin address. With this generator it is possible to generate a random Bitcoin address.By clicking on the generate button based on the selection the Bitcoin public, wallet and private key then is generated. All keys can be copied to clipboard with the corresponding copy button.

Next, I looked at the OpenSSLlibcrypto C library, in EC_KEY_generate_key (the function mentioned in the Stack Overflow post). Here’s the line that performs the multiplication:

In this case, I’m supplying priv_key, and pub_key is the output parameter, so I just need the appropriate group for the first parameter. OpenSSL has already defined the secp256k1 curve, so it’s just a matter of getting the right data representation. Here is the header for EC_POINT_mul from the OpenSSL library:

Looks like we need an EC_GROUP. To create one we call EC_GROUP_new_by_curve_name.

Putting everything together, here’s a function priv2pub that computes a public key from a private key (disclaimer: the code has no error-checking so don’t use this in production):

The function assumes that the input private key is in hex, and returned public key is in hex as well. I had to first convert the private key to BIGNUM, which is OpenSSL’s number representation for arbitrary precision arithmetic. The computed public key is an OpenSSL EC_POINT data structure, which represents a curve coordinate. The curve coordinate is converted back to hex using EC_POINT_point2hex. Public keys can either be compressed or uncompressed, and the format of the output of priv2pub depends on the form input parameter, which can be one of three values.

To test this function, I found a sample public/private key pair from this Bitcoin wiki article. The private key from the article is 18E14A7B6A307F426A94F8114701E7C8E774E7F9A47E2C2035DB29A206321725 and the public key is 0450863AD64A87AE8A2FE83C1AF1A8403CB53F53E486D8511DAD8A04887E5B23522CD470243453A299FA9E77237716103ABC11A1DF38855ED6F2EE187E9C582BA6. The public key begins with 0x04so we know it’s in uncompressed form (see section 2.3.3) and is 65 bytes long (see ANSI X9.62 for more details).

I used the following main function to test if priv2pub can compute the public key using the private key from the example:

I save the code above to a file priv2pub.c:

Bitcoin generate private key c key

Success!

Let’s try another example. I generated a private key with bitaddress.org, 5JQZaZrYCbJ1Kb96vFBMEefrQGuNfHSqbHbviC3URUNGJ27frFe, but it’s in Base58Check encoding and not hex. We’ll deal with Base58 encoding later so for now I went to the “Wallet Details” tab at bitaddress.org, entered the base58 key, and found that the private key in hex is 4DD3D47E491C5D34F9540EBF3444E3D6675015A46B61AF37B4EB7F17DDDF4E61 and the public key is 0492EDC09A7311C2AB83EF3D133331D7B73117902BB391D9DAC3BE261547F571E171F16775DDA6D09A6AAF1F3F6E6AA3CFCD854DCAA6AED0FA7AF9A5ED9965E117. Let’s check what our code says:

Hurrah!

A Racket Version

I’m using Racket, a modern LISP dialect, to experiment with Bitcoin so I want a Racket version of my conversion function as well. Fortunately, Racket has an FFI that enables Racket code to call C functions directly.

First I create a slightly different version of my C function:

The difference is an extra parameter and the representation of the public key output. This new function uses EC_POINT_point2oct to return a byte string instead of a hex string. The problem is that the hex conversion function, EC_POINT_point2hex, allocates, but I don’t want to manually manage memory in Racket. Because priv2pub_bytes consumes an additional buffer parameter, Racket can allocate a buffer controlled by the GC prior to calling the function, and then pass in this allocated buffer.

Next I use Racket’s FFI to create a Racket wrapper function for the priv2pub_bytes C function. The FFI requires a library file, so I compile the .c file to a .so library.

This creates a dynamic library file named libpriv2pub.so.1.0.

To create a Racket value for this library, we use the Racket ffi-lib function:

The first argument to ffi-lib is the path of the library and the second argument specifies a list of acceptable version numbers.

Once we have a hook into the C library, we can create Racket wrappers for individual functions in the library. We use the Racket get-ffi-obj function to do this:

This creates a Racket function priv2pub_bytes where the first argument is a (Racket) string, the second is an integer indicating whether the output should be in compressed or uncompressed form, and the third is the output buffer. A pointer to the output buffer is also returned by the function. We make the size the output buffer equal to the uncompressed form since that is the maximum size.

Let’s make things easier to use with a couple more functions:

Bitcoin Generate Private Key C Key

priv-key->pub-key consumes a private key in hex and returns an uncompressed public key, also in hex. priv-key->pub-key/compressed is similar except it returns a compressed public key (note that this function extracts only the first 33 bytes of the output buffer).

Testing our examples again, with the Racket (extended) REPL, we see that our Racket functions produce the same results:

Software

Private Key Bitcoin

The C code from this post is available here and the Racket code is available here. In this post, I’m using OpenSSL 1.0.1e and gcc 4.7.2, running in Debian 7.0. I had to install the libssl-dev package to get the proper header files.