简体   繁体   English

点倍增 (P -> 2P) Secp256k1 椭圆曲线的基点

[英]Point Doubling (P -> 2P) The Base Point of the Secp256k1 Elliptic Curve

as a learning exercise, I am trying to code the first point doubling (Base point P -> 2P) for the Secp256k1 Elliptic Curve.作为一项学习练习,我正在尝试为 Secp256k1 椭圆曲线编写第一个点加倍(基点 P -> 2P)。 I am using Javascript, and the ethers package for BigNumber.我正在使用 Javascript 和用于 BigNumber 的醚 package。 Frustratingly, I am running into a problem where the result I am getting for 2P doesn't appear to lie on the curve.令人沮丧的是,我遇到了一个问题,我得到的 2P 结果似乎并不在曲线上。 Can someone please help me determine where I am making a mistake?有人可以帮我确定我在哪里犯了错误吗?

The coordinates I'm getting as a result are:我得到的坐标是:

X: 0xf1b9e9c77c87bf0ac622382b581826898cfc9232e025d86d904bfd33375faf1a
Y: 0x8162c7b446b54638e9181b71770b2d718e6953a360625a02392097c7db09c608

Which returns false from my isPointOnCurve() method.从我的 isPointOnCurve() 方法返回 false 。 As a sanity check, I checked the base point in the isPointOnCurve() method, and that returns true (thankfully).作为健全性检查,我检查了 isPointOnCurve() 方法中的基点,结果返回 true(谢天谢地)。

Please see my code below:请在下面查看我的代码:

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);
}

As kelalaka pointed out in a comment on the original post, I was confusing the the order of the group and the finite field F p .正如 kelalaka 在对原始帖子的评论中指出的那样,我混淆了组的顺序和有限域 F p I was getting values modulo the Group Order, when I should've been using the values modulo prime p used to define the finite field.当我本应使用用于定义有限域的模素数 p 时,我得到了对 Group Order 取模的值。

The new and correct result I get is:我得到的新的和正确的结果是:

X: 0xc6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5
Y: 0x1ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a

If anyone would like to use this code, I've updated it to be correct, and cleaned it up to make it a little more readable:如果有人想使用此代码,我已将其更新为正确,并对其进行清理以使其更具可读性:

bigZero = BigNumber.from(0);
bigTwo = BigNumber.from(2);
bigThree = BigNumber.from(3);
ellipticCurveB = BigNumber.from(7);
generatorPrime =     BigNumber.from("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F");
baseXCoord = BigNumber.from("0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798");
baseYCoord = BigNumber.from("0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8");

// slope = ( (3*x^2) * (2*y)^-1 ) mod order
threeXSquared = bigThree.mul(baseXCoord.pow(bigTwo));
modInv2y = modinv(bigTwo.mul(baseYCoord), generatorPrime);
m = threeXSquared.mul(modInv2y).mod(generatorPrime);

// 2Px = slope^2 - 2*baseXCoord
mSquared = m.pow(bigTwo);
twoXbase = bigTwo.mul(baseXCoord);
TwoPx = (mSquared.sub(twoXbase)).mod(generatorPrime);

// 2Py = slope * ( 2Px - baseXCoord ) - baseYCoord
pointSlopeX = m.mul(baseXCoord.sub(TwoPx)); 
TwoPy = (pointSlopeX).sub(baseYCoord).mod(generatorPrime);

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 modulus(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 modulus(tuple[1], y);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM