C語言實例_獲取文件MD5值

一、MD5介紹

MD5(Message Digest Algorithm 5)是一種常用的哈希函數算法。將任意長度的數據作為輸入,并生成一個唯一的、固定長度(通常是128位)的哈希值,稱為MD5值。MD5算法以其高度可靠性和廣泛應用而聞名。

image-20230626224839130

MD5算法主要具備以下特點:

(1)不可逆性:給定MD5值無法通過逆運算得到原始數據。

(2)唯一性:不同的輸入數據會生成不同的MD5值。

(3)高效性:對于給定的數據,計算其MD5值是非常快速的。

MD5值的應用場景包括:

(1)數據完整性驗證:MD5值可以用于驗證文件是否在傳輸過程中被篡改。發送方計算文件的MD5值并發送給接收方,接收方在接收到文件后重新計算MD5值,然后與發送方的MD5值進行比較,如果一致,則說明文件未被篡改。

(2)密碼存儲:在許多系統中,用戶密碼通常不會以明文形式存儲,而是將其轉換為MD5值后存儲。當用戶登錄時,系統會將用戶輸入的密碼轉換為MD5值,然后與存儲的MD5值進行比較,以驗證密碼的正確性。

(3)安全認證:MD5值也可用于數字證書等安全認證中,用于驗證文件的完整性和認證信息的真實性。

(4)數據指紋:MD5值可以作為數據的唯一標識符,用于快速比對和查找重復數據。

二、示例代碼

2.1 獲取數據MD5值(openssl庫)

在C語言中獲取一段數據的MD5值,可以使用現有的第三方庫實現。以下是一個使用 OpenSSL 庫計算數據的MD5值的示例代碼:

(1)需要安裝 OpenSSL 庫(如果尚未安裝)并包含相關頭文件:

#include <stdio.h>
#include <stdlib.h>
#include <openssl/md5.h>

(2)創建一個子函數來計算數據的MD5值:

void calculate_md5(const unsigned char* data, size_t length, unsigned char* md5_hash) {MD5_CTX ctx;MD5_Init(&ctx);MD5_Update(&ctx, data, length);MD5_Final(md5_hash, &ctx);
}

該函數接受三個參數:data 為待計算的數據指針,length 為數據長度,md5_hash 為存儲MD5值的數組。

下面是一個完整的程序,展示如何調用以上子函數并打印MD5值:

#include <stdio.h>
#include <stdlib.h>
#include <openssl/md5.h>void calculate_md5(const unsigned char* data, size_t length, unsigned char* md5_hash) {MD5_CTX ctx;MD5_Init(&ctx);MD5_Update(&ctx, data, length);MD5_Final(md5_hash, &ctx);
}void print_md5(const unsigned char* md5_hash) {for (int i = 0; i < MD5_DIGEST_LENGTH; i++) {printf("%02x", md5_hash[i]);}printf("\n");
}int main() {const unsigned char data[] = "Hello, World!";size_t length = sizeof(data) - 1; // 減去字符串末尾的空字符unsigned char md5_hash[MD5_DIGEST_LENGTH];calculate_md5(data, length, md5_hash);printf("MD5: ");print_md5(md5_hash);return 0;
}

這個示例程序將輸出一段數據的MD5值。可以將待計算的數據存儲在 data 數組中,并根據需要調整數據長度。

這里使用的是 OpenSSL 提供的 MD5 函數。在編譯時,需要鏈接 OpenSSL 庫。在 Linux 系統上,可以使用 -lssl -lcrypto 參數進行鏈接。在 Windows 系統上,需要下載并安裝 OpenSSL 庫,并配置正確的鏈接路徑和庫文件名稱。

2.2 獲取文件的MD5值(openssl庫)

以下是使用 OpenSSL 庫計算文件的MD5值的示例代碼:

(1)需要安裝 OpenSSL 庫(如果尚未安裝)并包含相關頭文件:

#include <stdio.h>
#include <stdlib.h>
#include <openssl/md5.h>

(2)創建一個子函數來計算文件的MD5值:

void calculate_file_md5(const char* filename, unsigned char* md5_hash) {FILE* file = fopen(filename, "rb");if (file == NULL) {printf("Failed to open file: %s\n", filename);return;}MD5_CTX ctx;MD5_Init(&ctx);unsigned char buffer[1024];size_t read;while ((read = fread(buffer, 1, sizeof(buffer), file)) != 0) {MD5_Update(&ctx, buffer, read);}fclose(file);MD5_Final(md5_hash, &ctx);
}

