SECP256K1签名

#include <iostream>
#include <secp256k1.h>
#include <string>
#include <sstream>
#include <iomanip>
#include <assert.h>
#include <openssl/sha.h>
//十六进制字符串转字符串, 如 "313233" -> "123"
std::string hex2string(const std::string &strHex);
//字符串转二进制字符串, 如 "123" -> "313233"
std::string string2hex(const std::uint8_t *data, int len);
int main()
{
    secp256k1_context *ctx = nullptr;
    secp256k1_pubkey pubkey;
    
    //随机一个256位的私钥
    std::uint8_t private_key[] = "18E14A7B6A307F426A94F8114701E7C8E774E7F9A47E2C2035DB29A206321725";
    int pk_size = std::extent<decltype(private_key)>::value;
    std::cout << "private key : " << private_key << "|" << pk_size << std::endl;
    //创建一个上下文
    assert(ctx == nullptr);
    ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY|SECP256K1_CONTEXT_SIGN);
    assert(ctx != nullptr);
    //二进制私钥
    std::string prikey = hex2string((const char *)private_key);
    //根据私钥生成公钥
    secp256k1_ec_pubkey_create(ctx, &pubkey, (unsigned char *)prikey.c_str());
    unsigned char pub[65];
    size_t publen = 65;
    //将公钥转为64字节的公钥, 不是可读字符串, 需要string2hex()转换
    secp256k1_ec_pubkey_serialize(ctx, pub, &publen, &pubkey, SECP256K1_EC_UNCOMPRESSED);
    std::cout << "pub: " << string2hex((unsigned char *)pub, 65) << std::endl;
    //签名
    unsigned char hash[33] = { 0 };
    //对一个字符串进行hash, 签名就是对32字节的hash进行签名的
    SHA256((const unsigned char *)"123", 3, hash);
    std::cout << string2hex(hash, 32) << std::endl;
    secp256k1_ecdsa_signature sig;
    int ret = secp256k1_ecdsa_sign(ctx, &sig, hash, (const unsigned char *)prikey.c_str(), NULL, NULL);
    assert(ret == 1);
    //转为der格式, 这里用不到, len要足够大能放下der结果
    //unsigned char der[200];
    //size_t derlen = 200;
    //ret = secp256k1_ecdsa_signature_serialize_der(ctx,
    //    der, &derlen, &sig);
    //assert(ret == 1);
    //将签名转为64字节的签名格式
    unsigned char sig64[65] = { 0 };
    secp256k1_ecdsa_signature_serialize_compact(ctx,
        sig64, &sig);
    std::cout << "sig64 : " << string2hex(sig64, 64) << std::endl;
    //std::cout << "der : " << string2hex(der, derlen) << std::endl;
    
    //验证签名, 返回值为1, 则验证通过
    ret = secp256k1_ecdsa_verify(ctx, &sig, hash, &pubkey);
    assert(ret == 1);
    return 0;
}
std::string hex2string(const std::string &strHex)
{
    if (strHex.size() % 2 != 0)
    {
        return "";
    }
    std::string strBin;
    strBin.resize(strHex.size() / 2);
    for (size_t i = 0; i < strBin.size(); i++)
    {
        uint8_t cTemp = 0;
        for (size_t j = 0; j < 2; j++)
        {
            char cCur = strHex[2 * i + j];
            if (cCur >= '0' && cCur <= '9')
            {
                cTemp = (cTemp << 4) + (cCur - '0');
            }
            else if (cCur >= 'a' && cCur <= 'f')
            {
                cTemp = (cTemp << 4) + (cCur - 'a' + 10);
            }
            else if (cCur >= 'A' && cCur <= 'F')
            {
                cTemp = (cTemp << 4) + (cCur - 'A' + 10);
            }
            else
            {
                return "";
            }
        }
        strBin[i] = cTemp;
    }
    return strBin;
}
std::string string2hex(const std::uint8_t *data, int len)
{
    std::string result;
    std::string tmp;
    std::stringstream ss;
    for (int i = 0; i < len; i++)
    {
        int r = int(data[i]);
        ss << std::hex << std::setw(2)
            << std::setfill('0') << r << std::endl;
        ss >> tmp;
        result += tmp;
    }
    return result;
}
发布了506 篇原创文章 · 获赞 40 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/huang714/article/details/104749025