C++11 ECDSA-withSHA256验签

简介: 这里不做签名,只验签

这里不做签名,只验签


使用方法:


openssl版本:1.0.2g 其他的自行验证


编译:g++ test.cpp -o test -lssl -lcrypto -std=c++11


执行:./test


签名过程:随机数进行SHA256哈希后再使用私钥对其签名


验签过程:用随机数的SHA256和公钥来验证签名


以下代码是验证签名


#include <iostream>
#include <memory>
#include <string>
#include <sstream>
#include <stdio.h>
#include <string.h>
#include <openssl/ecdsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/conf.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/ec.h>
#include <openssl/bn.h>
bool verify_signature(const unsigned char* hash, const ECDSA_SIG* signature, EC_KEY* eckey)
{
    int verify_status = ECDSA_do_verify(hash, SHA256_DIGEST_LENGTH, signature, eckey);
    if (1 != verify_status)
    {
        printf("Failed to verify EC Signature\n");
        return false;
    }
    printf("Verifed EC Signature\n");
    return true;
}
void SetOpensslSignature(const std::string& sSignatureInHex, ECDSA_SIG* pSign)
{
    // std::unique_ptr< BIGNUM, std::function<void(BIGNUM*)>> rr(NULL, [](BIGNUM* b) { BN_free(b); });
    // BIGNUM* r_ptr = rr.get();
    // std::unique_ptr< BIGNUM, std::function<void(BIGNUM*)>> ss(NULL, [](BIGNUM* b) { BN_free(b); });
    // BIGNUM* s_ptr = ss.get();
    std::string sSignatureR = sSignatureInHex.substr(0, sSignatureInHex.size() / 2);
    std::string sSignatureS = sSignatureInHex.substr(sSignatureInHex.size() / 2);
    pSign->r = BN_new();
    pSign->s = BN_new();
    BN_hex2bn(&pSign->r, sSignatureR.c_str());
    BN_hex2bn(&pSign->s, sSignatureS.c_str());
    return;
}
bool SetOpensslPublicKey(const std::string& sPublicKeyInHex, EC_KEY* pKey)
{
    const char* sPubKeyString = sPublicKeyInHex.c_str();
    char cx[65];
    std::unique_ptr< BIGNUM, std::function<void(BIGNUM*)>> gx(NULL, [](BIGNUM* b) { BN_free(b); });
    std::unique_ptr< BIGNUM, std::function<void(BIGNUM*)>> gy(NULL, [](BIGNUM* b) { BN_free(b); });
    BIGNUM* gx_ptr = gx.get();
    BIGNUM* gy_ptr = gy.get();
    EC_KEY_set_asn1_flag(pKey, OPENSSL_EC_NAMED_CURVE);
    memcpy(cx, sPubKeyString, 64);
    cx[64] = 0;
    if (!BN_hex2bn(&gx_ptr, cx)) {
        std::cout << "Error getting to binary format" << std::endl;
    }
    if (!BN_hex2bn(&gy_ptr, &sPubKeyString[64])) {
        std::cout << "Error getting to binary format" << std::endl;
    }
    if (!EC_KEY_set_public_key_affine_coordinates(pKey, gx_ptr, gy_ptr)) {
        std::cout << "setting public key attributes" << std::endl;
    }
    if (EC_KEY_check_key(pKey) == 1)
    {
        printf("EC Key valid.\n");
        return true;
    }
    else {
        printf("EC Key Invalid!\n");
        return false;
    }
}
std::string sha256(const std::string str)
{
    unsigned char hash[SHA256_DIGEST_LENGTH];
    SHA256_CTX sha256;
    SHA256_Init(&sha256);
    SHA256_Update(&sha256, str.c_str(), str.size());
    SHA256_Final(hash, &sha256);
    std::stringstream ss;
    for (int i = 0; i < SHA256_DIGEST_LENGTH; i++)
    {
        ss << hash[i];
    }
    return ss.str();
}
bool Verify(const std::string& sRandomNumber, const std::string& sSignature, const std::string& sDevicePubKeyInHex)
{
    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... 
    SetOpensslSignature(sSignature, zSignature.get());
    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); });
    if (!SetOpensslPublicKey(sDevicePubKeyInHex, zPublicKey.get()))
        std::cout << "Failed to get the public key from the hex input" << std::endl;
    std::string sHash = sha256(sRandomNumber);
    return verify_signature((const unsigned char*)sHash.c_str(), zSignature.get(), zPublicKey.get());
}
int main(int argc, char* argv[])
{
    std::string sSignatureInHex = "D506D976EC17DD3717C40329E28FD8DB4F32D6A3773454A6427FD12E69728157508086B661D91E07ADF5B57E787EA1EEA526A84500436E430E89B1C1F8532A41";
    std::string sPublicKeyInHex = "94E62E0C77A2955B1FB3EE98AEAA99AACAD742F20E45B727EACDD10487C2F7D0D8257C6102921880ABE953245D573D7E33EC88A67E2BA930980CB9C3D6722F8A";
    std::string sRandomNumber = "65560886818773090201885807838738706912015073749623293202319529";
    if (!Verify(sRandomNumber, sSignatureInHex, sPublicKeyInHex))
        std::cout << "Verification failed." << std::endl;
    else
        std::cout << "Verification succeeded" << std::endl;
}
目录
相关文章
|
算法
RSA和RSA2签名算法区别
RSA和RSA2签名算法 什么是数字签名? 一个很好的说明文档可以参考:What is a Digital Signature?,中文翻译可以参考:数字签名是什么?. 简单来说,签名主要包含两个过程:摘要和非对称加密,首先对需要签名的数据做摘要(类似于常见的MD5)后得到摘要结果,然后通过签名者的私钥对摘要结果进行非对称加密即可得到签名结果。
5249 0
|
1月前
|
算法 Java 数据安全/隐私保护
RSA 加解密 1024 位 & 2048 位
RSA 加解密 1024 位 & 2048 位
90 0
|
6月前
|
存储 算法 安全
C++ CryptoPP使用RSA加解密
Crypto++ (CryptoPP) 是一个用于密码学和加密的 C++ 库。它是一个开源项目,提供了大量的密码学算法和功能,包括对称加密、非对称加密、哈希函数、消息认证码 (MAC)、数字签名等。Crypto++ 的目标是提供高性能和可靠的密码学工具,以满足软件开发中对安全性的需求。RSA(Rivest-Shamir-Adleman)是一种非对称加密算法,由三位密码学家Ron Rivest、Adi Shamir和Leonard Adleman于1977年共同提出。RSA算法被广泛应用于信息安全领域,特别是在数字签名和密钥交换等场景中。
150 0
C++ CryptoPP使用RSA加解密
|
存储 编解码 算法
RSA加密/解密
RSA加密算法是一种可逆的非对称加密算法,即RSA加密时候用的密钥(公钥)和RSA解密时用的密钥(私钥)不是同一把。基本原理是将两个很大的质数相乘很容易得到乘积,但是该乘积分解质因数却很困难。RSA算法被广泛的用于加密解密和RSA签名/验证等领域。
522 0
|
算法 Linux 数据安全/隐私保护
RSA加密算法
RSA加密算法
178 0
RSA加密算法
|
算法 安全 Java
java实现ecc加密:通过AES获取公钥和私钥进行ECC加密
java实现ecc加密:通过AES获取公钥和私钥进行ECC加密
638 0
java实现ecc加密:通过AES获取公钥和私钥进行ECC加密
|
存储 Web App开发 编解码
加解密,加签、验签也就这肥事
加解密,加签、验签也就这肥事
1417 0
加解密,加签、验签也就这肥事
|
XML 算法 安全
公钥 私钥 签名 验签 说的啥?
公钥 私钥 签名 验签 说的啥?
281 0
公钥 私钥 签名 验签 说的啥?
|
C++
C++版本ECDSA-with-SHA256签名验证
由于项目需要验证签名,这里不做签名,只验签,所以直接上代码。
375 0
|
存储 缓存 算法
IdentityServer4之JWT签名(RSA加密证书)及验签
JWT是一个非常轻巧的规范,一般被用来在身份提供者和服务提供者间传递安全可靠的信息。JWT令牌是一个自包含的访问令牌 - 它是一个带有声明和过期的受保护数据结构
999 0
IdentityServer4之JWT签名(RSA加密证书)及验签