C语言实现SHA-256算法校验文件(win32-API)

一、前言

在数字化时代,信息安全与数据完整性成为了不可忽视的关键议题。在众多保障数据完整性的方法中,散列函数扮演着至关重要的角色。SHA-256(Secure Hash Algorithm 256)作为一种先进的散列算法,以其高度的安全性和广泛的应用性脱颖而出,尤其在文件校验、密码存储、数字签名等领域展现出了卓越的表现力。

image-20240715164411050

SHA-256算法是SHA-2家族的一员,由美国国家安全局(NSA)设计,经由美国国家标准与技术研究院(NIST)发布。不同于MD5算法,SHA-256不仅提供了更长的散列值长度——256位(32字节),增强了抗碰撞能力,还引入了一系列复杂的数学运算,包括模运算、位移、异或、加法等,以确保即使输入的微小变化也能引起散列值的显著差异,这种特性被称为雪崩效应。SHA-256的输出通常以64位十六进制字符串表示,每一个字符代表4位,总共需要32个字符来完整表示256位的散列值。

在实现文件的SHA-256校验时,C语言结合Win32 API提供了强大的工具集。通过调用CryptoAPI(Cryptographic Application Programming Interface)中的相关函数,可以高效地计算出文件的SHA-256值。CryptoAPI是Windows操作系统内置的加密库,它封装了包括SHA-256在内的多种加密和散列算法,简化了复杂加密操作的实现难度。在C语言环境中,开发者可以通过一系列步骤,如获取加密服务提供者(CSP)句柄、创建散列对象、分块读取文件数据并进行散列计算、获取散列结果等,来完成SHA-256值的计算。这一过程不仅能够确保文件的完整性,还能有效抵御数据篡改和非法访问,尤其是在网络传输和存储环节,SHA-256的校验机制能够为数据的来源和状态提供强有力的验证。

相较于MD5算法,SHA-256在安全性上有着显著的优势。MD5算法由于存在碰撞攻击的风险,即不同的输入可能导致相同的散列值,已被证实不够安全,尤其是对于高安全需求的场景。而SHA-256通过其更长的散列值和更复杂的运算逻辑,极大地降低了碰撞的概率,提升了算法的鲁棒性和安全性。因此,在涉及敏感信息处理、身份验证、电子交易等高风险领域,SHA-256成为了首选的散列算法。

SHA-256算法凭借其强大的数据完整性保护能力和广泛的适用性,在现代信息安全体系中占据了举足轻重的地位。借助C语言与Win32 API的结合,开发者能够轻松地集成SHA-256校验功能,为数据的传输、存储和处理提供了一层坚实的保护罩。无论是对于个人用户还是企业机构,掌握并应用SHA-256算法,都是维护数据安全、防范潜在威胁的重要手段。

二、代码实操

2.1 计算数组的SHA-256值(win32-API)

要在Windows上使用C语言并且不依赖于任何第三方库(如OpenSSL)来计算SHA-256哈希,可以使用Windows Crypto API (Cryptographic Application Programming Interface, CAPI)。

下面是使用Windows Crypto API来计算一个字符串的SHA-256哈希值的示例代码:

#include <windows.h>
#include <wincrypt.h>
#include <stdio.h>void PrintHex(const BYTE *data, DWORD len) {for (DWORD i = 0; i < len; i++) {printf("%02X", data[i]);}
}int main() {HCRYPTPROV hProv = NULL;HCRYPTHASH hHash = NULL;// 定义要计算SHA-256的数组BYTE testData[] = "Hello, this is a test message for SHA-256.";DWORD testDataLen = sizeof(testData) - 1; // 减1是因为数组末尾有'\0'// 初始化Crypto APIif (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {printf("Error: %d\n", GetLastError());return 1;}// 创建一个哈希对象if (!CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash)) {printf("Error: %d\n", GetLastError());CryptReleaseContext(hProv, 0);return 1;}// 添加数据到哈希对象if (!CryptHashData(hHash, testData, testDataLen, 0)) {printf("Error: %d\n", GetLastError());CryptDestroyHash(hHash);CryptReleaseContext(hProv, 0);return 1;}// 获取哈希摘要的大小DWORD dwHashSize = 0;if (!CryptGetHashParam(hHash, HP_HASHVAL, NULL, &dwHashSize, 0)) {printf("Error: %d\n", GetLastError());CryptDestroyHash(hHash);CryptReleaseContext(hProv, 0);return 1;}// 分配内存以保存哈希摘要BYTE *pbHash = (BYTE *)malloc(dwHashSize);if (pbHash == NULL) {printf("Error allocating memory.\n");CryptDestroyHash(hHash);CryptReleaseContext(hProv, 0);return 1;}// 获取哈希摘要if (!CryptGetHashParam(hHash, HP_HASHVAL, pbHash, &dwHashSize, 0)) {printf("Error: %d\n", GetLastError());free(pbHash);CryptDestroyHash(hHash);CryptReleaseContext(hProv, 0);return 1;}// 输出哈希摘要printf("SHA-256 Digest: ");PrintHex(pbHash, dwHashSize);printf("\n");// 清理free(pbHash);CryptDestroyHash(hHash);CryptReleaseContext(hProv, 0);return 0;
}

