Cryptography 如何利用雅可比坐标系计算椭圆曲线上的点加法

Cryptography 如何利用雅可比坐标系计算椭圆曲线上的点加法,cryptography,coordinate-systems,elliptic-curve,Cryptography,Coordinate Systems,Elliptic Curve,我正在写一个关于椭圆曲线密码的小项目,当我使用仿射坐标系时,程序运行良好,这意味着每个点由2个坐标(x',y')表示 现在我尝试用雅可比坐标系来代替仿射坐标系,其中每个点由3个坐标(x,y,z)表示,x'=x/z²和y'=y/z³ 我想知道如何将仿射坐标转换为雅可比坐标**。在一些教程中,人们使用以下公式:(x,y)=(x,y,1) 这意味着z坐标始终设置为1。但我不确定这是否正确 然后对于椭圆曲线上的点加法,计算p(x1,y1,z1)+Q(x2,y2,z2)=R(x3,y3,z3)。我在程序中

我正在写一个关于椭圆曲线密码的小项目,当我使用仿射坐标系时,程序运行良好,这意味着每个点由2个坐标(x',y')表示

现在我尝试用雅可比坐标系来代替仿射坐标系,其中每个点由3个坐标(x,y,z)表示,x'=x/z²和y'=y/z³

我想知道如何将仿射坐标转换为雅可比坐标**。在一些教程中,人们使用以下公式:(x,y)=(x,y,1) 这意味着z坐标始终设置为1。但我不确定这是否正确

然后对于椭圆曲线上的点加法,计算p(x1,y1,z1)+Q(x2,y2,z2)=R(x3,y3,z3)。我在程序中使用了以下公式:

u1 = x1.z2²
u2 = x2.z1²
s1 = y1.z2³
s2 = y2.z1³
h = u2 - u1
r = s2 - s1
x3 = r² - h³ - 2.u1.h²
Y3 = r. (U1.h² - x3) - s1.h³
z3 = z1.z2.h
但是当我测试我的程序时,我得到一些负坐标,例如(-2854978200,-5344897546224578)。当我试图用公式(x'=x/z²,y'=y/z³)将结果转换回仿射坐标系时,我得到(-8545,-27679),实际上x坐标是-8545.689。。。。雅可比x坐标不能被z²整除

如果坐标不是整数,我该怎么办?如果是阴性呢?我尝试用曲线的字段大小进行修改,但结果也不正确

因此,使用雅可比坐标
(x,y,1)
的点是正确的,但不是唯一的。满足
(a^2.x,a^3.y,a)
的所有点都是等效的。在我的程序中,曲线是在素数字段中定义的,所以当我计算
u1,u2,s1,s2…
时,我应该对每个变量应用MOD p

为了将最终结果转换回仿射坐标,例如x坐标,实际上它不是一个除法,它是一个模逆?例如,我的曲线定义在有限素数域
p=11
,我有一个点使用雅可比坐标
(15,3,2)
,要将雅可比x坐标转换为仿射x坐标,我必须计算
2^2=4=>x=4^-1 mod p=>x=3
,以及
15.3 mod p=1
,所以仿射x坐标是1,对吗

