前言

openssl API中有两套接口进行签名(sign)和校验(verify)操作, 一套是老接口 EVP_Sign* 一套是新接口EVP_DigestSign*和EVP_DigestVerify*.后续推荐使用新的接口

下面的例子使用新的接口来进行签名和校验,

概览

一般来说,签名一个消息分为3个步骤:

  • 初始化(init)一个context,传入摘要/哈希函数和一个EVP_PKEY类型的私钥
  • 传入(Update)要被签名的消息数据(如果数据量较大,这一步可以重复多次,分段将数据传入,避免内存不够的问题)
  • Finalize context 得到签名数据

初始化时,有两点需要注意:

  1. 我们需要选取一个摘要算法,这个体现在传入的摘要函数上
  2. 我们为摘要算法提供一个包含私钥的EVP_PKEY指针对象

初始化调用EVP_DigestSignInit.

传入被签名的消息调用EVP_DigestSignUpdate (支持循环调用,分段传入)

最终Finalize调用EVP_DigestSignFinal.

一般来说,校验者手上有的是公钥,校验的步骤是类似的,不同点在于使用EVP_DigestVerify*这套接口并且EVP_PKEY是包含的公钥

如果校验者手上有私钥,也可以这么校验。使用私钥使用EVP_DigestSign*接口进行签名得到签名数据,最后再和传入的签名数据进行对比来判断。

代码示例

签名代码

void signText(){#define PRIVATEKEYPATH "/home/gateway/Eden/Test/openssl/rsa_key.private"EVP_MD_CTX *mdctx = NULL;int ret = 0;unsigned char *sig = NULL;size_t slen, len ,len1;FILE* fd;const char *msg = (const char*)readFile("/home/gateway/Eden/Test/openssl/config", "r", len);std::unique_ptr<BIO, decltype(&BIO_free_all)> keybio(BIO_new_file(PRIVATEKEYPATH, "r"), BIO_free_all);std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)> keyevp(PEM_read_bio_PrivateKey(keybio.get(), NULL,NULL,/*&cb_data*/ NULL), EVP_PKEY_free);size_t siglen = EVP_PKEY_size(keyevp.get());cout << "siglen =" << siglen <<  endl;/* Create the Message Digest Context */if(!(mdctx = EVP_MD_CTX_create())) goto err;ret = 1;/* Initialise the DigestSign operation - SHA-256 has been selected as the message digest function in this example */if(1 != EVP_DigestSignInit(mdctx, NULL, EVP_sha256(), NULL, keyevp.get())) goto err;ret = 2;/* Call update with the message */if(1 != EVP_DigestSignUpdate(mdctx, msg, len)) goto err;ret = 3;/* Finalise the DigestSign operation *//* First call EVP_DigestSignFinal with a NULL sig parameter to obtain the length of the* signature. Length is returned in slen */if(1 != EVP_DigestSignFinal(mdctx, NULL, &slen)) goto err;++ret;/* Allocate memory for the signature based on size in slen */if(!(sig = (unsigned char*)OPENSSL_malloc(sizeof(unsigned char) * slen))) goto err;++ret;/* Obtain the signature */if(1 != EVP_DigestSignFinal(mdctx, sig, &slen)) goto err;++ret;/* Success */err:if(ret != 6){cout << "ret=" << ret <<  endl;/* Do some error handling */}/* Clean up */if(sig && !ret) OPENSSL_free(sig);if(mdctx) EVP_MD_CTX_destroy(mdctx);
}

sig就是对应的签名数据。

验证代码

bool VerifySign(){
#define PUBLICKEYPATH "/home/gateway/Eden/Test/openssl/rsa_key.public"size_t siglen, len ;int r;const char *msg = (const char*)readFile("/home/gateway/Eden/Test/openssl/config", "r", len);unsigned char *sig = NULL;std::unique_ptr<BIO, decltype(&BIO_free_all)> bmd(BIO_new(BIO_f_md()), BIO_free_all);std::unique_ptr<BIO, decltype(&BIO_free_all)> keybio(BIO_new_file(PUBLICKEYPATH, "r"), BIO_free_all);std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)> keyevp(PEM_read_bio_PUBKEY(keybio.get(), NULL,NULL,/*&cb_data*/ NULL), EVP_PKEY_free);std::unique_ptr<BIO, decltype(&BIO_free_all)> sigbio(BIO_new_file("/home/gateway/Eden/Test/openssl/sgn2.sign", "rb"), BIO_free_all);siglen = EVP_PKEY_size(keyevp.get());if(1 != EVP_DigestSignInit(mdctx.get(), NULL, EVP_sha256(), NULL, keyevp.get())){//DEBUG(Debug::WARN, "Error EVP_DigestSignInit\n");return false;}if(1 != EVP_DigestVerifyUpdate(mdctx.get(), msg, len)){//DEBUG(Debug::WARN, "Error EVP_DigestSignUpdate\n");return false;}sig = (unsigned char *)OPENSSL_malloc(siglen);siglen = BIO_read(sigbio.get(), sig, siglen);r=EVP_DigestVerifyFinal(mdctx.get(), sig, siglen);OPENSSL_free(sig);if(1 == r){DEBUG(Debug::NOTICE, "VerifySign true\n");return true;}else{DEBUG(Debug::WARN, "VerifySign false\n");return false;}
}

如果签名数据和公钥都已经存在于内存中,使用如下示例:

