当我使用 C++ 拥有十六进制格式的公钥时,我可以创建 openssl EC_KEY 吗

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

主机(PC APP)向客户端发送一个随机数,客户端(设备)用其私钥对该随机数进行签名。这个HEX格式的签名和HEX格式的公钥被发送到PC APP进行验证。我在将十六进制格式的公钥转换为 openssl 中的 EC_KEY 结构时遇到问题。

我尝试过以下操作 1.从HEX转换为ascii,然后从ascii转换为base64,并使用PEM_read_bio_EC_PUBKEY读取密钥。 2.我尝试使用BN_hex2bn来获取密钥的x和y分量,然后使用EC_KEY_set_public_key_affine_cooperatives。

这些似乎都不适合我。

bool OpensslUtility::computeSHA256Hash(const std::string& unhashed, std::string& hashed)
{
    bool success = false;

    EVP_MD_CTX* context = EVP_MD_CTX_new();

    if (context != NULL)
    {
        if (EVP_DigestInit_ex(context, EVP_sha256(), NULL))
        {
            if (EVP_DigestUpdate(context, unhashed.c_str(), unhashed.length()))
            {
                unsigned char hash[EVP_MAX_MD_SIZE];
                unsigned int lengthOfHash = 0;

                if (EVP_DigestFinal_ex(context, hash, &lengthOfHash))
                {
                    std::stringstream ss;
                    for (unsigned int i = 0; i < lengthOfHash; ++i)
                    {
                        ss << std::hex << std::setw(2) << std::setfill('0') << (int)hash[i];
                    }

                    hashed = ss.str();
                    success = true;
                }
            }
        }
        convertToUpperCase(hashed);
        EVP_MD_CTX_free(context);
    }

    return success;
}

void Example1()
{
    std::unique_ptr< ECDSA_SIG, std::function<void(ECDSA_SIG*)>> zSignature(ECDSA_SIG_new(), [](ECDSA_SIG* b) { ECDSA_SIG_free(b); });
    // Set up the signature... 
    BIGNUM* rr = NULL, * ss = NULL;

    std::string sSignatureR = "1B87DA77F29B7C891436B5477BFFBA919EDF42167F27EB525B94EB0A4D295FE8";
    std::string sSignatureS = "6E80B434A88D8609E63D3B2FA4E171C428CCAABEF84F5ECDB646E99AAE095983";

    BN_hex2bn(&rr, sSignatureR.c_str());
    BN_hex2bn(&ss, sSignatureS.c_str());

    ECDSA_SIG_set0(zSignature.get(), rr, ss);

    // Set up the public key.... 
    const char* sPubKeyString = "E3A7E51FE102286D071026111088F680761FDCD7031E3D56244BBE07451601E78AD08AD40EADCF380900985A1FAB94DE6D02DB91920F1144E9EBC4E248444969";

    char cx[65];
    BIGNUM* gx = NULL;
    BIGNUM* gy = NULL;

    std::unique_ptr< EC_KEY, std::function<void(EC_KEY*)>> zPublicKey(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1), [](EC_KEY* b) { EC_KEY_free(b); });
    EC_KEY_set_asn1_flag(zPublicKey.get(), OPENSSL_EC_NAMED_CURVE);
    memcpy(cx, sPubKeyString, 64);
    cx[64] = 0;

    if (!BN_hex2bn(&gx, cx)) {
        std::cout << "Error getting to binary format" << std::endl;
    }

    if (!BN_hex2bn(&gy, &sPubKeyString[64])) {
        std::cout << "Error getting to binary format" << std::endl;
    }

    if (!EC_KEY_set_public_key_affine_coordinates(zPublicKey.get(), gx, gy)) {
        std::cout << "setting public key attributes" << std::endl;
    }

    EC_KEY* pPubKey = zPublicKey.get();
    //PEM_read_bio_EC_PUBKEY(bo.get(), &pPubKey, NULL, NULL);


    if (EC_KEY_check_key(pPubKey) == 1)
    {
        printf("EC Key valid.\n");
    }
    else {
        printf("EC Key Invalid!\n");
    }

    std::string sRandomNumber = "bef2fc87919a11d8312dc118ece116b108377aa4d771b1c1e5aaed41b85d50"; //Message to sign (Given to arduino.....)

    std::string sHash;
    OpensslUtility::computeSHA256Hash(sRandomNumber, sHash);

    int iVerify = OpensslUtility::verify_signature((const unsigned char*)sHash.c_str(), zSignature.get(), pPubKey);

}



std::string OpensslUtility::HexToBytes(const std::string& hex)
{
    std::string bytes;

    for (unsigned int i = 0; i < hex.length(); i += 2) {
        std::string byteString = hex.substr(i, 2);
        char byte = (char)strtol(byteString.c_str(), NULL, 16);
        bytes.push_back(byte);
    }

    return bytes;
}

