Путаница вокруг добавления точек на secp256k1

Я использую https://github.com/HareInWeed/gec для добавления точек на secp256k1. Код ниже добавляет две точки на кривую secp256k1 и отображает результаты.

      #include <gec/utils/macros.hpp>
#include <gec/bigint.hpp>
#include <gec/curve.hpp>
#include <iostream>

// g++ testing.cpp -O3

using namespace gec::bigint::literal; // use the bigint literal

// use uint64 x 4 to store a single element on finite field
using Bigint256 = gec::bigint::ArrayBE<uint64_t, 4>;

// define parameters required by montgomery multiplication:
GEC_DEF_GLOBAL(MOD, Bigint256,     // cardinality of finite field
    0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f_int);
constexpr Bigint256::LimbT MOD_P = // -MOD^-1 mod 2^64
    0xd838091dd2253531ull;
GEC_DEF_GLOBAL(RR, Bigint256,      // 2^512 mod MOD
    0x01000007a2000e90a1_int);
GEC_DEF_GLOBAL(ONE_R, Bigint256,   // 2^256 mod MOD
    0x1000003d1_int);

// define the finite field type
using Field = GEC_BASE_FIELD(Bigint256, MOD, MOD_P, RR, ONE_R);

// define parameters required by montgomery multiplication:
GEC_DEF_GLOBAL(CARD, Bigint256,       // cardinality of the elliptic curve
    0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141_int);
constexpr Bigint256::LimbT CARD_P =   // -CARD^-1 mod 2^64
    0x4b0dff665588b13full;
GEC_DEF_GLOBAL(CARD_RR, Bigint256,    // 2^512 mod CARD
    0x9d671cd581c69bc5e697f5e45bcd07c6741496c20e7cf878896cf21467d7d140_int);
GEC_DEF_GLOBAL(CARD_ONE_R, Bigint256, // 2^256 mod CARD
    0x14551231950b75fc4402da1732fc9bebf_int);

// define the scalar type
using Scalar = GEC_BASE_FIELD(Bigint256, CARD, CARD_P, CARD_RR, CARD_ONE_R);

// parameters of the elliptic curve, in montgomery form
const Field A(0);                 // = A * 2^256 mod MOD
const Field B(0x700001ab7_int);  // = B * 2^256 mod MOD

// define the curve with Jacobian coordinate
using Secp256k1_  = GEC_CURVE(gec::curve::JacobianCurve, Field, A, B);
// use the specialized implementation for curves whose A = 0 to boost performance
using Secp256k1   = GEC_CURVE_B(gec::curve::JacobianCurve, Field, B);

// define the generator, in montgomery form
const Secp256k1 GEN(
    Field(0x9981e643e9089f48979f48c033fd129c231e295329bc66dbd7362e5a487e2097_int),
    Field(0xcf3f851fd4a582d670b6b59aac19c1368dfc5d5d1f1dc64db15ea6d2d3dbabe2_int),
    Field(0x1000003d1_int)
);

int main()
{
    Secp256k1 p1, p2, p3;
    Secp256k1::mul(p1, 1, GEN);
    Secp256k1::mul(p2, 2, GEN);
    Secp256k1::add(p3, p1, p2);
    std::cout << p3;
    return 0;
}

Когда p1 = GEN и p2 = GEN, мы получаем p3 следующим образом

              Secp256k1 p1, p2, p3;
        Secp256k1::mul(p1, 1, GEN);
        Secp256k1::mul(p2, 1, GEN);
        Secp256k1::add(p3, p1, p2);
        std::cout << p3;

{0x7c75dd9524177d59 3c03889b8dcd9b1c b05fb7d2a3da7fe8 ba9f29b104e7db13,
 0x55debb381f4ad034 cc27cb48a46449aa a87d43fdb563384b 1cd20838e6fddc9f,
 0x9e7f0a3fa94b05ac e16d6b355833826d 1bf8baba3e3b8c9b 62bd4da6a7b75b95}

Когда мы просто вычисляем 2*GEN, мы получаем разное значение! Этого не должно произойти!

      Secp256k1 p1;
Secp256k1::mul(p1, 2, GEN);
cout << p1;

{0x0000000000000000 0000000000000000 0000000000000000 0000000000000000,
 0x0000000000000000 0000000000000000 0000000000000000 0000000000000000,
 0x0000000000000000 0000000000000000 0000000000000000 0000000000000000}

