RSA加密简单实现.docx
- 文档编号:4960284
- 上传时间:2022-12-12
- 格式:DOCX
- 页数:13
- 大小:134.38KB
RSA加密简单实现.docx
《RSA加密简单实现.docx》由会员分享,可在线阅读,更多相关《RSA加密简单实现.docx(13页珍藏版)》请在冰豆网上搜索。
RSA加密简单实现
网络安全实验报告
—RSA加密解密的简单实现
RSA介绍:
当前最著名、应用最广泛的公钥系统RSA是在1978年,由美国麻省理工学院(MIT)的Rivest、Shamir和Adleman在题为《获得数字签名和公开钥密码系统的方法》的论文中提出的。
RSA算法是第一个既能用于数据加密也能用于数字签名的算法,因此它为公用网络上信息的加密和鉴别提供了一种基本的方法。
它通常是先生成一对RSA密钥,其中之一是保密密钥,由用户保存;另一个为公开密钥,可对外公开,甚至可在网络服务器中注册,人们用公钥加密文件发送给个人,个人就可以用私钥解密接受。
为提高保密强度,RSA密钥至少为500位长,一般推荐使用1024位。
公钥加密算法中使用最广的是RSA。
RSA算法研制的最初理念与目标是努力使互联网安全可靠,旨在解决DES算法秘密密钥的利用公开信道传输分发的难题。
而实际结果不但很好地解决了这个难题;还可利用RSA来完成对电文的数字签名以抗对电文的否认与抵赖;同时还可以利用数字签名较容易地发现攻击者对电文的非法篡改,以保护数据信息的完整性。
此外,RSA加密系统还可应用于智能IC卡和网络安全产品。
一.系统总体方案:
1.要求:
编写RSA加密解密演示程序,用户自己输入两个素数P,Q以及公钥E,程序判断P,Q为素数后计算得到公钥(e,n),私钥(d,n)并显示。
输入明文密文并可以进行加密解密。
2.数学原理:
1.密钥的生成选择p,q为两个大的互异素数计算n=p*q,ψ(n)=(p-1)(q-1)
选择整数e使gcd(ψ(n),e)=1(互质),(1 计算d,使d=eˆ-1(modψ(n))(求乘法逆元) 公钥Pk={e,n};私钥Sk={d,n}。 (定义若a•xmodn=1,则称a与x对于模n互为逆元) 2.加密(用e,n)明文M 3.解密(用d,n)对于密文C由M=Cˆd(modn)得到明文M。 3.实现过程: 1.输入p,q判断为素数,计算n=p*q,ψ(n)=(p-1)(q-1) 2.输入e判断是否与ψ(n)互质,计算d=eˆ-1(modψ(n)) 3.输出公钥为(e,n)私钥为(d,n) 4.输入明文(数字)M计算密文C=Mˆe(modn) 5.输入密文C计算明文M=Cˆd(modn) 二.设计思路: 1.关键问题: (1)素数的判断: 首先在输入p,q之后应该有一个函数intsushu()可以判断p,q是否为素数,并返回1(是)或0(否)。 考虑到程序中数据类型为long型,依次用2~√n之间的数去除n,如果能整除则不为素数。 该算法时间复杂度为O(√n)。 intsushu(longm) {inti; for(i=2;i*i<=m;i++) if(m%i==0)return0; return1;} (2)互质的判断: 在输入e之后需要判断e与ψ(n)是否互质,所以用该有判断互质的函数intgcd()返回1(是),其他(否)。 根据欧几里德算法 gcd(a,b)=gcd(b,amodb) 证明: a可以表示成a=kb+r,则r=amodb 假设d是a,b的一个公约数,则有 d|a,d|b,而r=a-kb,因此d|r 因此d是(b,amodb)的公约数 假设d是(b,amodb)的公约数,则 d|b,d|r,但是a=kb+r 因此d也是(a,b)的公约数 因此(a,b)和(b,amodb)的公约数是一样的,其最大公约数也必然相等 所以若gcd(a,b)=1则a与b互质。 intgcd(longa,longb) {if(b==0)returna; returngcd(b,a%b);} (3)求乘法逆元: 因为需要计算私钥d=eˆ-1(modψ(n)),所以有函数longExtendedEuclid()计算d并返回d的值,这里用到扩展欧几里德算法。 大体思路与欧几里德算法一致: 如果gcd(a,b)=d,则存在m,n,使得d=ma+nb,称呼这种关系为a、b组合整数d,m,n称为组合系数。 当d=1时,有ma+nb=1,此时可以看出m是a模b的乘法逆元,n是b模a的乘法逆元。 longExtendedEuclid(longf,longd,long*result) {intx1,x2,x3,y1,y2,y3,t1,t2,t3,q; x1=y2=1;x2=y1=0;x3=(f>=d)? f: d;y3=(f>=d)? d: f; while (1){ if(y3==0){*result=x3;return0;} if(y3==1){*result=y2;return1;} 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)快速幂模算法: 在加密解密时都要用到类似AˆB(modC)的计算,当指数B较大时,如果先计算AˆB的值时间较慢,且结果过大会溢出。 依据模运算的性质(a*b)modn=((amodn)*(bmodn))modn可以将AˆB分解为较小几个数的乘积分别进行模运算 例如(3^999)可以分解为(3^512)*(3^256)*(3^128)*(3^64)*(3^32)*(3^4)*(3^2)*3 这样只要做16次乘法。 把999转为2进制数: 1111100111,其各位就是要乘的数。 所以程序中要有函数inta_b_Mod_c(longa,longb,longc)计算aˆbmodc的值并返回结果。 inta_b_Mod_c(longa,longb,longc) {intdigit[32];longi,k,resualt=1; i=0; while(b) {digit[i++]=b%2; b>>=1;} for(k=i-1;k>=0;k--) {resualt=(resualt*resualt)%c; if(digit[k]==1){resualt=(resualt*a)%c;} } returnresualt; } 2.总操作界面: 1.输入两个素数P,Q 2.输入公钥E 3.查看当前密钥信息 4.加密 5.解密 6.帮助 0.退出 三.程序实现流程图: (1)流程图: (2)各功能模块: 命令 对应函数 功能描述 1 input_P_Q 输入素数P,Q 2 input_E 输入公钥E 3 print_miyao 显示密钥信息 4 jiami 加密 5 jiemi 解密 6 print_help 帮助 四.程序测试: 1输入两个素数p=47,q=71则n=47*71=3337 2.输入e=79,计算得d=eˆ-1mod(p-1)(q-1)=79ˆ-1mod3220=1019因此公钥为(79,3337)私钥为(1019,3337) 3.输入明文688并加密 4.输入密文1570并解密 五.总结、改进思考: 1.大数类库的建立: 本程序作为RSA加密解密过程演示程序,变量均为long型,因此密钥长度较小,而RSA的安全性建立在密钥长度很长,大素数难以分解的前提上。 所以为了能够提高安全性,应该建立一个大数类库,对512位或1024位大数进行存取,及简单运算。 一个最容易理解的方法就是将大数用十进制表示,并将每一位(0–9)都做为一个单独的数用数组进行管理。 做加减乘除等运算时,人工的对其进行进、借位。 然而计算机对于10进制数的处理并不在行,而且表示非2n进制的数会浪费很多空间,所以应该采用8进制、16进制、32进制、64进制的表示法,使得每一位数字都能占据一个完整的内存空间。 目前绝大多数PC机都是基于32位运算的,所以采用2ˆ32进制表示大数将会很大提高计算机的处理效率。 现实中,就使用32位的整数数组进行存储每一位数,另设一个布尔值表示正负。 进行计算时常会遇到进位借位的情况,而且常常会超过2ˆ32次方,幸好目前的编译器都支持64位整数,可以满足(232-1)*(232-1)以内的运算,所以使用64位整数作为运算中间量将会是很好的选择。 大数除了加减乘除等基本运算以外,还有一些如赋值、比较、左右移位、或、与等,为了方便使用,我们可以利用面向对象的方法把大数进行封装,并利用C++的特性进行运算符重载,使它成为一个整体对象来进行操作。 这样我们就可像使用int一样来使用它了。 2.大素数随机生成,以及判断: 真正的RSA加密时密钥的生成应该是自动完成的,而不是用户手动制定p,q,e。 所以在使用大数类库后随之而来一个问题就是如何随机的生成两个大素数,以及大素数的判断。 由于素数有无穷多个,且没有固定的生成方式,所以大素数的生成基本是采用在一定范围内(比如奇数,且不会被小素数整除的)随机选取大数后再进行素数检测,直到有通过检测的数。 因此大数的素数检测算法就是关键了,如果按照之前的素数检测算法需要依次除2到√n的数,时间复杂度O(√n)太大。 所以我们要用更为快速的算法。 米勒拉宾测试是一个不确定的算法,只能从概率意义上判定一个数可能是素数。 是目前公认的最高效的素性测试之一。 大体步骤如下: 输入奇数n,判断n为素数或者合数。 计算r和R,使得 ,R奇。 随即选择a, 。 fori=0tor,计算 。 若 ,则输入合数。 若 ,则输入素数。 设j=max{i: },则输入素数。 若 ,则输出素数,否则输出合数。 参考书目: [1]刘嘉勇等《应用密码学》 [2]胡道元闵京华《网络安全》 [3]张四兰等《可信赖的高效素数生成和检验算法》 附程序代码: #include #include #include voidinput_P_Q(long&P,long&Q,long&N,long&N1); voidinput_E(long&E,long&D,longn1); voidprint_miyao(longe,longn,longd); voidjiami(longe,longn); voidjiemi(longd,longn); voidprint_help(); intsushu(longm); intgcd(longa,longb); longExtendedEuclid(longf,longd,long*result); inta_b_Mod_c(longa,longb,longc); voidmain() { longP=0,Q=0,E=0,N=0,N1=0,D=0; cout<<"==========================RSA模拟==========================="< cout<<"1.输入两个素数P,Q\n"; cout<<"2.输入公钥E\n"; cout<<"3.查看当前密钥信息\n"; cout<<"4.加密\n"; cout<<"5.解密\n"; cout<<"6.帮助\n"; cout<<"0.退出\n"; cout<<"\n输入你的选择: "; longch; do {cin>>ch; switch(ch) {case1: input_P_Q(P,Q,N,N1);break; case2: input_E(E,D,N1);break; case3: print_miyao(E,N,D);break; case4: jiami(E,N);break; case5: jiemi(D,N);break; case6: print_help();break; case0: break;} } while(ch);} intgcd(longa,longb) {if(b==0) returna; returngcd(b,a%b);} intsushu(longm) {inti; for(i=2;i*i<=m;i++) if(m%i==0)return0; return1;} longExtendedEuclid(longf,longd,long*result) {intx1,x2,x3,y1,y2,y3,t1,t2,t3,q; x1=y2=1;x2=y1=0;x3=(f>=d)? f: d;y3=(f>=d)? d: f; while (1) {if(y3==0) {*result=x3;return0;} if(y3==1) {*result=y2;return1;} 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;} } inta_b_Mod_c(longa,longb,longc) {intdigit[32];longi,k,resualt=1;i=0; while(b) {digit[i++]=b%2;b>>=1;} for(k=i-1;k>=0;k--) {resualt=(resualt*resualt)%c; if(digit[k]==1)resualt=(resualt*a)%c;} returnresualt; } voidinput_P_Q(long&P,long&Q,long&N,long&N1) {cout<<"输入第一个素数p: \n"; while (1) {if(cin>>P)break; else {cout<<"P应为数字,请重新输入: "< cin.clear();cin.ignore();} } while (1) {if(sushu(P))break; else {cout<<"P应为素数,请重新输入: "< cin.clear();cin.ignore();} cin>>P; } cout<<"输入第二个素数Q: \n"; while (1) {if(cin>>Q)break; else {cout<<"Q应为数字,请重新输入: "< cin.clear();cin.ignore();} } while (1) {if(sushu(Q))break; else {cout<<"Q应为素数,请重新输入: "< cin.clear();cin.ignore();} cin>>Q; } N=P*Q;N1=(P-1)*(Q-1); } voidinput_E(long&E,long&D,longn1) {if(n1==0) {cout<<"请先输入两个素数P,Q"< longz=0; cout<<"输入一个小于"< \n"; while (1) {if(cin>>E)break; else {cout<<"E应为数字,请重新输入: "< cin.clear();cin.ignore();} } while (1) {if(gcd(E,n1)==1)break; else {cout<<"E应与"< "< cin.clear();cin.ignore();} cin>>E; } if(ExtendedEuclid(E,n1,&z))D=z; elsecout<<"错误"< } voidprint_miyao(longe,longn,longd) {cout<<"公钥为: \n";cout<<"("< cout<<"公钥为: \n";cout<<"("< voidjiami(longe,longn) {if(e==0,n==0) {cout<<"请先输入密钥"< longc,m;cout<<"输入要加密的明文: \n"; while (1) {if(cin>>m)break; else {cout<<"明文应为数字,请重新输入: "< cin.clear();cin.ignore();} } while (1) {if(m else {cout<<"明文应小于"< "< cin.clear();cin.ignore();} } c=a_b_Mod_c(m,e,n);cout<<"密文为: "< } voidjiemi(longd,longn) {if(d==0,n==0) {cout<<"请先输入密钥"< longc,m;cout<<"输入要解密的密文: \n"; while (1) {if(cin>>c)break; else {cout<<"密文应为数字,请重新输入: "< cin.clear();cin.ignore();} } m=a_b_Mod_c(c,d,n);cout<<"明文为: "< } voidprint_help() { cout<<"1.输入两个素数P,Q\n"; cout<<"2.输入公钥E\n"; cout<<"3.查看当前密钥信息\n"; cout<<"4.加密\n"; cout<<"5.解密\n"; cout<<"6.帮助\n"; cout<<"0.退出\n"; }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- RSA 加密 简单 实现