I am trying to check if some compressed public key corresponds to an elliptic curve equation (secp256r1). 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. Supposing that I have the following key:
pubkey = 027d550bc2384fd76a47b8b0871165395e4e4d5ab9cb4ee286d1c60d074d7d60ef
I am able to extract x-coordinate (do to it in this case I strip 02), so in theory I should be able to calculate it in the following way (as below), but id doesn't work as expected. I don't know if it is related to round during sqrt operation or not, does anyone have any idea what I am doing wrong ?
https://wandbox.org/permlink/uQltlj9Mu6rVPvym
#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{"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)};
{
std::cout << "############# with MODULO ################" << std::endl;
auto const right = (bmp::pow(x, 3) + (a * x) + b) % p;
bmp::uint1024_t const y = bmp::sqrt(right) % p;
auto const left = bmp::pow(y, 2);
std::cout << "x: " << x << std::endl;
std::cout << "y: " << y << std::endl;
std::cout << "right: " << right << std::endl;
std::cout << " left: " << left << std::endl;
is_address_correct = (left == right);
}
{
std::cout << std::endl << "############# without MODULO ################" << std::endl;
auto const right = (bmp::pow(x, 3) + (a * x) + b);
bmp::uint1024_t const y = bmp::sqrt(right);
auto const left = bmp::pow(y, 2);
std::cout << "x: " << x << std::endl;
std::cout << "y: " << y << std::endl;
std::cout << "right: " << right << std::endl;
std::cout << " left: " << left << 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;
}
Program output:
############# with MODULO ################ x: 56689369228784262545363082847328735491157691224156776757613891264163121815791 y: 183766007163050801754608903653841862618 right: 33769945388650438579771708095049232540048570303667364755388658443270938208149 left: 33769945388650438579771708095049232539920934980046904834800557419775585813924
############# without MODULO ################ x: 56689369228784262545363082847328735491157691224156776757613891264163121815791 y: 13497472057468355938572038677065615761097144061311551195730691629950308697806550176813818086835150901176637717416722 right: 182181751942139053636431558335628486248480898622843767538654320228825581987479906778155585847291878917907922072895611492267301384350099726325450762811050934436031042086671820982050911377912589308184841627685631347496623032412958678 left: 182181751942139053636431558335628486248480898622843767538654320228825581987479906778155585847291878917907922072895585240175884415988084178980651571231083458654830397520853615320131308334828726829265223601702424747233734581005225284
is valid: 0