該函數接受兩個參數:filename 為待計算的文件名,md5_hash 為存儲MD5值的數組。

下面是一個完整的示例程序,展示如何調用以上子函數并打印文件的MD5值:

#include <stdio.h>
#include <stdlib.h>
#include <openssl/md5.h>void calculate_file_md5(const char* filename, unsigned char* md5_hash) {// ... 函數實現見上文 ...void print_md5(const unsigned char* md5_hash) {for (int i = 0; i < MD5_DIGEST_LENGTH; i++) {printf("%02x", md5_hash[i]);}printf("\n");
}int main() {const char* filename = "path/to/file";unsigned char md5_hash[MD5_DIGEST_LENGTH];calculate_file_md5(filename, md5_hash);printf("MD5: ");print_md5(md5_hash);return 0;
}

這個示例程序將打開指定文件并計算其MD5值。需要將文件路徑存儲在 filename 字符串中,并根據需要調整該字符串。

請這里使用的是 OpenSSL 提供的 MD5 函數。在編譯時,需要鏈接 OpenSSL 庫。在 Linux 系統上,可以使用 -lssl -lcrypto 參數進行鏈接。在 Windows 系統上,需要下載并安裝 OpenSSL 庫,并配置正確的鏈接路徑和庫文件名稱。

2.3 自己寫算法獲取MD5值

實現MD5算法比較復雜,涉及位操作、邏輯運算、位移等。

以下是一個簡化版本的純C語言MD5算法實現:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>typedef unsigned char uint8;
typedef unsigned int uint32;// MD5常量定義
const uint32 MD5_CONSTANTS[] = {0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
};// 循環左移
#define LEFT_ROTATE(x, n) (((x) << (n)) | ((x) >> (32 - (n))))// 轉換為大端字節序
void to_big_endian(uint32 value, uint8* buffer) {buffer[0] = (uint8)(value & 0xff);buffer[1] = (uint8)((value >> 8) & 0xff);buffer[2] = (uint8)((value >> 16) & 0xff);buffer[3] = (uint8)((value >> 24) & 0xff);
}// 處理消息塊
void process_block(const uint8* block, uint32* state) {uint32 a = state[0];uint32 b = state[1];uint32 c = state[2];uint32 d = state[3];uint32 m[16];// 將消息塊劃分為16個32位字,并進行字節序轉換for (int i = 0; i < 16; i++) {m[i] = (((uint32)block[i * 4 + 0]) << 0) |(((uint32)block[i * 4 + 1]) << 8) |(((uint32)block[i * 4 + 2]) << 16) |(((uint32)block[i * 4 + 3]) << 24);}// MD5循環運算for (int i = 0; i < 64; i++) {uint32 f, g;if (i < 16) {f = (b & c) | ((~b) & d);g = i;} else if (i < 32) {f = (d & b) | ((~d) & c);g = (5 * i + 1) % 16;} else if (i < 48) {f = b ^ c ^ d;g = (3 * i + 5) % 16;} else {f = c ^ (b | (~d));g = (7 * i) % 16;}uint32 temp = d;d = c;c = b;b = b + LEFT_ROTATE((a + f + MD5_CONSTANTS[i] + m[g]), 7);a = temp;}// 更新狀態state[0] += a;state[1] += b;state[2] += c;state[3] += d;
}// 計算MD5值
void calculate_md5(const uint8* message, size_t length, uint8* digest) {// 初始化狀態uint32 state[4] = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 };// 填充消息size_t padded_length = ((length + 8) / 64 + 1) * 64;uint8* padded_message = (uint8*)calloc(padded_length, 1);memcpy(padded_message, message, length);padded_message[length] = 0x80;  // 添加一個1to_big_endian((uint32)(length * 8), padded_message + padded_length - 8);  // 添加長度(以位為單位)// 處理消息塊for (size_t i = 0; i < padded_length; i += 64) {process_block(padded_message + i, state);}// 生成摘要for (int i = 0; i < 4; i++) {to_big_endian(state[i], digest + i * 4);}free(padded_message);
}// 打印MD5值
void print_md5(const uint8* digest) {for (int i = 0; i < 16; i++) {printf("%02x", digest[i]);}printf("\n");
}int main() {const char* message = "Hello, World!";size_t length = strlen(message);uint8 digest[16];calculate_md5((const uint8*)message, length, digest);printf("MD5: ");print_md5(digest);return 0;
}

