【发布时间】:2021-08-05 15:43:36
【问题描述】:
作为学习练习,我正在尝试为 Secp256k1 椭圆曲线编写第一个点倍增(基点 P -> 2P)。我正在使用 Javascript,以及 BigNumber 的 ethers 包。令人沮丧的是,我遇到了一个问题,我得到的 2P 结果似乎并不在曲线上。有人可以帮我确定我在哪里犯了错误吗?
我得到的坐标是:
X: 0xf1b9e9c77c87bf0ac622382b581826898cfc9232e025d86d904bfd33375faf1a
Y: 0x8162c7b446b54638e9181b71770b2d718e6953a360625a02392097c7db09c608
从我的 isPointOnCurve() 方法返回 false。作为健全性检查,我检查了 isPointOnCurve() 方法中的基点,结果返回 true(谢天谢地)。
请看我下面的代码:
const { ethers, BigNumber } = require('ethers');
//variable initialization found from https://en.bitcoin.it/wiki/Secp256k1
bigZero = BigNumber.from(0);
bigTwo = BigNumber.from(2);
bigThree = BigNumber.from(3);
ellipticCurveB = BigNumber.from(7);
generatorPrime = BigNumber.from("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F");
order = BigNumber.from("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141");
baseXCoord = BigNumber.from("0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798");
baseYCoord = BigNumber.from("0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8");
// slope = ( (3*x^2) * (2*y)^-1 ) mod order
// 2Px = slope^2 - 2*baseXCoord
// 2Py = slope * ( 2Px - baseXCoord ) - baseYCoord
m = (bigThree.mul(baseXCoord.pow(bigTwo)).mul(modinv(bigTwo.mul(baseYCoord), order))).mod(order);
TwoPx = (m.pow(bigTwo).sub(bigTwo.mul(baseXCoord))).mod(order);
TwoPy = ((m.mul(baseXCoord.sub(TwoPx))).sub(baseYCoord)).mod(order);
console.log(TwoPx);
console.log(TwoPy);
console.log(isPointOnCurve(TwoPx, TwoPy));
// Helper Functions:
// Check if point is on Curve, Calculate extended GCD, modular inverse
function isPointOnCurve(x,y){
b = ellipticCurveB;
p = generatorPrime;
rem = (y.pow(bigTwo).sub(x.pow(bigThree)).sub(b)).mod(p);
return rem.eq(bigZero);
}
function egcd(a, b) {
var s = BigNumber.from(0), t = BigNumber.from(1), u = BigNumber.from(1), v = BigNumber.from(0);
while (!a.eq(BigNumber.from(0))) {
var q = b.div(a) | BigNumber.from(0), r = b.mod(a);
var m = s.sub(u.mul(q)), n = t.sub(v.mul(q));
b = a;
a = r;
s = u;
t = v;
u = m;
v = n;
}
return [b, s, t];
}
function mod(x, y) {
return (x.mod(y).add(y)).mod(y);
}
function modinv(x, y) {
var tuple = egcd(x.mod(y), y);
if (!tuple[0].eq(BigNumber.from(1))) {
return null;
}
return mod(tuple[1], y);
}
【问题讨论】:
-
您混淆了组的顺序和定义曲线的字段。曲线坐标定义在 F_p where
p=FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F所以你需要找到逆并根据这个模数执行坐标的模归约。 -
@kelalaka 所以我进入了我的代码并将模数更改为 p(我称之为 primeGenerator),它起作用了!谢谢!我会马上去更新帖子。不过,我肯定很困惑。除了确定合法私钥的范围之外,组顺序还有什么用?计算中的任何内容?
-
组顺序对于discrete log 很重要。考虑 [a]G 和 [b]G 是在 DHKE 期间通过的对,并且双方都计算 [ab]G。 ([2]G 是翻倍,[3]G 是三倍,等等。)那么如果攻击者可以解决 Dlog 而不是繁荣!
-
您可以发布您的更新代码作为答案,至少我会投票。并使其更具可读性 m、twoPx 和 twoPy 并不是很容易掌握,使用中间变量...
-
@kelalaka 非常感谢!你帮了我很大的忙,我学到的东西比我预期的要多得多。考虑到您的 cmets,我已经发布了我的答案。
标签: javascript cryptography ethereum bitcoin elliptic-curve