由于项目需要验证签名,这里不做签名,只验签
直接上代码:

使用方法:
openssl版本:1.0.2g 其他的自行验证
编译:g++ x509.cpp -o x509 -lssl -lcrypto
执行:./x509

#include <openssl/pem.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <cstring>
#include <iostream>// base64 编码
char *base64_encode(const char *buffer, int length) {BIO *bmem = NULL;BIO *b64 = NULL;BUF_MEM *bptr;char *buff = NULL;b64 = BIO_new(BIO_f_base64());BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);bmem = BIO_new(BIO_s_mem());b64 = BIO_push(b64, bmem);BIO_write(b64, buffer, length);BIO_flush(b64);BIO_get_mem_ptr(b64, &bptr);BIO_set_close(b64, BIO_NOCLOSE);buff = (char *)malloc(bptr->length + 1);memcpy(buff, bptr->data, bptr->length);buff[bptr->length] = 0;BIO_free_all(b64);return buff;
}// base64 解码
char *base64_decode(char *input, int length) {BIO *b64 = NULL;BIO *bmem = NULL;char *buffer = NULL;buffer = (char *)malloc(length);memset(buffer, 0, length);b64 = BIO_new(BIO_f_base64());BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);bmem = BIO_new_mem_buf(input, length);bmem = BIO_push(b64, bmem);BIO_read(bmem, buffer, length);BIO_free_all(bmem);return buffer;
}int get_str_len(const char *in) {int num = 0;if(in == NULL) {return 0;}while (!((*(in + num) == NULL) && (*(in + num + 1) == NULL) \&& (*(in + num + 2) == NULL) && (*(in + num + 3) == NULL) \&& (*(in + num + 4) == NULL)&& (*(in + num + 5) == NULL) \&& (*(in + num + 6) == NULL)&& (*(in + num + 7) == NULL))) {num++;}return num;
}
static const char hex_table[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
// 字节转十六进制字符串
std::string BytesToHexStr(const char* aInStr, int len)
{std::string hex_str;for (int i = 0; i < len; ++i) {hex_str.append(&hex_table[(aInStr[i] & 0xF0) >> 4], 1);hex_str.append(&hex_table[aInStr[i] & 0xF], 1);}std::cout << hex_str << std::endl;return hex_str;
}
// 字符串截取
char* substring(char* ch,int pos,int length)
{  // 定义字符指针 指向传递进来的ch地址char *pch = ch;// 通过calloc来分配一个length长度的字符数组,返回的是字符指针。char *subch = (char*)calloc(sizeof(char),length+1);int i;// 只有在C99下for循环中才可以声明变量,这里写在外面,提高兼容性。pch = pch + pos;// 是pch指针指向pos位置。for(i = 0; i < length; i++) {subch[i] = *(pch++); // 循环遍历赋值数组。}  subch[length]='\0'; // 加上字符串结束符。return subch;       // 返回分配的字符数组地址。
} int ECDSA_WithSHA256_do_verify(const char *strx509, char *message, unsigned int messageLen, char *signBuf, unsigned int signLen) {EC_KEY * ec_key;EVP_MD_CTX md_ctx;int ret = -1;char *Sigbuff = NULL, *Signature = NULL, *r = NULL, *s = NULL;char dst_str[2][512+1];unsigned char digest[EVP_MAX_MD_SIZE];unsigned int digestLen = 0;BIO *bio_mem = BIO_new(BIO_s_mem());BIO_puts(bio_mem, strx509);X509 * x509 = PEM_read_bio_X509(bio_mem, NULL, NULL, NULL);EVP_PKEY *pkey = X509_get_pubkey(x509); // 获取证书的公钥if (pkey->type == EVP_PKEY_EC) {ec_key = EVP_PKEY_get1_EC_KEY(pkey);if (!ec_key) {printf("get EVP_PKEY_get1_EC_KEY fail \n");}}EVP_PKEY_free(pkey);Sigbuff = base64_decode(message,messageLen);  // base64解码后的验证数据Signature = base64_decode(signBuf,signLen);     // base64解码后的签名数据printf("Sigbuff: %s\n", Sigbuff);printf("Signature: %s\n Signature len: %d\n EVP_MAX_MD_SIZE: %d\n", Signature,get_str_len(Signature), EVP_MAX_MD_SIZE);r = substring(Signature,0,get_str_len(Signature)/2);s = substring(Signature,get_str_len(Signature)/2,get_str_len(Signature));std::string rSignatureInHex = BytesToHexStr(r,get_str_len(Signature)/2);std::string sSignatureInHex = BytesToHexStr(s,get_str_len(Signature)/2);free(r);free(s);EVP_MD_CTX_init(&md_ctx);if (!EVP_DigestInit(&md_ctx, EVP_sha256())) {printf("EVP_digest fail \n");}if (!EVP_DigestUpdate(&md_ctx, (const void *)Sigbuff, get_str_len(Sigbuff))) {printf("EVP_DigestUpdate fail \n");}if (!EVP_DigestFinal(&md_ctx, digest, &digestLen)) {printf("EVP_DigestFinal fail \n");}free(Sigbuff);free(Signature);ECDSA_SIG *sig = (ECDSA_SIG *)malloc(sizeof(ECDSA_SIG));strncpy(dst_str[0], rSignatureInHex.c_str(), 512);strncpy(dst_str[1], sSignatureInHex.c_str(), 512);printf("dst_str[0]: %s\n", &dst_str[0]);printf("dst_str[1]: %s\n", &dst_str[1]);sig->r = BN_new();sig->s = BN_new();BN_hex2bn(&(sig->r), dst_str[0]); //十六进制转二进制BN_hex2bn(&(sig->s), dst_str[1]);/*do verify*/ret = ECDSA_do_verify((const unsigned char*)digest, digestLen, sig, ec_key);if (ret == -1) {printf("ECDSA_verify failed\n");} else if (ret == 0) {printf("ECDSA_verify incorrect signature\n");} else {printf("ECDSA_verify ok\n");}BN_free(sig->r);BN_free(sig->s);free(sig);if (ec_key) {EC_KEY_free(ec_key);ec_key = NULL;}BIO_free(bio_mem);X509_free(x509);return ret;
}int main(int argc, char **argv)
{OpenSSL_add_all_algorithms();// 需要验证的数据的base64编码char message[] = "hGpTaWduYXR1cmUxTaIESDSaQrDC0HKOASZAWQECpAQaZF2BgAYaYUOemQFiSVQ5AQOhAaRhdoGqYmRuAWJtYW1PUkctMTAwMDAxNjk5YnZwajExMTkzMDUwMDViZHRqMjAyMS0wNS0wNWJjb2JJVGJjaXgmMDFJVDVBMUM2NEYyREYwODQ3RjI5Rjc0MTA2MjA1OEFGQUUwIzFibXBsRVUvMS8yMS8xNTI5Ymlzdk1pbmlzdGVybyBkZWxsYSBTYWx1dGVic2QBYnRnaTg0MDUzOTAwNmNuYW2kY2ZudGdQQU5ESU5JYmZuZ1BBTkRJTkljZ250ZkFORFJFQWJnbmZBTkRSRUFjdmVyZTEuMC4wY2RvYmoxOTUyLTA5LTI4";// 摘要签名数据的base64编码char signBuf[] = "a0KNpWa23iFQue19IioU/jrUPd/Utoo9A4prMG9LvS3FCsNEHHAwoAUpO4/KIfLB6R1MiIakaIJo4lIBawvUOA==";// 证书std::string str = "MIIEDzCCAfegAwIBAgIURldu5rsfrDeZtDBxrJ+SujMr2IswDQYJKoZIhvcNAQELBQAwSTELMAkGA1UEBhMCSVQxHzAdBgNVBAoMFk1pbmlzdGVybyBkZWxsYSBTYWx1dGUxGTAXBgNVBAMMEEl0YWx5IERHQyBDU0NBIDEwHhcNMjEwNTEyMDgxODE3WhcNMjMwNTEyMDgxMTU5WjBIMQswCQYDVQQGEwJJVDEfMB0GA1UECgwWTWluaXN0ZXJvIGRlbGxhIFNhbHV0ZTEYMBYGA1UEAwwPSXRhbHkgREdDIERTQyAxMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEnL9+WnIp9fvbcocZSGUFlSw9ffW/jbMONzcvm1X4c+pXOPEs7C4/83+PxS8Swea2hgm/tKt4PI0z8wgnIehoj6OBujCBtzAfBgNVHSMEGDAWgBS+VOVpXmeSQImXYEEAB/pLRVCw/zBlBgNVHR8EXjBcMFqgWKBWhlRsZGFwOi8vY2Fkcy5kZ2MuZ292Lml0L0NOPUl0YWx5JTIwREdDJTIwQ1NDQSUyMHhcMSxPPU1pbmlzdGVybyUyMGRlbGxhJTIwU2FsdXRlLEM9SVQwHQYDVR0OBBYEFC4bAbCvpArrgZ0E+RrqS8V7TNNIMA4GA1UdDwEB/wQEAwIHgDANBgkqhkiG9w0BAQsFAAOCAgEAjxTeF7yhKz/3PKZ9+WfgZPaIzZvnO/nmuUartgVd3xuTPNtd5tuYRNS/1B78HNNk7fXiq5hH2q8xHF9yxYxExov2qFrfUMD5HOZzYKHZcjcWFNHvH6jx7qDCtb5PrOgSK5QUQzycR7MgWIFinoWwsWIrA1AJOwfUoi7v1aoWNMK1eHZmR3Y9LQ84qeE2yDk3jqEGjlJVCbgBp7O8emzy2KhWv3JyRZgTmFz7p6eRXDzUYHtJaufveIhkNM/U8p3S7egQegliIFMmufvEyZemD2BMvb97H9PQpuzeMwB8zcFbuZmNl42AFMQ2PhQe27pU0wFsDEqLe0ETb5eR3T9L6zdSrWldw6UuXoYV0/5fvjA55qCjAaLJ0qi16Ca/jt6iKuws/KKh9yr+FqZMnZUH2D2j2i8LBA67Ie0JoZPSojr8cwSTxQBdJFI722uczCj/Rt69Y4sLdV3hNQ2A9hHrXesyQslr0ez3UHHzDRFMVlOXWCayj3LIgvtfTjKrT1J+/3Vu9fvs1+CCJELuC9gtVLxMsdRc/A6/bvW4mAsyY78ROX27Bi8CxPN5IZbtiyjpmdfr2bufDcwhwzdwsdQQDoSiIF1LZqCn7sHBmUhzoPcBJdXFET58EKow0BWcerZzpvsVHcMTE2uuAUr/JUh1SBpoJCiMIRSl+XPoEA2qqYU=";str.insert(0,"-----BEGIN CERTIFICATE-----" "\n");str.append( "\n" "-----END CERTIFICATE-----" "\n");int ret = ECDSA_WithSHA256_do_verify(str.c_str(), message, sizeof(message), signBuf, sizeof(signBuf));printf("ECDSA_WithSHA256 ret = %d\n", ret);
}
/*
使用方法:
openssl版本:1.0.2g 其他的自行验证
编译:g++ x509.cpp -o x509 -lssl -lcrypto
执行:./x509
*/

C++版本ECDSA-with-SHA256签名验证相关推荐

  1. 微信商家券V3版本领券回调,签名验证-JAVA

    先附上官方文档:微信支付-开发者文档 一.微信商家券回调参数样式 1.微信回调的参数分两部分,这里两部分参数都要用的! A.Body { "id":"8b33f79f-8 ...

  2. Java实现密码学工具,集成了对称加密算法DES,AES,IDEA,公开加密算法RSA,ECC,散列算法MD5,SHA1,CRC32,以及RSA,DSA,ECDSA数字签名验证示例。

    密码学综合工具 前言 git网址 项目结构 项目预览 String与byte[]互转 通过`String`类转换 通过`Base64`互转[jdk-8] 前言 我们网络信息安全的实验...要我们找各种 ...

  3. 使用Crypto++ ecdsa 进行签名和认证

    这里记录使用Crypto++ ecdsa 进行签名和认证的代码片段,可直接运行. 运行环境:Windows, Visual Studio 2017 需安装Crypto++库,可使用cvpkg工具直接集 ...

  4. android studio 正式版本

    注意:以下 Android Studio 下载链接全是 dl.google.com 开头的官方下载,无需tizi,建议用浏览器直接从官方原始链接下载,不要用迅雷下载.不要用迅雷下载.不要用迅雷下载,重 ...

  5. ECDSA数字签名算法(java实现ECDSA签名验签)

    一.ECDSA概述 椭圆曲线数字签名算法(ECDSA)是使用椭圆曲线密码(ECC)对数字签名算法(DSA)的模拟.ECDSA于1999年成为ANSI标准,并于2000年成为IEEE和NIST标准.它在 ...

  6. 区块链 - 区块链基础知识:交易哈希链

    区块链 - 区块链基础知识:深入了解交易哈希链 本文的主题是执行有关交易哈希链. 交易池的角色以及 一个最长的区块链如何永远占据主导. 讨论的细节包括以下内容: 事务哈希链的实现细节 交易池的角色 为 ...

  7. 坚持自主可控,长安链ChainMaker全面拥抱国密的技术实践

    密码技术作为与核技术.航天技术并列的国家三大安全核心技术之一,在保障信息安全,增强我国行业信息系统的"安全可控"等方面具有关键作用.长期以来国际上较为通用的商用算法是由美国安全局发 ...

  8. 《密码编码学与网络安全》William Stalling著---学习笔记(二)【知识点速过】【数字签名+密钥管理分发+用户认证】

    提示:博文有点长,请保持耐心哦~ 前一篇文章: <密码编码学与网络安全>William Stalling著-学习笔记(一)[知识点速过][传统密码+经典对称加密算法+经典公钥密码算法+密码 ...

  9. FIDO UAF Specification Protocol(Considerations节译)

    原文链接:http://blog.csdn.net/u014142287/article/details/69487015 4.Considerations 4.1核心协议设计思考 本部分描述一些在协 ...

  10. TLS协议中的握手协议

    TLS 握手协议(handshake protocol) 握手是TLS协议中最精密复杂的部分.在这个过程中,通信双方协商连接参数(沟通双方各有什么加密算法,选择一个最合适的算法),并且完成身份验证.根 ...

最新文章

  1. java C语言内存占用_使用Cgroup限制Java使用的内存量-思路
  2. linux共享文件丢失,【干货分享】linux平台下数据文件被误删后,如何及时得知并进行恢复...
  3. python删除列表中的偶数_Python:从列表中删除奇数
  4. MySql的Delete、Truncate、Drop分析
  5. 24暴力枚举四平方和
  6. MATLAB设置当前工作目录
  7. 修改vCenter client无法连接
  8. snackbar_Android Snackbar示例教程
  9. Mac下Vmware Fusion配置虚拟机虚拟网卡并配置CENTOS上网
  10. 安卓:android.process.media意外停止解决方法
  11. Captaris WorkFlow的开发和部署
  12. CH579 以太网转串口 串口服务器代码!
  13. 【多媒体基础知识】 --- 什么是流媒体技术
  14. 初学者之路100个视频教程
  15. 搞死SAP系统系列 让系统无法登录
  16. 微信公众号赞赏账户头像在哪里修改?附详细图文教程
  17. Tensorflow中的各种梯度处理gradient
  18. Launcher启动流程及初始化
  19. 1000份电子技术(模电、数电、电子元件、电路视频教程)全套资料!
  20. ISO/IEC 27001:2013 版变化

热门文章

  1. 读浅墨博客 十二 笔记
  2. 达人评测 i5 13400和r5 7600x选哪个好 酷睿i513400和锐龙r57600x差距
  3. ip数据报格式;ip数据报分片
  4. 电脑上出现应用程序无法正常启动0xc0000142的解决方法
  5. 单位不同意签署无期限劳动合同怎么办
  6. 基于javaweb的驾校预约管理系统(java+ssm+html+layui+bootstrap+mysql)
  7. 美刊评出2009年度十大发明
  8. 直播页面6:直播中的弹幕_烈焰弹幕使
  9. java mybatis 返回map_Mybatis中返回Map
  10. python爬取地图数据_高德3地图之python爬取POI数据及其边界经纬度(根据关键字在城市范围内搜索)...