1. 程式人生 > >MD5演算法原理介紹與C++實現

MD5演算法原理介紹與C++實現

MD5演算法原理介紹與C++實現

原始碼傳送門:https://github.com/dick20/Web-Security/tree/master/MD5


一. 演算法原理概述

The MD5 message-digest algorithm is a widely used hash function producing a 128-bit hash value. Although MD5 was initially designed to be used as a cryptographic hash function, it has been found to suffer from extensive vulnerabilities. ——Wikipedia

  • MD5 使用 little-endian (小端模式),輸入任意不定長度資訊,以512-bit 進行分組,生成四個32-bit 資料,最後聯合輸出固定128-bit 的資訊摘要。
  • MD5 演算法的基本過程為:填充、分塊、緩衝區初始化、迴圈壓縮、得出結果。

MD5的基本流程圖如下

1

二. 總體結構

1.填充

在長度為 K bits 的原始訊息資料尾部填充長度為 P bits 的標識100…0,1 \leq

P \leq 512 (即至少要填充1個bit),使得填充後的訊息位數為:K + P \equiv 448 (mod 512).

  • 注意到當 K
    \equiv
    448 (mod 512) 時,需要 P= 512.

再向上述填充好的訊息尾部附加 K 值的低64位 (即 K mod 264),最後得到一個長度位數為 K + P + 6 \equiv 0 (mod 512) 的訊息。

2.分塊

  • 把填充後的訊息結果分割為 L 個 512-bit 分組: Y 0 Y_0 , Y 1 Y_1 , …, Y L 1 Y_{L-1}
  • 分組結果也可表示成 N 個32-bit 字 M 0 M_0 , M 1 M_1 , …, M N 1 M_{N-1} ,N = L*16。

3.緩衝區初始化

初始化一個128-bit 的 MD 緩衝區,記為 C V q CV_q ,表示成4個32-bit暫存器 (A, B, C, D); C V 0 CV_0 = IV。迭代在 MD 緩衝區進行,最後一步的128-bit 輸出即為演算法結果。

  • 暫存器 (A, B, C, D) 置16進位制初值作為初始向量 IV,並採用小端儲存 (little-endian) 的儲存結構:
    • A = 0x67452301
    • B = 0xEFCDAB89
    • C = 0x98BADCFE
    • D = 0x10325476

4.迴圈壓縮

以512-bit 訊息分組為單位,每一分組 Yq (q = 0, 1, …, L-1) 經過4個迴圈的壓縮演算法,表示為:

  • C V 0 CV_0 = IV
  • C V i CV_i = H M D 5 H_{MD5} ( C V i 1 CV_{i-1} , Y i {Y_i} )
  • 輸出結果:MD = C V L CV_L .

三. 模組分解

a. MD5 壓縮函式 HMD5——輪函式

HMD5 從 CV 輸入128位,從訊息分組輸入512位,完成4輪迴圈後,輸出128位,用於下一輪輸入的 CV 值。

每輪迴圈分別固定不同的生成函式 F, G, H, I,結合指定的 T 表元素 T[] 和訊息分組的不同部分 X[] 做16次迭代運算,生成下一輪迴圈的輸入。

4輪迴圈總共有64次迭代運算。

4輪迴圈中使用的生成函式(輪函式) g 是一個32位非線性邏輯函式,在相應各輪
的定義如下:

輪次 Function g g(b,c,d)
1 F(b, c, d) (b \bigwedge c) \bigvee (~b \bigwedge d)
2 G(b, c, d) ( b d b \bigwedge d ) \bigvee ( c c \bigwedge ~d)
3 H(b, c, d) b \bigoplus c \bigoplus d
4 I(b, c, d) c \bigoplus (b \bigvee ~d)

b. MD5 壓縮函式 HMD5——迭代運算

  • 每輪迴圈中的一次迭代運算邏輯
    (1) 對 A 迭代:a \leftarrow b + ((a + g(b, c, d) + X[k] + T[i]) <<<s)
    (2) 緩衝區 (A, B, C, D) 作迴圈輪換:(B, C, D, A) \leftarrow (A, B, C, D)
  • 說明:
    • a, b, c, d : MD 緩衝區 (A, B, C, D) 的當前值。
    • g : 輪函式 (F, G, H, I 中的一個)。
    • <<<s : 將32位輸入迴圈左移 (CLS) s 位。
    • X[k] : 當前處理訊息分組的第 k 個 (k = 0…15) 32位字,即
      M q 16 + k M_{q*16+k}
    • T[i] : T 表的第 i 個元素,32位字;T 表總共有64個元素,也
      稱為加法常數。
    • +: 模 232 加法