這個程序可以計算給定字符串的MD5值。將待計算的數據存儲在 message 字符串中,根據需要調整數據長度。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/41704.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/41704.shtml
英文地址,請注明出處:http://en.pswp.cn/news/41704.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

全球磁強計市場價值約為16.2億美元,預測期內將以超過5.21%的增長率增長

磁強計是一種用于測量磁場強度和方向的儀器。它可以檢測和測量地球磁場、物體的磁性、地下礦藏、磁性材料等。磁強計在地球科學、物理學、地質學、勘探、礦業等領域具有廣泛的應用。 根據阿譜爾&#xff08;APO&#xff09;的統計及預測&#xff0c;2022年全球磁強計市場價值約…

跳跳!(c++題解)

題目描述 你是一只小跳蛙&#xff0c;你特別擅長在各種地方跳來跳去。 這一天&#xff0c;你和朋友小 F 一起出去玩耍的時候&#xff0c;遇到了一堆高矮不同的石頭&#xff0c;其中第 ii 塊的石頭高度為 hi?&#xff0c;地面的高度是 h0?0。你估計著&#xff0c;從第 ii 塊…

ts與vue

ts與Vue 如果你已經學習了typeScript,但不知道如何在vue項目中使用&#xff0c;那么這篇文章將會很適合你。參考千峰教育 kerwin視頻 1.會自動推導&#xff0c;隱士推導。提示 類型系統。 獨立模塊。 isolatedModules選項&#xff1a;是否配置為獨立的模塊。 減少報錯 let …

dispatcherServlet在tomcat啟動時如何被加載(1)

目錄 在springboot工程中, 如何添加一個servlet呢? 方法1 : 使用WebServlet注解 方法2 : 使用ServletRegistrationBean進行注冊 springmvc 采用的就是方式2和springboot集成的, 看一下源碼 springboot 字段裝配里面有這個類, 看一下源碼 90行, 創建了一個DispatcherServlet對象…

深入探究Socks5代理與IP代理在網絡安全與爬蟲中的應用

1. Socks5代理&#xff1a;打開網絡隧道的多功能工具 Socks5代理是一種流行的代理協議&#xff0c;它在傳輸層為數據包提供了隧道。相較于之前的版本&#xff0c;Socks5不僅支持TCP連接&#xff0c;還可以處理UDP流量&#xff0c;使其在需要實時數據傳輸的應用中表現出色。在網…

Zabbix配置通用的TCP/IP:port監控項

我們經常的用接口&#xff0c;比如說FTP、HTTP、DNS、數據庫接口&#xff0c;都可以用IP:PORT方式探測其是否存活&#xff0c;那么我們去繁就簡&#xff0c;就簡單監控一下IP&#xff1a;PORT吧&#xff01; 1、新建主機&#xff1a; 填入主機名稱、群組、Agent就是127.0.0.1…

解決Adobe Flash Player已被屏蔽

問題&#xff1a;該插件不支持 原因&#xff1a;現在瀏覽器默認禁用flash 博主當前使用的是谷歌瀏覽器Chrome 2個主要方法都已經失效 搜索一圈后&#xff0c;之前博客給出的2個主要方法都已經失效。 1、flash.cn 下載本地播放器 2、在chrome中打開flash的禁用開關 2023年解…

LangChain源碼逐行解密之系統(二)

LangChain源碼逐行解密之系統 20.2 serapi.py源碼逐行剖析 我們可以看一下Google查詢的例子,在LangChain中有多種實現的方式。 如圖20-5所示,在utilities的serpapi.py代碼文件中實現了SerpAPIWrapper。 圖20- 5 utilities的serpapi.py的SerpAPIWrapper 在langchain目錄的se…

@pyrallis.wrap()

pyrallis.wrap import pyrallis pyrallis.wrap() 這個pyrallis.wrap()是什么 pyrallis.wrap() 是一個 Python 裝飾器&#xff08;Decorator&#xff09;&#xff0c;用于將函數或方法包裝在 Pyrallis 框架提供的性能分析器中。裝飾器是 Python 中的一種特殊語法&#xff0c;允許…

如何避免爬蟲IP被屏蔽

