密码学实验4

时间:2024.4.13

实验4   非对称密码算法RSA

一、        实验目的

通过实际编程了解非对称密码算法RSA的加密和解密过程,加深对非对称密码算法的认识。

二、        实验原理

1、算法原理

步骤如下(这里设B为是实现者)

(1)B寻找出两个大素数p和q。

(2)B计算出n=p*q和(n)=)(p-1)*(q-1)。

(3)B选择一个随机数e(0<e<(n)),满足(e,(n))=1 (即e与欧拉函数互素(n))。

(4)B使用欧几里得算法计算e的模余(n)的乘法逆元素d。

(5)B在目录中公开n和e作为他的公开密钥,保密p、q和d。

加密时,对每一明文m计算密文

                           cΞme(modn)

解密时,对每一密文c计算明文

                               mΞcd(modn)

三、        实验环境

运行Windows或者Linux操作系统的PC机,具有gcc(Linux)、VC(Windows)等C语言编译环境。

四、        实验内容

1、为了加深对算法的了解,根据输入的参数p,q,M,手工计算公私钥,并对明文进行加密,然后对密文进行解密。

2、编写程序,加密一段文字,了解算法原理。尝试加密一大段文字,记录程序的运行时间。使用DES算法加密相同的文字,比较两种算法加密的速度。

3、编写一个程序,随机选择3个 较大的数 ,计算 ,记录 程序运行时间。

查阅资料给出简单说明大数在计算机上是如何表示,如何进行运算。

4、查阅资料,找出目前实际可行的素数判定法则,并比较各自的优缺点。

五、实验步骤

1主要函数说明

(1)判断一个数是否为素数函数

bool prime(int n) 

{

              int m=sqrt(n);

              for(int i=2;i<m;i++)

              {

                     if(n%i==0)

                            break;

              }

              if(i>=m)

                     return 1;

              else return 0;

}

(2)模幂算法 (这里以明文m为一个为例)

①令f=1;

②用for循环遍历从i=1到i=b,令f=(f*a)%n

③输出f,f的值即为模幂的结果。

int multiplication(int a,int b,int n)       

{

    int f=1;

       for(int i=1;i<=b;i++)

       {

             

                     f=(f*a)%n;

       }

       return f;

}

(3)扩展欧几里得算法

由扩展欧几里得算法可以计算整数s和t ,使得s*e+t*N=(e,N)=1,则e的乘法逆元等价于s mod N。

①定义变量 x1,x2,x3,y1,y2,y3,t1,t2,t3,q;

②令 x1 = y2 = 1;  x2 = y1 = 0;

③计算q = x3/y3;    t1 = x1 - q*y1;

      t2 = x2 - q*y2;    t3 = x3 - q*y3;

④  x1 = y1;  x2 = y2;   x3 = y3;   y1 = t1;   y2 = t2;    y3 = t3;

⑤当 y3 =1时,*result = y2;  result 的结果即为所求乘法逆元;如果y3 !=1,则返回顺序执行③、④步直到满足 y3 =1

int ExtendedEuclid( int f,int d ,int *result)

{

       int x1,x2,x3,y1,y2,y3,t1,t2,t3,q;

       x1 = y2 = 1;

       x2 = y1 = 0;

       if(f>=d)

       {

              x3=f;

              y3=d;

       }

       else

       {

              x3=d;

              y3=f;

       }

       while( 1 )

       {

              if ( y3 == 1 )

              {

                     *result = y2;      /* 两个数互素则resutl为其乘法逆元,此时返回值为1 */

                  return 1;

              } 

              q = x3/y3;

              t1 = x1 - q*y1;

              t2 = x2 - q*y2;

              t3 = x3 - q*y3;

              x1 = y1;

              x2 = y2;

              x3 = y3;

              y1 = t1;

              y2 = t2;

              y3 = t3;

       }

}

(4)主函数

①输入两个数字判断是否为素数,当不为素数时重新输入。如输入 17 11

②输入e,得到公钥。如输入e为7

