信息安全实验:信息摘要函数的设计与验证

一、实验目的
信息摘要函数(Hash函数)的设计与性质验证

二、实验步骤
1.设计符合原理要求的信息摘要函数H(m)。
2.对于如下明文信息m:
Once upon a time, there lived a monkey in the woods. The monkey climbed up the tree and looked down at the river everyday. One day, the monkey saw fishermen throw a net over the river. He watched how the fishermen caught fish. Sometime after, the fishermen left the net and went to have lunch. Then, the monkey climbed down from the tree and went to the riverside. The monkey was planning to throw the net like the fishermen did. The monkey was confident since he was good at imitating. Yet, the net wound around the monkey when he touched it. Tied up in the net, the monkey fell into the water.The monkey regretted his behavior, but it was too late. “I should have learned how to use the net before touching it. After believing my prowess and showing off, I am in a bad fix.” The monkey who did not behave carefully drowned in the water.
调用H(m)算法,产生Hash值。
3. 随机改变m的任意一位字符,产生新的Hash值,如此实验10次,记新的Hash值为 H1,H2,…H10
4. 设计函数计算H0和Hi 的相似度 i=1,2,…10
5. 分析结果,得出结论。

三、实验原理
1.信息摘要函数具有固定的输出数位。
2.信息摘要函数满足不可求逆,不可伪造和在可行时间之内找不到碰撞等特性。

四、实验过程
Md5.cpp:

#include<iostream>
#include<string>
using namespace std;
#define shift(x, n) (((x) << (n)) | ((x) >> (32-(n))))//右移的时候,高位一定要补零,而不是补充符号位
#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)))
#define A 0x67452301
#define B 0xefcdab89
#define C 0x98badcfe
#define D 0x10325476
//strBaye的长度
 int strlength;
//A,B,C,D的临时变量
 int atemp;
 int btemp;
 int ctemp;
 int dtemp;
//常量ti unsigned int(abs(sin(i+1))*(2pow32))
const int k[]={
        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};
//向左位移数
const int s[]={7,12,17,22,7,12,17,22,7,12,17,22,7,
        12,17,22,5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20,
        4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23,6,10,
        15,21,6,10,15,21,6,10,15,21,6,10,15,21};
const char str16[]="0123456789abcdef";
void mainLoop( int M[])
{
     int f,g;
     int a=atemp;
     int b=btemp;
     int c=ctemp;
     int d=dtemp;
    for (int i = 0; i < 64; i++)
    {
        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;
        }
         int tmp=d;
        d=c;
        c=b;
        b=b+shift((a+f+k[i]+M[g]),s[i]);
        a=tmp;
    }
    atemp=a+atemp;
    btemp=b+btemp;
    ctemp=c+ctemp;
    dtemp=d+dtemp;
}
/*
*填充函数
*处理后应满足bits≡448(mod512),字节就是bytes56(mode64)
*填充方式为先加一个1,其它位补零
*最后加上64位的原来长度
*/
 int* add(string str)
{
     int num=((str.length()+8)/64)+1;//512,64个字节为一组
     int *strByte=new  int[num*16];    //64/4=16,所以有16个整数
    strlength=num*16;
    for ( int i = 0; i < num*16; i++)
        strByte[i]=0;
    for ( int i=0; i <str.length(); i++)
    {
        strByte[i>>2]|=(str[i])<<((i%4)*8);//一个整数存储四个字节,i>>2表示i/4 一个unsigned int对应4个字节,保存4个字符信息
    }
    strByte[str.length()>>2]|=0x80<<(((str.length()%4))*8);//尾部添加1 一个unsigned int保存4个字符信息,所以用128左移
    /*
    *添加原长度,长度指位的长度,所以要乘8,然后是小端序,所以放在倒数第二个,这里长度只用了32*/
    strByte[num*16-2]=str.length()*8;
    return strByte;
}
string changeHex(int a)
{
    int b;
    string str1;
    string str="";
    for(int i=0;i<4;i++)
    {
        str1="";
        b=((a>>i*8)%(1<<8))&0xff;   //逆序处理每个字节
        for (int j = 0; j < 2; j++)
        {
            str1.insert(0,1,str16[b%16]);
            b=b/16;
        }
        str+=str1;
    }
    return str;
}
string getMD5(string source)
{
    atemp=A;    //初始化
    btemp=B;
    ctemp=C;
    dtemp=D;
     int *strByte=add(source);
    for( int i=0;i<strlength/16;i++)
    {
         int num[16];
        for( int j=0;j<16;j++)
            num[j]=strByte[i*16+j];
        mainLoop(num);
    }
    return changeHex(atemp).append(changeHex(btemp)).append(changeHex(ctemp)).append(changeHex(dtemp));
}
 int main()
{
    string ss;
    string s=getMD5("Once upon a time, there lived a monkey in the woods. The monkey climbed up the tree and looked down at the river everyday. One day, the monkey saw fishermen throw a net over the river. He watched how the fishermen caught fish. Sometime after, the fishermen left the net and went to have lunch. Then, the monkey climbed down from the tree and went to the riverside. The monkey was planning to throw the net like the fishermen did. The monkey was confident since he was good at imitating. Yet, the net wound around the monkey when he touched it. Tied up in the net, the monkey fell into the water.The monkey regretted his behavior, but it was too late. I should have learned how to use the net before touching it. After believing my prowess and showing off, I am in a bad fix. The monkey who did not behave carefully drowned in the water.");
    cout<<s;
    return 0;
}

相似度计算.c:

#include<stdio.h>
int main()
{
    char a[]={'f','l','a','9','4','c','4','9','6','5','b','e','2','7','1','f','0','a','c','d','8','e','c','e','0','8','5','c','5','f','8','a'};
    char b[32];
    int i,amount=0;
    double c;
    for(i=0;i<32;i++)
    {
        scanf("%c",&b[i]);
    }
    for(i=0;i<32;i++)
    {
        if(a[i]==b[i])
        amount++;
    }
    c=(float)amount/32;
    printf("%lf",c);
    return 0;
}

相似度计算.c:

#include<stdio.h>
int main()
{
    char a[]={'f','l','a','9','4','c','4','9','6','5','b','e','2','7','1','f','0','a','c','d','8','e','c','e','0','8','5','c','5','f','8','a'};
    char b[32];
    int i,amount=0;
    double c;
    for(i=0;i<32;i++)
    {
        scanf("%c",&b[i]);
    }
    for(i=0;i<32;i++)
    {
        if(a[i]==b[i])
        amount++;
    }
    c=(float)amount/32;
    printf("%lf",c);
    return 0;
}

五、实验结果
hash值:
在这里插入图片描述在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
相似度:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值