2017-07-16 128 views
1

我想爲橢圓曲線製作自己的庫。 有些事情可以工作,但有些則不行。橢圓曲線乘法函數

要從私鑰計算公鑰,您應該將發生器點與私鑰相乘,並獲得另一個點:公鑰點(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有一個特定的乘法器算法嗎?

+0

什麼是您的輸入,預期輸出和當前輸出? – tima

+0

輸入= 059E2BF5E2C7A4098C164B29A91CF70508D2FD1A256A60656FD2593BDB980FAA /輸出中預計04 = +(DA43096D079CED007CDF810ECB27030FFBDBCCAB0400A5A040D282EF8049805B,A4F8D0BE0BDABE528524245B5BBD5A125835A302F61156CE6BE48530B8F53C66) –

回答

1

是的,你的代碼有問題;當您需要以Zp(又名Z/pZ)進行分割時,您試圖在Z中分割(使用BigInteger),其中p是定義基礎字段的曲線參數(對於secp256k1,請參閱SEC2)。模塊化的劃分是通過採用模塊化的逆模塊化和乘法的Java實現的;見Scalar Multiplication of Point over elliptic Curve。此外,您還需要至少獲得最終結果模式p,並且逐步執行結果通常也更有效。

+0

它的工作原理,但此功能僅適用於secp256k1或只爲總理曲線?哪裏可以找到橢圓曲線(Prime,F2M等)的完整文檔? –

+0

@BenvanHartingsveldt:這些公式適用於Weierstrass格式的主要字段上的曲線,其中包括常用字段。我認爲任何一個地方都沒有完整的文檔,因爲這是一個新的且仍在不斷變化的領域,但對於它所覆蓋的曲線,我喜歡www.secg.org上的SECG文檔 - 它們包括我你)需要沒有大量的離題和絨毛。當然,Stack總是很好,尤其是crypto.SX和security.SX :-) –