Java 使用bouncycastle的椭圆曲线点加法

Java 使用bouncycastle的椭圆曲线点加法,java,bouncycastle,elliptic-curve,Java,Bouncycastle,Elliptic Curve,我的问题非常简单:我需要使用Java在Fp上添加两点。只要JavaAPI缺少一些ecc实用程序,我就使用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("4018974056

我的问题非常简单:我需要使用Java在
Fp
上添加两点。只要JavaAPI缺少一些ecc实用程序,我就使用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脚本和服务 结果是一样的,但和我的不同

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)

有人能告诉我,为了得到正确的结果,我需要解决什么问题吗?

下面是一个代码示例,它显示了显式计算,以及如何使用内置的库功能来实现这一点。在这两种情况下,输出与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));
    }
}
当您看到涉及椭圆曲线点坐标的公式时,应该理解,这些计算需要在坐标所属的有限域中进行,而您仅使用BigInteger math进行计算,例如
alpha
。结果,
除法
特别出错

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



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

非常感谢您的澄清。我还用
bcprov-1.46的可运行代码更新了您的答案