int OpensslUtility::verify_signature(const unsigned char* hash, const ECDSA_SIG* signature, EC_KEY* eckey)
{
    int verify_status = ECDSA_do_verify(hash, strlen((const char*)hash), signature, eckey);
    if (1 != verify_status)
    {
        printf("Failed to verify EC Signature\n");
        return -1;
    }

    printf("Verifed EC Signature\n");

    return 1;
}

std::string OpensslUtility::base64(const char* input, int length)
{
    std::unique_ptr< BIO, std::function<void(BIO*)>> b64(BIO_new(BIO_f_base64()), [](BIO* b) { BIO_free(b); });
    std::unique_ptr< BIO, std::function<void(BIO*)>> bmem(BIO_new(BIO_s_mem()), [](BIO* b) { BIO_free(b); });

    BUF_MEM* bptr;
    BIO* b64_ptr = b64.get();

    b64_ptr = BIO_push(b64.get(), bmem.get());
    BIO_write(b64_ptr, input, length);
    BIO_flush(b64_ptr);
    BIO_get_mem_ptr(b64_ptr, &bptr);

    std::unique_ptr< char, std::function<void(char*)>> buff((char*)malloc(bptr->length), [](char* b) { free(b); });

    memcpy(buff.get(), bptr->data, bptr->length - 1);
    buff.get()[bptr->length - 1] = 0;
    std::string sTo64(buff.get());

    return sTo64;
}


void Example2()
{
    std::unique_ptr< ECDSA_SIG, std::function<void(ECDSA_SIG*)>> zSignature(ECDSA_SIG_new(), [](ECDSA_SIG* b) { ECDSA_SIG_free(b); });
    // Set up the signature... 
    BIGNUM* rr = NULL, * ss = NULL;

    std::string sSignatureR = "1B87DA77F29B7C891436B5477BFFBA919EDF42167F27EB525B94EB0A4D295FE8";
    std::string sSignatureS = "6E80B434A88D8609E63D3B2FA4E171C428CCAABEF84F5ECDB646E99AAE095983";

    BN_hex2bn(&rr, sSignatureR.c_str());
    BN_hex2bn(&ss, sSignatureS.c_str());

    ECDSA_SIG_set0(zSignature.get(), rr, ss);

    // Set up the public key.... 
    const char* sPubKeyString = "E3A7E51FE102286D071026111088F680761FDCD7031E3D56244BBE07451601E78AD08AD40EADCF380900985A1FAB94DE6D02DB91920F1144E9EBC4E248444969";

    std::unique_ptr< EC_KEY, std::function<void(EC_KEY*)>> zPublicKey(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1), [](EC_KEY* b) { EC_KEY_free(b); });
    EC_KEY_set_asn1_flag(zPublicKey.get(), OPENSSL_EC_NAMED_CURVE);

    EC_KEY* pPubKey = zPublicKey.get();


    std::string sKeyInAscii = OpensslUtility::HexToBytes(sPubKeyString);
    std::string sPub64(base64_encode(sKeyInAscii));
    std::string sKeyInPem = std::string("-----BEGIN PUBLIC KEY-----\n") + sPub64 + std::string("\n-----END PUBLIC KEY-----");

    const char* pzKey = sKeyInPem.c_str();
    std::unique_ptr< BIO, std::function<void(BIO*)>> bo(BIO_new(BIO_s_mem()), [](BIO* b) { BIO_free(b); });
    BIO_write(bo.get(), pzKey, strlen(pzKey));

    EC_KEY_set_asn1_flag(zPublicKey.get(), OPENSSL_EC_NAMED_CURVE);

    PEM_read_bio_EC_PUBKEY(bo.get(), &pPubKey, NULL, NULL);


    if (EC_KEY_check_key(pPubKey) == 1)
    {
        printf("EC Key valid.\n");
    }
    else {
        printf("EC Key Invalid!\n");
    }

    std::string sRandomNumber = "bef2fc87919a11d8312dc118ece116b108377aa4d771b1c1e5aaed41b85d50"; //Message to sign (Given to arduino.....)

    std::string sHash;
    OpensslUtility::computeSHA256Hash(sRandomNumber, sHash);

    int iVerify = OpensslUtility::verify_signature((const unsigned char*)sHash.c_str(), zSignature.get(), pPubKey);

}
c++ encryption openssl cryptography
1个回答
0
投票

是的,您必须设置组和点

EC_POINT* Hex_to_point_NID_secp256k1(char* str) {
   EC_KEY* ecKey = EC_KEY_new_by_curve_name(NID_secp256k1);
   const EC_GROUP* ecGroup = EC_KEY_get0_group(ecKey);
   EC_POINT* ecPoint = EC_POINT_hex2point(ecGroup, str, NULL, NULL);
   return ecPoint;
}

然后

EC_KEY* pubKey = EC_KEY_new_by_curve_name(NID_secp256k1);
EC_KEY_set_public_key(pubKey, Hex_to_point_NID_secp256k1(hexPublicKey));
© www.soinside.com 2019 - 2024. All rights reserved.