MD5演算法--C++實現
函式說明:
update函式:這是一個可重入的函式。每次呼叫傳進去的字串都會和之前的字串連結。當然,第一次呼叫update時,之前的字串長度為0。count[]陣列內部儲存了字串長度的位數,所以每次用count[]陣列計算時要注意byte與bit的轉化。
呼叫該函式時,首先會計算字串長度,等於已有字串長度加上新加字串長度,然後判斷總長度是否大於64,或者說判斷新加的字串有沒有補上之前字串差的那一部分。
有兩種情況:
1.如果大於,那麼把補上的這部分加之前的用線性函式去轉化雜湊。把除去補的那部分剩餘部分放在緩衝區等待下一次呼叫update函式,因為後面我們會填充10000...0以及長度。
2.如果不大於,那就直接把字串放進緩衝區,等待補位。
3.如果特別特別大,是一個chunks,那麼就把chunks劃分成64bytes為一組,足夠64bytes的就轉化,不足的和上面一樣,放進緩衝區,等待補位。
finalize函式:
負責填充1000...0以及長度length,長度是以bit為單位的。一共預留512-448=64位即8個位元組來存放長度,所以長度最大值為2^64,超出了只保留最低64位。
參考圖:
程式碼如下:
md5_config.h
#pragma once
//constants for md5transform routine
#define S11 7
#define S12 12
#define S13 17
#define S14 22
#define S21 5
#define S22 9
#define S23 14
#define S24 20
#define S31 4
#define S32 11
#define S33 16
#define S34 23
#define S41 6
#define S42 10
#define S43 15
#define S44 21
md5.h
#ifndef _MD5_H
#define _MD5_H
#include "lb_util.h"
#include "md5_config.h"
namespace lb
{
typedef unsigned int u_int;
typedef unsigned char u_char;
static const int BUFFER_SIZE = 1000; //buffer size
static const int BLOCK_SIZE = 64; //64 //64 * sizeof(u_char) = 512;
static const int DIGEST_SIZE = 16; //16 //16 * 8 = 128
class md5 {
public:
md5(const std::string& sz);
void update(const u_char* input, size_t length);
void update(const char* input, size_t length);
void digest(char* buf) const;
protected:
void init();
void finalize();
void transform(const u_char block[BLOCK_SIZE]);
void encode(u_char *output, const u_int *input, size_t len);
void decode(u_int *output, const u_char *input, size_t len);
private:
bool finalized_;
u_char buffer_[BUFFER_SIZE]; //the max storge capacity is 512
u_char digest_[DIGEST_SIZE]; //16 * 8 = 128
u_int count_[2]; //which storge the length of the string by bits
u_int state_[4]; //iter state, eventually turned into results
};
inline u_int shift_left(u_int x, int n) //ROL
{
return (x << n) | (x >> (32 - n));
}
inline u_int F(u_int x, u_int y, u_int z) { return (x & y) | ((~x) & z); }
inline u_int G(u_int x, u_int y, u_int z) { return (x & z) | (y & (~z)); }
inline u_int H(u_int x, u_int y, u_int z) { return (x ^ y ^ z); }
inline u_int I(u_int x, u_int y, u_int z) { return (y ^ (x | ~z)); }
inline void FF(u_int &a, u_int b, u_int c, u_int d, u_int x, u_int s, u_int ac)
{
a = shift_left(a + F(b, c, d) + x + ac, s) + b;
}
inline void GG(u_int &a, u_int b, u_int c, u_int d, u_int x, u_int s, u_int ac)
{
a = shift_left(a + G(b, c, d) + x + ac, s) + b;
}
inline void HH(u_int &a, u_int b, u_int c, u_int d, u_int x, u_int s, u_int ac)
{
a = shift_left(a + H(b, c, d) + x + ac, s) + b;
}
inline void II(u_int &a, u_int b, u_int c, u_int d, u_int x, u_int s, u_int ac)
{
a = shift_left(a + I(b, c, d) + x + ac, s) + b;
}
}
#endif
md5.cpp
#include "md5.h"
md5::md5(const std::string& sz)
{
init();
update(sz.c_str(), sz.length());
finalize();
}
void md5::init()
{
finalized_ = false;
memset(count_, 0, sizeof(count_));
memset(digest_, '\0', sizeof(digest_));
state_[0] = 0x67452301; //they were saved as 01234567 89abcdef fedcba98 76543210 in memory
state_[1] = 0xefcdab89;
state_[2] = 0x98badcfe;
state_[3] = 0x10325476;
}
void md5::update(const u_char* input, size_t length)
{
size_t index = (count_[0] >> 3) & 0x3f; //count the index by mod 64
count_[0] += length << 3; //accumulative length, using old_len + length
if(count_[0] < (length << 3)) //carry
++count_[1];
count_[1] += length >> 29; //avoid the loss of overflow
size_t partlen = BLOCK_SIZE - index; //the number of bytes we need to fill
size_t i = 0;
if(length >= partlen){
memcpy(buffer_+index, input, partlen);
transform(buffer_);
for(int i=partlen; i+BLOCK_SIZE <= length; i+=BLOCK_SIZE) //handle the chunks
transform(input+i);
index = 0; //need to be zero
}
memcpy(buffer_+index, input+i, length-i); //maybe i is zero
}
void md5::update(const char* input, size_t length)
{
update(reinterpret_cast<const u_char*>(input), length);
}
void md5::finalize()
{
static const u_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,
};
if(!finalized_){
u_char bits[8];
encode(bits, count_, 8); //encode the total length
size_t index = (count_[0] >> 3) & 0x3f;
size_t pad_len = index < 56 ? (56 - index) : (120 - index); //reserve 8 bits for length
update(padding, pad_len); //fill the 1000....0, not 64 enough
update(bits, 8); //append the length, account 64 bits up to now
encode(digest_, state_, 16); //also 16 * 8 = 128
memset(buffer_, 0, sizeof(buffer_));
memset(count_, 0, sizeof(count_));
finalized_ = true;
}
}
void md5::digest(char *buf) const
{
assert(finalized_);
for(int i=0; i<16; ++i)
sprintf(buf+i*2, "%02x", digest_[i]); //still 16 * 8 = 128, hex = 4 + 4 = 8bits, such as 7E 03 ...
buf[32] = '\0';
}
void md5::transform(const u_char block[BLOCK_SIZE])
{
u_int a = state_[0], b = state_[1], c = state_[2], d = state_[3];
u_int x[16]; //16 * 8 = 128
decode(x, block, BLOCK_SIZE);
FF (a, b, c, d, x[ 0], S11, 0xd76aa478); //round 1, 1
FF (d, a, b, c, x[ 1], S12, 0xe8c7b756);
FF (c, d, a, b, x[ 2], S13, 0x242070db);
FF (b, c, d, a, x[ 3], S14, 0xc1bdceee);
FF (a, b, c, d, x[ 4], S11, 0xf57c0faf);
FF (d, a, b, c, x[ 5], S12, 0x4787c62a);
FF (c, d, a, b, x[ 6], S13, 0xa8304613);
FF (b, c, d, a, x[ 7], S14, 0xfd469501);
FF (a, b, c, d, x[ 8], S11, 0x698098d8);
FF (d, a, b, c, x[ 9], S12, 0x8b44f7af);
FF (c, d, a, b, x[10], S13, 0xffff5bb1);
FF (b, c, d, a, x[11], S14, 0x895cd7be);
FF (a, b, c, d, x[12], S11, 0x6b901122);
FF (d, a, b, c, x[13], S12, 0xfd987193);
FF (c, d, a, b, x[14], S13, 0xa679438e);
FF (b, c, d, a, x[15], S14, 0x49b40821);
GG (a, b, c, d, x[ 1], S21, 0xf61e2562); //round 2, 17
GG (d, a, b, c, x[ 6], S22, 0xc040b340);
GG (c, d, a, b, x[11], S23, 0x265e5a51);
GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa);
GG (a, b, c, d, x[ 5], S21, 0xd62f105d);
GG (d, a, b, c, x[10], S22, 0x2441453);
GG (c, d, a, b, x[15], S23, 0xd8a1e681);
GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8);
GG (a, b, c, d, x[ 9], S21, 0x21e1cde6);
GG (d, a, b, c, x[14], S22, 0xc33707d6);
GG (c, d, a, b, x[ 3], S23, 0xf4d50d87);
GG (b, c, d, a, x[ 8], S24, 0x455a14ed);
GG (a, b, c, d, x[13], S21, 0xa9e3e905);
GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8);
GG (c, d, a, b, x[ 7], S23, 0x676f02d9);
GG (b, c, d, a, x[12], S24, 0x8d2a4c8a);
HH (a, b, c, d, x[ 5], S31, 0xfffa3942); //round 3, 33
HH (d, a, b, c, x[ 8], S32, 0x8771f681);
HH (c, d, a, b, x[11], S33, 0x6d9d6122);
HH (b, c, d, a, x[14], S34, 0xfde5380c);
HH (a, b, c, d, x[ 1], S31, 0xa4beea44);
HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9);
HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60);
HH (b, c, d, a, x[10], S34, 0xbebfbc70);
HH (a, b, c, d, x[13], S31, 0x289b7ec6);
HH (d, a, b, c, x[ 0], S32, 0xeaa127fa);
HH (c, d, a, b, x[ 3], S33, 0xd4ef3085);
HH (b, c, d, a, x[ 6], S34, 0x4881d05);
HH (a, b, c, d, x[ 9], S31, 0xd9d4d039);
HH (d, a, b, c, x[12], S32, 0xe6db99e5);
HH (c, d, a, b, x[15], S33, 0x1fa27cf8);
HH (b, c, d, a, x[ 2], S34, 0xc4ac5665);
II (a, b, c, d, x[ 0], S41, 0xf4292244); //round 4 , 49
II (d, a, b, c, x[ 7], S42, 0x432aff97);
II (c, d, a, b, x[14], S43, 0xab9423a7);
II (b, c, d, a, x[ 5], S44, 0xfc93a039);
II (a, b, c, d, x[12], S41, 0x655b59c3);
II (d, a, b, c, x[ 3], S42, 0x8f0ccc92);
II (c, d, a, b, x[10], S43, 0xffeff47d);
II (b, c, d, a, x[ 1], S44, 0x85845dd1);
II (a, b, c, d, x[ 8], S41, 0x6fa87e4f);
II (d, a, b, c, x[15], S42, 0xfe2ce6e0);
II (c, d, a, b, x[ 6], S43, 0xa3014314);
II (b, c, d, a, x[13], S44, 0x4e0811a1);
II (a, b, c, d, x[ 4], S41, 0xf7537e82);
II (d, a, b, c, x[11], S42, 0xbd3af235);
II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb);
II (b, c, d, a, x[ 9], S44, 0xeb86d391); //64
state_[0] += a; //finally four state into the result string
state_[1] += b;
state_[2] += c;
state_[3] += d;
memset(x, 0, sizeof(x));
}
void md5::encode(u_char *output, const u_int *input, size_t len) //u_int to u_char, 1 u_int -> 4 u_char
{
size_t i=0, j=0;
while(j < len){
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;
++i;
j += 4;
}
}
void md5::decode(u_int *output, const u_char *input, size_t len) //u_char to u_int
{
size_t i=0, j=0;
while(j < len){
output[i] = input[j] |
(input[j+1] << 8) |
(input[j+2] << 16) |
(input[j+3] << 24);
++i;
j += 4;
}
}
test.cpp
#include "md5.h"
#include <iostream>
using namespace std;
int main()
{
//const char* str = "admin";
md5 m("123456");
char buf[33];
m.digest(buf);
cout<<buf<<endl;
return 0;
}
相關文章
- 利用 C++ 實現 md5 演算法C++演算法
- 淺談md5加密 以及C++實現加密C++
- C++實現Prim演算法C++演算法
- 快速排序演算法C++實現排序演算法C++
- qt實現md5加密QT加密
- java MD5 加密實現Java加密
- Javascript實現MD5加密JavaScript加密
- 遺傳演算法與C++實現演算法C++
- C# 實現MD5加密處理 MD5 加密C#加密
- python 實現md5加密Python加密
- MD5演算法演算法
- c++實現的模擬退火演算法C++演算法
- C++實現蠻力最近對演算法C++演算法
- 各類排序演算法的c++實現排序演算法C++
- NDT演算法詳解與C++實現演算法C++
- MD5的介紹,演算法和實現。 ――――娃娃/[CCG] (23千字)演算法
- MD5加密演算法加密演算法
- Golang兩種方法實現MD5加密Golang加密
- java實現MD5加鹽加密方法Java加密
- 設計模式——原型模式(C++)——演算法實現設計模式原型C++演算法
- DES演算法C++程式碼實現-密碼學演算法C++密碼學
- MD5演算法詳解演算法
- 常見快取演算法和LRU的c++實現快取演算法C++
- 使用OpenCV和C++實現的分水嶺演算法(Watershed)OpenCVC++演算法
- MD5訊息摘要演算法演算法
- MD5雜湊加密演算法加密演算法
- [C++]實現memcpyC++memcpy
- C++ binder 實現C++
- 資料結構與演算法——B樹的C++實現資料結構演算法C++
- Boyer-Moore 精確匹配演算法實現(C/C++)演算法C++
- C語言實現MD5加密,竟如此簡單!C語言加密
- 詳解 MD5 資訊摘要演算法演算法
- MD5加密演算法簡介 (轉)加密演算法
- 糾正:HashPasswordForStoringInConfigFile中的Md5演算法並非常用的Md5演算法 (轉)演算法
- 最小生成樹的性質與prim演算法(C++實現)演算法C++
- DPLL 演算法(求解k-SAT問題)詳解(C++實現)演算法C++
- 決策樹ID3分類演算法的C++實現演算法C++
- 演算法:如何使用C++實現一個簡單的集合類演算法C++