title: Custom Java public key generation (Bitcoin)
body: <p>A private key is random generated and it is not correlated with any wallet.</p>
  
  <p>I want to prepare custom (naive) implementation of public key generation for a Bitcoin. However, after a few attempts my results was incorrect. I compared them with online generators. I've recognized I used division instead of modinv. Unfortunately, after changing division into modinv I got "java.lang.ArithmeticException: BigInteger not invertible.". I tired to follow <a href="https://www.mobilefish.com/services/cryptocurrency/cryptocurrency.html#refProdedure" rel="nofollow noreferrer">https://www.mobilefish.com/services/cryptocurrency/cryptocurrency.html#refProdedure</a> and <a href="https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication" rel="nofollow noreferrer">https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication</a> Could you help me recognize where I did a mistake?</p>
  
  <pre><code>public class ECDSAUtils {
  
      private static final CurvePoint G = new CurvePoint(new BigInteger("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", 16), new BigInteger("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", 16));
      private static CurvePoint zero;
      private static BigInteger base;
      private static final BigInteger three = new BigInteger("3", 10);
  
      public static void main(String[] args){
          ECDSAUtils e = new ECDSAUtils();
          BigInteger privateKey = new BigInteger("fdc668381ab251673ef8552851a2c7cf346a6e09ea86be0f55a94d2a12253557", 16);
          CurvePoint r = e.mult(G, privateKey);
          System.out.println(r.x.toString(16).toUpperCase() + " " + r.y.toString(16).toUpperCase());
      }
  
      public ECDSAUtils(){
          zero = new CurvePoint(new BigInteger("0", 16), new BigInteger("0", 16));
          base = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16);
      }
  
      public static CurvePoint add(CurvePoint p, CurvePoint q){
          CurvePoint result = null;
          if (p.equals(zero)){
              result = q;
          } else if (q.equals(zero)){
              result = p;
          } else {
              BigInteger lambda = q.y.subtract(p.y).modInverse(q.x.subtract(p.x)).mod(base);
              BigInteger x = lambda.multiply(lambda).subtract(p.x).subtract(q.x).mod(base);
              BigInteger y = lambda.multiply(p.x.subtract(x)).subtract(p.y).mod(base);
              result = new CurvePoint(x, y);
          }
          return result;
      }
  
      public static CurvePoint doublePoint(CurvePoint p){
          BigInteger lambda = p.x.multiply(p.x).multiply(three).modInverse(p.y.add(p.y)).mod(base);
          BigInteger x = lambda.multiply(lambda).subtract(p.x).subtract(p.x).mod(base);
          BigInteger y = lambda.multiply(p.x.subtract(x)).subtract(p.y).mod(base);
          return new CurvePoint(x, y);
      }
  
      public CurvePoint mult(CurvePoint N, BigInteger p) {
          CurvePoint Q = zero;
  //EDIT:
          for (int i = p.bitLength() - 1; i &gt; -1; i --) {
              if (p.testBit(i)) {
                  Q = add(Q, N);
              }
              N = doublePoint(N);
          }
  
          return Q;
      }
  }
  
  public class CurvePoint {
      BigInteger x;
      BigInteger y;
  
      public CurvePoint(BigInteger x, BigInteger y) {
          this.x = x;
          this.y = y;
      }
  }
  
  </code></pre>
  
  <pre><code>Exception in thread "main" java.lang.ArithmeticException: BigInteger not invertible.
      at java.math.MutableBigInteger.mutableModInverse(MutableBigInteger.java:1986)
      at java.math.BigInteger.modInverse(BigInteger.java:3154)
      at naive.ECDSAUtils.doublePoint(ECDSAUtils.java:41)
      at naive.ECDSAUtils.mult(ECDSAUtils.java:51)
      at naive.ECDSAUtils.main(ECDSAUtils.java:15)
  </code></pre>