这个程序初始化Crypto API环境,然后创建一个SHA-256哈希对象。接着,将要计算哈希的数据传递给CryptHashData函数,之后通过CryptGetHashParam获取哈希摘要。最后,使用PrintHex函数打印出十六进制格式的摘要。

2.2 计算数组的SHA-256值(OpenSSL库)

在C语言中使用SHA-256算法计算一段数组数据的散列值,可以选择使用OpenSSL库,下面是一个使用OpenSSL库的C语言代码示例,用于计算一个字节数组的SHA-256散列值,并将其以十六进制格式打印出来。

确保开发环境中已经安装了OpenSSL库。在Visual Studio中,需要在项目属性的“链接器”->“输入”->“附加依赖项”中添加libeay32.libssleay32.lib。如果是使用GCC编译器,编译时需要添加-lcrypto选项。

接下来是C语言代码示例:

#include <stdio.h>
#include <string.h>
#include <openssl/sha.h>// 函数声明,用于打印字节数据为十六进制
void print_hex(const unsigned char *data, size_t len);int main() {// 定义一个测试数组unsigned char testData[] = "Hello, this is a test message for SHA-256.";// SHA-256摘要长度unsigned int digest_len = SHA256_DIGEST_LENGTH;// 创建一个字节数组存储摘要unsigned char digest[digest_len];// 计算SHA-256摘要SHA256(testData, strlen((const char *)testData), digest);// 打印摘要的十六进制形式printf("SHA-256 Digest: ");print_hex(digest, digest_len);printf("\n");return 0;
}// 函数实现,用于打印字节数据为十六进制
void print_hex(const unsigned char *data, size_t len) {for (size_t i = 0; i < len; i++) {printf("%02x", data[i]);}
}

在这个代码中,定义了一个测试数组testData,使用SHA256函数计算其SHA-256摘要。SHA256_DIGEST_LENGTH是一个宏,定义了SHA-256摘要的长度,即32字节。print_hex函数用于将摘要数据转换为十六进制字符串并打印出来。

2.3 计算文件的SHA-256值(win32-API)

为了使用Win32 API计算一个文件的SHA-256哈希值,需要对文件进行分块读取并逐块添加到哈希上下文中。

下面是一个使用CryptHashData函数和文件I/O函数来计算文件SHA-256哈希值的C语言示例代码:

#include <windows.h>
#include <wincrypt.h>
#include <stdio.h>
#include <stdlib.h>#define BUFFER_SIZE 4096void PrintHex(const BYTE *data, DWORD len) {for (DWORD i = 0; i < len; ++i) {printf("%02X", data[i]);}
}int main(int argc, char **argv) {if (argc != 2) {printf("Usage: %s <filename>\n", argv[0]);return 1;}HCRYPTPROV hCryptProv = NULL;HCRYPTHASH hCryptHash = NULL;HANDLE hFile = CreateFile(argv[1], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);if (hFile == INVALID_HANDLE_VALUE) {printf("Failed to open file: %d\n", GetLastError());return 1;}if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {printf("Error acquiring cryptographic context: %d\n", GetLastError());CloseHandle(hFile);return 1;}if (!CryptCreateHash(hCryptProv, CALG_SHA_256, 0, 0, &hCryptHash)) {printf("Error creating hash object: %d\n", GetLastError());CryptReleaseContext(hCryptProv, 0);CloseHandle(hFile);return 1;}BYTE buffer[BUFFER_SIZE];DWORD bytesRead = 0;while (ReadFile(hFile, buffer, BUFFER_SIZE, &bytesRead, NULL)) {if (bytesRead == 0)break;if (!CryptHashData(hCryptHash, buffer, bytesRead, 0)) {printf("Error hashing data: %d\n", GetLastError());CryptDestroyHash(hCryptHash);CryptReleaseContext(hCryptProv, 0);CloseHandle(hFile);return 1;}}if (GetLastError() != ERROR_SUCCESS) {printf("Error reading file: %d\n", GetLastError());CryptDestroyHash(hCryptHash);CryptReleaseContext(hCryptProv, 0);CloseHandle(hFile);return 1;}DWORD hashSize = 0;if (!CryptGetHashParam(hCryptHash, HP_HASHVAL, NULL, &hashSize, 0)) {printf("Error getting hash size: %d\n", GetLastError());CryptDestroyHash(hCryptHash);CryptReleaseContext(hCryptProv, 0);CloseHandle(hFile);return 1;}BYTE *hash = (BYTE *)malloc(hashSize);if (hash == NULL) {printf("Memory allocation failed.\n");CryptDestroyHash(hCryptHash);CryptReleaseContext(hCryptProv, 0);CloseHandle(hFile);return 1;}if (!CryptGetHashParam(hCryptHash, HP_HASHVAL, hash, &hashSize, 0)) {printf("Error getting hash value: %d\n", GetLastError());free(hash);CryptDestroyHash(hCryptHash);CryptReleaseContext(hCryptProv, 0);CloseHandle(hFile);return 1;}printf("SHA-256 Digest: ");PrintHex(hash, hashSize);printf("\n");free(hash);CryptDestroyHash(hCryptHash);CryptReleaseContext(hCryptProv, 0);CloseHandle(hFile);return 0;
}