То же самое для 3*GEN.

      Secp256k1 p1;
Secp256k1::mul(p1, 3, GEN);
cout << p1;

{0x0000000000000000 0000000000000000 0000000000000000 0000000000000000,
 0x0000000000000000 0000000000000000 0000000000000000 0000000000000000,
 0x0000000000000000 0000000000000000 0000000000000000 0000000000000000}

Когда p1 = 1 GEN и p2 = 2GEN, мы получаем разные значения.

      Secp256k1 p1, p2, p3;
Secp256k1::mul(p1, 1, GEN);
Secp256k1::mul(p2, 2, GEN);
Secp256k1::add(p3, p1, p2);
cout << p3;

 {0x9981e643e9089f48 979f48c033fd129c 231e295329bc66db d7362e5a487e2097,
 0xcf3f851fd4a582d6 70b6b59aac19c136 8dfc5d5d1f1dc64d b15ea6d2d3dbabe2,
 0x0000000000000000 0000000000000000 0000000000000000 00000001000003d1}

Когда p1 = 4 GEN, p2 = 7GEN и когда p1 = 5 GEN, p2 = 6GEN, мы получаем разные значения.

      Secp256k1 p1, p2, p3;
Secp256k1::mul(p1, 4, GEN);
Secp256k1::mul(p2, 7, GEN);
Secp256k1::add(p3, p1, p2);
cout << p3;

{0x1fb5dd34380d1e8d df3cf8dcfacd3c43 5d532ba6446d8835 a4e1b7ee985a3ad2,
 0xa6a243e38cd1de5c 8bd5ab69e2291ed0 2073df16b7be047a 58dcce5a9df4f0bd,
 0x64d172d2254b1eb3 179345a5659e730e 814a734b032e6909 61fa5d4503c4cc2e}


Secp256k1 p1, p2, p3;
Secp256k1::mul(p1, 5, GEN);
Secp256k1::mul(p2, 6, GEN);
Secp256k1::add(p3, p1, p2);
cout << p3;

{0xd942c4c06e83a9f5 e120c1290faf9e8a 2ef18b316e0d17c5 e6e5daacca8fff58,
 0xf0bfc458cf399c0c 11715c0681eb3d2d 2ad8303fdd3fa737 92cefd0dbf159625,
 0xcc7ba9867d26b3fd 23553b5204634b6d 4c8e97ec206fa6ae 0dbc34de96615f6f}

Предполагается, что они должны быть такими же, как и при проверке в форме кривой Вейерштрасса.

Когда p1=4GEN и p2=6GEN, мы получаем

      Secp256k1 p1, p2, p3;
Secp256k1::mul(p1, 4, GEN);
Secp256k1::mul(p2, 6, GEN);
Secp256k1::add(p3, p1, p2);
cout << p3;

{0xde7053edb5e85ddf 98953ed4b0f65454 adae855e9701f282 4d4b2f91dc02ee5a,
 0xe6eb4afe1dc5fd6f f3f9a41b4ceb756f 00dcf2d8ebd0c6aa 93ee5d50600bc498,
 0x4bebd311ef1b73d3 271587b52ae56b5e 23fd07dec301cf5b f779ca1675b48117}

Но когда p1=6GEN и p2=4GEN, мы получаем

      Secp256k1 p1, p2, p3;
Secp256k1::mul(p1, 6, GEN);
Secp256k1::mul(p2, 4, GEN);
Secp256k1::add(p3, p1, p2);
cout << p3;

{0xde7053edb5e85ddf 98953ed4b0f65454 adae855e9701f282 4d4b2f91dc02ee5a,
 0x1914b501e23a0290 0c065be4b3148a90 ff230d27142f3955 6c11a2ae9ff43797,
 0xb4142cee10e48c2c d8ea784ad51a94a1 dc02f8213cfe30a4 088635e88a4b7b18}

Обратите внимание, что первые строки одинаковы..

Вопрос: Может ли кто-нибудь помочь мне разобраться с этой путаницей? Кто-нибудь может объяснить, что происходит? Есть ли ошибка в коде? Какая-то постоянная не в порядке?

Знайте, что в функциональности этих очков нет ничего особенного. Думайте о них как о сложении чисел. 0 должно быть 0. 4+7 должно быть равно 5+6.

0 ответов

Другие вопросы по тегам