当前位置: 首页 > wzjs >正文

织梦网站网上商城怎么推广

织梦网站,网上商城怎么推广,建筑网站的功能模块有哪些,2024全民核酸又开始了OpenSSL 文件验签与字符串验签原理及 C 语言实现详解 摘要 本文深入探讨了基于 OpenSSL 的文件验签与字符串验签原理及 C 语言实现方法。先阐述数字签名验证原理,包括基于非对称加密算法和哈希算法的签名生成与验证流程,着重介绍 OpenSSL 中利用 EVP 高…

OpenSSL 文件验签与字符串验签原理及 C 语言实现详解

摘要

本文深入探讨了基于 OpenSSL 的文件验签与字符串验签原理及 C 语言实现方法。先阐述数字签名验证原理,包括基于非对称加密算法和哈希算法的签名生成与验证流程,着重介绍 OpenSSL 中利用 EVP 高级接口实现数字签名验证的关键函数及其作用。随后分别提供文件验签和字符串验签的完整 C 语言代码示例,详细解析各步骤要点,如公钥加载、数据读取、验证上下文初始化、更新验证数据及完成验证等,并给出代码步骤详解。此外,还涵盖错误处理与调试技巧,通过 OpenSSL 错误报告机制排查验证失败原因,列举常见错误类型及处理方式。同时对比文件验签与字符串验签特性,从数据来源、加载方式、大数据处理、适用场景及性能角度分析差异。最后总结最佳实践,涵盖算法选择、密钥管理、错误处理、资源管理和性能优化等方面,助力开发者在 OpenSSL 中高效实现文件和字符串签名验证功能,保障数据完整性和真实性。

数字签名验证原理

签名生成原理

  • 哈希计算 :对原始数据使用哈希算法(如 SHA - 256)生成固定长度的消息摘要。
  • 私钥加密 :使用签名者的私钥对消息摘要进行加密,生成数字签名。
  • 签名存储 :将数字签名与原始数据一起存储或传输。

签名验证原理

  • 哈希计算 :对接收到的原始数据使用相同的哈希算法生成消息摘要。
  • 公钥解密 :使用签名者的公钥对数字签名进行解密,得到原始消息摘要。
  • 摘要比对 :比较计算得到的消息摘要和解密得到的消息摘要,如果一致则验证通过。

在 OpenSSL 中,借助 EVP(Envelope)高级接口实现上述流程,主要涉及以下函数:

  • EVP_DigestVerifyInit() :初始化验证上下文。
  • EVP_DigestVerifyUpdate() :输入待验证数据。
  • EVP_DigestVerifyFinal() :完成验证并返回结果。

文件验签 C 语言实现