这段代码首先检查命令行参数,然后打开指定的文件,并使用CryptAcquireContextCryptCreateHash初始化加密上下文和哈希对象。接着,从文件中读取数据,每次读取BUFFER_SIZE字节,直到文件结束。对于每个读取的数据块,都调用CryptHashData来更新哈希。最后,它调用CryptGetHashParam来获取最终的哈希值并打印出来。

请注意,BUFFER_SIZE定义了每次读取文件的字节数,可以根据需要调整这个值。如果文件非常大,较大的缓冲区可以提高性能,但也会消耗更多内存。反之亦然,较小的缓冲区会降低内存使用量,但可能需要更多的磁盘I/O操作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/414947.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VScode + Python 下载及安装|python环境配置|中文乱码解决

1&#xff0c;下载安装VScode 直接点击2024.9https://vscode.download.prss.microsoft.com/dbazure/download/stable/fee1edb8d6d72a0ddff41e5f71a671c23ed924b9/VSCodeUserSetup-x64-1.92.2.exe 或者百度搜索VScode&#xff0c;可下载安装最新版 点击后等一下&#xff0c;就…

逆向工程核心原理 Chapter 21 | Windows消息钩取

开始DLL注入章节的学习。 知识点学习 消息钩子 这里主要是要弄明白Windows GUI程序的工作模式/流程。 GUI以事件驱动方式工作。核心概念&#xff1a;message queue 最具代表性的&#xff1a;MS提供的spy SetWindowsHookEX() SetWindowsHookExA 函数 (winuser.h) - Win32 a…

网易易盾携手雷斧科技,打造公平竞技环境

这是一个充满复古像素风格的游戏世界&#xff0c;玩家们控制着自己的像素角色&#xff0c;手持着各种像素化武器&#xff0c;时而酣畅对战&#xff0c;时而自由创作地图、武器和皮肤。 《像素射击》是由雷斧科技开发的一款集生存、对战、沙盒创造于一体的像素风格的3D多人在线…

极狐GitLab 17.3 重点功能解读

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;可以私有化部署&#xff0c;对中文的支持非常友好&#xff0c;是专为中国程序员和企业推出的企业级一体化 DevOps 平台&#xff0c;一键就能安装成功。安装详情可以查看官网指南。 极狐GitLab 17.3 正式发布了多项与敏捷项目管…

ecmascript和javascript的区别

ECMAScript ECMAScript&#xff08;通常缩写为ES&#xff09;是JavaScript的规范&#xff0c;由Ecma International组织制定和维护。ECMAScript是一种脚本语言标准&#xff0c;主要用于Web应用程序开发&#xff0c;但也适用于其他类型的应用程序&#xff0c;如桌面和移动应用程…

相亲交友小程序开发功能分析

相亲交友小程序的开发功能分析可以从用户端和管理后台两个主要方面来进行。 用户端功能 注册与登录&#xff1a; 用户可以通过手机号、微信号或其他第三方平台进行注册登录&#xff0c;简化注册流程。 实名认证&#xff1a; 引入实名认证机制&#xff0c;确保用户信息的真实…

Java 技术教程:@JsonInclude(JsonInclude.Include.NON_EMPTY) 注解详解

