精华内容
下载资源
问答
  • 现代密码学pdf

    2018-08-07 13:18:08
    现代密码学pdf现代密码学pdf现代密码学pdf现代密码学pdf
  • 关注互联网安全性,这种安全性是由阻止、防止、检测和纠正违反有关信息传输的安全性的措施组成
  • 现代密码学(杨波)

    2018-08-07 10:28:57
    现代密码学讲述了密码学的一些基本知识和概念。----------------------------------------
  • 经典密码学与现代密码学 中文影印 pdf(4-4)
  • Cryptography and Network Security 4th Ed,Stallings,William,Prentice Hall(2005) 习题答案~
  • 现代密码学答案,你需要,PDF版 现代密码学_清华大学_杨波著 习题答案 现代密码学_清华大学_杨波著 习题答案 现代密码学_清华大学_杨波著 习题答案
  • 密码学期末复习笔记,这门课的书是《密码学原理与实践
  • 第一章 | 密码学概论 ...第四章 | 分组密码 第五章 | 序列密码 第六章 | Hash密码 第七章 | 公钥密码体制 第八章 | 数字密码签名 第九章 | 密码协议 第十章 | 密钥管理 ...

    在这里插入图片描述
    第一章 | 密码学概论
    在这里插入图片描述
    在这里插入图片描述
    第二章 | 密码学基础
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    第三章 | 古典密码体制
    在这里插入图片描述
    在这里插入图片描述
    第四章 | 分组密码
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    第五章 | 序列密码
    在这里插入图片描述
    在这里插入图片描述
    第六章 | Hash密码
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    第七章 | 公钥密码体制
    在这里插入图片描述
    在这里插入图片描述
    第八章 | 数字密码签名
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    第九章 | 密码协议
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    第十章 | 密钥管理
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • 这是一本密码学领域的经典教材,也可以作为密码学研究人员和密码爱好者的工具书,参考书。
  • 经典密码学与现代密码学 中文影印下载 pdf(4-1)
  • 密码学原理与实践 国外计算机教材系列 课后答案 解压缩得到pdf 需要自取
  • 古典与现代密码学的常见破解

    千次阅读 2020-07-07 02:26:40
    本文是对之前自学密码学的一个总结,包含了一些总结总结的一些有趣密码的破解方式和自己写的代码。有些是CTF大佬搭建的CTF题目服务器上寻的题,感谢大佬们搭建的平台(题目需 中南大学 内网)。那么开始: 目 录 ...

    本文是对之前自学密码学的一个总结,包含了一些总结总结的一些有趣密码的破解方式和自己写的代码。有些是CTF大佬搭建的CTF题目服务器上寻的题,感谢大佬们搭建的平台(题目需 中南大学 内网)。那么开始:

                         目 录
    
    一、古典密码······ 
        1.移位密码解密·············
        2.仿射密码揭秘·············
    3.列换位密码解密············
     二、现代密码······
        1.维吉尼亚密码解密···········
        2.Many-Time-Pad攻击··········
    三、安全协议······
        1.数字签名···············
    

    实验一 古典密码学

    1、移位密码解密:
    阅读题目代码,可以理解其加密具体思路,题目部分关键代码:

    密钥为随机生成:
    int offset = rand() % 51 % 26;   //随机生成
    加密方式:
    for(int i = 0; i < 511; ++i){
    		if(isupper(origin[i])){
    			casear[i] = (origin[i] - 'A' + offset) % 26 + 'A';
    		}else if(islower(origin[i])){
    			casear[i] = (origin[i] - 'a' + offset) % 26 + 'a';
    		}else{casear[i] = origin[i];}  //大小写相同密钥,符号不加密
    
    综上所述,由于密钥空间只有26,暴力破解最简单,源代码如下:
    #include<iostream>
    #include<stdio.h>
    using namespace std;
    #define MAX 1000
    int main()
    {
       char a[MAX];
       char m[MAX];
       gets(a);
       for(int i=1;i<=26;i++){
        printf("ÒÆλ%d:",i);
        int j=0;
        for(;a[j]!='\0';j++)
        {
            if(islower(a[j]))m[j]=(a[j]-'a'+i)%26+'a';
            else if(isupper(a[j]))m[j]=(a[j]-'A'+i)%26+'A';
            else m[j]=a[j];
            printf("%c",m[j]);
        }
        printf("\n");
        printf("\n");
       }
       return 0;
    }
    

    代码运行如下,当移位25时接触明文:
    在这里插入图片描述
    服务器提交:
    在这里插入图片描述

    2、仿射密码解密:
    经过分析题目,可以看出就是传统仿射加密方式,不同的是符号“ ”、“,”、“.”也参与加密。顺序:“abcdefghijklmnopqrstuvwxyz .,”
    在这里插入图片描述
    解法一:可以计算密钥的传统解法

    源代码:

    #include<iostream>
    #include<stdio.h>
    using namespace std;
    #define  MAX 1000
    int ny(int a,int b)
    {
        int i=1;
        while(a*i%b!=1)i++;
        return i;
    }
    int main()
    {
       char a[MAX];
       char m[MAX];
       int b[29];int e[1000];
       for(int q=0;q<29;q++)b[q]=0;
       int i=0,max=0,min=0,va=0,vi=0;int x1,y1,x2,y2;
       char txt[]="abcdefghijklmnopqrstuvwxyz .,";
       printf("输入密文:");
       fgets(a,1000,stdin);
       for(i=0;a[i]!='\n';i++)
       {
           if(islower(a[i])){ b[a[i]-'a']++; e[i]=a[i]-'a';}
           else if(a[i]==' '){b[26]++;e[i]=26; } else if(a[i]=='.'){b[27]++;e[i]=27; } else if(a[i]==','){b[28]++;e[i]=28; }
       }
       for(i=0;i<29;i++){ if(max<b[i]){ max=b[i];va=i;} }
       for(i=0;i<29;i++){ if(min<b[i]&&b[i]<max){ min=b[i];vi=i;} }
       x1=ny(22,29)*(va-vi)%29; if(x1<0)x1+=29;
       y1=(va-x1*27)%29;        if(y1<0)y1+=29;
       x2=ny(x1,29);
       y2=(-x2*y1)%29;          if(y2<0)y2+=29;
       printf("\n加密密钥:(%d,%d)\n解密密钥:(%d,%d)\n\n",x1,y1,x2,y2);
       printf("明文:");
       for(int i=0;a[i]!='\n';i++)
       {
           if(islower(a[i])||a[i]==' '||a[i]==','||a[i]=='.')m[i]=txt[(e[i]*x2+y2-1)%29];
           else m[i]=a[i];
           printf("%c",m[i]);
       }
       return 0;
    }
    

    结果如下:
    在这里插入图片描述
    解法二:暴力破解+筛选法

    #include<iostream>
    #include<stdio.h>
    using namespace std;
    #define MAX 1000
    int main()
    {
        int a=2,b=1;
        char txt[]="abcdefghijklmnopqrstuvwxyz .,";
        char s[MAX];
        printf("输入明文:");
        fgets(s,513,stdin);
        printf("\n筛选的可能密文:\n________________________________________\n");
        for(a=2;a<30;a++)
        {
            for(b=1;b<30;b++)
            {
                int k=0;int q=0;
                int n[29];for(q=0;q<29;q++)n[q]=0;
                char m[511];
                for(k=0;k<511;k++)
                {
                   if(islower(s[k]))m[k]=txt[(a*(s[k]-'a')+b-1)%29];
                   else if(s[k]==' ')m[k]=txt[(a*26+b-1)%29];
                   else if(s[k]=='.')m[k]=txt[(a*27+b-1)%29];
                   else if(s[k]==',')m[k]=txt[(a*28+b-1)%29];
                   else m[k]=s[k];
                   if(islower(m[k]))n[m[k]-'a']++;
                   else if(m[k]==' ')n[26]++;
                   else if(m[k]=='.')n[27]++;
                   else if(m[k]==',')n[28]++;
                }
                double g,h;
                g=(double)n[26]/511.0;
                h=(double)n[4]/511.0;
                if(g>0.1&&h>0.1){int i=0;for(i=0;i<511;i++)printf("%c",m[i]);printf("\n________________________________\n");}
            }
        }
        return 0;
    }
    

    该代码会对暴力破解结果进行筛选,显示频率满足要求的。
    提交结果:
    在这里插入图片描述

    3、列位移密码解密:
    分析加密代码,加密原理选取一个行数(1-12),将明文进行分行,纵向读出密文。
    解密过程即为逆过程

    #include<iostream>
    #include<stdio.h>
    using namespace std;
    int main()
    {
        char m[1000];
         fgets(m,1000,stdin);
         int a=0;
         for(int i=0;m[i]!='\n';i++){a++;}
        int r=2,i=0,j;
        for(r=2;r<13;r++)
        {
            printf("\n__________________________________\n每行字符数(r值):%d\n",r);
            if(a%r==0)
            {
                int h=a/r;
                for(i=0;i<h;i++)
                {
                    for(j=i;j<a;j+=h)
                    {
                        printf("%c",m[j]);
                    }
                }
            }
            else
            {
                int h=a/r+1;
                int c=a%r;
                for(i=0;i<h;i++)
                {
                    j=i;
                    if(i!=h-1)
                    {
                      int d=0;
                      for(d=0;d<c;d++)
                        {
                            printf("%c",m[j]);
                            j+=h;
                        }
                        for(d=c;d<r;d++)
                        {
                            printf("%c",m[j]);
                            j=j+h-1;
                        }
                    }
                    else
                    {
                       int n=0;
                       for(n=0;n<c;n++)
                       {
                           printf("%c",m[j]);
                           j+=h;
                       }
                    }
                }
            }
        }
    }
    

    运行结果:
    在这里插入图片描述
    提交结果:
    在这里插入图片描述
    4、维基利亚密码解密:
    维基利亚常见破解方式为重合指数法,源代码如下:

    #include<iostream>                  //字符不占位,单独提出出来加密
    #include<stdio.h>
    #include<conio.h>
    using namespace std;
    int max(double t[],int n)
    {
        int max=0;int i=0;double j=0;
        for(i=0;i<n;i++)
        {
            if(t[i]>j){j=t[i];max=i;}
        }
        return max;
    }
    
    double max_(double t[],int n)     //该函数多余
    {
        double max=0;int i=0;
        for(i=0;i<n;i++)
        {
            if(t[i]>max){max=t[i];}
        }
        return max;
    }
    
    int main()
    {
        char m[1200];char a[1100];
        printf("输入密文:");
        fgets(m,1200,stdin);
        int t=0;int j=0;
        for(t=0;m[t]!='\n';t++)
        {
            if(isupper(m[t])||islower(m[t])){a[j]=m[t];j++;}
        }
        char txt1[]="abcdefghijklmnopqrstuvwxyz";
        char txt2[]="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        double P[26]={0.082, 0.015, 0.028, 0.043, 0.127, 0.022, 0.020,0.061, 0.070,
                      0.002, 0.008, 0.040, 0.024, 0.067,0.075, 0.019, 0.001, 0.060,
                      0.063, 0.091,0.028, 0.010, 0.023, 0.001, 0.020, 0.001};
        int i=2;
        for(i=2;i<14;i++)
        {
            double ic=0,IC0=0,IC=0;
            if(j%i==0)
            {
                int h=j/i;int o=0;
                for(o=0;o<i;o++)
                {
                    int n=0;int zm[26]={0};int mix=0;
                    for(n=0;n<h;n++)
                    {
                        if(isupper(a[o+n*i]))zm[a[o+n*i]-'A']++;
                        else zm[a[o+n*i]-'a']++;
                    }
                    int l=0;
                    for(l=0;l<26;l++)
                    {
                        mix+=zm[l]*(zm[l]-1);
                    }
                    ic=(double)mix/(double)(h*(h-1));
                    IC0+=ic;
                }
            }
            else
            {
                int h1=j/i+1;int h2=h1-1;int len1=j%i;
                int o=0;
                for(o=0;o<len1;o++)
                {
                    int n=0;int zm[26]={0};int mix=0;
                    for(n=0;n<h1;n++)
                    {
                        if(isupper(a[o+n*i]))zm[a[o+n*i]-'A']++;
                        else zm[a[o+n*i]-'a']++;
                    }
                    int l=0;
                    for(l=0;l<26;l++)
                    {
                        mix+=zm[l]*(zm[l]-1);
                    }
                    ic=(double)mix/(double)(h1*(h1-1));
                    IC0+=ic;
                }
                int q=len1;
                for(q=len1;q<i;q++)
                {
                    int n=0;int zm[26]={0};int mix=0;
                    for(n=0;n<h2;n++)
                    {
                        if(isupper(a[q+n*i]))zm[a[q+n*i]-'A']++;
                        else zm[a[q+n*i]-'a']++;
                    }
                    int l=0;
                    for(l=0;l<26;l++)
                    {
                        mix+=zm[l]*(zm[l]-1);
                    }
                    ic=(double)mix/(double)(h2*(h2-1));
                    IC0+=ic;
                }
            }
            IC=IC0/i;
            printf("\n假设密钥长度为%d,重合指数IC——————————————————> %lf\n",i,IC);
        }
        printf("\n输入任意键继续。。。\n");
        char ch;
        ch=getch();
        int mm;
        printf("\nIC最接近0.067即为密钥长度,输入密钥长度:");
        scanf("%d",&mm);
        int dy[mm];char key[mm];
        if(j%mm==0)
        {
            int o=0;int h=j/mm;
            for(o=0;o<mm;o++)
                {
                    int zm[26]={0};int n=0;
                    for(n=0;n<h;n++)
                    {
                        if(isupper(a[o+n*mm]))zm[a[o+n*mm]-'A']++;
                        else zm[a[o+n*mm]-'a']++;
                    }
                    int KEY=0; int s=0;
                    double ZM[26]={0};double Ti[26]={0};
                    for(KEY=0;KEY<26;KEY++)
                    {
                        for(s=0;s<26;s++)
                       {
                         ZM[KEY]+=(double)(zm[(s+KEY)%26]*P[s])/(double)h;
                       }
                    }
                    key[o]=txt1[max(ZM,26)];
                }
        }
        else
        {
            int h1=j/mm+1;int h2=h1-1;int len1=j%mm;
                int o=0;
                for(o=0;o<len1;o++)
                {
                    int n=0;int zm[26]={0};
                    for(n=0;n<h1;n++)
                    {
                        if(isupper(a[o+n*mm]))zm[a[o+n*mm]-'A']++;
                        else zm[a[o+n*mm]-'a']++;
                    }
                    int KEY=0; int s=0;
                    double ZM[26]={0};
                    for(KEY=0;KEY<26;KEY++)
                    {
                        for(s=0;s<26;s++)
                       {
                         ZM[KEY]+=(double)(zm[(s+KEY)%26]*P[s])/(double)h1;
                       }
                    }
                    key[o]=txt1[max(ZM,26)];
                }
                int q=len1;
                for(q=len1;q<mm;q++)
                {
                    int n=0;int zm[26]={0};
                    for(n=0;n<h2;n++)
                    {
                        if(isupper(a[q+n*mm]))zm[a[q+n*mm]-'A']++;
                        else zm[a[q+n*mm]-'a']++;
                    }
                    int KEY=0; int s=0;
                    double ZM[26]={0};
                    for(KEY=0;KEY<26;KEY++)
                    {
                        for(s=0;s<26;s++)
                       {
                         ZM[KEY]+=(double)(zm[(s+KEY)%26]*P[s])/(double)h2;
                       }
                    }
                    key[q]=txt1[max(ZM,26)];
                }
        }
        printf("\n加密密钥为:");
        for(t=0;t<mm;t++)printf("%c",key[t]);  printf("\n\n");
        char mw[1200];
       for(t=0;m[t]!='\n';t++)
       {
           if(isupper(m[t]))
           {
               if((m[t]-key[(t)%mm]+'a'-'A')>0)mw[t]=txt2[(m[t]-key[(t)%mm]+'a'-'A')%26];
               else mw[t]=txt2[(m[t]-key[(t)%mm]+'a'-'A'+26)%26];
           }
           else if(islower(m[t]))
           {
               if((m[t]-key[(t)%mm])>0)mw[t]=txt1[(m[t]-key[(t)%mm])%26];
               else mw[t]=txt1[(m[t]-key[(t)%mm]+26)%26];
           }
           else mw[t]=m[t];
           printf("%c",mw[t]);
       }
       printf("\n");
       return 0;
    }
    

    运行结果:
    在这里插入图片描述
    在这里插入图片描述
    提交结果:
    在这里插入图片描述
    #该题还可以用Python来写,要简单一点,Python版关键代码如下(思想一样,不做过多详解):
    计算重合指数:

     for klen in range(0,15):
            r = 0
            for i in range(0,klen):
                s = sec_msg[i::klen]
                len_str = len(s)
                sum_a = 0
                for y in range(0,26):
                    x = s.count(chr(97+y), 0, len_str)
    		x += s.count(chr(65+y), 0, len_str)
                    sum_a += x*(x-1)
                klv = float(sum_a)/(len_str*(len_str-1))#重合指数
                r += klv
            if klen:
                r = r/klen
          进行解密:
                for i in range(tlen):
            j = i % keylen
            k = ord(key[j])-97
    	k = 26-k
            m = ord(text[i])
    	if m>=97 and m<=122:
    		c = m-97
    		plaintext += chr(97+(c+k)%26)
    	elif m>=65 and m<=90:
    		c = m-65
    		plaintext += chr(65+(c+k)%26)
    	else:
    		plaintext += text[i]
    

    课后题:
    1、密钥空间:25
    2、密钥空间:811
    3、密钥空间:n
    4、(1)重合指数攻击法:
    重合指数,即相当于求在某个密文中随机无放回地抽取其中的两位,这两位的字母相同的概率 其中c是归一化系数,用于对不同字母表进行归一化处理(英语为26),n 下标a是字母“a”出现在文本中的次数,N是文本的长度。
    维吉尼亚密码可以被分解为若干组平移密码来破译,而一个明文足够长的平移密码的重合指数接近0.0687。
    破解时将密码堆叠成若干列,如果密钥大小恰好与假定的列数相同,那么单个列中的所有字母都将使用相同的密钥字母加密,实际上是一个简单的恺撒密码,应用于随机选择的英文明文字符。与它们相应的密文字母组,尽管每个字母已被置换(移位对应于密钥字母的量,参考本文第四节),也应具有类似于英语的频率分布的粗糙度。所以,计算每一行重合指数。密钥空间内去最接近0.0687的,即为密钥长度。
    然后就可以将维基利亚密码转换成一列一列的仿射密码,依次求解即可。
    (2)变简单了。暴力破解,字母、双标和三标频率计数:频率分析是一种计算不同密文字符发生次数的方法,希望这些信息能够被用来破解密码。

    实验二 现代密码学

    1、因数分解攻击:
    首先熟练掌握RSA加密解密方式。

    然后观察公钥形势,发现n并不大。于是对其因式分解。
    运用phollard算法,关键代码如下:
    (首先定义C++大数运算类(big类),各种常见的运算用大数重载重新定义一次)

    big gcd(ll a, ll b)
    {
    	if(b == 0)	return a;
    	else	return gcd(b, a%b);
    }
     
    big Pollard_Rho(ll n, int c)
    {
    	ll i = 1, k = 2, x = rand()%(n-1)+1, y = x;
    	while(1){
    		i++;
    		x = (multi(x, x, n)+c)%n;
    		ll p = gcd((y-x+n)%n, n);
    		if(p != 1 && p != n)	return p;
    		if(y == x)	return n;
    		if(i == k){
    			y = x;
    			k <<= 1;
    		}	
    	}
    }
    

    然后即可算出p和q,进而得出d,然后用Python进行次方运算,即可得出结果。
    12646322214713542457分解得出因子分别为2972442247和4254522431。算出d解出明文。
    提交算出结果:

    2、选择密文攻击:
    破解思路如下:
    设攻击者为A,密文接受者为T,公钥对为(e, n),私钥为d,T收到的密文为c,c对应的明文为m。
    现在A想知道m = c^d mod n,但是他不想分解n。于是T找了一个随机数r,r < n。他进行如下计算:
    x = r^e mod n (对r用T的公钥加密,得到临时密文x)
    y = (x * c) mod n (将临时密文x与密文c相乘)
    t = r^(-1) mod n
    A利用了RSA加密和解密过程的特点,即:
    如果x = r^e mod n,那么 r = x^d mod n
    现在A要做的是使T用d对t签名:u = t^d mod n。A需要获得u,然后计算
    m = (t * u) mod n
    计算结果是这样推导的:
    t *u mod n = [r^(-1) * y^d] mod n
    = [r^(-1) * x^d * c^d] mod n
    = c^d mod n
    = m

    由以下代码得到欧几里得算法形式,代码实行如下:

    #include<stdio.h>
     #define ll long long
     void gcd(ll a,ll b,ll& d,ll& x,ll& y){
          if(!b){d=a;x=1;y=0;}
          else {gcd(b,a%b,d,y,x);y-=x*(a/b);}
     }
    int main(){
         ll a,b,d,x,y;
         while(scanf("%lld%lld",&a,&b)!=EOF){
             gcd(a,b,d,x,y);
             printf("%lld*%lld+%lld*%lld=%lld\n",a,x,b,y,d);
         }
         return 0;
     }
    由下面代码计算乘法逆元:
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    void exgcd(ll a,ll b,ll& d,ll& x,ll& y)
    {if(!b) { d = a; x = 1; y = 0; }
        else{ exgcd(b, a%b, d, y, x); y -= x*(a/b); }}
    ll inv(ll a, ll p)
    {
        ll d, x, y;
        exgcd(a, p, d, x, y);
        return d == 1 ? (x+p)%p : -1;
    }
    int main()
    {
        ll a,p;
        while(1)
        {
            scanf("%lld %lld",&a,&p);
            printf("%lld\n",inv(a,p));
        }
    }
    

    算出数据用python进行基础大数运算,即可出结果。
    结合其中基本的pow(,,)函数和简单计算处理即可算出结果。
    提交结果:

    3、共用模数攻击:

    Python利用欧几里得求大数逆元源代码:

    def gcd(a, b):
        while a != 0:
            a, b = b % a, a
        return b
    

    定义一个函数,参数分别为a,n,返回值为b

    def main(a, m):  # 这个扩展欧几里得算法求模逆
    if gcd(a, m) != 1:
            return None
        u1, u2, u3 = 1, 0, a
        v1, v2, v3 = 0, 1, m
        while v3 != 0:
            q = u3 // v3
            v1, v2, v3, u1, u2, u3 = (u1 - q * v1), (u2 - q * v2), (u3 - q * v3), v1, v2, v3
        return u1 % m
    if __name__ == '__main__':
       c=main(65537,8120390679110304563)
       print(c)
    

    求出逆元再次结合Python求大数次方运算,得出:
    提交结果:
    4、广播攻击:
    原理如下:
    化简结合中国剩余定理CRT:

    根据原理经过Python大数运算,可得结果,提交结果:

    课后题:
    1、质因数分解记录:经过Google、Google学术和密码学书籍查找,都是2014年以前的数据,并未找到目前精确的具体值·····
    2、RSA加密常用的填充方式有下面3种:
    (1)RSA_PKCS1_PADDING 填充模式,最常用的模式
    要求:
    输入:必须 比 RSA 钥模长(modulus) 短至少11个字节, 也就是 RSA_size(rsa) – 11。如果输入的明文过长,必须切割, 然后填充
    输出:和modulus一样长
    根据这个要求,对于512bit的密钥,block length = 512/8 – 11 = 53 字节
    (2)RSA_PKCS1_OAEP_PADDING
    输入:RSA_size(rsa) – 41
    输出:和modulus一样长
    (3)for RSA_NO_PADDING  不填充
    输入:可以和RSA钥模长一样长,如果输入的明文过长,必须切割, 然后填充
    输出:和modulus一样长
    3、
    (1)选择密文攻击:
    设攻击者为A,密文接受者为T,公钥对为(e, n),私钥为d,T收到的密文为c,c对应的明文为m。
    现在A想知道m = c^d mod n,但是他不想分解n。于是T找了一个随机数r,r < n。他进行如下计算:
    x = r^e mod n (对r用T的公钥加密,得到临时密文x)
    y = (x * c) mod n (将临时密文x与密文c相乘)
    t = r^(-1) mod n
    A利用了RSA加密和解密过程的特点,即:
    如果x = r^e mod n,那么 r = x^d mod n
    现在A要做的是使T用d对t签名:u = t^d mod n。A需要获得u,然后计算
    m = (t * u) mod n
    计算结果是这样推导的:
    t *u mod n = [r^(-1) * y^d] mod n
    = [r^(-1) * x^d * c^d] mod n
    = c^d mod n
    = m
    (2)公用模数攻击:

    4、中国剩余定理密码学中应用:(1)基于CRT的密钥分发协议:通过中国剩余定理得到一个数并广播。(2)构建Asmuth-Bloom门限方案 (3)RSA算法选用较小素数公钥:解密时用CRT简化运算,提高效率。

    实验三 安全协议
    构建数字签名协议:MD5&RSA数字签名协议
    编程语言:C++、Python
    1.可以使用私钥进行签名,公钥进行验证。
    2.支持对文件进行签名、校验。
    3.拥有密钥管理功能

    具体实现(关键代码):
    (1)MD5哈希运算实现头文件(数字签名具体实现算法):

    #include "MD5.h"
    #include<string.h>
    #include<string>
    /* F, G, H and I are basic MD5 functions.
    */
    inline UNIT F(UNIT x, UNIT y,UNIT z) {return (UNIT)(((x) & (y)) | ((~x) & (z))); }
    inline UNIT G(UNIT x, UNIT y,UNIT z) {return (UNIT)(((x) & (z)) | ((y) & (~z))); }
    inline UNIT H(UNIT x, UNIT y, UNIT z) {return (UNIT )((x) ^ (y) ^ (z)) ;}
    inline UNIT I(UNIT x, UNIT y, UNIT z) {return (UNIT)((y) ^ ((x) | (~z))) ;}
    
    /* ROTATE_LEFT rotates x left n bits.
    */
    inline UNIT ROTATE_LEFT(UNIT x,UNIT n) {return UNIT(((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.
    */
    void FF(UNIT &a, UNIT &b, UNIT &c, UNIT &d, UNIT x, UNIT s, UNIT ac){
    a += F ((b), (c), (d)) + (x) + ac;
    a = ROTATE_LEFT ((a), (s));
    a += b;
    }
    void GG(UNIT &a,UNIT &b, UNIT &c,UNIT &d, UNIT x, UNIT s,UNIT ac) {
    (a) += G ((b), (c), (d)) + (x) + ac;
    (a) = ROTATE_LEFT ((a), (s));
    (a) += (b);
    }
    void HH(UNIT &a,UNIT &b, UNIT &c,UNIT &d, UNIT x, UNIT s,UNIT ac) {
    (a) += H ((b), (c), (d)) + (x) + ac;
    (a) = ROTATE_LEFT ((a), (s));
    (a) += (b);
    }
    void II(UNIT &a,UNIT &b, UNIT &c,UNIT &d, UNIT x, UNIT s,UNIT ac) {
    (a) += I ((b), (c), (d)) + (x) + ac;
    (a) = ROTATE_LEFT ((a), (s));
    (a) += (b);
    }
    const int s[16]={
    7,12,17,22,
    5,9,14,20,
    4,11,16,23,
    6,10,15,21
    };
    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'};
    
    MD5::MD5()
    {
    reset();
    }
    MD5::MD5(const string &str){
    reset();
    update(str);
    }
    MD5::MD5(const void* input,size_t length){
    reset();
    update(input,length);
    }
    MD5::MD5(ifstream &ifs){
    reset();
    update(ifs);
    }
    void MD5::reset(){
    _state[0] = 0x67452301;
    _state[1] = 0xefcdab89;
    _state[2] = 0x98badcfe;
    _state[3] = 0x10325476;
    
    _finished = false;
    _count[0]=_count[1]=0;
    }
    
    const byte* MD5::digest(){
    if(!_finished){
    _finished = true;
    final();
    }
    return _digest;
    }
    void MD5::final(){
    byte bits[8];
    UNIT oldState[4];
    UNIT oldCount[2];
    UNIT index,padLen;
    
    memcpy(oldState,_state,16);
    memcpy(oldCount,_count,8);
    
    encode(_count,bits,8);
    
    index = (UNIT)((_count[0]>>3)&(0x3f));
    padLen = (index < 56)?(56-index):(120-index);
    
    update(PADDING,padLen);
    update(bits,8);
    encode(_state,_digest,16);
    
    
    }
    
    void MD5::update(const void *input,size_t length){
    update((const byte*)input,length);
    }
    void MD5::update(const string &str){
    update((const byte*)str.c_str(),str.length());
    }
    void MD5::update(ifstream &ifs){
    if(!ifs){
    return;
    }
    streamsize length;
    char buffer[BUFFER_SIZE];
    while(!ifs.eof()){
    ifs.read(buffer,BUFFER_SIZE);
    length = ifs.gcount();
    if(length >0){
    update(buffer,length);
    }
    }
    ifs.close();
    }
    void MD5::update(const byte* input,size_t length){
    UNIT index,partLen,i;
    _finished = false;
    //Compute number of bytes mod 64
    index = (UNIT)((_count[0]>>3)&0x3f);
    
    if((_count[0] += ((UNIT)length<<3))<((UNIT)length<<3)){
    _count[1]++;
    }
    _count[1] += ((UNIT)length>>29);
    
    partLen = 64 - index;
    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;
    memcpy(&_buffer[index],&input[i],length-i);
    }
    
    void MD5::transform(const byte block[64]){
    UNIT a = _state[0], b = _state[1],c = _state[2], d = _state[3],x[16];
    decode(block,x,64);
    int i=0;
    
    FF (a, b, c, d, x[ 0], s[i++], 0xd76aa478); /* 1 */
    FF (d, a, b, c, x[ 1], s[i++], 0xe8c7b756); /* 2 */
    FF (c, d, a, b, x[ 2], s[i++], 0x242070db); /* 3 */
    FF (b, c, d, a, x[ 3], s[i++], 0xc1bdceee); /* 4 */
    i-=4;
    FF (a, b, c, d, x[ 4], s[i++], 0xf57c0faf); /* 5 */
    FF (d, a, b, c, x[ 5], s[i++], 0x4787c62a); /* 6 */
    FF (c, d, a, b, x[ 6], s[i++], 0xa8304613); /* 7 */
    FF (b, c, d, a, x[ 7], s[i++], 0xfd469501); /* 8 */
    i-=4;
    FF (a, b, c, d, x[ 8], s[i++], 0x698098d8); /* 9 */
    FF (d, a, b, c, x[ 9], s[i++], 0x8b44f7af); /* 10 */
    FF (c, d, a, b, x[10], s[i++], 0xffff5bb1); /* 11 */
    FF (b, c, d, a, x[11], s[i++], 0x895cd7be); /* 12 */
    i-=4;
    FF (a, b, c, d, x[12], s[i++], 0x6b901122); /* 13 */
    FF (d, a, b, c, x[13], s[i++], 0xfd987193); /* 14 */
    FF (c, d, a, b, x[14], s[i++], 0xa679438e); /* 15 */
    FF (b, c, d, a, x[15], s[i++], 0x49b40821); /* 16 */
    
    
    /* Round 2 */
    GG (a, b, c, d, x[ 1], s[i++], 0xf61e2562); /* 17 */
    GG (d, a, b, c, x[ 6], s[i++], 0xc040b340); /* 18 */
    GG (c, d, a, b, x[11], s[i++], 0x265e5a51); /* 19 */
    GG (b, c, d, a, x[ 0], s[i++], 0xe9b6c7aa); /* 20 */
    i-=4;
    GG (a, b, c, d, x[ 5], s[i++], 0xd62f105d); /* 21 */
    GG (d, a, b, c, x[10], s[i++], 0x2441453); /* 22 */
    GG (c, d, a, b, x[15], s[i++], 0xd8a1e681); /* 23 */
    GG (b, c, d, a, x[ 4], s[i++], 0xe7d3fbc8); /* 24 */
    i-=4;
    GG (a, b, c, d, x[ 9], s[i++], 0x21e1cde6); /* 25 */
    GG (d, a, b, c, x[14], s[i++], 0xc33707d6); /* 26 */
    GG (c, d, a, b, x[ 3], s[i++], 0xf4d50d87); /* 27 */
    GG (b, c, d, a, x[ 8], s[i++], 0x455a14ed); /* 28 */
    i-=4;
    GG (a, b, c, d, x[13], s[i++], 0xa9e3e905); /* 29 */
    GG (d, a, b, c, x[ 2], s[i++], 0xfcefa3f8); /* 30 */
    GG (c, d, a, b, x[ 7], s[i++], 0x676f02d9); /* 31 */
    GG (b, c, d, a, x[12], s[i++], 0x8d2a4c8a); /* 32 */
    
    /* Round 3 */
    HH (a, b, c, d, x[ 5], s[i++], 0xfffa3942); /* 33 */
    HH (d, a, b, c, x[ 8], s[i++], 0x8771f681); /* 34 */
    HH (c, d, a, b, x[11], s[i++], 0x6d9d6122); /* 35 */
    HH (b, c, d, a, x[14], s[i++], 0xfde5380c); /* 36 */
    i-=4;
    HH (a, b, c, d, x[ 1], s[i++], 0xa4beea44); /* 37 */
    HH (d, a, b, c, x[ 4], s[i++], 0x4bdecfa9); /* 38 */
    HH (c, d, a, b, x[ 7], s[i++], 0xf6bb4b60); /* 39 */
    HH (b, c, d, a, x[10], s[i++], 0xbebfbc70); /* 40 */
    i-=4;
    HH (a, b, c, d, x[13], s[i++], 0x289b7ec6); /* 41 */
    HH (d, a, b, c, x[ 0], s[i++], 0xeaa127fa); /* 42 */
    HH (c, d, a, b, x[ 3], s[i++], 0xd4ef3085); /* 43 */
    HH (b, c, d, a, x[ 6], s[i++], 0x4881d05); /* 44 */
    i-=4;
    HH (a, b, c, d, x[ 9], s[i++], 0xd9d4d039); /* 45 */
    HH (d, a, b, c, x[12], s[i++], 0xe6db99e5); /* 46 */
    HH (c, d, a, b, x[15], s[i++], 0x1fa27cf8); /* 47 */
    HH (b, c, d, a, x[ 2], s[i++], 0xc4ac5665); /* 48 */
    
    /* Round 4 */
    II (a, b, c, d, x[ 0], s[i++], 0xf4292244); /* 49 */
    II (d, a, b, c, x[ 7], s[i++], 0x432aff97); /* 50 */
    II (c, d, a, b, x[14], s[i++], 0xab9423a7); /* 51 */
    II (b, c, d, a, x[ 5], s[i++], 0xfc93a039); /* 52 */
    i-=4;
    II (a, b, c, d, x[12], s[i++], 0x655b59c3); /* 53 */
    II (d, a, b, c, x[ 3], s[i++], 0x8f0ccc92); /* 54 */
    II (c, d, a, b, x[10], s[i++], 0xffeff47d); /* 55 */
    II (b, c, d, a, x[ 1], s[i++], 0x85845dd1); /* 56 */
    i-=4;
    II (a, b, c, d, x[ 8], s[i++], 0x6fa87e4f); /* 57 */
    II (d, a, b, c, x[15], s[i++], 0xfe2ce6e0); /* 58 */
    II (c, d, a, b, x[ 6], s[i++], 0xa3014314); /* 59 */
    II (b, c, d, a, x[13], s[i++], 0x4e0811a1); /* 60 */
    i-=4;
    II (a, b, c, d, x[ 4], s[i++], 0xf7537e82); /* 61 */
    II (d, a, b, c, x[11], s[i++], 0xbd3af235); /* 62 */
    II (c, d, a, b, x[ 2], s[i++], 0x2ad7d2bb); /* 63 */
    II (b, c, d, a, x[ 9], s[i++], 0xeb86d391); /* 64 */
    
    _state[0] += a;
    _state[1] += b;
    _state[2] += c;
    _state[3] += d;
    }
    void MD5::encode(const UNIT *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);
    }
    
    }
    void MD5::decode(const byte *input,UNIT *output,size_t length){
    for(size_t i=0,j=0;j<length;i++,j+=4){
    output[i] = ((UNIT)(input[j])|((UNIT)(input[j+1])<<8)
    |((UNIT)(input[j+2])<<16)|((UNIT)(input[j+3])<<24));
    }
    }
    
    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 MD5::toString(){
    return bytesToHexString(digest(),16);
    }
    MD5::~MD5(void)
    {
    }
    
    大数运算定义的头文件(部分代码):
    class integer                         
    {
        friend istream& operator>>(istream& is,integer&);
        friend ostream& operator<<(ostream& os,const integer&);//
        friend bool operator>(const integer &,const integer&);//
        friend bool operator<(const integer &,const integer&);//
        friend bool operator>=(const integer &,const integer&);//
        friend bool operator<=(const integer &,const integer&);//
        friend bool operator==(const integer &,const integer&);//
        friend bool operator!=(const integer &,const integer&);//
        friend integer operator+(const integer&,const integer&);//
        friend integer operator-(const integer&,const integer&);//
        friend integer operator*(const integer&,const integer&);//
        friend integer operator/(const integer&,const integer&);//
        friend integer operator%(const integer&,const integer&);//
        friend integer abs(const integer&);//
        friend integer operator-(const integer& num);//
    public:
        integer& operator=(const integer &);//
        integer& operator++();
        integer operator++(int);
        integer& operator--();
        integer operator--(int);
        integer& operator+=(const integer&);
        integer& operator-=(const integer&);
        integer& operator*=(const integer&);
        integer& operator/=(const integer&);
        integer& operator%=(const integer&);
        integer(const char* s="0");//
        integer(const long long int& num);//
        integer(const integer& num);//
    virtual ~integer();//
    private:
        struct _int
        {
    public:
            _int(const char*str="0");
            _int(const long long&);
            _int(const _int&);
            void show()const;
            ~_int();
            _int(size_t,short);
            static _int add(const _int&,const _int&);
            static _int sub(const _int&,const _int&);
            static _int mul(const _int&,const _int&);
            static _int div(const _int&,const _int&);
            static _int mod(const _int&,const _int&);
            static void intcpy(_int&,const _int&);
            static bool big(const _int&,const _int&);
            static bool low(const _int&,const _int&);
            static bool equ(const _int&,const _int&);
            short *p;
            size_t len;
        }*p;
        bool sign;
    };
    
    (3)RSA加密实现:
      1.随机私钥的产生:
       integer mi=f[190000+rand()%100000];integer ni=f[190000+rand()%100000];
        while((ni-1)*(mi-1)%3==0)
            {mi=f[190000+rand()%100000];
             ni=f[190000+rand()%100000];}
        cout<<endl<<endl<<"随机私钥d:"<<inv(3,(mi-1)*(ni-1))<<"  "<<"公钥为("<<"e=3,"<<"n="<<(mi*ni)<<")"<<endl<<endl;
    2.加密部分:
       for(;;)
    {
    string str;string str1;
    cout<<endl<<"Please input a string:"<<endl;
    cin>>str;
    cout<<"Source Code:"<<str<<endl<<endl<<"MD5:"<<MD5(str).toString()<<endl<<endl;
    str1=MD5(str).toString();
    change(str1);
    siyao();
    cout<<endl<<endl<<"--------------------------------------"<<endl;
    cout<<"if continue?(y/n)";
    char aa;
    cin>>aa;
    if(aa=='n')break;
    else continue;
    }
    system("pause");
    
    cout<<endl<<"text.txt MD5:";
    MD5 tt("C:/Users/len/Desktop/MD5&RSA数字签名/text.txt");
    cout << tt.toString() << endl << endl;
    change(tt.toString());
    siyao();
    rsa();
    3.文件加密:
    string FileDigest(const string &file) {
    
    ifstream in(file.c_str(), ios::binary);
    if (!in)
    return "";
    
    MD5 md5;
    std::streamsize length;
    char buffer[1024];
    while (!in.eof()) {
    in.read(buffer, 1024);
    length = in.gcount();
    if (length > 0)
    md5.update(buffer, length);
    }
    in.close();
    return md5.toString();
    }
    
    (4)公钥发送给用户:
        ofstream myfile("C:/Users/len/Desktop/MD5&RSA数字签名/key.txt",ios::out);
        if(!myfile)
        {
           cout<<"error !";
        }
         else
         {
           myfile<<"公钥:(e=3,n="<<b<<")";
           myfile.close();
         }
    

    (5)持有公钥方的验证:

       def decode(mw, ned):
                                     # 明文C = 密文B的d次方 模 n, ned为私钥匙
                                     #mw就是密文B, ned【1】是e,ned【1】是d
        C = pow(mw,ned[1]) % ned[0]
        return C
    
    if __name__=='__main__':
        pbvk = main()
        pbk = generate_pbk_pvk(pbvk, 0) #公钥  if 0 return pbk if 1 return pvk
        A = int(input("请输入明文: "))
        print("加密中....")
        B = encryption(A,pbk) #加密
        print("生成的密文是: ", B)
        pvk = generate_pbk_pvk(pbvk, 1)  #私钥
        print("解密中....")
        C = decode(B,pvk)     #解密
        print("解密后的明文是: ", C)
        if A==C:
            print("加密前的明文和解密后的明文一样,成功!!!")
        elif printf(“失败!!!”) 
    

    运行结果如下:
    MD5值转换:

    文件加密:

    RSA加密:

    验证方会在本地文本文件key中收到公钥:

    验证方按照对方所述正确明文验证:

    对方说谎,不一致时:

    验证功能实现。
    分析:
    构建的MD5算法与RSA加密可以保证数字签名的可靠性和效率,满足私钥进行签名,公钥进行验证、以及文件加密的要求。其次引入随机选取、重置机制和公钥发送机制可以实现对密钥的管理,保证其隐私性,可以控制密钥的使用次数仅为一次及限定密钥更新。
    通过这次设计,对数字签名过程及其实现有了一个全面、深度的认知。

    课后题:
    1、通信中减缓中间人攻击:(1)带“盐”Hash生成数字摘要。(2)如用电子邮件,请先检查发件人。(3)不要在公共Wi-Fi网络上购买或发送敏感数据。(4)加密消息(5)引入共享密钥加密密钥
    2、数字签名软件:1.ID-SignforMSOffice:当我们使用微软的Office办公时,他会进行数字签名。2. Adobe Acrobat Reader DC:当我们阅读、使用PDF文件时,他会进行数字签名 3.JSignPdf:同样,仍然是一款Windows开发的针对PDF的数字签名软件,用于对PDF加密时。
    攻击方法:(1)穷举攻击(不现实,但是是最基本、简单的,如果以后两字计算机实现会大大提高效率);(2)对单向散列函数攻击,找到非常非常罕见的碰撞现象;(3)利用数字签名攻击公钥密码;
    3、秘密分(共)享协议应用:(1)电子商务中的电子现金、电子拍卖:找到用户信息,追踪犯罪资金(2)安全多方计算中的作用(3)网络中门限数字签名中的应用:是群体多个个体具有合成签名权利(4)密钥协商中的应用(分布式的密钥生成)(5)电子竞选 。

    展开全文
  • Introduction to modern cryptography Chapter 4消息认证码(Message authentication code)完整性的...本文将对密码学书中MAC方案一章进行介绍,主要从完整性的概念,MAC方案的定义,安全的MAC方案定义以及如何构造一个

    消息认证码(Message authentication code)

    本文将对密码学书中MAC方案一章进行介绍,主要从完整性的概念,MAC方案的定义,安全的MAC方案定义以及如何构造一个安全的MAC方案进行介绍。

    完整性的概念

    密码学的一个基本目标是保证安全的通信,安全的通信主要通过两方面实现:机密性secrecy和完整性Intrigrity。
    机密性主要是保证信息不被通信双方之外的第三方所获取。
    完整性这里不考虑机密性,即信息是公开的,需要保证信息的来源是合法的(只有持有对称密钥的合法用户才能够生成标签)以及信息的内容不被篡改。比如说政府下发的文件,允许社会公众进行阅读学习,但是不允许对文件进行篡改。
    通信机密性主要通过加密方案(流加密,块加密等)来实现,而完整性则通过MAC方案实现。

    MAC方案的定义

    一个MAC方案由三个概率多项式PPT算法组成,密钥生成算法Gen,标签生成算法Mac,标签验证算法Vrfy。
    Gen:输入安全参数 1 n 1^n 1n,输出密钥 K K K,密钥长度 ∣ K ∣ ≥ |K|\geq K n n n
    Mac:输入密钥K,任意长度的信息 m m m ∈ \in {0,1}* , 输 出 ,输出 t , , t\leftarrow$ M a c k Mac_k Mack(m)表示Mac算法可能是随机的。
    Vrfy:输入密钥 K K K m m m t t t,输出 b b b b : = V r f y k ( m , t ) b:=Vrfy_k(m,t) b:=Vrfyk(m,t)
    MAC方案必须满足 V r f y k ( m , M a c k ( m ) ) Vrfy_k(m,Mac_k(m)) Vrfyk(m,Mack(m))
    通常情况下MAC方案合法的用户共享对称密钥 K K K,Gen( 1 n 1^n 1n)算法通常忽略。
    如果Mac算法是确定性算法(即每次输入相同的 K K K m m m得到的 t t t是相同的),此时验证算法Vrfy可以通过使用 t ‾ = M a c k ( m ) \overline{t}=Mac_k(m) t=Mack(m)再次计算,比较输入 t ‾ \overline{t} t 是否等于 t t t

    安全的MAC方案

    对于一个安全的MAC方案,不存在任何有效的攻击者能够在任何新的信息上生成有效的标签。新信息指通信方之前没有发送的信息,没有在网络上出现的信息。
    攻击者的能力:能够窃听所有网络中发送的消息及标签对( m i m_i mi, t i t_i ti),能够进行选择信息攻击,即访问 M a c k ( . ) Mac_k(.) Mack(.)谕言机的能力。
    攻击目标:攻击者能够伪造出一对消息标签对 ( m , t ) (m,t) (m,t)并且 m ∉ m\notin m/ Q Q Q Q = { m i } Q=\{{m_i}\} Q={mi} m i {m_i} mi是攻击者访问谕言机的消息。
    Mac-forge A , π {A,\pi} A,π

    1. K K K ← \leftarrow G e n ( 1 n ) Gen(1^n) Gen(1n),生成长度为 n n n的密钥 K K K
    2. 攻击者 A A A:输入 1 n 1^n 1n,并且可以访问 M a c k ( . ) Mac_k(.) Mack(.)谕言机,输出 ( m , t ) (m,t) (m,t) Q = { m i } Q=\{{m_i}\} Q={mi} Q Q Q是攻击者访问谕言机的消息集合。
    3. 当且仅当 V r f y k ( m , t ) = 1 Vrfy_k(m,t)=1 Vrfyk(m,t)=1并且 m ∉ m\notin m/ Q Q Q,则攻击者挑战成功。

    对于 ∀ \forall A A A(具有访问 M a c ( . ) Mac(.) Mac(.)谕言机能力),攻击者能够在新的信息上伪造出合法标签的概率小可忽略的概率,则称MAC方案 π \pi π具有存在不可伪造性,或者说该方案是安全的。
    P r [ M a c − f o r g e A , π ( n ) = 1 ] ≤ n e g l Pr[Mac-forge_{A,\pi}(n)=1]\leq negl Pr[MacforgeA,π(n)=1]negl

    强安全MAC方案

    具有存在不可伪造性的MAC方案,或者说安全的MAC方案,能够确保攻击者不能够在新的消息上生成合法的标签,但是攻击者可能在先去窃听的消息上,如 ( m , t ) (m,t) (m,t)生成伪造的的消息标签对 ( m , t ‾ ) (m,\overline{t}) (m,t),因此提出了更强的安全MAC方案定义。
    攻击者的能力:与先前一致,能够窃听所有网络中发送的消息及标签对( m i m_i mi, t i t_i ti),能够进行选择信息攻击,即访问 M a c k ( . ) Mac_k(.) Mack(.)谕言机的能力。
    攻击目标:攻击者能够伪造出一对消息标签对 ( m , t ) (m,t) (m,t)并且 m ∉ m\notin m/ Q Q Q Q = { m i , t i } Q=\{{m_i},t_i\} Q={mi,ti} { m i , t i } \{{m_i,t_i}\} {mi,ti}是攻击者访问谕言机的消息及得到的标签对,相当于放宽了攻击目标,攻击者只要能够伪造出一对消息标签 ( m , t ) (m,t) (m,t) m m m可以是网络中出现的信息,则攻击者攻击成功。
    Mac-sforge A , π {A,\pi} A,π

    1. K K K ← \leftarrow G e n ( 1 n ) Gen(1^n) Gen(1n),生成长度为 n n n的密钥 K K K
    2. 攻击者 A A A:输入 1 n 1^n 1n,并且可以访问 M a c k ( . ) Mac_k(.) Mack(.)谕言机,输出 ( m , t ) (m,t) (m,t) Q = { m i , t i } Q=\{{m_i},t_i\} Q={mi,ti} Q Q Q是攻击者访问谕言机的消息及得到的标签对集合
    3. 当且仅当 V r f y k ( m , t ) = 1 Vrfy_k(m,t)=1 Vrfyk(m,t)=1并且 m ∉ m\notin m/ Q Q Q,则攻击者挑战成功。

    对于 ∀ \forall A A A(具有访问 M a c ( . ) Mac(.) Mac(.)谕言机能力),攻击者能够在任意信息上伪造出新的合法标签的概率小可忽略的概率,则称MAC方案 π \pi π具有强存在不可伪造性,或者说该方案是强安全的。
    P r [ M a c − s f o r g e A , π ( n ) = 1 ] ≤ n e g l Pr[Mac-sforge_{A,\pi}(n)=1]\leq negl Pr[MacsforgeA,π(n)=1]negl
    当Mac算法是确定性算法有: M A C   s e c u r e    ⟺    M A C   s t r o n g   s e c u r e MAC \ secure \iff MAC\ strong\ secure MAC secureMAC strong secure

    构造安全的MAC方案

    构造固定长度消息的安全MAC方案

    伪随机函数PRF函数是构造MAC方案常用的工具,在介绍由PRF构造一个固定长度的MAC方案之前,首先介绍一下伪随机函数与真随机函数的区别,如下图所示:
    在这里插入图片描述
    PRF函数与真随机函数都是映射集合,PRF函数相当于固定密钥 K K K之后从 X X X Y Y Y的映射,显而易见,PRF函数的映射关系集合是真随机函数的真子集,由于真随机函数映射集合空间很大,PRF函数是安全的前提就是攻击者无法区分PRF与真随机函数的区别,攻击者一般无法找到映射关系 f f f,只能通过遍历值域空间 Y Y Y
    下面介绍由PRF构造一个固定长度的MAC方案,构造4.5如下:
    Gen:输入安全参数 1 n 1^n 1n,输出密钥 K K K,密钥长度 ∣ K ∣ = |K|= K= n n n
    Mac:输入密钥 K K K,长度 n n n的信息 m m m ∈ \in { \{ { 0 , 1 } n {0,1\}}^n 0,1}n,输出 t t t ∈ \in { \{ { 0 , 1 } n {0,1\}}^n 0,1}n t : = t := t:= F k F_k Fk(m)表示Mac算法是确定性的。
    Vrfy:输入密钥 K K K ∈ \in { \{ { 0 , 1 } n {0,1\}}^n 0,1}n m m m ∈ \in { \{ { 0 , 1 } n {0,1\}}^n 0,1}n t t t ∈ \in { \{ { 0 , 1 } n {0,1\}}^n 0,1}n,首先判断 ∣ K ∣ = ∣ m ∣ = ∣ t ∣ = n |K| =|m|= |t|=n K=m=t=n,然后判断 t = ? F k ( m ) t \overset{?}{=} F_k(m) t=?Fk(m),验证成功则输出1,反之输出0。
    定理:如果F是PRF函数,则基于PRF构建的固定长MAC方案 π \pi π是安全的。
    在这里插入图片描述
    证明:主要思路如果攻击者能够区分真随机和伪随机函数,那么攻击者就可以伪造出合法的标签。

    1. 构造另一个方案 π ‾ \overline{\pi} π与上述方案 π \pi π是一致的,只是Mac算法不使用PRF函数 F k F_k Fk而是真随机函数 f f f
    2. 上图是攻击者访问 M a c ( . ) Mac(.) Mac(.)谕言机以及输出 ( m , t ) (m,t) (m,t)挑战过程。

    b ′ = 0 , P r [ M a c − f o r g e A , π ( n ) = 1 ] = P r [ D F k ( . ) ( 1 n ) = 1 ] b'=0,Pr[Mac-forge_{A,\pi}(n)=1]=Pr[D^{F_k(.)}(1^n)=1] b=0Pr[MacforgeA,π(n)=1]=Pr[DFk(.)(1n)=1]即攻击者伪造出标签的概率等于攻击者能够区分真随机以及伪随机函数的概率。
    b ′ = 1 , P r [ M a c − f o r g e A , π ‾ ( n ) = 1 ] = P r [ D f k ( . ) ( 1 n ) = 1 ] ≤ 2 − n b'=1,Pr[Mac-forge_{A,\overline{\pi}}(n)=1]=Pr[D^{f_k(.)}(1^n)=1] \leq 2^{-n} b=1Pr[MacforgeA,π(n)=1]=Pr[Dfk(.)(1n)=1]2n攻击者在真随机函数的情况下伪造出标签的概率也就是遍历标签 T T T的概率 2 − n 2^{-n} 2n
    由于PRF函数时安全的有: P r [ D F k ( . ) ( 1 n ) = 1 ] − P r [ D f k ( . ) ( 1 n ) = 1 ] ≤ n e g l Pr[D^{F_k(.)}(1^n)=1]-Pr[D^{f_k(.)}(1^n)=1] \leq negl Pr[DFk(.)(1n)=1]Pr[Dfk(.)(1n)=1]negl
    所以有 P r [ M a c − f o r g e A , π ( n ) = 1 ] ≤ n e g l + 2 − n Pr[Mac-forge_{A,\pi}(n)=1] \leq negl + 2^{-n} Pr[MacforgeA,π(n)=1]negl+2n
    所以该MAC方案是安全。

    构造任意长度消息的安全MAC方案

    如何构造任意长度的MAC,有两个思路,思路一就是如果PRF函数可以输入任意长度的消息,则上述的固定长MAC方案将变为任意长消息的安全MAC方案,但是由于PRF实际中只接受短的固定长度的信息,所以思路一不可行;思路二就是将信息分块,然后将每一块信息输入到固定长的MAC方案之中。下面基于思路二构建任意长的安全MAC方案。
    如果直接将消息分块 m = m 1 ∣ ∣ m 2 ∣ ∣ m 3 . . . ∣ ∣ m n m=m_1||m_2||m_3...||m_n m=m1m2m3...mn,是不安全的,下面给出反例,注意攻击者是具有选择信息攻击的能力,也就是能够访问 M a c ( . ) Mac(.) Mac(.)谕言机。

    1. 假设标签 t i = M a c k ( m i ) t_i=Mac_k(m_i) ti=Mack(mi)。攻击者首先利用 M a c ( . ) Mac(.) Mac(.)谕言机输入 m = m 1 ∣ ∣ m 2 m=m_1||m_2 m=m1m2,输出 < t 1 , t 2 > <t_1,t_2> <t1,t2>,此时攻击者可以伪造出 m ’ = m 2 ∣ ∣ m 1 m’=m_2||m_1 m=m2m1 t ′ = < t 2 , t 1 > t'=<t_2,t_1> t=<t2,t1>,这种攻击称为重排列攻击。
    2. 为了解决重排列攻击,可以在加入块序号字段,即 t i = M a c k ( i ∣ ∣ m i ) t_i=Mac_k(i||m_i) ti=Mack(imi),注意由于块长固定,加入了块序号字段,此时块中 m m m长度要减少为1/2。但是这种方案仍是不安全的,攻击者首先利用 M a c ( . ) Mac(.) Mac(.)谕言机输入 m = m 1 ∣ ∣ m 2 m=m_1||m_2 m=m1m2,输出 < t 1 , t 2 > <t_1,t_2> <t1,t2>,此时攻击者可以伪造出 m ’ = m 1 m’=m_1 m=m1 t ′ = < t 1 > t'=<t_1> t=<t1>,这种攻击称为截断攻击。
    3. 为了解决截断攻击,可以在加入长度字段,即 t i = M a c k ( l ∣ ∣ i ∣ ∣ m i ) t_i=Mac_k(l||i||m_i) ti=Mack(limi),注意由于块长固定,加入了块序号长度字段,此时块中 m m m长度要减少为1/3。但是这种方案仍是不安全的,攻击者首先利用 M a c ( . ) Mac(.) Mac(.)谕言机输入 m = m 1 ∣ ∣ m 2 m=m_1||m_2 m=m1m2 m ′ = m 1 ′ ∣ ∣ m 2 ′ m'=m_1'||m_2' m=m1m2,输出 < t 1 , t 2 > <t_1,t_2> <t1,t2> < t 1 ′ , t 2 ′ > <t_1',t_2'> <t1,t2>,此时攻击者可以伪造出 m ’ ′ = m 1 ∣ ∣ m 2 ′ m’'=m_1||m2' m=m1m2 t ′ = < t 1 , t 2 ′ > t'=<t_1,t_2'> t=<t1,t2>,这种攻击称为混搭攻击。
    4. 如何解决混搭攻击,可以在块中加入随机标识符,最终我们提出了基于固定长度安全MAC方案构建任意长度安全的MAC方案。

    构造4.7: π \pi π是固定长度为 n n n的MAC方案,由固定长度MAC方案构建任意长度信息的MAC方案如下:
    Gen:输入安全参数 1 n 1^n 1n,输出密钥 K K K,密钥长度 ∣ K ∣ = |K|= K= n n n
    Mac:输入密钥 K K K,任意长度的信息 m m m ∈ \in { \{ { 0 , 1 } ∗ {0,1\}}^* 0,1}( l < 2 n / 4 l<2^{n/4} l<2n/4), m = m 1 , m 2 . . . m d m=m_1,m_2...m_d m=m1,m2...md d d d块,每块长度为 n / 4 n/4 n/4,如果消息长度不是 n / 4 n/4 n/4的整数倍则需要填充0,然后选择随机标识符 r r r ∈ \in { \{ { 0 , 1 } n / 4 {0,1\}}^{n/4} 0,1}n/4,计算 t ← t \leftarrow t M a c k ( r ∣ ∣ l ∣ ∣ i ∣ ∣ m ) Mac_k(r||l||i||m) Mack(rlim),输出 t = < r , t 1 , . . . t d > t=<r,t_1,...t_d> t=<r,t1,...td>
    Vrfy:输入密钥 K K K ∈ \in { \{ { 0 , 1 } n {0,1\}}^n 0,1}n m m m ∈ \in { \{ { 0 , 1 } ∗ {0,1\}}^* 0,1} t = < r , t 1 , . . . t d > t=<r,t_1,...t_d> t=<r,t1,...td>,对每一块 m i {m_i} mi进行验证对应的标签 t i t_i ti,判断 V r f y ( r ∣ ∣ l ∣ ∣ i ∣ ∣ m i , t i ) = ? 1 Vrfy(r||l||i||m_i,t_i)\overset{?}{=}1 Vrfy(rlimi,ti)=?1,验证成功则输出1,反之输出0。
    定理:如果固定长度为n的 π \pi π方案是安全的MAC方案,则构造4.7任意长度的MAC方案也是安全的。
    证明的思路就是说当前方案能够抵抗先前存在的攻击(重排序,截断,混搭),并且这些攻击是唯一可能存在的。

    CBC-MAC

    固定长度的CBC-MAC方案

    上述任意长的MAC方案是基于固定长的MAC方案实现的,每一块增加了额外的信息,导致相应标签的计算次数也要增加,不是很有效,下面介绍更有效的方案CBC-MAC。
    构造4.9:基本的CBC-MAC(任意固定长消息),任意固定长消息是指通信双方可以发送任意长的消息,但是双方需要提前协商好发送的长度 l l l,之后每次发送长度为 l l l的消息。该方案也是基于PRF函数构建的,具体方案如下:
    Gen:输入安全参数 1 n 1^n 1n,输出密钥 K K K,密钥长度 ∣ K ∣ = |K|= K= n n n
    Mac:输入密钥 K K K,任意固定长度的信息 m m m ∈ \in { \{ { 0 , 1 } l ( n ) . n {0,1\}}^{l(n).n} 0,1}l(n).n(令 l = l ( n ) l=l(n) l=l(n)), m = m 1 , m 2 . . . m l m=m_1,m_2...m_l m=m1,m2...ml l l l块,每块长度为 n n n t 0 = 0 n t_0=0^n t0=0n t i = F k ( t i − 1 ⨁ m i ) t_i= F_k(t_{i-1} \bigoplus m_i) ti=Fk(ti1mi),只输出最后一块的标签 t l t_l tl
    Vrfy:输入密钥 K K K ∈ \in { \{ { 0 , 1 } n {0,1\}}^n 0,1}n m m m ∈ \in { \{ { 0 , 1 } l . n {0,1\}}^{l.n} 0,1}l.n t l t_l tl,判断 t l = ? M a c k ( m ) t_l\overset{?}{=}Mac_k(m) tl=?Mack(m),验证成功则输出1,反之输出0。
    定理:如果 l l l是多项式,F是PRF,则构造4.9是固定长度为 l ( n ) . n l(n).n l(n).n的安全的MAC方案。
    下面给出如果长度不固定,该MAC方案是不安全的反例,攻击者是具有访问 M a c k ( . ) Mac_k(.) Mack(.)谕言机的能力。
    在这里插入图片描述
    下面对比一下CBC-MAC与CBC-Encryption:
    在这里插入图片描述
    两者区别在于CBC-MAC不需要初始向量IV,以及CBC-MAC不输出中间结果。
    如果CBC-MAC包含初始向量IV时,攻击者将可以伪造信息及标签如下:
    在这里插入图片描述
    如果CBC-MAC输出中间结果,MAC方案也不再安全,如下:
    在这里插入图片描述

    任意长度信息CBC-MAC方案

    下面直接介绍如何由Basic CBC-MAC扩展为任意长度信息的CBC-MAC方案,有两种方案:

    1. 在CBC-MAC方案前添加一块消息,表示消息长度 ∣ m ∣ |m| m具体如下:
      CBC-MAC扩展方案1
      2.对CBC-MAC方案的输出使用另一个PRF函数进行运算,如下:
      CBC-MAC扩展方案2
      这种方案的优点是不需要提前知道消息的长度,缺点是需要生成两个密钥,实际中两个密钥 K 1 K 2 K1 K2 K1K2可以基于密钥 K K K生成。

                      K 1 = F k ( 1 )    K 2 = F k ( 2 ) \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ K1 = F_k(1) \ \ K2=F_k(2)                  K1=Fk(1)  K2=Fk(2)

    下面介绍一下扩展1中如果长度 ∣ m ∣ |m| m字段加到最后一块MAC方案也是不安全的,如下:
    攻击者发动选择信息攻击
    攻击者通过访问 M a c ( . ) Mac(.) Mac(.)谕言机得到了标签 t 1 t 2 t 3 t_1t_2t_3 t1t2t3以及对应的信息对进而可以构建如下:
    攻击者伪造标签

    上述基本完成了对于消息认证码方案的所有介绍,下面简要介绍一下最新修改版新增的第一个随机MAC方案,基于差分通用hash函数以及PRF函数构建的MAC方案,GMAC以及Ploy1305都是基于该方案在有限域上实现,下面直接贴出原文以及相应找到的资料内容。
    书中给出的定义
    ϵ ( n ) \epsilon (n) ϵ(n)差分通用函数实际就是 ϵ \epsilon ϵXOR通用hash函数,表达的含义应该是这种hash函数碰撞更小,并且如果攻击者知道一对 ( m , h k ( m ) ) (m,h_k(m)) (m,hk(m))后,对于另一个 m m m ≠ \neq = m ′ m' m,攻击者没有任何的优势去猜测 h k ( m ′ ) h_k(m') hk(m),猜测成功的概率为 1 / ∣ T ∣ 1/|T| 1/T,可忽略的概率。
    在这里插入图片描述
    下面给出具体MAC方案的定义:
    h h h ϵ ( n ) \epsilon (n) ϵ(n)差分通用函数, F F F是PRF函数, { M n } \{M_n\} {Mn}是消息空间, { K n } \{K_n\} {Kn}是密钥空间, { T n } \{T_n\} {Tn}是标签空间,在这三个空间集合中取样更有效更快。
    Gen:输入安全参数 1 n 1^n 1n,从 K n K_n Kn中均匀选择密钥 k h k_h kh,选择 k F k_F kF ∈ \in { \{ { 0 , 1 } n {0,1\}}^n 0,1}n,输出 ( k h , k F ) (k_h,k_F) (kh,kF)
    Mac:输入密钥 ( k h , k F ) (k_h,k_F) (kh,kF),任意固定长度的信息 m m m ∈ \in M n M_n Mn,均匀选择 r r r ∈ \in { \{ {${0,1}}^n,输出标签 t : = < r , h k h ( m ) + F k F ( r ) ) > t:=<r,h_{k_h}(m) + F_{k_F}(r))> t:=<r,hkh(m)+FkF(r))>
    Vrfy:输入密钥 ( k h , k F ) (k_h,k_F) (kh,kF),消息 m m m ∈ \in M n M_n Mn,标签 t = < r , s > t=<r,s> t=<r,s>,判断 s = ? h k h ( m ) + F k F ( r ) s\overset{?}{=}h_{k_h}(m) + F_{k_F}(r) s=?hkh(m)+FkF(r),验证成功则输出1,反之输出0。

    课后练习

    4.6 F是PRF函数,说明下面基于PRF固定长度消息的MAC是不安全的,其中密钥生成 G e n Gen Gen得到的密钥都是均匀随机的。
    证明MAC方案是不安全的,只要找到攻击者伪造标签成功的一种情况即可,此时攻击者是具有选择信息攻击的能力即访问 M a c k ( . ) Mac_k(.) Mack(.)谕言机的能力。
    ( a ) (a) (a)攻击如下:固定长度L=2
    攻击者输入 ( m 1 , m 2 ) (m_1,m_2) (m1,m2),可以得到 t = F k ( m 1 ) t=F_k(m_1) t=Fk(m1) ⨁ \bigoplus F k ( m 2 ) F_k(m_2) Fk(m2)
    攻击者进而可以伪造出消息 ( m 2 , m 1 ) (m_2,m_1) (m2,m1),标签 t ′ = t t'=t t=t
    ( b ) (b) (b)固定长度L=2
    攻击者输入 m 1 = m 1 ∣ ∣ m 2 m^1 = m_1 || m_2 m1=m1m2, m 2 = m 3 ∣ ∣ m 2 m^2 = m_3 || m_2 m2=m3m2 m 3 = m 3 ∣ ∣ m 4 m^3 = m_3 || m_4 m3=m3m4可以得到对应的标签分别为 t 1 = F k ( ⟨ 1 ⟩ ∣ ∣ m 1 ) ⊕ F k ( ⟨ 2 ⟩ ∣ ∣ m 2 ) t_1 = F_k(\langle 1 \rangle || m_1) \oplus F_k(\langle 2 \rangle || m_2) t1=Fk(1m1)Fk(2m2)
    t 2 = F k ( ⟨ 1 ⟩ ∣ ∣ m 3 ) ⊕ F k ( ⟨ 2 ⟩ ∣ ∣ m 2 ) t_2 = F_k(\langle 1 \rangle || m_3) \oplus F_k(\langle 2 \rangle || m_2) t2=Fk(1m3)Fk(2m2)
    t 3 = F k ( ⟨ 1 ⟩ ∣ ∣ m 3 ) ⊕ F k ( ⟨ 2 ⟩ ∣ ∣ m 4 ) t_3 = F_k(\langle 1 \rangle || m_3) \oplus F_k(\langle 2 \rangle || m_4) t3=Fk(1m3)Fk(2m4)
    进而攻击者可以伪造出消息: m ∗ = m 1 ⊕ m 2 ⊕ m 3 = m 1 ∣ ∣ m 4 m^* = m^1 \oplus m^2 \oplus m^3 = m_1 || m_4 m=m1m2m3=m1m4标签: t = t 1 ⊕ t 2 ⊕ t 3 = F k ( ⟨ 1 ⟩ ∣ ∣ m 1 ) ⊕ F k ( ⟨ 2 ⟩ ∣ ∣ m 4 ) t = t_1 \oplus t_2 \oplus t_3 = F_k(\langle 1 \rangle || m_1) \oplus F_k(\langle 2 \rangle || m_4) t=t1t2t3=Fk(1m1)Fk(2m4)

    ( c ) (c) (c) 固定长度L=1
    攻击者选择 r = ⟨ 1 ⟩ ∣ ∣ m r = \langle 1 \rangle || m r=1m 此时标签 t t t的计算为: t = F k ( r ) ⊕ F k ( ⟨ 1 ⟩ ∣ ∣ m ) = 0 n t = F_k(r) \oplus F_k(\langle 1 \rangle || m) = 0^n t=Fk(r)Fk(1m)=0n 输出标签:
    t = ⟨ ⟨ 1 ⟩ ∣ ∣ m , 0 n ⟩ t = \left\langle \langle 1 \rangle || m, 0^n \right\rangle t=1m,0n攻击者可以伪造任意的消息,对应的标签都为0。
    4.7 F是PRF函数,说明下面长度为2n的MAC方案是不安全的:均匀随机选择 k k k ∈ \in { \{ { 0 , 1 } n {0,1\}}^n 0,1}n,输入消息 m 1 ∣ ∣ m 2 m_1 || m_2 m1m2,输出标签 F k ( m 1 ) F_k(m_1) Fk(m1) ∣ ∣ || F k ( F k ( m 2 ) ) F_k(F_k(m_2)) Fk(Fk(m2))
    下面给出攻击者可以伪造出标签的反例:
    首先攻击者输入 m 1 = m 1 ∣ ∣ m 1 m^1=m_1||m_1 m1=m1m1 m 2 = m 2 ∣ ∣ m 2 m^2=m_2||m_2 m2=m2m2可以得到对应的标签
    t 1 = F k ( m 1 ) ∣ ∣ F k ( F k ( m 1 ) ) t^1 = F_k(m_1) || F_k(F_k(m_1)) t1=Fk(m1)Fk(Fk(m1)) t 2 = F k ( m 2 ) ∣ ∣ F k ( F k ( m 2 ) ) t^2= F_k(m_2) || F_k(F_k(m_2)) t2=Fk(m2)Fk(Fk(m2)),由于PRF函数是输出长度是固定的,很容易可以 F k ( F k ( m 2 ) ) F_k(F_k(m_2)) Fk(Fk(m2)) F k ( m 1 ) F_k(m_1) Fk(m1),借此攻击者可以伪造出信息及标签对:
    m = m 1 ∣ ∣ m 2 m=m_1||m_2 m=m1m2, t = F k ( m 1 ) ∣ ∣ F k ( F k ( m 2 ) ) t =F_k(m_1) ||F_k(F_k(m_2)) t=Fk(m1)Fk(Fk(m2))

    以上便是密码学第四章所有分享内容,欢迎大家批评指正,谢谢。

    参考网址

    学习过程主要参考了以下网址及书籍还有Dan Boneh相关视频:
    [1]: Katz J, Lindell Y. Introduction to modern cryptography[M]. CRC press, 2020.
    [2]: http://web.cse.ohio-state.edu/~lai.1/5351/5.MAC.pdf
    [3]: https://github.com/LuminousXLB/MyCryptography

    展开全文
  • 计算机安全复习课.pdf计算机安全复习课龙宇/index.php/Yu_Long考试安排考试时间:2010年1月3 日下午1:00-3:00考试地点:工程馆301考试类型:闭卷题型:单选题:25题,共50分简答题: 5题,共20分计算题: 3题...

    计算机安全学复习课.pdf

    计算机安全学复习课

    龙宇

    /index.php/Yu_Long

    考试安排

    考试时间:2010年1月3 日

    下午1:00-3:00

    考试地点:工程馆301

    考试类型:闭卷

    题型:

    单选题:25题,共50分

    简答题: 5题,共20分

    计算题: 3题,共20分(4+6+10 )

    设计题: 1题,共10分

    第一讲:计算机安全引论

    1.1 计算机、网络及信息安全概况

    (了解)安全概况、对网络的依赖、现状及攻击、举例

    1.2 计算机、网络及信息安全的基本问题

    信息、安全服务

    基本的安全服务(如认证性、保密性、数据完整性、不可否

    认。。)(理解)

    安全策略与安全机制的区别?(掌握)

    安全策略是对允许什么、禁止什么的规定

    安全机制是实施安全策略的一种方法、工具或者规程

    主动攻击与被动攻击(特点,区别,种类)

    (掌握)给定攻击行为描述,能判定其属于主动还是被动攻击

    1.3 信息安全发展前景(了解)

    1.4 信息安全中基本概念

    网络安全/计算机安全模型(理解)

    密码学定义、安全通信模型、密码学基本术语(理解、

    掌握)

    保密学vs. 密码分析

    M,C,K

    对称加密体制(单钥体制)与双钥体制(公钥体制)

    密码分析:唯密文攻击、已知明文攻击、选择明文攻

    击、选择密文攻击的定义

    第二讲信息论基础与古典加密技术

    信息论基础(理解)

    理论依据:Shannon的“保密系统的通信理论”

    信息量应当是概率的单调递减函数

    完善保密系统的含义,无条件安全与计算安全的区别

    基于代换技术的古典密码体制及密码分析(了解)

    Caesar密码

    单表代换密码

    Playfair密码

    Hill密码

    多表代换密码与一次一密

    基于置换技术的古典密码体制及密码分析(了解)

    栅栏技术

    其他

    转轮机、隐写术及一些实例(了解)

    第三讲分组密码与数据加密标准

    分组密码简介

    对称加密算法的分类及各自的特点(分组加密、流密码)(掌握)

    Feistel密码(了解)

    SPN

    Feistel的思想:

    乘积密码:依次使用两个或者两个以上的基本密码,所得结果的密码强度将强于

    所有单个密码的强度

    基于可逆的乘积密码。目标是逼近简单代换密码

    混淆和扩散的区别?(掌握)

    简化DES (了解,理解)

    数据加密标准Data Encryption Standard (了解)

    DES的参数(key=56bit,M=64bit,16轮,8个S盒子)

    雪崩效应的定义,位独立准则的定义

    DES的强度(了解)

    差分分析和线性分析

    第四讲现代分组加密技术

    三重DES — 3DES (理解)

    为何使用3DES ?

    双重DES不能提高DES的安全性

    2个key的3DES的工作方式

    国际数据加密算法— IDEA (了解)

    分组大小:64bit;密钥长度:128bit ;不是Feistel结构

    高级数据加密标准—AES (了解,理解)

    基本要求(比三重DES快,至少和三重DES一样安全,

    分组长度128比特,支持密钥长度为128/192/256比特)

    AES128 的参数:128,128

    分组密码的工作模式(了解)

    电码本模式、密码分组链接模式、密码反馈模式、输出

    反馈模式、计数器模式

    第五讲用对称密码实现保密性

    通信保密的位置

    链路加密,端对端加密,各自特点及逻辑位置

    (理解)

    通信流量分析攻击和预防措施(了解)

    主密钥vs. 会话密钥(掌握)

    具有可信第三方的安全密钥生成(理解)

    展开全文
  • 计算机英语(第四版

    千次阅读 2017-09-07 12:23:29
    一章 计算机硬件 1.1 计算机的组成  audio 声[音]频的,声音的  bus 总线  computer 计算机  central processing
  • 计算机安全复习课-Basic-上海交通大学计算机安全复习课上海交通大学计算机系龙 环一讲:计算机安全引论1.1 计算机、网络及信息安全概况 (了解)安全概况、对网络的依赖、现状及攻击、举例1.2 计算机、网络及...
  • 密码学与网络安全—知识点总结

    千次阅读 2021-12-23 16:33:34
    先附上所有知识点的wordpdf版,并添加了目录,方便复习。 文章目录前言一、概念(名词解释)1、对称加密2、会话密钥3、混合密码体制:4、非对称加密/公钥/私钥:5、数字证书(digital certificate)6、CA机构7、...
  • 前言:谈区块链离不开密码学。从凯撒密码到维吉尼亚密码,从单表位移到多表代换,从对称加密,到非对称加密,密码学已经走过了漫长的三千年。作为一门古老的学科,如今却又因为互联网和区块链技术重新闪耀光彩。传统...
  • 精通以太坊4:以太坊背后的密码学

    千次阅读 2020-03-28 17:18:47
    精通以太坊4:以太坊背后的密码学 密码学是以太坊的技术基石。 在计算机安全领域有广泛应用 密码学可以用来进行知识证明,在不公开秘密数据的情况下,证明直到秘密的信息(数字签名) 也可以用作证明信息的真实性...
  • CTF密码学总结(二)

    千次阅读 2021-11-03 22:32:47
    CTF 密码学总结 出人意料的flag: 指在题目中获取到了flag,但是这个flag可能长得不像flag,或者flag还要经过进一步的脑洞处理,而不是常规的解密处理。 非预期行为: 指解题中出现与预想结果不符合的一系列...
  • CTF-密码学相关

    千次阅读 2019-09-09 20:30:44
    参考:千千秀字、百度百科、CTF编码和加密总结、CTF常见编码和加密特征 、CTF中Crypty(密码类)入门必看 目录 字符编码 1.ASCII编码 2.Unicode编码 3.UTF-8编码 4.UTF-16编码 5.进制转换 6.URL字符编码 7....
  • 分析上述8个关键字可知,关键字从左到右的1、2、3、6位取值比较集中,不宜作为哈希地址,剩余的4、5、7、8位取值较均匀,可选取其中的两位作为哈希地址。设选取最后两位作为哈希地址,则这8个关键字的哈希地址...
  • 原文链接 https://eprint.iacr.org/2014/758.pdf 作者:Ilya Mironov,Noah Stephens-...并且最近一系列的公告也显示广泛应用的密码学软件经常包含削弱其自身安全性的漏洞。这促使我们考虑以下(看似荒谬的)...
  • 分享一些学习资料-大量PDF电子书

    千次阅读 2014-10-15 21:01:24
    分享一些学习用的电子书籍,给那些喜欢看书...提取密码: np33 主要包括几个部分的东西: C/C++/数据结构、算法类的,也会有一些计算机基础的,如《深入理解计算机系统》 PHP书籍及周边。如Apache,Nginx, mysql, H
  • 密码学期末复习

    千次阅读 2019-01-25 13:50:48
    含义:密码学是一个非常庞大而复杂的信息处理系统,涉及信息的机密性、完整性、认证性、不可否认性等许多方面,属于信息安全范畴。 主要功能: 机密性:是指保证信息不被泄露给非授权的用户或实体,确保存储的信息和...
  • 密码的定义:采用特定变换的方法对信息进行加密保护、安全认证的技术、产品和服务 信息系统的要素有:计算机硬件、网络和通讯设备、计算机软件、信息资源、信息用户和规章制度 信息安全的主要目的是:保证信息的...
  • 《C语言程序设计:现代方法》(2) 《深入理解计算机系统》(修订2) 《C语言程序设计》(2) 《程序员修炼之道》 《C和指针》 《C primer plus》(入门首选) 《高质量...
  • Python 学习资源大全中文

    千次阅读 2017-07-16 10:57:15
    Python 学习资源大全中文我想很多程序员应该记得 GitHub 上有一个 Awesome - XXX 系列的资源整理。awesome-python 是 vinta 发起维护的 Python 资源列表,内容包括:Web框架、网络爬虫、网络内容提取、模板引擎、...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,891
精华内容 756
关键字:

现代密码学第四版pdf

友情链接: 80C51PID.rar