简体   繁体   English

证明用户压缩公钥对应曲线方程(secp256k1)

[英]Proof that user compressed public key corresponds the curve equation (secp256k1)

I am trying to check if some compressed public key corresponds to an elliptic curve equation (secp256k1).我正在尝试检查某些压缩公钥是否对应于椭圆曲线方程(secp256k1)。 As far as I know it should be valid once the following equation is fulfill y^2 = x^3 + ax + b or y^2 % p = (x^3 +ax +b) % p .据我所知,一旦满足以下等式,它应该是有效的y^2 = x^3 + ax + by^2 % p = (x^3 +ax +b) % p Supposing that I have the following key:假设我有以下密钥:

pubkey = 027d550bc2384fd76a47b8b0871165395e4e4d5ab9cb4ee286d1c60d074d7d60ef公钥 = 027d550bc2384fd76a47b8b0871165395e4e4d5ab9cb4ee286d1c60d074d7d60ef

I am able to extract x-coordinate (do to it in this case I strip 02), in theory to calculate y without sqrt operation (due to losing precision) we can do in this case: y = (x^exp) % p , where exp = (p+1)/4 based on https://crypto.stackexchange.com/questions/101142/proof-that-user-compressed-public-key-corresponds-the-curve-equation-secp256k1我能够提取 x 坐标(在这种情况下我去除 02),理论上在没有 sqrt 操作的情况下计算 y(由于失去精度)我们可以在这种情况下执行: y = (x^exp) % p , 其中exp = (p+1)/4基于https://crypto.stackexchange.com/questions/101142/proof-that-user-compressed-public-key-corresponds-the-curve-equation-secp256k1

Now based on how I calculate y :现在基于我如何计算y

bmp::uint1024_t const y = bmp::powm(x, pp, p);

//or

bmp::uint1024_t const yy = (x^pp) % p;

I have other results, which impact later computations, generally the second example gives correct final result, but it seems, that for some reasons it doesn't work as it should... for power operation it gives the following result:我还有其他结果,这会影响以后的计算,通常第二个示例给出了正确的最终结果,但似乎由于某些原因它不能正常工作......对于电源操作,它给出了以下结果:

bmp::pow(x, pp): 5668936922878426254536308284732873549115769122415677675761389126416312181579**1**
x^pp: 5668936922878426254536308284732873549115769122415677675761389126416312181579**0**

Even in python3 code for x^pp I have the same result as the second one, so should I use something other than boost::multiprecision?即使在 x^pp 的 python3 代码中,我的结果与第二个相同,所以我应该使用 boost::multiprecision 以外的东西吗? or do these computation in other way?或者以其他方式进行这些计算?

Code can be test here: https://wandbox.org/permlink/JQ3ipCq6yQjptUet代码可以在这里测试: https://wandbox.org/permlink/JQ3ipCq6yQjptUet

#include <numeric>
#include <iostream>
#include <string>

#include <boost/multiprecision/cpp_int.hpp>

namespace bmp = boost::multiprecision;

bool verify(std::string const& address, std::size_t const stripped_prefix_size)
{
    auto is_address_correct{false};
    bmp::uint1024_t const p = bmp::uint1024_t{"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"} % 4;//3 % 4;//{"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"};
    bmp::uint1024_t const a{"0x0000000000000000000000000000000000000000000000000000000000000000"};
    bmp::uint1024_t const b{"0x0000000000000000000000000000000000000000000000000000000000000007"};

    bmp::uint1024_t x{std::string{"0x"} + address.substr(2, address.size() - stripped_prefix_size)};

        
        auto const right = (bmp::pow(x, 3) + (a * x) + b) % p;
        //bmp::uint1024_t const y = bmp::sqrt(right) % p;
        bmp::uint1024_t pp = (p + 1) / 4;
        bmp::uint1024_t const y = bmp::powm(x, pp, p);
        bmp::uint1024_t const yy = (x^pp) % p;//bmp::powm(x, pp, p);
        auto const left = bmp::powm(y, 2, p);
        auto const left2 = bmp::powm(yy, 2, p);

        std::cout << "x: " << x << std::endl;
        std::cout << "y pow pp: " << bmp::pow(x, pp.convert_to<int>()) << std::endl;
        std::cout << "    y^pp: " << bmp::uint1024_t{x^pp} << std::endl;
        std::cout << "yy mod p: " << yy << std::endl;
        std::cout << " y mod p: " << y << std::endl;
        std::cout << "yy: " << yy << std::endl;
        std::cout << "right: " << right << std::endl; 
        std::cout << " left: " << left << std::endl;
        std::cout << "left2: " << left2 << std::endl;
        is_address_correct = (left == right);

    return is_address_correct;
}