③调用ExtendedEuclid(e,N,&d)函数,得到d,和私钥。如d=23

④输入明文长度。如输入 5    如输入明文为 56 88 78 12 23

⑤开始加密,调用加密函数 Encryption()。 则输入密文为 78 11 56 177 133

⑥开始解密,调用解密函数 Decipher()。   则解密后明文为  56 88 78 12 23

2、打开VC++,编写程序如下:

#include<iostream.h>

#include<math.h>

int p,q,n,e,d,N,m1[100],m2[100],len;

 //判断一个数是否为素数,为素数返回1,否则返回0

bool prime(int n) 

{

        int m=sqrt(n);

        for(int i=2;i<m;i++)

        {

            if(n%i==0)

                break;

        }

        if(i>=m)

            return 1;

        else return 0;

}

//扩展欧几里得算法求乘法逆元,两数互素返回1

int ExtendedEuclid( int f,int d ,int *result)

{

    int x1,x2,x3,y1,y2,y3,t1,t2,t3,q;

    x1 = y2 = 1;

    x2 = y1 = 0;

    if(f>=d)

    {

        x3=f;

        y3=d;

    }

    else

    {

        x3=d;

        y3=f;

    }

    while( 1 )

    {

        if ( y3 == 1 )

        {

            *result = y2;      /* 两个数互素则resutl为其乘法逆元,此时返回值为1 */

           return 1;

   

        } 

        q = x3/y3;

        t1 = x1 - q*y1;

        t2 = x2 - q*y2;

        t3 = x3 - q*y3;

        x1 = y1;

        x2 = y2;

        x3 = y3;

        y1 = t1;

        y2 = t2;

        y3 = t3;

    }

}

//将十进制数据转化为二进制数组

void to_bit(int b,int bit[32])

{        

    int n=0;

    while(b>0)

    {

        bit[n]=b%2;

        n++;

        b/=2;

    }

}

//模幂算法

int multiplication(int a,int b,int n)       

{

    int f=1;

for(int i=1;i<=b;i++)

    {

       

            f=(f*a)%n;

    }

    return f;

}

//加密函数

void Encryption()

{

    cout<<"******************开始加密*****************"<<endl;

    int i;

    cout<<"请输入明文:";

    for(i=0;i<len;i++)

        cin>>m1[i];

    for(i=0;i<len;i++)

        m2[i]=multiplication(m1[i],e,n);

    cout<<"加密后的密文为:";

    for(i=0;i<len;i++)

        cout<<m2[i]<<" ";

    cout<<endl;

}

//解密函数

void Decipher()

{

    int i;

    cout<<"*************开始解密*************"<<endl;

    for(i=0;i<len;i++)

        m2[i]=multiplication(m2[i],d,n);

    cout<<"解密后的明文为:";

    for(i=0;i<len;i++)

        cout<<m2[i]<<" ";

    cout<<endl;

}

void main()

{

    cout<<"输入两个素数p和q:\n";

    while(1)

    {

        cin>>p;

        if(prime(p))

        {

        cout<<p<<"是素数"<<endl;

        break;

        }

    else

    {

        cout<<p<<"不是素数"<<endl;

    continue;

    }

    }

while(1)

    {

        cin>>q;

        if(prime(q))

        {

        cout<<q<<"是素数"<<endl;

        break;

        }

    else

    {

        cout<<q<<"不是素数"<<endl;

    continue;

    }

    }

cout<<"两个素数为:"<<p<<","<<q<<endl;

    n=p*q;

    N=(p-1)*(q-1);

   for(int i=2;i<N;i++)

    {

        if(N%i==0)

        {

            cout<<i<<" ";

        }

       

    }

    cout<<endl;

    cout<<"请输入一个随机数,该数不等于上面的任何一个数!"<<endl;

    cin>>e;

    cout<<"公钥为<"<<e<<","<<n<<">"<<endl;

  if(ExtendedEuclid(e,N,&d))

    cout<<e<<"的乘法逆元是:"<<d<<endl;

  cout<<"私钥为<"<<d<<","<<n<<">"<<endl;

  cout<<"请输入明文长度: ";

    cin>>len;

  Encryption();

  Decipher();

}