c. MD5 壓縮函式 HMD5——各輪迴圈的 X[k]

各輪迴圈中第 i 次迭代 (i = 1…16) 使用的 X[k] 的確定:
設 j = i -1:

  • 第1輪迭代:k = j.
    • 順序使用 X[0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15]
  • 第2輪迭代:k = (1 + 5j) mod 16
    • 順序使用 X[1, 6,11, 0, 5,10,15, 4, 9,14, 3, 8,13, 2, 7,12]
  • 第3輪迭代:k = (5 + 3j) mod 16.
    • 順序使用 X[5, 8,11,14, 1, 4, 7,10,13, 0, 3, 6, 9,12,15, 2]
  • 第4輪迭代:k = 7j mod 16.
    • 順序使用 X[0, 7,14, 5,12, 3,10, 1, 8,15, 6,13 , 4,11, 2, 9]

d. MD5 壓縮函式 HMD5——T表的生成

T[i] = int($ 2^{32} *|sin(i)|$)

  • int 取整函式,sin 正弦函式,以 i 作為弧度輸入

各次迭代運算採用的 T 值:

  • T[ 1… 4] = { 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee }
  • T[ 5… 8] = { 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501 }
  • T[ 9…12] = { 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be }
  • T[13…16] = { 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821 }
  • T[17…20] = { 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa }
  • T[21…24] = { 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8 }
  • T[25…28] = { 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed }
  • T[29…32] = { 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a }
  • T[33…36] = { 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c }
  • T[37…40] = { 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70 }
  • T[41…44] = { 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05 }
  • T[45…48] = { 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665 }
  • T[49…52] = { 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039 }
  • T[53…56] = { 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1 }
  • T[57…60] = { 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1 }
  • T[61…64] = { 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391

e. MD5 壓縮函式 HMD5——左迴圈移位的 s 值

各次迭代運算採用的左迴圈移位的 s 值:

  • s[ 1…16] = { 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22 }
  • s[17…32] = { 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20 }
  • s[33…48] = { 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23 }
  • s[49…64] = { 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 }

四. 資料結構

我的MD5演算法使用了C++類的設計來實現,主要使用陣列來表示迴圈移位表,unsigned int與unsigned char來表示不同的位數,char為8位,int為32位,在不同的表示函式中各有作用,故需要對其進行轉換。

	unsigned int state[4];		// 四個暫存器,MD緩衝區,共128位
	unsigned int count[2];		// 統計長度,僅保留前64位
	unsigned char buffer[512];	// 輸入
	unsigned char digest[128];	// 輸出

表示state狀態時,我使用的是16進製表達64位,這樣較簡便

	// 初始化獲取IV
	state[0] = 0x67452301;
	state[1] = 0xefcdab89;
	state[2] = 0x98badcfe;
	state[3] = 0x10325476;

關於S表,則直接用二維陣列

// 左迴圈移位表
int s[4][4] = {{7,12,17,22},{5,9,14,20},{4,11,16,23},{6,10,15,21}};

對於填充的內容,是1000···000,最多512位,最少要有一位,這是根據填充長度來決定的,使用我直接要預設填充長度為512位。

unsigned char padding[64] = 
{0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
	

表示輪函式,則直接根據T表來進行書寫。例如下面

	H_F(a, b, c, d, x[0], s[0][0], 0xd76aa478);
	H_F(d, a, b, c, x[1], s[0][1], 0xe8c7b756);
	H_F(c, d, a, b, x[2], s[0][2], 0x242070db);
	···

關於int與char的轉換,是這次演算法實現比較關鍵的部分,因為關於使用byte還是bit取決於函式的需要。以下第一個函式是int轉為char,將1個int轉為4個char,這裡使用位運算+移位的方法,不斷取8位轉化為char。第二個函式是char轉int,也像之前類似,不過是要將4個char轉為1個int,這裡用到的是移位+或運算,這樣就可以得到1個32位int型別。

void my_md5::int_to_char(unsigned char *output,  const unsigned int  *input, int length){
	for (int i = 0, j = 0; i < length; ++i)
	{
		output[j] = input[i] & 0xff;
		output[j+1] = (input[i] >> 8) & 0xff;
		output[j+2] = (input[i] >> 16) & 0xff;
		output[j+3] = (input[i] >> 24) & 0xff;
		j += 4;
	}
}

void my_md5::char_to_int(unsigned int  *output, const unsigned char *input, int length){
	for (int i = 0, j = 0; i < length; i += 4)
	{
		output[j] = input[i] | (input[i+1] << 8) | (input[i+2] << 16) | (input[i+3] << 24);
		j++;
	}
}

五. 原始碼

1.MD5類設計

class my_md5
{
public:
	my_md5(string& str);
	my_md5(); 
	void update(const unsigned char* input_str, int str_length);
	// 將128位結果,轉化為16個byte輸出
	void show_result();
    // 對輸入的字串進行MD5加密
	void decode_string(string& str);
	~my_md5();
	
private:
	unsigned int state[4];		// 四個暫存器,MD緩衝區,共128位
	unsigned int count[2];		// 統計長度,僅保留前64位
	unsigned char buffer[512];	// 輸入
	unsigned char digest[128];	// 輸出
	bool is_padding;
	char result[33];			// 32位的輸出結果

	// 私有輔助函式,用以變換
	// 對於其中一個區塊做變換
	void transform(unsigned char block[64]);
	// 填充函式,新增長度
	void padding();
	// 以下兩個函式用以將32位的unsigned int與8位的unsigned char互相轉換輸出
	void int_to_char(unsigned char *output,  const unsigned int  *input, int length);
	void char_to_int(unsigned int  *output, const unsigned char *input, int length);
	// 左移函式
	unsigned int shift_left(unsigned int num, int pos);
	// 輪函式
	unsigned int F(unsigned int b, unsigned int c, unsigned int d);
	unsigned int G(unsigned int b, unsigned int c, unsigned int d);
	unsigned int H(unsigned int b, unsigned int c, unsigned int d);
	unsigned int I(unsigned 
            
           

相關推薦

MD5演算法原理介紹C++實現

MD5演算法原理介紹與C++實現 原始碼傳送門:https://github.com/dick20/Web-Security/tree/master/MD5 一. 演算法原理概述 The MD5 message-digest algorithm is a wid

機器學習系列文章:Apriori關聯規則分析演算法原理分析程式碼實現

1.關聯規則淺談     關聯規則(Association Rules)是反映一個事物與其他事物之間的相互依存性和關聯性,如果兩個或多個事物之間存在一定的關聯關係,那麼,其中一個事物就能通過其他事物預測到。關聯規則是資料探勘的一個重要技術,用於從大量資料中挖掘出有價值的資料

textRank演算法原理介紹摘要提取

TextRankTextRank 公式在 PageRank 公式的基礎上,為圖中的邊引入了權值的概念:wijwij 就是是為圖中節點 ViVi 到 VjVj 的邊的權值 。dd 依然為阻尼係數,代表從圖中某一節點指向其他任意節點的概率,一般取值為0.85。In(Vi)In(V

歸併排序演算法原理分析程式碼實現

  歸併排序是建立在歸併操作上的一種有效的排序演算法。該演算法是採用分治法(Divide and Conquer)的一個非常典型的應用,歸併排序將兩個已排序的表合併成一個表。 歸併排序基本原理

第五篇:樸素貝葉斯分類演算法原理分析程式碼實現

1 #==================================== 2 # 輸入: 3 # 空 4 # 輸出: 5 # postingList: 文件列表 6 # classVec: 分類標籤列表 7 #=

加密演算法簡要介紹JAVA實現

【1】MD5是什麼 MD5即Message-Digest Algorithm 5(資訊-摘要演算法5),用於確保資訊傳輸完整一致。是計算機廣泛使用的雜湊演算法之一(又譯摘要演算法、雜湊演算法),主流程式語言普遍已有MD5實現。將資料(如漢字)運算為另一固定長度

MD5演算法原理實現

由於各種原因,可能存在諸多不足,歡迎斧正! 一、MD5概念 MD5,全名Message Digest Algorithm 5 ,中文名為訊息摘要演算法第五版,為電腦保安領域廣泛使用的一種雜湊函式,用以提供訊息的完整性保護。上面這段話話引用自百度百科,我的理解MD5是

資料結構演算法——普通樹的定義C++實現

用樹的第一個兒子和下一個兄弟表示法來表示一個樹。 樹的節點結構為: struct TreeNode{ TYPE element;//該節點的元素 TreeNode *firstChild;//指向該節點的第一個孩子 TreeNo

資料結構演算法——B樹的C++實現

It is recommended to refer following posts as prerequisite of this post. B-Tree is a type of a multi-way search tree. So, if you are not familiar with

k-d樹+bbf演算法介紹實現

最近還是一直在研究SIFT演算法,而SIFT特徵點匹配是一個比較經典的問題,使用暴力匹配的話確實可以得到結果,但是執行速度較慢。我的計算機處理是i5的二代系列,匹配兩張各檢測有2000+個SIFT特徵點的影象,通過正反匹配(即取影象1與影象2的匹配結果餘影象2和影象1的匹配

【無監督學習】DBSCAN聚類演算法原理介紹,以及程式碼實現

前言:無監督學習想快一點複習完,就轉入有監督學習 聚類演算法主要包括哪些演算法?主要包括:K-m

speex降噪演算法流程介紹演算法原理

一、speex降噪流程介紹 本文對speex去噪演算法步驟做一些簡要整理和介紹,以提供給對該演算法感興趣的讀者參考。  1)preprocess_analysis()包括兩部分,主要是加窗交疊傅立葉(fft)變換等常用的訊號處理演算法。 1.1)預處理    

C++智慧指標原理分析簡單實現

一個簡單智慧指標實現的思路如下:   智慧指標,簡單來講是使用引用計數的方法,來跟蹤監控指標。當引用計數為0時就delete 所跟蹤的目標指標,釋放記憶體   智慧指標將一個指標封裝到一個類中,當呼叫

一致性雜湊演算法C++實現

一. 演算法解決問題 一致性雜湊演算法在1997年由麻省理工學院提出的一種分散式雜湊(DHT)實現演算法,設計目標是為了解決因特網中的熱點(Hot spot)問題,初衷和CARP十分類似。一致性雜湊修正了CARP使用的簡 單雜湊演算法帶來的問題,使得分散式雜湊

邏輯迴歸原理介紹案例python程式碼實現

邏輯迴歸是用於分類的演算法。平常的線性迴歸方程為f(x)=wx+b,此時f(x)的取值可以是任意的,要讓預測的值可以分類,例如分類到class1是預測值為1,分類到class2時預測值為0。這時我們就要用到分類函式。下面來介紹一個分類函式sigmoid:其中z=wx+bf(z

MD5加密演算法原理及其Go語言實現

MD5訊息摘要演演算法(英語:MD5 Message-Digest Algorithm),一種被廣泛使用的密碼雜湊函式,可以產生出一個128位元(16位元組)的雜湊值(hash value),用於確保資訊傳輸完整一致。 go 呼叫 md5 方法 新建 m

K-近鄰演算法介紹程式碼實現

宣告:如需轉載請先聯絡我。 最近學習了k近鄰演算法,在這裡進行了總結。 KNN介紹 k近鄰法(k-nearest neighbors)是由Cover和Hart於1968年提出的,它是懶惰學習(lazy learning)的著名代表。它的工作機制比較簡單: 給定一個測試樣本 計算它到訓練樣本的距離 取

推薦模型DeepCrossing: 原理介紹TensorFlow2.0實現

DeepCrossing是在AutoRec之後,微軟完整的將深度學習應用在推薦系統的模型。其應用場景是搜尋推薦廣告中,解決了特徵工程,稀疏向量稠密化,多層神經網路的優化擬合等問題。所使用的特徵在論文中描述為兩個大類**數值型(文中couting feature)和類別型。如下圖** ![image](http

推薦模型NeuralCF:原理介紹TensorFlow2.0實現

### 1. 簡介 NCF是協同過濾在神經網路上的實現——**神經網路協同過濾**。由新加坡國立大學與2017年提出。 我們知道,在協同過濾的基礎上發展來的矩陣分解取得了巨大的成就,但是矩陣分解得到低維隱向量求**內積是線性的**,而神經網路模型能帶來**非線性的效果,非線性可以更好地捕捉使用者和物品空間

[轉]opencv3 圖像處理 之 圖像縮放( pythonc++實現

space original 註意 libs 波紋 輸出 uil iostream 3.5 轉自:https://www.cnblogs.com/dyufei/p/8205121.html 一. 主要函數介紹 1) 圖像大小變換 cvResize () 原型: void