1.資訊摘要函式(Hash函式)的設計與性質驗證實驗
2.實驗目的:資訊摘要函式(Hash函式)的設計與性質驗證,
2.1實驗設備:PC機 一臺/人
2.2實驗原理:
2.2.1.資訊摘要函式具有固定的輸出數位,
2.2.1資訊摘要函式滿足不可求逆,不可偽造和在可行時間之內找不到碰撞等特性,
3.實驗內容及注意事項:
資訊摘要函式的設計與Hash值的性質驗證
實驗步驟:
3.1設計符合原理要求的資訊摘要函式H(m),
3.2對于如下明文資訊m:
There was a grocery shop in a town. Plenty of mice lived in that grocery shop. Food was in plenty for them. They ate everything and spoiled all the bags. They also wasted the bread, biscuits and fruits of the shop. The grocer got really worried. So, he thought "I should buy a cat and let it stay at the grocery. Only then I can save my things." He bought a nice, big fat cat and let him stay there. The cat had a nice time hunting the mice and killing them. The mice could not move freely now. They were afraid that anytime the cat would eat them up. The mice wanted to do something. They held a meeting and all of them tweeted "We must get rid of the cat. Can someone give a suggestion"? All the mice sat and brooded. A smart looking mouse stood up and said, "The cat moves softly. That is the problem. If we can tie a bell around her neck, then things will be fine. We can know the movements of the cat". “Yes, that is answer," stated all the mice. An old mouse slowly stood up and asked, "Who would tie the bell?" After some moments there was no one there to answer this question.
呼叫H(m)演算法,產生Hash值,
3.3隨機改變m的任意一位字符,產生新的Hash值,
如此實驗10次,記新的Hash值為 H1,H2,…H10
3.4設計函式計算H0和Hi 的相似度 i=1,2,…10
3.5分析結果,得出結論
4.實驗程序
4.1設計 哈希函式Hash(m)的思路
? MD5摘要演算法是Hash摘要演算法中的一種摘要演算法,具有不可求逆性,不可偽造性,MD5 演算法自誕生之日起,就有很多人試圖證明和發現它的不安全之處,即存在碰撞(在對兩個不同的內容使用 MD5演算法運算的時候,有可能得到一對相同的結果值),2009年,中國科學院的謝濤和馮登國僅用了 的碰撞演算法復雜度,破解了MD5的碰撞抵抗,該攻擊在普通計算機上運行只需要數秒鐘 ,因此MD5演算法不具備實驗中要求的“在可行時間之內找不到碰撞”這個特性,
? 根據MD5的存在的缺點,為了加強MD5加密演算法的安全性(本身是不可逆的),從而加入了新的演算法部分即加鹽值,加鹽值是隨機生成的一組字串,可以包括隨機的大小寫字母、數字、字符,位數可以根據要求而不一樣,使用不同的加鹽值產生的最終密文是不一樣的,由于使用加鹽值以后的密碼相當的安全,即便是你獲得了其中的salt和最終密文,破解也是一個耗費相當多時間的程序,可以說是破解單純MD5的好幾倍,并且同一個明文在經過加鹽(這個鹽是隨機的,不同的)后進行MD5演算法產生的密文也是不同的,這就使得MD5演算法的抗碰撞性得到大幅度增強,因此可以滿足本次實驗要求,
4.2MD5+鹽的實作步驟
1).首先獲取需要進行md5普摘要演算法的明文text,
2).隨機生成加鹽值(可以由字母,數字,字符組成,位數可以自己決定,這里使用16位的字串)salt字串.
3)將生成的salt字串追加到明文text中,得到組合的字串 mergeText = text +salt
4)使用md5普通摘要演算法獲取mergeText 的hash值得到一個32位的字串decodeText,
5).將鹽salt字串的每個字符逐個插入到字串decodeText是 i *3+1(i = 0,1,2,…16)的位置上,得到一個新的48位的字串 decode,
6)最終的decode字串就是所要的密文,位長為48個字符,
該代碼已經用c++實作,具體請看:C++實作MD5摘要演算法加鹽salt值
4.3具體代碼實作
4.3.1MD5的普通加密演算法
4.3.1.1.將二進制位元組陣列轉換為16進制的字串
/* Convert byte array to hex string. */
string MD5::bytesToHexString(const byte *input, size_t length) {
string str;
str.reserve(length << 1);
for (size_t i = 0; i < length; i++) {
int t = input[i];
int a = t / 16;
int b = t % 16;
str.append(1, HEX[a]);
str.append(1, HEX[b]);
}
return str;
}
string EncryptUtil::md5Hex(const string& text) {
//首先更新md5中需要進行摘要的字串
this->md5->update(text);
//使用md5的方法生成對應的摘要后的字串
return this->md5->toString();
}
4.3.2產生鹽值字串的演算法
/**
產生鹽值字串salt
*/
string EncryptUtil::createSalt()
{
//隨機生成兩個亂數
int num1 = rand() % 99999999;
int num2 = rand() % 99999999;
string salt = "";
//將這兩個亂數轉換為字串后追加到salt中
salt.append(to_string(num1));
salt.append(to_string(num2));
//salt不夠十六位就在后面加0
int len = salt.size();
if (len < 16) {
for (int i = 0; i < 16 - len; i++) {
salt.append("0");
}
}
return salt;
}
4.3.3獲取md5普通摘要函式+鹽值salt操作后的最終密文
/**
* 加鹽MD5
* @param text : 需要進行加鹽后摘要的text明文
* @return string:回傳進行摘要演算法后的字串
*/
string EncryptUtil::encryptBySalt(const string& text) {
//產生鹽值字串salt
string salt = createSalt();
//將產生的salt追加到需要進行摘要的明文text中,得到由明文text和salt組成的字串
string merge_str = text + salt;
//使用md5演算法進行摘要計算得到相應的32位的密文
string encodeText = md5Hex(merge_str);
char cs [48];
//將32位的密文和產生的16位的salt進行重組形成新的48位的字串,
//這里表示,在新的字符陣列cs中,salt中的字符添加到cs字符陣列中位置是i*3+1的位置,其它位置由摘要密文encodeText中的字符填充
for (int i = 0; i < 48; i += 3) {
cs[i] = encodeText[i / 3 * 2];
char c = salt[i / 3];
cs[i + 1] = c;
cs[i + 2] = encodeText[i / 3 * 2 + 1];
}
//將組合成的cs字符陣列轉化為字串得到48位的加鹽后形成的md5摘要密文
string code = "";
for (int i = 0; i < 48; i++)
{
code.append(1,cs[i]);
}
return code;
}
4.3.4校驗加鹽后是否和原文一致
/**
* 校驗加鹽后是否和原文一致
* @param text : 進行摘要演算法的明文
* @param encryptText : 進行加鹽摘要演算法后的密文
* @return 如果加鹽后和原明文text一致則回傳true,否則回傳false
*/
bool EncryptUtil::verify( string text, string encryptText) {
char md5Text[32];
char salt[16];
//首先將加鹽后md5演算法摘要得到的encryptText密文進行拆分成一個32位的普通md5摘要演算法密文md5Text和一個16位的字串salt,
//這里就是進行salt和md5摘要密文形成48位新的字串encryptText時的逆向操作,encryptText中salt[i] = encryptText[ 3* i + 1], i = 0,1,2,...16
for (int i = 0; i < 48; i += 3) {
md5Text[i / 3 * 2] = encryptText[i];
md5Text[i / 3 * 2 + 1] = encryptText[i + 2];
salt[i / 3] = encryptText[i + 1];
}
//將拆分的16個隨機字串追salt加到明文text中
for (int i = 0; i < 16; i++)
{
text.append(1,salt[i]);
}
//使用md5摘要演算法進行生成密文得到enCs2
string enCs2 = md5Hex(text);
//比較兩個字串相等,如果相等則回傳true,只要有一個字符不相等就回傳false
for (int i = 0; i < enCs2.size(); i++)
{
if (enCs2[i] != md5Text[i])
{
return false;
}
}
return true;
}
4.3.5 逐個比較兩個密文相同位置上字符是否相同來計算兩個明文進行md5加密后的相似度,
/**
逐個比較兩個密文相同位置上字符是否相同來計算兩個明文進行md5加密后的相似度,
@param str1: md5摘要演算法后的字串
@param str2:md5摘要演算法后的字串
@return double: 回傳相似度
*/
double EncryptUtil::similarityDegree(const string& str1, const string& str2)
{
if (str1.size() <= 0 && (str1.size() != str2.size()))
{
return 0;
}
int count = 0;
//統計對應位置上字符相同的個數
for (int i = 0; i < str1.size(); i++)
{
if (str1[i] == str2[i])
{
count++;
}
}
//計算相似度
double result = count * 1.0 / str1.size();
return result;
}
4.3.6為了方便,將明文保存到檔案中,然后讀取檔案內容作為字串
string loadTextToString(const string textFilePath) {
ifstream* ism = new ifstream(textFilePath,ios::app|ios::binary);
if (ism->is_open())
{
string text = "";
char ch;
while (!ism->eof())
{
ism->get(ch);
text.append(1,ch);
}
return text;
}
else {
cout << "打開檔案失敗!" << endl;
return "";
}
}
5.驗證實驗內容
設計函式驗證獲取H0到H10的密文,并計算相似度,
string randomReplace(string text,int index,string replaceChar) {
return text.replace(index,1,replaceChar);
}
void test() {
string text = loadTextToString("hashtext.txt");
cout << "需要加密的明文為:\n" << text << endl;
EncryptUtil util;
string md0 = util.encryptBySalt(text);
cout << "md5加鹽后加密的md5值H0:" + md0 << endl;
vector<string> vec;
for (int i = 0; i < 10; i++)
{
//替換十個字符,每個原來的字符+1
string newStr = randomReplace(text, i * 5,string(1, text[i * 5] + 1));
//計算每個替換后字符的hash值
string encodeText =util.encryptBySalt(newStr);
vec.push_back(encodeText);
}
for (size_t i = 0; i < 10; i++)
{
cout << "md5加鹽后加密的md5值H"+ to_string(i + 1) + ":" + vec[i]<< endl;
}
for (size_t i = 0; i < 10; i++)
{
//計算H0和H的相似度
cout << "H0和H" + to_string(i + 1) + "的相似度:" + to_string(util.similarityDegree(md0, vec[i])) << endl;
}
}
![[外鏈圖片轉存中...(img-GMQD1fac-1607789521383)]](https://img.uj5u.com/2020/12/14/204636141250222.png)
md5加鹽后加密的md5值H0:051293435697829a9bc1de2ff8ed0cb0a908706504302100
md5加鹽后加密的md5值H1:061233445697859a2bc8de3ff0ed0cb0a908706504302100
md5加鹽后加密的md5值H2:021203415697819a2bc1de9ff1ed6cb0a908706504302100
md5加鹽后加密的md5值H3:091243475677819a6bc4de1ff3ed0cb0a908706504302100
md5加鹽后加密的md5值H4:031203425687869a4bc8de6ff3ed0cb0a908706504302100
md5加鹽后加密的md5值H5:011253485697809a1bc5de5ff0ed7cb0a908706504302100
md5加鹽后加密的md5值H6:031203485607829a1bc5de3ff6ed6cb0a908706504302100
md5加鹽后加密的md5值H7:031203425617829a1bc5de0ff8ed0cb0a908706504302100
md5加鹽后加密的md5值H8:011293475627869a2bc0de0ff9ed0cb0a908706504302100
md5加鹽后加密的md5值H9:021223425667899a1bc2de7ff0ed0cb0a908706504302100
md5加鹽后加密的md5值H10:091293415627829a3bc6de5ff5ed0cb0a908706504302100
H0和H1的相似度:0.833333
H0和H2的相似度:0.833333
H0和H3的相似度:0.812500
H0和H4的相似度:0.812500
H0和H5的相似度:0.812500
H0和H6的相似度:0.812500
H0和H7的相似度:0.854167
H0和H8的相似度:0.833333
H0和H9的相似度:0.812500
H0和H10的相似度:0.854167
6.拓展
6.1驗證md5經過摘要演算法后和原來明文一致
void test9() {
string text = loadTextToString("hashtext.txt");
EncryptUtil util;
string encodeText = util.encryptBySalt(text);
string encodeText1 = util.encryptBySalt(text);
cout << "md5加鹽后加密的md5值:" + encodeText << endl;
cout << "md5加鹽后加密的md5值:" + encodeText1 << endl;
if (encodeText.compare(encodeText1) == 0)
{
cout << "兩次生成的加鹽密文相等!" << endl;
}
else {
cout << "兩次生成的加鹽密文不相等!" << endl;
}
bool fla = util.verify(text, encodeText);
if (fla == true)
{
cout << "原來的明文和加鹽后的明文一致得到驗證!" << endl;
}
else {
cout << "原來的明文和加鹽后的明文不一致!" << endl;
}
}
![[外鏈圖片轉存中...(img-eCm0qnl5-1607789521389)]](https://img.uj5u.com/2020/12/14/204636141250221.png)
md5加鹽后加密的md5值:071263445647839a7bc0de0ff0ed0cb0a908706504302100
md5加鹽后加密的md5值:021253435637849a1bc6de1ff8ed9cb0a908706504302100
兩次生成的加鹽密文不相等!
原來的明文和加鹽后的明文一致得到驗證!
由結果知道,雖然加鹽后得到的密文不一樣,但是相同的明文產生的密文是可以通過驗證知道原來的明文是否一致的,
7.完整的代碼
#pragma once
#include<iostream>
#include<string>
#include"Md5.h"
#include<time.h>
using namespace std;
class EncryptUtil
{
public:
EncryptUtil();
/**
*@param text:需要進行普通md5摘要演算法計算的明文
*@return string:回傳普通md5摘要算計算后的字串
*/
string md5Decode(const string& text);
/**
產生鹽值字串salt
*/
string createSalt();
/**
* 加鹽MD5
* @param text : 需要進行加鹽后摘要的text明文
* @return string:回傳進行摘要演算法后的字串
*/
string encryptBySalt(const string& text);
/**
* 獲取十六進制字串形式的MD5摘要
* @param text: 需要進行摘要演算法的明文
* @return string: 回傳進行普通md5摘要后的字串
*/
string md5Hex(const string& src);
/**
* 校驗加鹽后是否和原文一致
* @param text : 進行摘要演算法的明文
* @param encryptText : 進行加鹽摘要演算法后的密文
* @return 如果加鹽后和原明文text一致則回傳true,否則回傳false
*/
bool verify( string text, string md5Text);
/**
逐個比較兩個密文相同位置上字符是否相同來計算兩個進行md5加密后的相似度,
@param str1: md5摘要演算法后的字串
@param str2:md5摘要演算法后的字串
@return double: 回傳相似度
*/
double similarityDegree(const string& str1, const string& str2);
~EncryptUtil();
private:
MD5* md5 = nullptr;
};
#include "EncryptUtil.h"
EncryptUtil::EncryptUtil()
{
//初始化MD5這個類
this->md5 = new MD5();
//設定亂數種子,在產生鹽時可以產生亂數,
srand(time(NULL));
}
/**
*@param text:需要進行普通md5摘要演算法計算的明文
*@return string:回傳普通md5摘要算計算后的字串
*/
string EncryptUtil::md5Decode(const string & text)
{
//呼叫md5Hex(text)函式即可
return this->md5Hex(text);
}
/**
產生鹽值字串salt
*/
string EncryptUtil::createSalt()
{
//隨機生成兩個亂數
int num1 = rand() % 99999999;
int num2 = rand() % 99999999;
string salt = "";
//將這兩個亂數轉換為字串后追加到salt中
salt.append(to_string(num1));
salt.append(to_string(num2));
//salt不夠十六位就在后面加0
int len = salt.size();
if (len < 16) {
for (int i = 0; i < 16 - len; i++) {
salt.append("0");
}
}
//cout << "產生的鹽值字串為:" <<salt<< endl;
return salt;
}
/**
* 加鹽MD5
* @param text : 需要進行加鹽后摘要的text明文
* @return string:回傳進行摘要演算法后的字串
*/
string EncryptUtil::encryptBySalt(const string& text) {
//產生鹽值字串salt
string salt = createSalt();
//將產生的salt追加到需要進行摘要的明文text中,得到由明文text和salt組成的字串
string merge_str = text + salt;
//使用md5演算法進行摘要計算得到相應的32位的密文
string encodeText = md5Hex(merge_str);
char cs [48];
//將32位的密文和產生的16位的salt進行重組形成新的48位的字串,
//這里表示,在新的字符陣列cs中,salt中的字符添加到cs字符陣列中位置是i*3+1的位置,其它位置由摘要密文encodeText中的字符填充
for (int i = 0; i < 48; i += 3) {
cs[i] = encodeText[i / 3 * 2];
char c = salt[i / 3];
cs[i + 1] = c;
cs[i + 2] = encodeText[i / 3 * 2 + 1];
}
//將組合成的cs字符陣列轉化為字串得到48位的加鹽后形成的md5摘要密文
string code = "";
for (int i = 0; i < 48; i++)
{
code.append(1,cs[i]);
}
return code;
}
/**
* 獲取十六進制字串形式的MD5摘要
* @param text: 需要進行摘要演算法的明文
* @return string: 回傳進行普通md5摘要后的字串
*/
string EncryptUtil::md5Hex(const string& text) {
//首先更新md5中需要進行摘要的字串
this->md5->update(text);
//使用md5的方法生成對應的摘要后的字串
return this->md5->toString();
}
/**
* 校驗加鹽后是否和原文一致
* @param text : 進行摘要演算法的明文
* @param encryptText : 進行加鹽摘要演算法后的密文
* @return 如果加鹽后和原明文text一致則回傳true,否則回傳false
*/
bool EncryptUtil::verify( string text, string encryptText) {
char md5Text[32];
char salt[16];
//首先將加鹽后md5演算法摘要得到的encryptText密文進行拆分成一個32位的普通md5摘要演算法密文md5Text和一個16位的字串salt,
//這里就是進行salt和md5摘要密文形成48位新的字串encryptText時的逆向操作,encryptText中salt[i] = encryptText[ 3* i + 1], i = 0,1,2,...16
for (int i = 0; i < 48; i += 3) {
md5Text[i / 3 * 2] = encryptText[i];
md5Text[i / 3 * 2 + 1] = encryptText[i + 2];
salt[i / 3] = encryptText[i + 1];
}
//將拆分的16個隨機字串追salt加到明文text中
for (int i = 0; i < 16; i++)
{
text.append(1,salt[i]);
}
//使用md5摘要演算法進行生成密文得到enCs2
string enCs2 = md5Hex(text);
//比較兩個字串相等,如果相等則回傳true,只要有一個字符不相等就回傳false
for (int i = 0; i < enCs2.size(); i++)
{
if (enCs2[i] != md5Text[i])
{
return false;
}
}
return true;
}
/**
逐個比較兩個密文相同位置上字符是否相同來計算兩個明文進行md5加密后的相似度,
@param str1: md5摘要演算法后的字串
@param str2:md5摘要演算法后的字串
@return double: 回傳相似度
*/
double EncryptUtil::similarityDegree(const string& str1, const string& str2)
{
if (str1.size() <= 0 && (str1.size() != str2.size()))
{
return 0;
}
int count = 0;
//統計對應位置上字符相同的個數
for (int i = 0; i < str1.size(); i++)
{
if (str1[i] == str2[i])
{
count++;
}
}
//計算相似度
double result = count * 1.0 / str1.size();
return result;
}
EncryptUtil::~EncryptUtil()
{
}
#pragma once
#ifndef MD5_H
#define MD5_H
#include <string>
#include <fstream>
using namespace std;
/* Type define */
typedef unsigned char byte;
typedef unsigned int uint32;
/* MD5 declaration. */
class MD5 {
public:
MD5();
MD5(const void *input, size_t length);
MD5(const string &str);
MD5(ifstream &in);
void update(const void *input, size_t length);
void update(const string &str);
void update(ifstream &in);
const byte* digest();
string toString();
private:
void reset();
void update(const byte *input, size_t length);
void final();
void transform(const byte block[64]);
void encode(const uint32 *input, byte *output, size_t length);
void decode(const byte *input, uint32 *output, size_t length);
string bytesToHexString(const byte *input, size_t length);
/* class uncopyable */
MD5(const MD5&);
MD5& operator=(const MD5&);
private:
uint32 _state[4]; /* state (ABCD) */
uint32 _count[2]; /* number of bits, modulo 2^64 (low-order word first) */
byte _buffer[64]; /* input buffer */
byte _digest[16]; /* message digest */
bool _finished; /* calculate finished ? */
static const byte PADDING[64]; /* padding for calculate */
static const char HEX[16];
static const size_t BUFFER_SIZE = 1024;
};
#endif/*MD5_H*/
#include "md5.h"
/* 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
/* F, G, H and I are basic MD5 functions.
*/
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))
/* ROTATE_LEFT rotates x left n bits.
*/
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
Rotation is separate from addition to prevent recomputation.
*/
#define FF(a, b, c, d, x, s, ac) { \
(a) += F ((b), (c), (d)) + (x) + ac; \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define GG(a, b, c, d, x, s, ac) { \
(a) += G ((b), (c), (d)) + (x) + ac; \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define HH(a, b, c, d, x, s, ac) { \
(a) += H ((b), (c), (d)) + (x) + ac; \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define II(a, b, c, d, x, s, ac) { \
(a) += I ((b), (c), (d)) + (x) + ac; \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
const byte MD5::PADDING[64] = { 0x80 };
const char MD5::HEX[16] = {
'0', '1', '2', '3',
'4', '5', '6', '7',
'8', '9', 'a', 'b',
'c', 'd', 'e', 'f'
};
/* Default construct. */
MD5::MD5() {
reset();
}
/* Construct a MD5 object with a input buffer. */
MD5::MD5(const void *input, size_t length) {
reset();
update(input, length);
}
/* Construct a MD5 object with a string. */
MD5::MD5(const string &str) {
reset();
update(str);
}
/* Construct a MD5 object with a file. */
MD5::MD5(ifstream &in) {
reset();
update(in);
}
/* Return the message-digest */
const byte* MD5::digest() {
if (!_finished) {
_finished = true;
final();
}
return _digest;
}
/* Reset the calculate state */
void MD5::reset() {
_finished = false;
/* reset number of bits. */
_count[0] = _count[1] = 0;
/* Load magic initialization constants. */
_state[0] = 0x67452301;
_state[1] = 0xefcdab89;
_state[2] = 0x98badcfe;
_state[3] = 0x10325476;
}
/* Updating the context with a input buffer. */
void MD5::update(const void *input, size_t length) {
update((const byte*)input, length);
}
/* Updating the context with a string. */
void MD5::update(const string &str) {
update((const byte*)str.c_str(), str.length());
}
/* Updating the context with a file. */
void MD5::update(ifstream &in) {
if (!in)
return;
std::streamsize length;
char buffer[BUFFER_SIZE];
while (!in.eof()) {
in.read(buffer, BUFFER_SIZE);
length = in.gcount();
if (length > 0)
update(buffer, length);
}
in.close();
}
/* MD5 block update operation. Continues an MD5 message-digest
operation, processing another message block, and updating the
context.
*/
void MD5::update(const byte *input, size_t length) {
uint32 i, index, partLen;
//_finished = false;
this->reset();
/* Compute number of bytes mod 64 */
index = (uint32)((_count[0] >> 3) & 0x3f);
/* update number of bits */
if ((_count[0] += ((uint32)length << 3)) < ((uint32)length << 3))
_count[1]++;
_count[1] += ((uint32)length >> 29);
partLen = 64 - index;
/* transform as many times as possible. */
if (length >= partLen) {
memcpy(&_buffer[index], input, partLen);
transform(_buffer);
for (i = partLen; i + 63 < length; i += 64)
transform(&input[i]);
index = 0;
}
else {
i = 0;
}
/* Buffer remaining input */
memcpy(&_buffer[index], &input[i], length - i);
}
/* MD5 finalization. Ends an MD5 message-_digest operation, writing the
the message _digest and zeroizing the context.
*/
void MD5::final() {
byte bits[8];
uint32 oldState[4];
uint32 oldCount[2];
uint32 index, padLen;
/* Save current state and count. */
memcpy(oldState, _state, 16);
memcpy(oldCount, _count, 8);
/* Save number of bits */
encode(_count, bits, 8);
/* Pad out to 56 mod 64. */
index = (uint32)((_count[0] >> 3) & 0x3f);
padLen = (index < 56) ? (56 - index) : (120 - index);
update(PADDING, padLen);
/* Append length (before padding) */
update(bits, 8);
/* Store state in digest */
encode(_state, _digest, 16);
/* Restore current state and count. */
memcpy(_state, oldState, 16);
memcpy(_count, oldCount, 8);
}
/* MD5 basic transformation. Transforms _state based on block. */
void MD5::transform(const byte block[64]) {
uint32 a = _state[0], b = _state[1], c = _state[2], d = _state[3], x[16];
decode(block, x, 64);
/* Round 1 */
FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */
FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */
FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */
FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */
FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */
FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */
FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */
FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */
FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */
FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */
FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
/* Round 2 */
GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */
GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */
GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */
GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */
GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */
GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */
GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */
GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */
GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */
GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */
GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
/* Round 3 */
HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */
HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */
HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */
HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */
HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */
HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */
HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */
HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */
HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */
HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */
/* Round 4 */
II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */
II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */
II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */
II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */
II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */
II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */
II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */
II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */
II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */
II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */
_state[0] += a;
_state[1] += b;
_state[2] += c;
_state[3] += d;
}
/* Encodes input (ulong) into output (byte). Assumes length is
a multiple of 4.
*/
void MD5::encode(const uint32 *input, byte *output, size_t length) {
for (size_t i = 0, j = 0; j < length; i++, j += 4) {
output[j] = (byte)(input[i] & 0xff);
output[j + 1] = (byte)((input[i] >> 8) & 0xff);
output[j + 2] = (byte)((input[i] >> 16) & 0xff);
output[j + 3] = (byte)((input[i] >> 24) & 0xff);
}
}
/* Decodes input (byte) into output (ulong). Assumes length is
a multiple of 4.
*/
void MD5::decode(const byte *input, uint32 *output, size_t length) {
for (size_t i = 0, j = 0; j < length; i++, j += 4) {
output[i] = ((uint32)input[j]) | (((uint32)input[j + 1]) << 8) |
(((uint32)input[j + 2]) << 16) | (((uint32)input[j + 3]) << 24);
}
}
/* Convert byte array to hex string. */
string MD5::bytesToHexString(const byte *input, size_t length) {
string str;
str.reserve(length << 1);
for (size_t i = 0; i < length; i++) {
int t = input[i];
int a = t / 16;
int b = t % 16;
str.append(1, HEX[a]);
str.append(1, HEX[b]);
}
return str;
}
MD5 & MD5::operator=(const MD5 &)
{
return *this;
}
/* Convert digest to string value */
string MD5::toString() {
return bytesToHexString(digest(), 16);
}
測驗檔案
#include<iostream>
#include"Md5.h"
#include<string>
#include<fstream>
#include"EncryptUtil.h"
#include<time.h>
#include<vector>
using namespace std;
string loadTextToString(const string textFilePath) {
ifstream* ism = new ifstream(textFilePath,ios::app|ios::binary);
if (ism->is_open())
{
string text = "";
char ch;
while (!ism->eof())
{
ism->get(ch);
text.append(1,ch);
}
return text;
}
else {
cout << "打開檔案失敗!" << endl;
return "";
}
}
void test2() {
}
void test1() {
string text = loadTextToString("hashtext.txt");
MD5 md5(text);
cout << md5.toString();
}
void test3() {
string s = "11";
s.append(to_string(121));
cout << s;
}
void test4() {
string text = loadTextToString("hashtext.txt");
EncryptUtil util;
string str = util.md5Decode(text);
cout << "\n普通加密后的md5值:" + str << endl;
cout << "普通加密后的md5值:" + util.md5Decode(text) << endl;
string encodeText =util.encryptBySalt(text);
string encodeText1 = util.encryptBySalt(text);
cout << "md5加鹽后加密的md5值:" + encodeText << endl;
cout << "md5加鹽后加密的md5值:" + encodeText1 << endl;
if (encodeText.compare(encodeText1) == 0)
{
cout << "兩次生成的加鹽秘鑰相等!" << endl;
}
else {
cout << "兩次生成的加鹽秘鑰不相等!" << endl;
}
bool fla = util.verify(text,encodeText);
if (fla == true)
{
cout << "相等!"<<endl;
}
else {
cout << "不相等" << endl;
}
}
void test5() {
string text = loadTextToString("hashtext.txt");
cout << endl;
}
void test6() {
srand(time(NULL));
cout << rand() % 99999999 <<" "<< rand()% 99999999 <<endl;
cout << rand() % 99999999 << " " << rand() % 99999999 << endl;
}
void test7() {
string text = loadTextToString("hashtext.txt");
cout << "需要加密的明文為:\n" << text<<endl;
EncryptUtil util;
string encodeText = util.encryptBySalt(text);
cout << "md5加鹽后加密的md5值:" + encodeText << endl;
}
string randomReplace(string text,int index,string replaceChar) {
return text.replace(index,1,replaceChar);
}
void test() {
string text = loadTextToString("hashtext.txt");
cout << "需要加密的明文為:\n" << text << endl;
EncryptUtil util;
string md0 = util.encryptBySalt(text);
cout << "md5加鹽后加密的md5值H0:" + md0 << endl;
vector<string> vec;
for (int i = 0; i < 10; i++)
{
//替換十個字符,每個原來的字符+1
string newStr = randomReplace(text, i * 5,string(1, text[i * 5] + 1));
//計算每個替換后字符的hash值
string encodeText =util.encryptBySalt(newStr);
vec.push_back(encodeText);
}
for (size_t i = 0; i < 10; i++)
{
cout << "md5加鹽后加密的md5值H"+ to_string(i + 1) + ":" + vec[i]<< endl;
}
for (size_t i = 0; i < 10; i++)
{
//計算H0和H的相似度
cout << "H0和H" + to_string(i + 1) + "的相似度:" + to_string(util.similarityDegree(md0, vec[i])) << endl;
}
}
void test8() {
string text = loadTextToString("hashtext.txt");
cout << "需要加密的明文為:\n" << text << endl;
EncryptUtil util;
string md0 = util.encryptBySalt(text);
cout << "md5加鹽后加密的md5值H0:" + md0 << endl;
string text1 = text.replace(10,1,"a");
string md1 = util.encryptBySalt(text1);
cout << "md5加鹽后加密的md5值H1:" + md1 << endl;
cout << "md0和md1相似度:" << util.similarityDegree(md0,md1)<<endl;
}
void test9() {
string text = loadTextToString("hashtext.txt");
EncryptUtil util;
string encodeText = util.encryptBySalt(text);
string encodeText1 = util.encryptBySalt(text);
cout << "md5加鹽后加密的md5值:" + encodeText << endl;
cout << "md5加鹽后加密的md5值:" + encodeText1 << endl;
if (encodeText.compare(encodeText1) == 0)
{
cout << "兩次生成的加鹽密文相等!" << endl;
}
else {
cout << "兩次生成的加鹽密文不相等!" << endl;
}
bool fla = util.verify(text, encodeText);
if (fla == true)
{
cout << "原來的明文和加鹽后的明文一致得到驗證!" << endl;
}
else {
cout << "原來的明文和加鹽后的明文不一致!" << endl;
}
}
int main() {
// test8();
test9();
system("pause");
return 0;
}
8.看完記得點贊哦,筆記整理不易,
9.本博客已經同步到個人博客,如有需要請移步:http://moyisuiying.com/index.php/cppstudy/information-secure/433.html
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/234362.html
標籤:其他
下一篇:Lecture1-Shell
