使用bouncycastle的椭圆曲线点加法

时间:2016-03-12 16:55:00

标签: java bouncycastle elliptic-curve

我的问题很简单:我需要使用Java在Fp上添加两个点。一旦java api缺少一些ecc utils,我就会使用bouncycastle。

以下是使用的公式:

P + Q = -R
α = (yq - yp)/(xq-xp)
уr = -yp + α(xp - xr)
xr = α^2 - xp - xq

在java中快速实现上面的公式:

String newline = System.lineSeparator();
BigInteger yp = new BigInteger("4018974056539037503335449422937059775635739389905545080690979365213431566280");
BigInteger yq = new BigInteger("17614944419213781543809391949654080031942662045363639260709847859438286763994");
BigInteger xp = new BigInteger("2");
BigInteger xq = new BigInteger("57520216126176808443631405023338071176630104906313632182896741342206604859403");
BigInteger p = new BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564821041");
BigInteger a_ = new BigInteger("7");
BigInteger b_ = new BigInteger("43308876546767276905765904595650931995942111794451039583252968842033849580414");
ECFieldElement x1 = new ECFieldElement.Fp(p, xp);
ECFieldElement y1 = new ECFieldElement.Fp(p, yp);

ECFieldElement x2 = new ECFieldElement.Fp(p, xq);
ECFieldElement y2 = new ECFieldElement.Fp(p, yq);


ECFieldElement a = new ECFieldElement.Fp(p, a_);
System.out.print("A = " + a.toBigInteger() + newline);
ECFieldElement b = new ECFieldElement.Fp(p, b_);
System.out.print("B = " + b.toBigInteger() + newline);

BigInteger alpha = (yq.subtract(yp)).divide((xq.subtract(xp)));
ECFieldElement alpha_ = new ECFieldElement.Fp(p, alpha);

ECFieldElement xr = new ECFieldElement.Fp(p,alpha.pow(2).subtract(x1.toBigInteger()).subtract(x2.toBigInteger()));
ECFieldElement yr = new ECFieldElement.Fp(p,y1.negate().add(x1.multiply(alpha_)).subtract(xr.multiply(alpha_)).toBigInteger());
System.out.print("P + Q x coordinate:" + xr.toBigInteger() + newline);
System.out.print("P + Q y coordinate:" + yr.toBigInteger() + newline);

输出如下:

A = 7
B = 43308876546767276905765904595650931995942111794451039583252968842033849580414
P + Q x coordinate:-57520216126176808443631405023338071176630104906313632182896741342206604859405
P + Q y coordinate:53877070562119060208450043081406894150999252942914736939037812638743133254761

这些结果不正确,因为遵循Sage脚本和this服务 有相同的结果,它与我的不同。

p = 57896044618658097711785492504343953926634992332820282019728792003956564821041;
A = 7;
B = 43308876546767276905765904595650931995942111794451039583252968842033849580414;
xp = 2;
yp = 4018974056539037503335449422937059775635739389905545080690979365213431566280;
xq = 57520216126176808443631405023338071176630104906313632182896741342206604859403;
yq = 17614944419213781543809391949654080031942662045363639260709847859438286763994;
F = GF(p)
C = EllipticCurve(F, [ A, B ])
P = C(xp, yp)
Q = C(xq, yq)
P + Q
(51107436475926671824327183547145585639291252685317542895128927043108270260044 : 8275382333273532770266263241039288966808027917805772529614893800343160424015 : 1)

有人可以指出我要解决的问题,以获得正确的结果吗?

1 个答案:

答案 0 :(得分:5)

这是一个代码示例,展示了显式计算以及如何仅使用内置库功能。在两种情况下,输出都与Sage输出一致。

package org.bc.sample;

import java.math.BigInteger;

import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECFieldElement;
import org.bouncycastle.math.ec.ECPoint;

public class ECPointAddition
{
    public static void main(String[] args)
    {
        BigInteger prime = new BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564821041");
        BigInteger A = new BigInteger("7");
        BigInteger B = new BigInteger("43308876546767276905765904595650931995942111794451039583252968842033849580414");

        ECCurve curve = new ECCurve.Fp(prime, A, B);

        BigInteger Px = new BigInteger("2");
        BigInteger Py = new BigInteger("4018974056539037503335449422937059775635739389905545080690979365213431566280");
        BigInteger Qx = new BigInteger("57520216126176808443631405023338071176630104906313632182896741342206604859403");
        BigInteger Qy = new BigInteger("17614944419213781543809391949654080031942662045363639260709847859438286763994");

        // Explicit affine addition
        ECFieldElement xp = curve.fromBigInteger(Px), yp = curve.fromBigInteger(Py);
        ECFieldElement xq = curve.fromBigInteger(Qx), yq = curve.fromBigInteger(Qy);
        ECFieldElement alpha = yq.subtract(yp).divide(xq.subtract(xp));
        ECFieldElement xr = alpha.square().subtract(xp).subtract(xq);
        ECFieldElement yr = xp.subtract(xr).multiply(alpha).subtract(yp);

        System.out.println("EXPLICIT");
        System.out.println(xr.toBigInteger().toString(10));
        System.out.println(yr.toBigInteger().toString(10));

        // Point addition using built-in formulae
        ECPoint P = curve.createPoint(Px, Py);
        ECPoint Q = curve.createPoint(Qx, Qy);
        ECPoint R = P.add(Q).normalize();

        System.out.println("BUILT-IN");
        System.out.println(R.getAffineXCoord().toBigInteger().toString(10));
        System.out.println(R.getAffineYCoord().toBigInteger().toString(10));
    }
}

当您看到涉及椭圆曲线点坐标的公式时,应该理解这些计算需要在坐标所属的有限域中完成,而您正在计算例如alpha只使用BigInteger数学。结果divide特别错误。

另请注意,如果两个输入点具有相同的x坐标,则此处的显式公式将无法工作。内置的库方法正确处理这种边缘情况,所以我建议你使用它。

可以找到可运行的代码版本here