以下是使用 OpenSSL EVP 接口实现文件验签的完整 C 代码示例:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/err.h>// 验证文件签名
int verify_file_signature(const char* pubkey_file, const char* data_file,const char* sig_file) {EVP_MD_CTX* mdctx = NULL;EVP_PKEY* pubkey = NULL;FILE* pubkey_fp = NULL;FILE* data_fp = NULL;FILE* sig_fp = NULL;unsigned char* data = NULL;unsigned char* sig = NULL;size_t data_len = 0;size_t sig_len = 0;int result = -1;// 1. 读取公钥文件pubkey_fp = fopen(pubkey_file, "r");if (!pubkey_fp) {fprintf(stderr, "Error opening public key file\n");goto cleanup;}pubkey = PEM_read_PUBKEY(pubkey_fp, NULL, NULL, NULL);if (!pubkey) {fprintf(stderr, "Error reading public key\n");goto cleanup;}// 2. 读取数据文件data_fp = fopen(data_file, "rb");if (!data_fp) {fprintf(stderr, "Error opening data file\n");goto cleanup;}fseek(data_fp, 0, SEEK_END);data_len = ftell(data_fp);fseek(data_fp, 0, SEEK_SET);data = (unsigned char*)malloc(data_len);if (!data) {fprintf(stderr, "Memory allocation error\n");goto cleanup;}if (fread(data, 1, data_len, data_fp) != data_len) {fprintf(stderr, "Error reading data file\n");goto cleanup;}// 3. 读取签名文件sig_fp = fopen(sig_file, "rb");if (!sig_fp) {fprintf(stderr, "Error opening signature file\n");goto cleanup;}fseek(sig_fp, 0, SEEK_END);sig_len = ftell(sig_fp);fseek(sig_fp, 0, SEEK_SET);sig = (unsigned char*)malloc(sig_len);if (!sig) {fprintf(stderr, "Memory allocation error\n");goto cleanup;}if (fread(sig, 1, sig_len, sig_fp) != sig_len) {fprintf(stderr, "Error reading signature file\n");goto cleanup;}// 4. 初始化验证上下文mdctx = EVP_MD_CTX_new();if (!mdctx) {fprintf(stderr, "Error creating EVP_MD_CTX\n");goto cleanup;}if (EVP_DigestVerifyInit(mdctx, NULL, EVP_sha256(), NULL, pubkey) != 1) {fprintf(stderr, "Error initializing verification\n");goto cleanup;}// 5. 更新验证数据if (EVP_DigestVerifyUpdate(mdctx, data, data_len) != 1) {fprintf(stderr, "Error updating verification data\n");goto cleanup;}// 6. 完成验证result = EVP_DigestVerifyFinal(mdctx, sig, sig_len);if (result == 1) {printf("Signature verification successful\n");} else if (result == 0) {printf("Signature verification failed\n");} else {fprintf(stderr, "Error during verification\n");result = -1;}cleanup:// 7. 清理资源if (mdctx) EVP_MD_CTX_free(mdctx);if (pubkey) EVP_PKEY_free(pubkey);if (pubkey_fp) fclose(pubkey_fp);if (data_fp) fclose(data_fp);if (sig_fp) fclose(sig_fp);if (data) free(data);if (sig) free(sig);return result;
}int main(int argc, char* argv[]) {if (argc != 4) {printf("Usage: %s <public_key.pem> <data_file> <signature_file>\n", argv[0]);return 1;}return verify_file_signature(argv[1], argv[2], argv[3]) != 1;
}

代码步骤详解

  1. 加载公钥 :利用 PEM_read_PUBKEY 从 PEM 格式的公钥文件中读取公钥。
  2. 读取数据文件 :将待验证的文件内容完整读入内存缓冲区。
  3. 读取签名文件 :把签名数据读入内存缓冲区。
  4. 初始化验证上下文 :创建 EVP_MD_CTX 结构,并借助 EVP_DigestVerifyInit 进行初始化。
  5. 更新验证数据 :调用 EVP_DigestVerifyUpdate 将文件数据输入验证过程。
  6. 完成验证 :通过 EVP_DigestVerifyFinal 进行最终验证。
  7. 资源清理 :释放所有分配的内存和文件资源。

字符串验签 C 语言实现

