简而言之,我试图在有限域Fp上的椭圆曲线上添加两个点y ^ 2 = x ^ 3 + ax + b。我已经在R上有一个有效的实现,但是不知道如何改变我发现的通用公式,以便它们能够在Fp上维持加法。
当P不等于Q,Z是P和Q的总和时:
dydx = (Q.y - P.y)/(Q.x - P.x)
Z.x = dydx**2 - P.x - Q.x
Z.y = dydx * (Z.x - P.x) + P.y
当P等于Q时,再次用Z作为总和:
dydx = (3 * (P.x)**2 + self.a)/(2 * P.y)
Z.x = dydx**2 - 2 * P.x
Z.y = dydx * (Z.x - P.x) + P.y
这些与找到的here相同。需要修改什么?
澄清:上面的代码适用于R上的椭圆曲线。我希望找到需要更改的内容,以便在finite field的订单p上添加点。
答案 0 :(得分:7)
这里有几个问题。首先是你有错误的公式:那些是总和的否定的公式,或者等效于通过P和Q的线上的第三个曲线点。与公式比较你链接到维基百科,你会发现你对Z.y
所拥有的是对它们所具有的价值的否定。
第二个问题是你的公式没有考虑到原点:如果P是群法中Q的倒数,那么P + Q将是原点,它不会出现在曲线的仿射部分因此不能被描述为一对(x, y)
坐标。因此,您需要一些方法来指定原点。
让我们写一些代码。首先,我们需要曲线上的点的表示。我们使用字符串'Origin'
来表示原点,并使用一个简单的命名元组来表示椭圆曲线的仿射部分上的点。
# Create a simple Point class to represent the affine points.
from collections import namedtuple
Point = namedtuple("Point", "x y")
# The point at infinity (origin for the group law).
O = 'Origin'
出于演示目的,我们选择特定的椭圆曲线和素数。素数应大于3
,以使加法公式有效。我们还编写了一个函数,我们可以用它来检查特定点是曲线上某个点的有效表示。这将有助于检查我们在实施添加公式时没有犯任何错误。
# Choose a particular curve and prime. We assume that p > 3.
p = 15733
a = 1
b = 3
def valid(P):
"""
Determine whether we have a valid representation of a point
on our curve. We assume that the x and y coordinates
are always reduced modulo p, so that we can compare
two points for equality with a simple ==.
"""
if P == O:
return True
else:
return (
(P.y**2 - (P.x**3 + a*P.x + b)) % p == 0 and
0 <= P.x < p and 0 <= P.y < p)
要以模p
为模进行除法,您需要一些方法来计算模{i}的逆。p
。这里一个简单而合理有效的技巧是使用Python的pow
函数的三参数变体:通过Fermat的小定理,pow(a, p-2, p)
将给出{{1的倒数} modulo a
(当然假设该逆存在 - 也就是说,p
不能被a
整除)。
p
最后,这里有两个函数来计算椭圆曲线上的否定和加法。加法函数直接基于您给出的公式(在更正def inv_mod_p(x):
"""
Compute an inverse for x modulo p, assuming that x
is not divisible by p.
"""
if x % p == 0:
raise ZeroDivisionError("Impossible inverse")
return pow(x, p-2, p)
的符号后),使用Z.y
执行模inv_mod_p
的除法,并以最终约简模数{ {1}}用于计算的p
和p
坐标。
x
我们可以通过在曲线上创建一些点并检查它们是否符合预期的算术规则来检查上面的代码。
y
答案 1 :(得分:-1)
您可以在https://github.com/user8547/fast-ecc-python查看secp256k1,secp256r1和ed25519的参考纯python实现。