我试图实现 ECDSA 公钥生成算法,但输出错误。我做错了什么?

问题描述 投票:0回答:0

出于教学目的,我尝试用 C++ 实现基本的 ECDSA 算法(并在非基于性能的离线程序中适度使用)。我尝试以编程方式使用基本方法来实现这一点,但它一直没有奏效,我不得不通过推迟这个特定模型来消除它。

我最近被提醒我没有展示这个,所以我决定寻求帮助。

椭圆曲线名称我做错了什么。有人,任何人,请教我如何以及为什么这不起作用。

是不是错误实现了mod反函数? 还是十进制转二进制的函数? 或者在循环的二进制字符中调用 ADD() 或 DOUBLE()?

我做错了什么?

我使用私钥的已知公钥输出,其值为

112757557418114203588093402336452206775565751179231977388358956335153294300646
.

Expected PublicKey = 
x: 338862860998134191820545952520423482146950914608322024530631065951421850289,
y: 95297529534878812336940782639534071162224996323592980142550971823499987176;

BigInteger 实现库源代码 bigint-2010.04.30.zip

所有使用的自定义函数都在代码中添加。

附言 在尝试生成签名和校验和哈希时,我也遇到了类似的错误计算。 非常感谢使这段代码工作的任何帮助。

#include "bignum_def.h"
#include <vector> // Include vector header file
#include <sstream> // Include sstream header file

using std::cout; // enables you to call as "cout" instead of "std::cout"
using std::string; // enables you to call as "string" instead of "std::string"
using std::stringstream; // enables you to call as "stringstream" instead of "std::stringstream"
using std::vector; // enables you to call as "vector" instead of "std::vector"


// GLOBAL Variables
BigInteger p = stringToBigInteger("1157920892316195423570985008687907853269984665640564039457584007908834671663");
BigInteger n = stringToBigInteger("11579208923161954235709850086879078528375642790904382605163141518161494337");
BigInteger G_X = stringToBigInteger("55066263022236695787188951685343262506034537775941755001860389116729240");
BigInteger G_Y = stringToBigInteger("32670510020758816978083085130507043184471238065924327593890433575382424");
BigInteger Gxy = stringToBigInteger("5506626302223669578718895168534326250603453777594175500186038911672924032670510020758816978083085130507043184471238065924327593890433575382424");

BigInteger expected_x = stringToBigInteger("338862860998134191820545952520423482146950914608322024530631065951421850289");
BigInteger expected_y = stringToBigInteger("95297529534878812336940782639534071162224996323592980142550971823499987176");
BigInteger Pub_xy = stringToBigInteger("33886286099813419182054595252042348214695091460832202453063106595142185028995297529534878812336940782639534071162224996323592980142550971823499987176");


// Function Prototypes

void Multiply(BigInteger PRIVATEKEY, vector<BigInteger> &PUBLICKEY);
BigInteger Inverse(BigInteger a, BigInteger m);
void Double(BigInteger &x, BigInteger &y);
void ADD(BigInteger &Point1_x, BigInteger &Point1_y, BigInteger Point2_x, BigInteger Point2_y);

BigInteger BigInteger_power(BigInteger n, BigInteger e)
{
    BigInteger x = n; // declare uint32_t decimal variable and assign the value of base number to it
    if (e == 0) // if exponent value is 0
        return n; // No need for loop, return 1
    if (n == 0) // if base value is 0
        return 1; // No need for loop, return 0

    for (BigInteger b = 1; b < e; b++) // for exponent value starting from an offset of 1
        n = n*x; // base value * base value
    return n; // return value
}


string BigToLittleAlphabets(string data)
{
    for (int i = 0; i < data.size(); i++)
    {
        if (data[i] == 'A')
            data[i] = 'a';
        if (data[i] == 'B')
            data[i] = 'b';
        if (data[i] == 'C')
            data[i] = 'c';
        if (data[i] == 'D')
            data[i] = 'd';
        if (data[i] == 'E')
            data[i] = 'e';
        if (data[i] == 'F')
            data[i] = 'f';
    }
    return data;
}


string IntegerToHex(BigInteger num)
{
    vector<char> arr;
    string cache;
    int i = 0;
    if (num == 0)
    {
        stringstream cs;
        cs << num;
        cs >> cache;
        cs.clear();
        return cache;
    }
    while(num != 0) 
    {
        int temp = 0;
        temp = (num % 16).toUnsignedInt();
        if(temp < 10)
        {
            arr.push_back(temp + 48);
            i++;
        } 
        else 
        {
            arr.push_back(temp + 55);
            i++;
        }
        num = num/16;
    }
    for(int j = i-1; j >= 0; j--)
        cache += arr[j]; // cache+= arr[j];
    
    // ENSURE 64 character hexadecimal output
    if ((cache.length() < 65) && (cache.length() != 64))
    {
        int mz = 64 - cache.length();
        for (int i = 0; i < mz; ++i)
            cache = "0" + cache; // pad beginning of hex with 0 as it has no significant value to current hex value 
    }

    return BigToLittleAlphabets(cache);
    // return cache;
} // 03:50PM 18/09/2022


