自定义 Java public 密钥生成(比特币)
Custom Java public key generation (Bitcoin)
私钥是随机生成的,不与任何钱包关联
我想为比特币准备 public 密钥生成的自定义(简单)实现。然而,经过几次尝试,我的结果是不正确的。我将它们与在线生成器进行了比较。我发现我使用了除法而不是 modinv。不幸的是,在将 division 更改为 modinv 之后,我得到了 "java.lang.ArithmeticException: BigInteger not invertible."。跟得累了https://www.mobilefish.com/services/cryptocurrency/cryptocurrency.html#refProdedure and https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication你能帮我看看哪里做错了吗?
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 > -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;
}
}
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)
当前表达式
编码如下:
y.modInverse(x).mod(p)
这是错误的,会导致出现观察到的错误消息。以下适用:
必须编码如下:
y.multiply(x.modInverse(p)).mod(p)
在add
方法中,案例:
未处理。在这里,add
方法必须 return zero
(即代表无穷远点的点)。在几何上,这种情况对应于垂直割线(2 个交叉点)。
同理,案例
未在 doublePoint
方法中处理。在这里,doublePoint
方法也必须 return zero
。在几何上,这种情况对应于垂直切线(1 个交点)。
mult
方法无效。但是关于代码中的注释,这可能是已知的。
如果使用小素数有限域,测试会更容易。 Here可以指定椭圆曲线并确定对应点。注意,必须使用带b != 0
的曲线,否则(0,0)
点是曲线的规则点,不能作为无穷远点的代表。
私钥是随机生成的,不与任何钱包关联
我想为比特币准备 public 密钥生成的自定义(简单)实现。然而,经过几次尝试,我的结果是不正确的。我将它们与在线生成器进行了比较。我发现我使用了除法而不是 modinv。不幸的是,在将 division 更改为 modinv 之后,我得到了 "java.lang.ArithmeticException: BigInteger not invertible."。跟得累了https://www.mobilefish.com/services/cryptocurrency/cryptocurrency.html#refProdedure and https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication你能帮我看看哪里做错了吗?
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 > -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;
}
}
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)
当前表达式
编码如下:
y.modInverse(x).mod(p)
这是错误的,会导致出现观察到的错误消息。以下适用:
必须编码如下:
y.multiply(x.modInverse(p)).mod(p)
在
add
方法中,案例:未处理。在这里,
add
方法必须 returnzero
(即代表无穷远点的点)。在几何上,这种情况对应于垂直割线(2 个交叉点)。同理,案例
未在
doublePoint
方法中处理。在这里,doublePoint
方法也必须 returnzero
。在几何上,这种情况对应于垂直切线(1 个交点)。mult
方法无效。但是关于代码中的注释,这可能是已知的。如果使用小素数有限域,测试会更容易。 Here可以指定椭圆曲线并确定对应点。注意,必须使用带
b != 0
的曲线,否则(0,0)
点是曲线的规则点,不能作为无穷远点的代表。