int main()
{
    auto const res = verify("027d550bc2384fd76a47b8b0871165395e4e4d5ab9cb4ee286d1c60d074d7d60ef", 2);
    std::cout << "\nis valid: " << res << std::endl;
 
    return 0;
}

Output: Output:

x: 56689369228784262545363082847328735491157691224156776757613891264163121815791
y pow pp: 56689369228784262545363082847328735491157691224156776757613891264163121815791
    y^pp: 56689369228784262545363082847328735491157691224156776757613891264163121815790

yy mod p: 2

 y mod p: 0

yy: 2

right: 1

 left: 0

left2: 1

is valid: 0

For the compressed key对于压缩密钥

027d550bc2384fd76a47b8b0871165395e4e4d5ab9cb4ee286d1c60d074d7d60ef

the uncompressed representation is未压缩的表示是

047d550bc2384fd76a47b8b0871165395e4e4d5ab9cb4ee286d1c60d074d7d60effbb6217403fe57ff1b2f84f74086b413c7682027bd6ddde4538c340ba1a25638

ie IE

x = 0x7d550bc2384fd76a47b8b0871165395e4e4d5ab9cb4ee286d1c60d074d7d60ef = 56689369228784262545363082847328735491157691224156776757613891264163121815791
y = 0xfbb6217403fe57ff1b2f84f74086b413c7682027bd6ddde4538c340ba1a25638 = 113852322045593354727100676608445520152048120867463853258291211042951302108728

This is also confirmed by the following code using the Boost library:使用 Boost 库的以下代码也证实了这一点:

bool verify(std::string const& address, std::size_t const stripped_prefix_size)
{
    auto is_address_correct{false};
    
    bmp::uint1024_t const p = bmp::uint1024_t{"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"};
    bmp::uint1024_t const a{"0x0000000000000000000000000000000000000000000000000000000000000000"};
    bmp::uint1024_t const b{"0x0000000000000000000000000000000000000000000000000000000000000007"};

    bmp::uint1024_t x{std::string{"0x"} + address.substr(2, address.size() - stripped_prefix_size)};
    bmp::uint1024_t right = (bmp::powm(x, 3, p) + (a * x) + b) % p;     
    bmp::uint1024_t y = bmp::powm(right, (p + 1) / 4, p); // even, i.e. equals the searched y value because of leading 0x02 byte
    bmp::uint1024_t left = bmp::powm(y, 2, p);
 
    std::cout << "x: " << x << std::endl;           // x: 56689369228784262545363082847328735491157691224156776757613891264163121815791
    std::cout << "y: " << y << std::endl;           // y: 113852322045593354727100676608445520152048120867463853258291211042951302108728
    std::cout << "right: " << right << std::endl;   // right: 33769945388650438579771708095049232540048570303667364755388658443270938208149 
    std::cout << "left: " << left << std::endl;     // left: 33769945388650438579771708095049232540048570303667364755388658443270938208149
    is_address_correct = (left == right);

    return is_address_correct;
}

The code contains the following fixes/considerations:该代码包含以下修复/注意事项:

  • When calculating y , not x but right must be applied.计算y时,不是x而是right必须应用。
  • Because of the leading 0x02 byte, that solution of +y/-y must be used which has an even value in the positive, and this is true here for +y .由于前导 0x02 字节,必须使用+y/-y的解决方案,该解决方案在正数中具有偶数,这对于+y来说是正确的。
  • The value for p must not be taken modulo 4 (see comment by President James K. Polk). p的值不能取模 4(见 James K. Polk 总统的评论)。 The congruence of the modulus to 3 modulo 4 is only relevant for finding the correct solution path.模数与 3 模数 4 的一致性仅与找到正确的解决方案路径有关。 A more detailed explanation can be found here .更详细的解释可以在这里找到。

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

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