string BigInteger2String(BigInteger value)
{
    string dd; // string variable declaration
    stringstream ss; // stream object initialization
    ss << value; // stream data into object
    ss >> dd; // stream data into string variable
    ss.clear(); // clear stream object
    return dd; // return value
}


string DecimalToBinary_Backwards(BigInteger num)
{
    BigInteger n, div = 2; // declare BigInteger variable
    string bin = "", temp; // declare string variables
    while(num > 0) // while num is not equal to 0
    {
        n = num % div; // mod value by 2 and store remainder
        num = num / div; // divide by 2 yo update but simultaneously decrease num
        temp += BigInteger2String(n); // convert to string and concatenate within string
    }
    return temp; // return value
}




BigInteger Inverse(BigInteger a, BigInteger m) // 1st implementation of mod inverse function
{
    BigInteger prevy(0), y(1), q, m_orig = m, der(0);
    // m = p;
    if (a < 0)
        a = a % m;

    while(a > 1) 
    {
        q = m/a;
        y = (prevy-q)*y;
        prevy = y;
        a = m % a;
        m = a;
    }
    der = y % m_orig;
    return der;
}


// which mod inverse implementation is correct?
BigInteger modInverse(BigInteger a, BigInteger m) // 2nd implementation of mod inverse function
{ 
    BigInteger m0 = m; 
    BigInteger y = 0, x = 1; 
  
    if (m == 1) 
      return 0; 
  
    while (a > 1) 
    { 
        BigInteger q = a / m; // q is quotient 
        BigInteger t = m; 
        m = a % m, a = t; // m is remainder now, process same as Euclid's algo 
        t = y;

        // Update y and x 
        y = x - q * y; 
        x = t; 
    } 
  
    // Make x positive 
    if (x < 0) 
       x += m0;

    return x;
} 



void Double(BigInteger &x, BigInteger &y)
{
    BigInteger _2(2), _3(3);
    BigInteger slope = _3 * (BigInteger_power(x, _2) * Inverse((_2*y), p)) % p;
    cout << "DOUBLE Slope = " << slope << "\n\n";
    BigInteger X = (BigInteger_power(slope, _2) - (_2 * x)) % p;
    BigInteger Y = ((slope * x) - X - y) % p;
    x = X, y = Y; // update values
}


void ADD(BigInteger &Point1_x, BigInteger &Point1_y, BigInteger Point2_x, BigInteger Point2_y)
{
    string h = BigInteger2String(Point1_x) + BigInteger2String(Point1_y);
    string k = BigInteger2String(Point2_x) + BigInteger2String(Point2_y);
    BigInteger a = String_2_BigInteger(h), b = String_2_BigInteger(k);
    if (a == b)
        Double(Point1_x, Point1_y);
    else
    {
        BigInteger _2(2);
        BigInteger slope = (Point1_y - (Point2_y * Inverse(Point1_x-Point2_x, p))) % p;
        cout << "ADD Slope = " << slope << "\n\n";
        BigInteger X = ((BigInteger_power(slope, _2) - Point1_x) - Point2_x) % p;
        BigInteger Y = ((slope * Point1_x) - X - Point1_y) % p;
        Point1_x = X, Point1_y = Y; // update values
    }
}


void Multiply(BigInteger PRIVATEKEY, vector<BigInteger> &PUBLICKEY)
{
    BigInteger XX = G_X, YY = G_Y; // XX and YY are updated within each curve function call
    string binaryVerse = DecimalToBinary_Backwards(PRIVATEKEY);
    cout << "Binary of privateKey = " << binaryVerse << "\n\n"; // FOR DEBUGGING PURPOSE ONLY!!
    int IterationLength = binaryVerse.length();
    
    for (int i = 1; i < IterationLength; ++i)
    {
        if (binaryVerse[i] == '0')
            Double(XX, YY);
        else if (binaryVerse[i] == '1')
        {
            // Double(XX, YY);
            ADD(XX, YY, G_X, G_Y);
            // Double(XX, YY);
        }
    }
    PUBLICKEY.clear();
    PUBLICKEY.push_back(XX); // Update vector with calculated publicKey Decimal
    PUBLICKEY.push_back(YY); // Update vector with calculated publicKey Decimal values
    cout << "Public Key x : " << XX << ", \nPublic Key y : " << YY << "\n\n";
}


int main(int argc, char const *argv[])
{
    vector<BigInteger> ZEN;
    BigInteger pk = String_2_BigInteger("112757557418114203588093402336452206775565751179231977388358956335153294300646");
    Multiply(pk, ZEN);
    
    cout << "Hexadecimal PublicKey x : " << IntegerToHex(ZEN[0]) << ", \nHexadecimal PublicKey y : " << IntegerToHex(ZEN[1]) << "\n\n";
    return 0;
}


c++ public-key ecdsa
© www.soinside.com 2019 - 2024. All rights reserved.