C++加密函數MD5使用方法詳解

一、MD5算法簡介

MD5算法是一種廣泛使用的密碼散列函數,可以將任意長度的文本轉換成128位(16位元組)的哈希值。由於哈希值的長度固定,因此可以用來驗證信息的完整性和一致性。MD5算法的產生是為了取代MD4算法(由於密碼分析學的進步及用戶的需求,MD4的安全性已經無法保證)。

MD5算法的核心思想是將輸入的信息進行分組,並按照規定的方式進行處理,最後得到一個定長的輸出。它的算法是基於位運算、模2的餘數運算和邏輯運算等算法的組合

二、MD5算法實現過程

1. 填充

MD5算法處理的是二進制數據,但是輸入的數據往往是以位元組為單位的,所以需要將輸入數據按照512位(64位元組)為一組進行劃分,並且需要將輸入的數據進行填充。
填充規則如下:
(1)如果輸入的數據的位元組數是64的倍數,不需要填充;
(2)如果輸入的數據的位元組數不足64位元組,需要在末尾填充一個1,其餘補0,直到滿足64位元組;
(3)如果輸入的數據的位元組數超過64位元組,需要在末尾填充一個1,其餘補0,直到末尾64位元組,然後將所有的64位元組分組按照算法進行處理。

2. MD5算法處理

(1)初始化
定義4個32位的參數:A、B、C、D,用於存儲中間狀態。
每次處理512位時,先將A、B、C、D分別賦成如下值:

A = 0x67452301;
B = 0xefcdab89;
C = 0x98badcfe;
D = 0x10325476;

(2)處理512位
將512位數據劃分成16組,每組32位。設當前處理的一組數據為X[i],則下一組數據為X[i+1]。

(3)四輪運算
分別進行4輪運算,每輪運算都將當前結果進行迭代,迭代方式如下:

1)輪 1:F(X,Y,Z) = (X & Y) | (~X & Z);
2)輪 2:G(X,Y,Z) = (X & Z) | (Y & ~Z);
3)輪 3:H(X,Y,Z) = X ^ Y ^ Z;
4)輪 4:I(X,Y,Z) = Y ^ (X | ~Z);

(4)更新中間狀態
每輪運算後,都需要更新中間狀態A、B、C、D。

A = A + F(B,C,D) + X[i] + T[i];
B = D;
C = B;
D = A;

(5)最終結果
處理完所有的數據塊後,將A、B、C、D拼接為一個128位的hash值,即為MD5算法處理結果。

三、使用方法

1. 環境要求

在VS2015中實現,需要用到以下頭文件:

#include 
#include 
#include 

由於MD5算法使用了位運算和邏輯運算,因此為了便於處理,可以使用uint32_t類型進行定義。

2. MD5算法代碼實現

#include 
#include 
#include 
#include 
#include 

using namespace std;

typedef unsigned int uint32_t;

const uint32_t A = 0x67452301;
const uint32_t B = 0xefcdab89;
const uint32_t C = 0x98badcfe;
const uint32_t D = 0x10325476;

const uint32_t T[64] = { 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 };

inline uint32_t leftrotate(uint32_t x, uint32_t n) {
    return x <> (32 - n);
}

uint32_t F(uint32_t X, uint32_t Y, uint32_t Z) {
    return (X & Y) | (~X & Z);
}

uint32_t G(uint32_t X, uint32_t Y, uint32_t Z) {
    return (X & Z) | (Y & ~Z);
}

uint32_t H(uint32_t X, uint32_t Y, uint32_t Z) {
    return X ^ Y ^ Z;
}

uint32_t I(uint32_t X, uint32_t Y, uint32_t Z) {
    return Y ^ (X | ~Z);
}

void md5(uint32_t* data, uint32_t len, uint32_t* digest) {
    uint32_t* X = new uint32_t[16];
    uint32_t a = A;
    uint32_t b = B;
    uint32_t c = C;
    uint32_t d = D;

    for (uint32_t i = 0; i < len; i += 16) {
        memcpy(X, data + i, 16 * sizeof(uint32_t));
        uint32_t aa = a;
        uint32_t bb = b;
        uint32_t cc = c;
        uint32_t dd = d;

        for (uint32_t i = 0; i < 64; ++i) {
            uint32_t f, g;
            if (i < 16) {
                f = F(b, c, d);
                g = i;
            }
            else if (i < 32) {
                f = G(b, c, d);
                g = (5 * i + 1) % 16;
            }
            else if (i < 48) {
                f = H(b, c, d);
                g = (3 * i + 5) % 16;
            }
            else {
                f = I(b, c, d);
                g = (7 * i) % 16;
            }
            uint32_t tmp = d;
            d = c;
            c = b;
            b = b + leftrotate(a + f + X[g] + T[i], 7);
            a = tmp;
        }
        a += aa;
        b += bb;
        c += cc;
        d += dd;
    }
    delete[] X;
    digest[0] = a;
    digest[1] = b;
    digest[2] = c;
    digest[3] = d;
}

