椭圆曲线乘法函数
我想为椭圆曲线制作自己的库。 有些事情可以工作,但有些则不行。椭圆曲线乘法函数
要从私钥计算公钥,您应该将发生器点与私钥相乘,并获得另一个点:公钥点(ECPoint = BigInteger * ECPoint)。
现在,我有一个私钥,我将它与Secp256k1曲线的发生器点相乘。我得到了一把钥匙,但这不是我应该得到的钥匙。
这是我的Java代码:
import java.math.BigInteger;
public class Point{
public static final Point INFINITY = new Point();
private final BigInteger x;
private final BigInteger y;
private Point(){
this.x = null;
this.y = null;
}
public Point(BigInteger x,BigInteger y){
if(x==null || y==null){
throw new NullPointerException("x or y is null");
}
this.x = x;
this.y = y;
}
public BigInteger getX(){
return this.x;
}
public BigInteger getY(){
return this.y;
}
public boolean isInfinite(){
return this.x==null || this.y==null;
}
public Point add(Curve ec,Point Q){
Point P = this;
if(P.isInfinite()){
return Q;
}
if(Q.isInfinite()){
return P;
}
if(P.getX().equals(Q.getX()) && P.getY().equals(Q.getY())){
return this.twice(ec);
}
BigInteger lambda = Q.getY().subtract(P.getY()).divide(Q.getX().subtract(P.getX()));
BigInteger xR = lambda.pow(2).subtract(P.getX()).subtract(Q.getX());
BigInteger yR = lambda.multiply(P.getX().subtract(xR)).subtract(P.getY());
Point R = new Point(xR,yR);
return R;
}
public Point twice(Curve ec){
if(this.isInfinite()){
return this;
}
BigInteger lambda = BigInteger.valueOf(3).multiply(this.getX().pow(2)).add(ec.getA()).divide(BigInteger.valueOf(2).multiply(this.getY()));
BigInteger xR = lambda.pow(2).subtract(this.getX()).subtract(this.getX());
BigInteger yR = lambda.multiply(this.getX().subtract(xR)).subtract(this.getY());
Point R = new Point(xR,yR);
return R;
}
public Point multiply(Curve ec,BigInteger k){
//Point P = this;
//Point R = Point.INFINITY;
if(this.isInfinite()){
return this;
}
if(k.signum()==0){
return Point.INFINITY;
}
BigInteger h = k.multiply(BigInteger.valueOf(3));
Point neg = this.negate();
Point R = this;
for(int i=h.bitLength()-2;i>0;i--){
R = R.twice(ec);
boolean hBit = h.testBit(i);
boolean eBit = k.testBit(i);
if(hBit!=eBit){
R = R.add(ec,(hBit?this:neg));
}
}
return R;
}
public Point negate(){
if(this.isInfinite()){
return this;
}
return new Point(this.x,this.y.negate());
}
}
是不是有什么我的代码? secp256k1有一个特定的乘法器算法吗?
是的,你的代码有问题;当您需要以Zp(又名Z/pZ)进行分割时,您试图在Z中分割(使用BigInteger),其中p是定义基础字段的曲线参数(对于secp256k1,请参阅SEC2)。模块化的划分是通过采用模块化的逆模块化和乘法的Java实现的;见Scalar Multiplication of Point over elliptic Curve。此外,您还需要至少获得最终结果模式p,并且逐步执行结果通常也更有效。
它的工作原理,但此功能仅适用于secp256k1或只为总理曲线?哪里可以找到椭圆曲线(Prime,F2M等)的完整文档? –
@BenvanHartingsveldt:这些公式适用于Weierstrass格式的主要字段上的曲线,其中包括常用字段。我认为任何一个地方都没有完整的文档,因为这是一个新的且仍在不断变化的领域,但对于它所覆盖的曲线,我喜欢www.secg.org上的SECG文档 - 它们包括我你)需要没有大量的离题和绒毛。当然,Stack总是很好,尤其是crypto.SX和security.SX :-) –
什么是您的输入,预期输出和当前输出? – tima
输入= 059E2BF5E2C7A4098C164B29A91CF70508D2FD1A256A60656FD2593BDB980FAA /输出中预计04 = +(DA43096D079CED007CDF810ECB27030FFBDBCCAB0400A5A040D282EF8049805B,A4F8D0BE0BDABE528524245B5BBD5A125835A302F61156CE6BE48530B8F53C66) –