Mastering Bitcoin chapter 4 - 01 Public and Private keys as points in a curve

{:deps {org.clojure/clojure {:mvn/version "1.11.1"}
        base58 {:git/url "https://github.com/fjsousa/base58"
                :sha "807fba7f9f38175531be81c4f4c4a682fc380433"}
        buddy/buddy-core {:mvn/version "1.10.413"}
        org.bouncycastle/bcprov-jdk15on {:mvn/version "1.70"}
        ;; complient is used for autocompletion
        ;; add your libs here (and restart the runtime to pick up changes)
        compliment/compliment {:mvn/version "0.3.9"}}}
Extensible Data Notation

(ns play-with-points
  (:require
   [buddy.core.hash :as hash]
   [buddy.core.codecs :as codecs]
   [base58.core :as base58])
  (:import java.math.BigInteger
   [org.bouncycastle.jce ECNamedCurveTable]))
1.3s

1 Private key

Private key k is a random 256 bit integer.

;; assuming an integer representation of a 256 bit random number
;; (Same as in Mastering bitcoin book)
(def k (BigInteger. "13840170145645816737842251482747434280357113762558403558088249138233286766301"))
(def k-hex (.toString k 16))
0.0s

2 Public key

We multiply the generator point G with k, basically adding G to itself k number of times.

Get the secp256k1 curve's parameters from bouncy castle library:

(def spec (ECNamedCurveTable/getParameterSpec "secp256k1"))
0.0s

Get the generator point G:

(def G (.getG spec))
0.0s

Multiply G with the private key to obtain the point P (the private key) and normalize (not sure what normalize means here). Points in the curve have a x and y coordinates.

(def P (.normalize (.multiply G k)))
0.1s
(def x (str (.getRawXCoord P)))
0.0s
(def y (str (.getRawYCoord P)))
0.0s

The public key is the string concatenation of prefix + x + y

(def public-key
  (str
    "04"
    (format "%064X" (BigInteger. x 16))
    (format "%064X" (BigInteger. y 16))))
(prn public-key)
0.4s

This exchange with chatGPT is also helpful:

Q: Bitcoin private keys are 256 bit integers. These are massive numbers. A public key, is achieved by multiplying the generator point of the secp256k1 curve, with the private key. how is this efficient?

A: Bitcoin private keys are 256-bit integers, which are large numbers. A public key is generated by multiplying a known generator point of the secp256k1 curve with the private key. This process is known as point multiplication and it is efficient because it takes advantage of the mathematical properties of elliptic curve cryptography.

The secp256k1 curve is defined by the equation y^2 = x^3 + 7, and the generator point is a specific point on this curve that has a large order. Point multiplication is performed by repeatedly adding a point to itself (doubling) and adding the generator point back in when the private key has a 1-bit. This process is called the "double-and-add" method.

The double-and-add method allows the multiplication to be performed in a very efficient way, because it requires very few additions and doublings. This is because the point multiplication is done by simple bit shifting and conditional bitwise operations that are much faster than traditional multiplication methods.

Additionally, the secp256k1 curve has been specifically chosen for its efficient point multiplication and the large order of the generator point. This makes it well-suited for use in public-key cryptography such as the one used in bitcoin.

In summary, the efficiency of point multiplication in generating public keys from private keys in bitcoin relies on the mathematical properties of the secp256k1 curve and the double-and-add method which is a very efficient way of doing point multiplication that takes advantage of the large order of the generator point and the specific characteristics of the secp256k1 curve.

Runtimes (1)