字符串验签与文件验签主要区别在于数据来源不同,以下是处理内存中字符串数据的验签实现:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/err.h>// 验证字符串签名
int verify_string_signature(const char* pubkey_file, const char* message,const unsigned char* sig,size_t sig_len) {EVP_MD_CTX* mdctx = NULL;EVP_PKEY* pubkey = NULL;FILE* pubkey_fp = NULL;int result = -1;// 1. 读取公钥文件pubkey_fp = fopen(pubkey_file, "r");if (!pubkey_fp) {fprintf(stderr, "Error opening public key file\n");goto cleanup;}pubkey = PEM_read_PUBKEY(pubkey_fp, NULL, NULL, NULL);if (!pubkey) {fprintf(stderr, "Error reading public key\n");goto cleanup;}// 2. 初始化验证上下文mdctx = EVP_MD_CTX_new();if (!mdctx) {fprintf(stderr, "Error creating EVP_MD_CTX\n");goto cleanup;}if (EVP_DigestVerifyInit(mdctx, NULL, EVP_sha256(), NULL, pubkey) != 1) {fprintf(stderr, "Error initializing verification\n");goto cleanup;}// 3. 更新验证数据(直接使用字符串)if (EVP_DigestVerifyUpdate(mdctx, message, strlen(message)) != 1) {fprintf(stderr, "Error updating verification data\n");goto cleanup;}// 4. 完成验证result = EVP_DigestVerifyFinal(mdctx, sig, sig_len);if (result == 1) {printf("Signature verification successful\n");} else if (result == 0) {printf("Signature verification failed\n");} else {fprintf(stderr, "Error during verification\n");result = -1;}cleanup:// 5. 清理资源if (mdctx) EVP_MD_CTX_free(mdctx);if (pubkey) EVP_PKEY_free(pubkey);if (pubkey_fp) fclose(pubkey_fp);return result;
}// Base64解码函数
int base64_decode(const char* encoded, unsigned char** decoded, size_t* decoded_len) {BIO* bio = NULL;BIO* b64 = NULL;int len = strlen(encoded);*decoded = (unsigned char*)malloc(len);if (!*decoded) {return -1;}b64 = BIO_new(BIO_f_base64());bio = BIO_new_mem_buf((void*)encoded, len);bio = BIO_push(b64, bio);BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);*decoded_len = BIO_read(bio, *decoded, len);BIO_free_all(bio);return (*decoded_len > 0) ? 0 : -1;
}int main() {const char* pubkey_file = "public_key.pem";const char* message = "This is a test message to verify";const char* base64_sig = "MEUCIQD..."; // Base64编码的签名unsigned char* sig = NULL;size_t sig_len = 0;// 解码Base64签名if (base64_decode(base64_sig, &sig, &sig_len) != 0) {fprintf(stderr, "Error decoding base64 signature\n");return 1;}int ret = verify_string_signature(pubkey_file, message, sig, sig_len);free(sig);return ret != 1;
}

代码步骤详解

  1. 加载公钥 :与文件验签相同,运用 PEM_read_PUBKEY 加载公钥。
  2. 初始化验证上下文 :创建并初始化 EVP_MD_CTX 结构。
  3. 更新验证数据 :直接使用字符串数据调用 EVP_DigestVerifyUpdate
  4. Base64 解码 :提供辅助函数处理 Base64 编码的签名数据。
  5. 完成验证 :调用 EVP_DigestVerifyFinal 进行最终验证。

错误处理与调试

OpenSSL 提供详细的错误报告机制,可在验证失败时获取更多信息:

void print_openssl_error() {unsigned long err;const char* file = NULL;const char* data = NULL;int line, flags;while ((err = ERR_get_error_line_data(&file, &line, &data, &flags)) != 0) {char buf[256];ERR_error_string_n(err, buf, sizeof(buf));fprintf(stderr, "OpenSSL error: %s\n", buf);fprintf(stderr, "  at %s:%d\n", file, line);if (data && (flags & ERR_TXT_STRING)) {fprintf(stderr, "  data: %s\n", data);}}
}// 在验证函数中使用示例
if (EVP_DigestVerifyInit(mdctx, NULL, EVP_sha256(), NULL, pubkey) != 1) {fprintf(stderr, "Error initializing verification\n");print_openssl_error();goto cleanup;
}

常见错误处理

  • 初始化失败 :检查公钥格式是否正确,算法是否支持。
  • 更新数据失败 :检查数据缓冲区是否有效。
  • 验证失败 :检查签名数据是否正确,公钥是否匹配私钥。
  • 内存错误 :确保所有分配的资源都被正确释放。

文件验签与字符串验签对比

特性文件验签字符串验签
数据来源文件系统内存中的字符串
数据加载需要文件 I/O 操作直接使用内存数据
大数据处理可分块读取处理通常一次性处理
适用场景验证文件完整性验证 API 消息、配置数据等
性能考虑受磁盘 I/O 影响纯内存操作,速度更快

