精华内容
下载资源
问答
  • 1.信息摘要函数(Hash函数)的设计与性质验证实验 2.实验目的:信息摘要函数(Hash函数)的设计与性质验证。 2.1实验设备:PC机 一台/人 2.2实验原理: 2.2.1.信息摘要函数具有固定的输出数位。 2.2.1信息摘要函数满足不...

    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)]

    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)]

    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

    展开全文
  • 信息安全与密码学3-数字摘要和Hash函数(哈希函数) 1、数字摘要 数字摘要是将任意长度的消息变成固定长度的短消息,它类似于一个自变量是消息的函数,也就是Hash函数。数字摘要就是采用单项Hash函数将需要加密...

    信息安全与密码学3-数字摘要和Hash函数(哈希函数)


    1、数字摘要

    数字摘要是将任意长度的消息变成固定长度的短消息,它类似于一个自变量是消息的函数,也就是Hash函数。数字摘要就是采用单项Hash函数将需要加密的明文“摘要”成一串固定长度(128位)的密文这一串密文又称为数字指纹,它有固定的长度,而且不同的明文摘要成密文,其结果总是不同的,而同样的明文其摘要必定一致


    一般来说,非对称加密是用来处理短消息的,而相对于较长的消息则显得有些吃力。当然,可以将长的消息分成若干小段,然后再分别签名。不过,这样做非常麻烦,而且会带来数据完整性的问题。比较合理的做法是在数字签名前对消息先进行数字摘要。
    是将任意长度的消息变成固定长度的短消息,它类似于一个自变量是消息的函数,也就是Hash函数。
    数字摘要就是采用单项Hash函数将需要加密的明文“摘要”成一串固定长度(128位)的密文这一串密文又称为数字指纹,它有固定的长度,而且不同的明文摘要成密文,其结果总是不同的,而同样的明文其摘要必定一致。
    一个Hash函数的好坏是由发生碰撞的概率决定的。如果攻击者能够轻易地构造出两个消息具有相同的Hash值,那么这样的Hash函数是很危险的。一般来说,安全Hash标准的输出长度为160位,这样才能保证它足够的安全。 这一加密方法亦称安全Hash编码法(SHA:Secure Hash Algorithm)或MD5(MD Standards for Message Digest由Ron Rivest所设计)。该编码法采用单向Hash函数将需加密的明文“摘要”成一串128bit的密文,这一串密文亦称为数字指纹(Finger Print),它有固定的长度,且不同的明文摘要成密文,其结果总是不同的,而同样的明文其摘要必定一致。这样这摘要便可成为验证明文是否是“真身”的“指纹”了。

    数字摘要使用:
    (1) 被发送文件用SHA编码加密产生128bit的数字摘要。
    (2) 发送方用自己的私用密钥对摘要再加密,这就形成了数字签名。
    (3) 将原文和加密的摘要同时传给对方。
    (4) 对方用发送方的公共密钥对摘要解密,同时对收到的文件用SHA编码加密产生又一摘要。
    (5) 将解密后的摘要和收到的文件在接收方重新加密产生的摘要相互对比。如两者一致,则说明传送过程中信息没有被破坏或篡改过。否则不然。

    2、Hash函数(哈希函数)

          Hash,一般翻译做"散列",也有直接音译为"哈希"的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。
          一些著名的hash算法,MD5 和 SHA1 可以说是目前应用最广泛的Hash算法,而它们都是以 MD4 为基础设计的。
    这里简单说一下:
    1) MD4
    MD4(RFC 1320)是 MIT 的Ronald L. Rivest在 1990 年设计的,MD 是 Message Digest 的缩写。它适用在32位字长的处理器上用高速软件实现--它是基于 32位操作数的位操作来实现的。
    2) MD5
    MD5(RFC 1321)是 Rivest 于1991年对MD4的改进版本。它对输入仍以512位分组,其输出是4个32位字的级联,与 MD4 相同。MD5比MD4来得复杂,并且速度较之要慢一点,但更安全,在抗分析和抗差分方面表现更好
    3) SHA1
    SHA1是由NIST NSA设计为同DSA一起使用的,它对长度小于2^64位的输入,产生长度为160bit的散列值,因此抗穷举(brute-force)性更好。SHA-1 设计时基于和MD4相同原理,并且模仿了该算法。
    美国国家安全局(NationalSecurityAgency,简写为NSA)美国国家标准与技术研究院(National Institute of Standards and Technology,NIST)


            HASH主要用于信息安全领域中加密算法,它把一些不同长度的信息转化成杂乱的128位的编码里,叫做HASH值. 也可以说,hash就是找到一种数据内容和数据存放地址之间的映射关系。Hash算法在信息安全方面的应用主要体现在以下的3个方面:
    1)文件校验
    我们比较熟悉的校验算法有奇偶校验和CRC校验,这2种校验并没有抗数据篡改的能力,它们一定程度上能检测并纠正数据传输中的信道误码,但却不能防止对数据的恶意破坏。
    MD5 Hash算法的"数字指纹"特性,使它成为目前应用最广泛的一种文件完整性校验和(Checksum)算法,不少Unix系统有提供计算md5 checksum的命令。
    2)数字签名
    Hash 算法也是现代密码体系中的一个重要组成部分。由于非对称算法的运算速度较慢,所以在数字签名协议中,单向散列函数扮演了一个重要的角色。对 Hash 值,又称"数字摘要"进行数字签名,在统计上可以认为与对文件本身进行数字签名是等效的。而且这样的协议还有其他的优点。
    3)鉴权协议
    如下的鉴权协议又被称作"挑战--认证模式:在传输信道是可被侦听,但不可被篡改的情况下,这是一种简单而安全的方法。


    著作权声明:本文由http://my.csdn.net/Nathan1987_原创,欢迎转载分享。请尊重作者劳动,转载时保留该声明和作者博客链接,谢谢
    展开全文
  • 网络安全-安全散列函数信息摘要SHA-1,MD5原理

    千次阅读 多人点赞 2014-07-04 23:06:26
    单向散列函数或者安全散列函数之所以重要,不仅在于消息认证(消息摘要,数据指纹),还有数字签名(加强版的消息认证)和验证数据的完整性。常见的单向散列函数有MD5和SHA 散列函数的要求  散列函数的目的是文件、...

    -----------------------------------------------欢迎查看网络安全连载博客-----------------------------------
    【网络安全】-安全散列函数,信息摘要SHA-1,MD5算法       【网络安全】-非对称加密,RSA算法,数字签名
    【网络安全】-RSA非对称算法算法、数字签名                         【网络安全】-建立安全socket连接、登录
    【网络安全】-【数字证书,证书链】
    ---------------------------------------------------------------------------------------------------------------------

    本文绝大部分内容来自《网络安全基础——应用与标准》第五版——清华大学出版社。其中蓝色部门是自己添加

    安全散列函数

            单向散列函数或者安全散列函数之所以重要,不仅在于消息认证(消息摘要,数据指纹),还有数字签名(加强版的消息认证)和验证数据的完整性。常见的单向散列函数有MD5和SHA

    散列函数的要求

            散列函数的目的是文件、消息或者其他数据块产生“指纹”。为满足在消息认证中的应用,散列函数H必须具有下列性质:

            (1)H可适用于任意长度的数据块。

            (2)H能够生成固定长度的输出。

            (2)对于任意给定的x,计算H(x)相对容易,并且可以用软/硬件实现。

            (4)对于任意给定的h,找到满足H(x)=h的x在计算上不可行,满足这一特性的散列函数称之为:具备抗原像攻击性。

            (5)对于任意给定的数据块x,找到满足H(y)=H(x)的y ≠ x在计算上是不可行;满足这一特性的散列函数称之为:抗弱碰撞性。

            (6)找到满足H(x) = H(y)的任意一对(x,y)在计算上是不可行的。满足这一特性的散列函数称之为:抗碰撞性。

            前三个性质是使用散列函数进行消息认证的实际可行要求。第四个属性,抗原像攻击,防止攻击者能够回复秘密值。抗弱碰撞性保证了对于给定的消息,不可能找到具有相同散列值的可替换消息。

            满足上面前5个性质的散列函数称之为弱散列函数。如果还满足第6个性质则称之为强散列函数。

    一般来说:能够认识散列函数的两个特点就OK,1.输出固定长度的 2. 不可逆转!

    散列函数的安全性

            有两种方法可以攻击安全散列函数:密码分析法和暴力攻击法。散列函数抵抗暴力攻击的强度完全依赖于算法生成的散列码长度。Van Oorschot和Wiener曾经提出,花费1000万美元涉及一个被专门用来搜索MD5算法碰撞的机器,则平均24天内就可以找到一个碰撞。

            2004年8月中国密码学家王小云教授等首次公布了提出一种寻找MD5碰撞的新方法。目前利用该方法用普通微机几分钟内即可找到MD5的碰撞。MD5已经呗彻底攻破。

    简单散列函数

            所有的散列函数都按照下面的基本操作。把输入(消息、文件等)看成n比特块的序列。对输入用迭代方法处理一块,生成n比特的散列函数。
            一种最简单散列函数的每一个数据块都按照比特异或。如下所示

                    Ci = bi1 bi2⊕ … ⊕ bim

            其中:
                    Ci为散列码的第i比特,1<=  i <=n;
                    m为输入中n比特数据块的数目;
                    b ij为第j块的第i比特;
                    为异或操作
            下图说明了这个操作:



    上图只是简单的散列函数。因为没一列都有相同的可能性。所以这个函数的有效性差。

    SHA安全散列函数

            近些年,应用最广泛的散列函数是SHA。由于其他每一种被广泛应用的散列函数都已经被证实存在这密码分析学中的缺陷,接着到2005年,SHA或许仅存的安全散列算法。SHA由美国国家标准与技术研究院(NIST)开发。
    ● 1995年公布SHA-1
    ● 2002年,公布了SHA-2(SHA-256、SHA-384、SHA-512)
    ● 2008年,增加了SHA-224
    更详细的如下图所示:



    下面对SHA-512做一下介绍,其他SHA算法与之很相似。该算法以最大长度不超过2 128比特作为输入,生成512比特的消息摘要输出。输入以1024比特的数据块进行处理。如图所示:



    处理过程:

    ● 第1步、追加填充比特

    填充消息使其长度模1024同余896[长度 896(模1024)]。及时消息已经是期望的长度,也总是要添加填充。填充部分是由单个比特1后接所需个数的比特0构成。

    ● 第2步、追加长度

    将128比特的数据块追加在消息上。该数据被看作是128比特的无符号整数,它含有原始消息的长度。经过前两步,生成了1024倍数的消息。如上图所示,被延展的消息表示为1024比特的数据块M1,M2,M3...Mn。
    结合这两点: “同余”比较难以理解,填充比特的逻辑可以这么理解:填充的目的是为了形成1024的倍数,但是,最后一个1024块的最后128比特必须保留(用于记录原始消息的长度), 举例:
    原始消息895比特,那么需要填充1个比特。这样895+1+128=1024
    原始消息896比特,这种情况下,加上128字节正好是1024,但是按照规则,仍是要填充1024个字节。
    原始消息897比特,897+128>1024,所以需要填充。填充1023个比特。

    ● 第3步、初始化散列缓冲区

    用512比特的缓冲区保存散列函数中间和最终结果。缓冲区可以是8个64比特的寄存器(a,b,c,d,e,f,g,h),这些寄存器初始化为64比特的整数(十六进制):
            a=6a09e667f3bcc908
            b=bb67ae8584caa73b
            c=3c6ef372fe94f82b
            d=a54ff53a5f1d36f1
            e=510e527fade682d1
            f=9b05688c2b3e6c1f
            g=1f83d9abfb41bd6b
            h=5be0cd19137e2179
    这些值以逆序的形式存储,即字的最高字节存在最低地址(最左边)字节位置。这些字的获取方式如下:前8个素数取平方跟,取小数部分前64位。

    ● 第4步、处理1024比特的数据块消息

            算法的核心是80轮迭代构成的模块。该模块在上图中标记为F,下图是其逻辑关系。每一轮都以512比特的缓冲区值abcdefgh作为输入,并且更新缓冲区内容。在第一轮时,缓冲区的值是中间值Hi-1.在任意t轮,使用从当前正在处理的1024比特的数据块(Mi)导出64位比特值Wt。每一轮还使用附加常数Kt,其中0<=t<=79表示80轮中的某一轮。这些常数的获取方式如下:前8个素数的立方根,取小数部分的前64位。这些常数提供了64位随机串集合,可以初步消除输入数据中的任何规则性。第80轮输出加到第1轮输入(Hi-1)生成Hi。缓冲区里的8个字与Hi-1中相应的字进行模264加法运算。

    ● 第5步、输出

    当所有N个1024比特的数据块都处理完毕后,从第N阶段输出的便是512比特的消息摘要。

            SHA-512算法使得散列码的任意比特都是输入端每1比特的函数。基本函数F的复杂迭代产生很好的混淆效果;即随机取两组相似的消息也不可能生成相同的散列码。除非SHA-512隐含一些直到现在都还没有公布的弱点。
    展开全文
  • Jmeter接口测试:__digest摘要函数

    千次阅读 2019-10-30 11:35:51
    digest函数返回指定哈希算法中的摘要值。 参数介绍: 摘要算法:MD2、MD5、SHA-1、SHA-224、SHA-256、SHA-384、SHA-512 String to be hashed:要计算的字符串; Salt to be used for hashing (optional):用于计算...

    __digest
    digest函数返回指定哈希算法中的摘要值。
    在这里插入图片描述
    参数介绍:
    摘要算法:MD2、MD5、SHA-1、SHA-224、SHA-256、SHA-384、SHA-512
    String to be hashed:要计算的字符串;
    Salt to be used for hashing (optional):用于计算散列的盐(可选项);
    Upper case result, defaults to false (optional):结果大写,默认为false(可选),即默认摘要值为小写
    存储结果的变量名(可选)
    举例:
    在这里插入图片描述
    查看结果:
    在这里插入图片描述
    也可以通过shell脚本调用外部算法实现。
    Jmeter接口测试:shell脚本实现sha256算法加密

    展开全文
  • 数字摘要和Hash函数(哈希函数

    千次阅读 2017-06-20 10:51:35
    数字摘要和Hash函数(哈希函数) 1、数字摘要 数字摘要是将任意长度的消息变成固定长度的短消息,它类似于一个自变量是消息的函数,也就是Hash函数。数字摘要就是采用单项Hash函数将需要加密的明文“摘要”成一串...
  • 信息摘要技术的实现

    2018-11-26 17:21:44
    (2)利用MD5实现函数,对特定文件(test-1.txt)进行信息摘要的计算,得到信息摘要M1;尝试改变特定文件中的内容(比如改变其中某个字母),再利用MD5计算一次信息摘要,看同之前得到的信息摘要是否相同;
  • 重构摘要10_简化函数调用

    千次阅读 2014-06-09 09:32:44
    《重构-改善既有代码的设计》Martin Fowler 摘要: 第十章 简化函数调用 Rename Method 函数改名 改一个自表达的名字吧!骚年 Add Parameter 添加参数 某个函数需要从调用端得到更多信息。 为此函数添加一个...
  • 散列函数,又称消息摘要函数、哈希函数、杂凑函数或单向函数。  它的主要作用不是用于加密与解密,而是用于验证信息的完整性。使用散列函数,为信息创建“数字指纹”,用于鉴别信息的身份。消息摘要算法也是数字...
  • 散列函数的返回值称为散列值、散列码,摘要或者简单散列。 也就是说散列函数能将任意长度的输入变换成固定长度的输出,该输出就是散列值。散列值空间通常远小于输入的空间。 散列函数的一些特性: 消息的长度不受...
  • 信息摘要与数字签名

    千次阅读 热门讨论 2015-10-25 15:42:53
    在做软考试题的时候,在信息摘要与数字签名这丢了好几次分,于是自己回顾了一遍视频,从新学习一下信息摘要和数字... 1、信息摘要定义:信息摘要算法实际上是一个单向散列函数。(单向散列函数就是不可逆的过程,比如
  • 信息安全概论:Hash函数概念与性质

    千次阅读 2020-04-02 18:20:39
    Hash函数可以将“任意长度“的输入经过变换以后得到固定长度的输出,也称为消息摘要。 消息摘要能有用于完成消息的认证功能,消息认证是保证信息完整性的重要措施。 Hash函数也成散列函数、哈希函数、杂凑函数等,是...
  • 摘要算法之MD5介绍及OpenSSL中MD5常用函数使用举例!
  • 1、聚合函数 聚合函数常用于GROUP BY子句,用于聚合分组的数据。所有聚合函数均为确定性函数,也就是说只要使用一组特定输入值调用聚合函数,该函数总是返回同类型的值。例如,计算一组整数型数值的总和或者平均...
  • 【数据库摘要】11_Sql_自有函数

    千次阅读 2014-05-26 10:25:07
    SQL 函数 SQL 拥有很多可用于计数和计算的内建函数。 SQL Aggregate 函数 SQL Aggregate 函数计算从列中取得的值,返回一个单一的值。 有用的 Aggregate 函数: AVG() - 返回平均值COUNT() - 返回行数FIRST() -...
  • 信息摘要算法——MessageDigest类

    千次阅读 2016-09-17 17:38:06
    信息摘要是安全的单向哈希函数,它接收任意大小的数据,并输出固定长度的哈希值。 MessageDigest 对象开始被初始化。该对象通过使用 update 方法处理数据。任何时候都可以调用 reset 方法重置摘要。一旦所有需要更新...
  • 摘要:波函数的理解,波函数怎么坍缩的,任何事情都可以叠加吗?测量导致波函数坍缩与信息的作用,测量引起波函数坍缩与意识有关系吗。   近来有许多文章说量子力学与佛教、神学理念相通。基督教、天主教的传教士...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 103,335
精华内容 41,334
关键字:

关于信息摘要函数