调试程序,程序运行如下:

六、实验心得和总结

    我是这次试验主要负责人, 因为实验要分组做,每个人都要负责一个项目,在我们组前两次实验中,我主要负责编写代码,像写报告、做PPT我几乎没有参与。但这次不一样了,所以的工作自己都要操起心来,比同组的同学多做一些工作,多分担一些,但是组员也很给力,实验的时候给了我很多建议与指导,制作PPT时给了我很多建议和帮助,有了团队精神所以效率提高了很多。所以这次试验下来感觉自己比以前做实验多学了好多东西,因为什么都要动手做,不懂得东西要查询清楚。

    我感觉做实验对学生真正掌握知识很重要。上课的时候只是听老师讲RSA算法顶多就是学会理论知识,而真正实践动手做的时候就会发现自己漏洞百出,因为考虑问题不周全,编写代码的时候总是出错,编写的不完善,算法的功能没有全部体现,最后又翻看了课本、大一的时候学的C++课本、大二学的密码学基础课本和信息安全概论课本。巩固了一些已经忘记了的基础知识,有不太理解的算法实现方法就通过上网查询以及与同学讨论来解决。这次写代码是我参与编写过的比较长的代码,RSA算法的算法原理我理解的比较清楚,所以对算法如何实现有一定的认识,编写起来也比较轻松一点。RSA算法用到了数论的知识,这次实验对我来说最难理解的就是扩展欧几里得算法,虽然在大二时学过了理论但实际编写还是有点难度的,通过查阅书籍及网上搜寻资料最终写出来扩展欧几里得算法实现函数。实在不容易啊。。。经过这次试验,我认识到了我编写代码的能力确实需要提升,需要平时更多的努力,相信以后在与组员以及其他同学的合作下,我能够学到更多知识。

3、打开VC++,编写程序如下:(此程序错误,因为数值过大产生溢出,请改之)

#include<iostream.h>

#include <ctime>

#include<cstdlib>

#include<stdio.h>

#include<time.h>

#include<stdlib.h>

#include <math.h>

//using namespace std;

int main(){

       clock_t start,end;

       long times;

       long x,e,n;

       cout<<"随机产生3个大数:"<<endl;

       //x=1000*(rand()%11)+100*(rand()%11)+10*(rand()%11)+rand()%11;

       x=1000000*(rand()%11)+100000*(rand()%11)+10000*(rand()%11)+1000*(rand()%11)+

              100*(rand()%11)+10*(rand()%11)+rand()%11;

       e=1000000*(rand()%11)+100000*(rand()%11)+10000*(rand()%11)+1000*(rand()%11)+

              100*(rand()%11)+10*(rand()%11)+rand()%11;

       n=1000000*(rand()%11)+100000*(rand()%11)+10000*(rand()%11)+1000*(rand()%11)+

              100*(rand()%11)+10*(rand()%11)+rand()%11;

       cout<<"x="<<x<<"  e="<<e<<"  n="<<n<<endl;

       start=clock();

       cout<<pow(x,e)<<endl;

       long answer=(int)pow(x,e)%n;       //指数运算

       end=clock();

       times=1000*(end-start);

       cout<<"花费的时间为:"<<times<<endl;

       return 0;

}

调试运行如下:

计算机上大数表示方法:

将大数看作一个n进制数组,对于目前的32位系统而言,n可以取值为2的32次方,即0x10000000,假如将一个1024位的大数转化成0x10000000进制,它就变成了32位,而每一位的取值范围就不是0-1或0-9,而是0-0xfffffff.我们正好可以用一个无符号长整数来表示这一数值.所以1024位的大整数就是一个有32个元素的unsigned long数组.而且0x10000000进制的数组排列与2进制流对于计算机来说,实际上是一回事,但是我们完全可以针对unsighed long数组进行”竖式计算”,而循环规模被降低到了32次之内,并且算法很容易理解.