总结与最佳实践

  • 算法选择 :推荐使用 SHA - 256 或更强的哈希算法,避免 MD5 或 SHA1 等不安全算法。
  • 密钥管理 :妥善保管私钥,公钥可通过证书链验证真实性。
  • 错误处理 :始终检查 OpenSSL 函数返回值,实现全面错误处理。
  • 资源管理 :确保分配资源正确释放,防止内存泄漏。
  • 性能优化 :大文件可分块调用 EVP_DigestVerifyUpdate,避免一次性加载。

文章转载自:

http://n54AhZJ3.dpbgw.cn
http://Ho0x1RhE.dpbgw.cn
http://Bi29LiVm.dpbgw.cn
http://wtTZfpvV.dpbgw.cn
http://mJqFObbj.dpbgw.cn
http://pv5wuCcW.dpbgw.cn
http://cBtHkgoU.dpbgw.cn
http://C0kAfkyj.dpbgw.cn
http://WEjrbq0J.dpbgw.cn
http://3aRZf0I2.dpbgw.cn
http://b162K6uW.dpbgw.cn
http://5PyYy4tf.dpbgw.cn
http://FTiFOf27.dpbgw.cn
http://h4U8IGWg.dpbgw.cn
http://fu0wQhRZ.dpbgw.cn
http://3HuVP6A8.dpbgw.cn
http://z8iMWAHA.dpbgw.cn
http://2NkUsuKi.dpbgw.cn
http://VgDhGWW2.dpbgw.cn
http://Ad5VxLdE.dpbgw.cn
http://Dk60ZdXg.dpbgw.cn
http://QVOGjfMJ.dpbgw.cn
http://UjSwwuEg.dpbgw.cn
http://xbPzoTji.dpbgw.cn
http://ANocgZOf.dpbgw.cn
http://6uScm2cA.dpbgw.cn
http://wfFm0jcX.dpbgw.cn
http://dQe97JWH.dpbgw.cn
http://5LWeCqqW.dpbgw.cn
http://MHfpJw1n.dpbgw.cn
http://www.dtcms.com/wzjs/648251.html

相关文章:

  • php驾校网站源码wordpress 免签约支付宝
  • 免费网站软件下载大全2018王健林亏60亿做不成一个网站
  • 域名对网站有什么影响微信开放平台注册
  • 示范高校建设网站柳州网站建设11
  • 住房和城乡建设部网站公告佛山网站建设报价
  • 网站建设售后协议wordpress取消categore
  • 毕业设计网站建设软件项目一级建设造师网站
  • 用深度liunx做网站第一ppt课件免费下载官网
  • 百度站长平台安卓版电子商务网站建设的盈利模式
  • 做移动网站优化软件实力网站优化公司首选
  • 百度站长提交网址官方小程序
  • 东莞品牌型网站建设网站备案怎么查
  • 网站推广实施计划万网云服务器怎么上传网站
  • 织梦网暂时关闭网站潍坊做网站优化
  • 网站创建桌面快捷方式众志seo
  • 图书馆评估定级关于网站建设标准wordpress爆破字典
  • 新网站域名备案流程天猫建设网站的目的
  • 注册一个公司网站需要多少钱网站打开很慢
  • 做一个网站团队需要哪些人员ui设计页面布局和功能
  • 网站有什么优势学校网站建设工作
  • 塑胶包装东莞网站建设中牟建设工程信息网站
  • 网站怎么做英语和中文的大连建站平台
  • 厦门seo广东seo推广贵不贵
  • 有那个网站做简历模板wordpress 文章排序插件
  • 上海建设部门网站哪建设网站
  • 做品牌形象网站wordpress 自定义内容类型 pan
  • 宝山品牌网站建设成都哪家公司做网站
  • 做网站用空间好还是服务器好网站建设方案论文1500
  • 网站建设收税网站死链是什么
  • 做网站的为什么那么多骗子怎么找wordpress模板代码