雅可比坐标的目的是避免加法过程中的除法。但是正如Thomas Pornin所说,当我们计算
P1+P2=P3
时,有一些特殊情况需要处理

  • P1和P2都是无限的:
    P3=infinite
  • P1是无限的:
    P3=P2
  • P2是无限的:
    P3=P1
  • P1和P2具有相同的x坐标,但不同的y坐标或两个y坐标均等于0:
    P3=infinite
  • P1和P2具有不同的x坐标:
    加法公式
  • P1和P2具有相同的坐标:
    倍增公式
  • 下面是我的C函数的原型:

    jac_addition(jacobian *, point *, jacobian *);
    jac_doubling(jacobian *, jacobian *);
    
    是表示仿射坐标系中定义的点的结构,对于雅可比坐标系,
    雅可比矩阵


    问题是当我处理这些特殊情况时,特别是第四种情况,我仍然需要将两个点转换回仿射坐标,或者我无法比较它们的坐标,这意味着我仍然需要计算除法。

    投影坐标的雅可比形式(与任何其他形式一样)不是唯一的-对于
    Z
    (0除外)的每个值,您都会得到其他
    X
    Y
    ,而实际点不会改变

    因此,如果在仿射坐标中有一个点
    (X',Y')
    ,则该对
    (X',Y',1)
    是该点的投影代表,以及
    (4·X',8·Y',2)
    (9·X',27·Y',3)
    等。具有1的一对最容易创建,因此通常您会使用该对

    虽然人们可以定义(并研究)任何域上的椭圆曲线,许多数学家研究复数上定义的曲线,但出于密码用途,坐标是某些有限域的元素。在最简单的情况下,我们有一个素数字段(即整数与素数的模),您必须在该字段中进行加法、减法、乘法和除法(可能还有求幂)

    只要
    Z
    不是零,您就应该能够除以
    ——这相当于乘以Z²的倒数,并且这样的元素存在,并且可以使用扩展的欧几里德算法高效地计算

    如果您的编程语言附带一些预定义了必要操作的大数库,比如Java的
    biginger
    类(及其
    mod
    modPow
    modInverse
    方法),那么这是最简单的


    所讨论的场(即模)是椭圆曲线定义的一部分,对一个场的运算给出的结果与对另一个场的运算完全不同。因此,请确保使用了正确的字段。

    处理椭圆曲线时,坐标在a中。对于密码学,这是一个;在你的例子中,“模素数p的整数”所有操作都是在该字段中进行的,也就是说,您应该执行模p的每一次加法、乘法或求逆操作

    在进行加分时,有一些特殊情况必须特别处理:

    • 有一个特殊的“无穷远点”,它没有坐标x和y。它是曲线加法的“零”。在一般的点添加例程中,您必须有一种方法来编码“无穷远处的点”,并专门检查它

    • 将(x,y)添加到(x',y')时,可能会出现x=x'。在这种情况下,y=y',然后是一个具有特定公式的点加倍(如果应用通用公式,则最终除以零,这将不起作用);或者,y=-y',在这种情况下,和是“无穷远点”

    因此,只有在处理了特殊情况后,才能应用通用公式。我
    def to_jacobian((Xp, Yp)):
        """
        Convert point to Jacobian coordinates
    
        :param (Xp,Yp,Zp): First Point you want to add
        :return: Point in Jacobian coordinates
        """
        return (Xp, Yp, 1)
    
    def from_jacobian((Xp, Yp, Zp), P):
        """
        Convert point back from Jacobian coordinates
    
        :param (Xp,Yp,Zp): First Point you want to add
        :param P: Prime number in the module of the equation Y^2 = X^3 + A*X + B (mod p)
        :return: Point in default coordinates
        """
        z = inv(Zp, P)
        return ((Xp * z**2) % P, (Yp * z**3) % P)
    
    def jacobian_add((Xp, Yp, Zp), (Xq, Yq, Zq), A, P):
        """
        Add two points in elliptic curves
    
        :param (Xp,Yp,Zp): First Point you want to add
        :param (Xq,Yq,Zq): Second Point you want to add
        :param P: Prime number in the module of the equation Y^2 = X^3 + A*X + B (mod p)
        :param A: Coefficient of the first-order term of the equation Y^2 = X^3 + A*X + B (mod p)
        :return: Point that represents the sum of First and Second Point
        """
        if not Yp:
            return (Xq, Yq, Zq)
        if not Yq:
            return (Xp, Yp, Zp)
        U1 = (Xp * Zq ** 2) % P
        U2 = (Xq * Zp ** 2) % P
        S1 = (Yp * Zq ** 3) % P
        S2 = (Yq * Zp ** 3) % P
        if U1 == U2:
            if S1 != S2:
                return (0, 0, 1)
            return jacobian_double((Xp, Yp, Zp), A, P)
        H = U2 - U1
        R = S2 - S1
        H2 = (H * H) % P
        H3 = (H * H2) % P
        U1H2 = (U1 * H2) % P
        nx = (R ** 2 - H3 - 2 * U1H2) % P
        ny = (R * (U1H2 - nx) - S1 * H3) % P
        nz = (H * Zp * Zq) % P
        return (nx, ny, nz)
    
    def fast_add(a, b, A, P):
        return from_jacobian(jacobian_add(to_jacobian(a), to_jacobian(b), A, P), P)