各位爬友們好&#xff0c;作為一名專業的爬蟲代理提供者&#xff0c;我要和大家分享一些避免爬蟲IP被屏蔽的實用技巧。你知道嗎&#xff0c;當我們爬取數據的時候&#xff0c;很容易被目標網站識別出來并封禁我們的IP地址&#xff0c;導致無法繼續爬取數據。這個問題困擾了很多…

7. 實現 API 自動生成

目錄 1. pom.xml中引用依賴 2. 引入相關的依賴 3. 編寫配置類 4. application.yml 中添加配置 5. API 常用注解 6. 訪問 API 列表 7. API 導入 Postman 使用 Springfox Swagger生成 API&#xff0c;并導入 Postman&#xff0c;完成API單元測試。 Swagger 簡介&#xff1a;Swag…

執行Lua腳本后一直查詢不到Redis中的數據(附帶問題詳細排查過程,一波三折)

文章目錄 執行Lua腳本后一直查詢不到Redis中的數據&#xff08;附帶詳細問題排查過程&#xff0c;一波三折&#xff09;問題背景問題1&#xff1a;Lua腳本無法切庫問題2&#xff1a;RedisTemlate切庫報錯問題3&#xff1a;序列化導致數據不一致問題4&#xff1a;Lua腳本中單引號…

Etcd備份及恢復

一、Etcd數據備份 1、備份命令 [rootlocalhost ~]# export ETCDCTL_API3 [rootlocalhost ~]# /data/etcd-3.4.9/bin/etcdctl --endpoints10.2.20.108:2379 snapshot save etcd-date "%Y-%m-%d_%H-%M-%S".snapshot 2、備份完成后會在當前目錄生成備份文件 [rootlo…

vue實現打印功能

在Vue應用中調用打印機功能&#xff0c;可以使用JavaScript的window.print()方法。這個方法會打開打印對話框&#xff0c;然后讓我們選擇打印設置并打印文檔&#xff0c;但是尼這種方法依賴于瀏覽器的打印功能。 以下是一個簡單的示例&#xff0c;演示如何在Vue組件中調用打印…

Linux Tracing Technologies

目錄 1. Linux Tracing Technologies 1. Linux Tracing Technologies Linux Tracing TechnologieseBPFXDPDPDK

Flask Web開發實戰(狼書)| 筆記第1、2章

前言 2023-8-11 以前對網站開發萌生了想法&#xff0c;又有些急于求成&#xff0c;在B站照著視頻敲了一個基于flask的博客系統。但對于程序的代碼難免有些囫圇吞棗&#xff0c;存在許多模糊或不太理解的地方&#xff0c;只會照葫蘆畫瓢。 而當自己想開發一個什么網站的時&…

ubuntu部署haproxy

HAProxy是可提供高可用性、負載均衡以及基于TCP和HTTP應用的代理. 1、更新系統報 通過在終端中運行以下命令&#xff0c;確保所有系統包都是最新的 sudo apt updatesudo apt upgrade2、安裝Haproxy sudo apt install haproxy設置開機自動啟動haproxy服務 sudo systemctl en…

Lnton羚通關于如何解決nanoPC-T4 upgrade報錯問題?

nanoPC-T4 在 ??# sudo apt update 和 sudo apt upgrade??升級或安裝軟件 ??sudo apt install xxx??時遇到以下問題&#xff1a;??Failed to set up interface with /etc/hostapd/? Setting up hostapd (2:2.6-15ubuntu2.8) ... Job for hostapd.service failed be…

ssm+vue醫院住院管理系統源碼和論文PPT

ssmvue醫院住院管理系統源碼和論文PPT012 開發工具&#xff1a;idea 數據庫mysql5.7(mysql5.7最佳) 數據庫鏈接工具&#xff1a;navcat,小海豚等 開發技術&#xff1a;java ssm tomcat8.5 摘 要 隨著時代的發展&#xff0c;醫療設備愈來愈完善&#xff0c;醫院也變成人們生…

基于IMX6ULLmini的linux裸機開發系列一:匯編點亮LED

思來想去還是決定記錄一下點燈&#xff0c;畢竟萬物皆點燈嘛 編程步驟 使能GPIO時鐘 設置引腳復用為GPIO 設置引腳屬性(上下拉、速率、驅動能力) 控制GPIO引腳輸出高低電平 使能GPIO時鐘 其實和32差不多 先找到控制LED燈的引腳&#xff0c;也就是原理圖 文件名 C:/Us…