int main() {
    string input = "hello world";
    uint32_t* data = new uint32_t[input.size() + 64];
    memcpy(data, input.c_str(), input.size());
    uint32_t len = ceil(8 * input.size() / 512) * 16;
    memset(data + input.size(), 0, (len - input.size()) * sizeof(uint32_t));
    data[input.size() / 4] |= 0x00000001 << (8 * input.size() % 32);
    uint32_t digest[4];
    md5(data, len, digest);
    delete[] data;

    printf("MD5 hash:\n");
    printf("%08x%08x%08x%08x\n", digest[0], digest[1], digest[2], digest[3]);
    return 0;
}

3. 示例

對字符串”hello world”進行MD5加密:

input: "hello world"
output: 5eb63bbbe01eeed093cb22bb8f5acdc3

完整代碼如下:

#include
#include
#include
#include
#include

using namespace std;

typedef unsigned int uint32_t;

const uint32_t A = 0x67452301;
const uint32_t B = 0xefcdab89;
const uint32_t C = 0x98badcfe;
const uint32_t D = 0x10325476;

const uint32_t T[64] = { 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 };

inline uint32_t leftrotate(uint32_t x, uint32_t n) {
return x <> (32 - n);
}

uint32_t

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/249194.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-12 13:32
下一篇 2024-12-12 13:32

相關推薦

  • Python中引入上一級目錄中函數

    Python中經常需要調用其他文件夾中的模塊或函數,其中一個常見的操作是引入上一級目錄中的函數。在此,我們將從多個角度詳細解釋如何在Python中引入上一級目錄的函數。 一、加入環…

    編程 2025-04-29
  • Python中capitalize函數的使用

    在Python的字符串操作中,capitalize函數常常被用到,這個函數可以使字符串中的第一個單詞首字母大寫,其餘字母小寫。在本文中,我們將從以下幾個方面對capitalize函…

    編程 2025-04-29
  • Python中set函數的作用

    Python中set函數是一個有用的數據類型,可以被用於許多編程場景中。在這篇文章中,我們將學習Python中set函數的多個方面,從而深入了解這個函數在Python中的用途。 一…

    編程 2025-04-29
  • Python中init方法的作用及使用方法

    Python中的init方法是一個類的構造函數,在創建對象時被調用。在本篇文章中,我們將從多個方面詳細討論init方法的作用,使用方法以及注意點。 一、定義init方法 在Pyth…

    編程 2025-04-29
  • 三角函數用英語怎麼說

    三角函數,即三角比函數,是指在一個銳角三角形中某一角的對邊、鄰邊之比。在數學中,三角函數包括正弦、餘弦、正切等,它們在數學、物理、工程和計算機等領域都得到了廣泛的應用。 一、正弦函…

    編程 2025-04-29
  • 單片機打印函數

    單片機打印是指通過串口或並口將一些數據打印到終端設備上。在單片機應用中,打印非常重要。正確的打印數據可以讓我們知道單片機運行的狀態,方便我們進行調試;錯誤的打印數據可以幫助我們快速…

    編程 2025-04-29
  • Python3定義函數參數類型

    Python是一門動態類型語言,不需要在定義變量時顯示的指定變量類型,但是Python3中提供了函數參數類型的聲明功能,在函數定義時明確定義參數類型。在函數的形參後面加上冒號(:)…

    編程 2025-04-29
  • Python定義函數判斷奇偶數

    本文將從多個方面詳細闡述Python定義函數判斷奇偶數的方法,並提供完整的代碼示例。 一、初步了解Python函數 在介紹Python如何定義函數判斷奇偶數之前,我們先來了解一下P…

    編程 2025-04-29
  • Python實現計算階乘的函數

    本文將介紹如何使用Python定義函數fact(n),計算n的階乘。 一、什麼是階乘 階乘指從1乘到指定數之間所有整數的乘積。如:5! = 5 * 4 * 3 * 2 * 1 = …

    編程 2025-04-29
  • Python符號定義和使用方法

    本文將從多個方面介紹Python符號的定義和使用方法,涉及注釋、變量、運算符、條件語句和循環等多個方面。 一、注釋 1、單行注釋 # 這是一條單行注釋 2、多行注釋 “”” 這是一…

    編程 2025-04-29

發表回復

登錄後才能評論