bool A71CH::VerifySign(char* publickeyPath, const char* msg, size_t msglen, const unsigned char* sig, size_t siglen){if(publickeyPath == NULL || msg == NULL || sig == NULL){DEBUG(Debug::WARN, "VerifySign paramters null");return false;}std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_free)> mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_free);std::unique_ptr<BIO, decltype(&BIO_free_all)> keybio(BIO_new_file(publickeyPath, "r"), BIO_free_all);std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)> keyevp(PEM_read_bio_PUBKEY(keybio.get(), NULL,NULL,NULL), EVP_PKEY_free);if(1 != EVP_DigestVerifyInit(mdctx.get(), NULL, EVP_sha256(), NULL, keyevp.get())){DEBUG(Debug::WARN, "VerifySign failed");return false;}if(1 != EVP_DigestVerifyUpdate(mdctx.get(), msg, msglen)){DEBUG(Debug::WARN, "VerifySign failed");return false;}if(1 == EVP_DigestVerifyFinal(mdctx.get(), sig, siglen)){DEBUG(Debug::NOTICE, "VerifySign OK");return true;}else{DEBUG(Debug::WARN, "VerifySign failed");return false;}
}

参考:https://wiki.openssl.org/index.php/EVP_Signing_and_Verifying

EVP 签名和校验 Signing and Verifying相关推荐

  1. [Xcode]iOS代码签名(Code Signing)

    在打包过程中让我吃了不少苦头,归根到底是对一些概念和一些原理不清楚不明白,... 代码签名 Code Signing 也叫 App 签名,它是依靠 iOS 证书来进行的,它保证了 App 的合法性.完 ...

  2. Code signing Guide代码签名探悉

    "用户会感激代码签名带来的好处" – Apple Developer Library: Code Signing Guide 在 iOS 或 OS X 平台上进行应用开发时,你所需 ...

  3. 给共享程序集延迟签名

    为了安全,公司一般只有少数人能访问到私钥.但是在开发和测试程序集时,访问这些受到严密保护的私钥可能有些费事儿.有鉴于此,.NET Framework提供了对延迟签名(delayed signing)的 ...

  4. java安全——数字签名+代码签名

    [0]README 1)本文文字描述转自 core java volume 2, 旨在学习 java安全--数字签名 的基础知识: 2)本文实践内容以及截图笔记均为原创: 3)如果要给予applet更 ...

  5. 一起谈.NET技术,Visual Studio对程序集签名时一个很不好用的地方

    由于我们的项目底层使用到一个通过LogicalCallContext实现的上下文数据管理框架,导致所有的Unit Test不能正常运行.具体的现象在<只在UnitTest和WebHost中的出现 ...

  6. 微信支付生成签名和验签SDK源码分析

    目录 一.签名分析 1.1 流程分析 1.构造签名串 2.计算签名值 3.设置请求头 二.源码级别分析 二.获取平台证书分析 三.验签分析 3.1 验签使用场景: 3.2 验证流程: 1.获取微信平台 ...

  7. APK签名机制原理详解

    转载请注明出处:https://blog.csdn.net/zwjemperor/article/details/80877203 github:https://github.com/rushgit/ ...

  8. Android安全检测 - Janus签名漏洞

    前言 这一章来说说Janus签名漏洞,网上关于这个漏洞的介绍很详细,其中的原理均为其它地方进行摘录,那么我主要做的就是POC测试,在文章末尾也会给出相应的样本,当然样本就是自己做的,用真实的上线项目来 ...

  9. OV代码签名和EV代码签名证书区别

    原文来自:OV代码签名和EV代码签名证书区别_代码签名证书_Gworg 如果代码分发在网络上,则可能会受到侵害.代码可能会在到达用户前被黑客攻击.被其他开发人员盗用,或者因为"身份不明的发布 ...

最新文章

  1. 用相对路径有时居然是这样,,加上%=basePath%
  2. 《HeadFirst设计模式》笔记
  3. 构建用户界面 Android 应用中一些常用的小部件
  4. 按id进行查找按名称进行排序_Excel工作表中如何按需要的顺序快速进行排序
  5. 第五十一期:互联网不如国企,去BAT的程序员都是diao丝?
  6. 区块链中涉及到密码学的场景
  7. SpringBoot2.0 整合 Shiro 框架,实现用户权限管理
  8. android曲线水波纹录音动画,Android-贝塞尔曲线实现水波纹动画
  9. 行连接和列连接的区别
  10. 学生社区(学校交流社区)网站源码推荐
  11. java中文字符串转化成英文字母
  12. KEIL4与KEIL5护眼配色方案
  13. 联想小新触摸板驱动_联想小新智能语音鼠标驱动
  14. 51个最佳jQuery教程和示例
  15. 内存颗粒和闪存颗粒的区别_内存条怎么判断好坏? 内存颗粒的种类及其差别介绍...
  16. 百分之九十的人都不清楚自己找的是Kanban软件还是看板软件(附Kanban工具测评)
  17. C++ 模板类与头文件
  18. C++类和对象(中)
  19. 小米米家空气净化器2S拆解
  20. java编写游戏_java编写小游戏-大球吃小球

热门文章

  1. Nginx源码学习(一):nginx进程模型解析
  2. 大话设计模式之观察者模式
  3. 汽车理论matlab编程,(百度)汽车理论matlab编程.ppt
  4. Android Gson在Kotlin data class中的使用
  5. 帝国CMS7.5仿《女人说》模板源码/帝国CMS内核女性生活时尚门户网站模板
  6. 易升更新win10 1903错误:此电脑无法升级到windows 10
  7. PostgreSQL最后的救命稻草 — pg_resetwal
  8. js求两圆交点_如何求两个圆的交点坐标,请举例
  9. 著名电子竞技游戏分析
  10. echarts可视化市级地图详细版(vue+element)