4、素性测试方法:

所谓素数,是指除了能被1和它本身整除而不能被其他任何数整除的数。据此,只需用2到N-1去除N,如果都除不尽,则为素数

(1)flag=1,i=2

(2)If n mod i=0 then flag=1 else i=i+1

(3)If flag=0 and i<n-1 then(2) else (4)

(4)If flag=0 then write yes else no

在最坏的情况下,即N为素数,算法需要执行N-2次,时间复杂性太大。

只需用2到根下N去除N,即可,于是上述算法改为

(3)If flag=0 and i<=int(根N)  then(2) else (4)

虽然快了不小,但有重复计算,如果用2去除N时若不尽,则用2的倍数去除N也除不尽,由此得

(1)for(i=2;int(根N);i++)             mark[i]=0;//mark是标记其初值为0,只要它的因子除不尽其值变为1

(2)i=2,flag=0

(3)while(flag=0 and i<int(根N)){

       If mark[i]=0

Then{

       If n mod i=0

Then flag=1

S=i+i

While s<int(根N){

       Mark[s]=1

S=s+i

}

}

       I=i+1

}

(4)if flag=0 then yes else no



更多相关推荐:
实验报告_密码学

信息安全实验报告学号学生姓名班级实验三密码学实验一古典密码算法实验一实验目的通过编程实现替代密码算法和置换密码算法加深对古典密码体制的了解为深入学习密码学奠定基础二编译环境运行windows或linux操作系统...

实验报告_密码学

密码学与网络安全技术课程上机报告学号119xx4339姓名许海龙班级网112班教师卫琳娜安徽工业大学密码学实验一古典密码算法实验一实验目的通过编程实现替代密码算法和置换密码算法加深对古典密码体制的了解为深入学习...

密码学实验报告

密码学实验报告学院计算机科学与技术班级学号姓名指导老师实验日志实验题目DES或AES分组密码实验目的熟悉分组密码加解密算法的基本原理加深对所提供的部分源程序的理解分组密码将明文分成一组一组在密钥的控制下经过加密...

密码学实验报告

密码学实验报告实验一DES加密算法实验一实验目的理解对称加解密算法的原理和特点理解DES算法的加解密原理二实验背景DES算法为密码体制中的对称密码体制又被称为美国数据加密标准是19xx年美国IBM公司研制的对称...

密码学实验报告

江苏大学学院专业姓名学号计算机学院信息安全09023090604035小组成员AES对称加密算法实现一AES对称加密算法实现原理AESTheAdvancedEncryptionStandard接受一个128位的...

密码学实验报告3

哈尔滨工程大学实验报告实验名称DES加密班级学号姓名实验时间20xx615成绩指导教师实验室名称哈尔滨工程大学实验室与资产管理处制一实验名称MD5加密二实验目的通过编程实现MD5加密的算法设计并加深对其的了解三...

密码学实验报告四

现代密码学实验报告报告创建时间

现代密码学实验报告(题目+代码)丁朋

实验报告实验课程名称现代密码学学院理学院年级03学生姓名丁朋学号开课时间学期

密码学 上机实验二报告(Matlab)

信息安全与密码学实验报告12346

中南大学 现代密码学实验报告

信息安全1302郁博文0906130205中南大学现代密码学实验报告学生姓名郁博文学号0906130205专业班级信息安全1302指导教师段桂华学院信息科学与工程学院完成时间20xx年5月信息安全1302郁博文...

密码学大报告_20xx3259_方立春

上海电力学院ShanghaiUniversityofElectricPower期末大报告院系名称计算机科学与技术学院课程名称密码编码学与网络安全实验项目名称流密码与RC4算法综述班级20xx251班学生姓名方立...

密码学课程设计报告

沈阳工程学院课程设计设计题目院系信息学院班级信安本111学生姓名学号指导教师祝世东王素芬职称工程师副教授起止日期20xx年1月6日起至20xx年1月10日止沈阳工程学院课程设计任务书课程设计题目简单的保密通信系...

密码学实验报告(37篇)