本人详解 作者:王文峰,参加过 CSDN 2020年度博客之星,《Java王大师王天师》 公众号:JAVA开发王大师,专注于天道酬勤的 Java 开发问题中国国学、传统文化和代码爱好者的程序人生,期待你的关注和支持!本人外号:神秘小峯 山峯 转载说明:务必注明来源(注明:作者:王文峰…

C语言连接MySql(vs2022、Vc++6.0、DevC++)

本文c&#xff08;OraOla编写&#xff09;与Java(Wideskyzz编写) 由于csdn的排版太垃圾了&#xff0c;所以可以直接看资料 上传资料也麻烦&#xff0c;所以可直接访问我的gitee C语言连接MySql: C语言&#xff08;vs2022、Vc6.0、DevC&#xff09;连接MySqlhttps://gitee.co…

Python检测和识别车牌-python经典练手项目

车牌检测与识别技术用途广泛&#xff0c;可以用于道路系统、无票停车场、车辆门禁等。这项技术结合了计算机视觉和人工智能。 本文将使用Python创建一个车牌检测和识别程序。该程序对输入图像进行处理&#xff0c;检测和识别车牌&#xff0c;最后显示车牌字符&#xff0c;作为…

OceanBase 的ODP OBproxy 的记录

OceanBase 的ODP的路由说明一、简述为什么使用ODP的原因 &#xff08;强一致性情况下&#xff09; 1.分布式数据库在SQL解析这块存在本地执行计划&#xff0c;远程执行计划&#xff0c;分布式执行计划。 本地执行计划&#xff1a;整个SQL的表都在session所在的Observer 节点上。…

数据结构代码集训day14(适合考研、自学、期末和专升本)

题目均来自b站up&#xff1a;白话拆解数据结构&#xff01; 今日题目如下&#xff1a;&#xff08;1&#xff09;试写一个算法判断给定字符序列是否是回文。 &#xff08;2&#xff09;给定一个算法判断输入的表达式中括号是否匹配。假设只有花、中、尖三种括号。 题1 回文序列…

教学能力知识

第一章课程理论知识 一、课程理念 二、课程目标 1.核心素养 2.课程总目标 三、教学建议 四、教学环节 第二章教学实施 第一节导入新课类 二.导入方法 第二节教学方法类 教学方法的选择依据 第三节教法实施原则类 设计意图 第四节设计意图类 1.教学目标 2.教学重难点 3.教学…

【Linux】:用户缓冲区

1.前言&#xff08;引出现象&#xff09; 我们看一段代码&#xff0c; 我们运行这段代码&#xff0c; 再次运行&#xff0c;并将打印结果重定向到文件log.txt中&#xff0c; 结果除了系统调用write的输出&#xff0c;其余输出都多打印一次。这是为什么呢&#xff1f;我们先…

《花100块做个摸鱼小网站! 》第五篇—通过xxl-job定时获取热搜数据

⭐️基础链接导航⭐️ 服务器 → ☁️ 阿里云活动地址 看样例 → &#x1f41f; 摸鱼小网站地址 学代码 → &#x1f4bb; 源码库地址 一、前言 我们已经成功实现了一个完整的热搜组件&#xff0c;从后端到前端&#xff0c;构建了这个小网站的核心功能。接下来&#xff0c;我们…

029、架构_高可用_水位和分组

GoldenDB分组技术 GoldenDB灵活智能的数据可用性策略名称是gTank。包含了分组技术和高低水位两个技术点。在分布式一主多备架构下,全节点的数据同步,耗时长、用户体验差。因此GoldenDB采用分组技术,将数据节点和事务节点GTM实现分组管理,实现业务的灵活配置。 数据节点集群…

基于 OpenCV 的数字图像处理实验平台设计

基于 OpenCV 的数字图像处理实验平台设计 前言简介正文资源链接&#xff08;含源码&#xff09; 前言 哈哈上学那会儿做的一个软件&#xff0c;当时把OpenCV各个基础算法都集成在了一起&#xff0c;还有一定程度的顺序执行部分相关算法的功能&#xff0c;那时候网上相关内容比较…

/单元测试

承接上文 统一异常处理&#xff0c;封装结果-CSDN博客 ******************************************** 登录业务 Service public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper, Employee> implements EmployeeService {Resourceprivate JwtUtils j…

jQuery入门(六)jQuery实现瀑布流分页案例

一、瀑布流分页案例分析 1.1) 功能分析&#xff1a; 鼠标下拉&#xff0c;加载分页数据(10条) &#xff0c;如下图&#xff1a; 案例分析&#xff1a; 1.2) 如何确定当前显示的数据已经浏览完毕&#xff1f; 公式&#xff1a;(滚动条距底部的距离 滚动条上下滚动的距离 当…

Echarts中国地图省市区县三级联动

NodeV14.20.0安装 # 历史版本Node下载地址 https://nodejs.org/en/download/prebuilt-installer# NodeV14.20.0配置与部署 https://nodejs.org/dist/v14.20.0/node-v14.20.0-x64.msi构建默认Vue3工程目录 npm install -g vue/cli --registryhttps://registry.npm.taobao.org …

22. K8S及DevOps

22. K8S及DevOps 一. 章节简介二. DevOps1. 简介2. CICD三. Kubernetes1. [官网](https://kubernetes.io/zh-cn/)2. K8S安装2.1 服务器要求2.2 准备工作演示服务器IP主副服务器设置`hostnamectl`设置host与ip绑定关闭防火墙时间同步关闭selinux安全策略关闭swap分区网桥过滤与地…