RSA密码算法设计

实验三 RSA算法设计和实现

(4学时)

一、实验目的

掌握并实现RSA算法。

 

二、实验内容

利用C\C++实现RSA算法的加、解密运算。

具体包括:

1) 利用扩展的EUCLID计算 a mod n 的乘法逆元;

2) Miller-Rabin素性测试算法对一个给定的大数进行测试;

3) 实现的运算,并计算;

4) 利用Fermat定理手工计算,并与3)计算的结果对比;

5) 实现RSA算法。并对"I LOVE THE PEOPLE'S REPUBLIC OF CHINA"加解密。说明:为了方便实现,分组可以小一点,比如两个字母一组。

 

字母及其数字编码

字母及其数字编码

空格    00

N        14

A       01

O        15

B       02

P        16

C       03

Q        17

D       04

R        18

E       05

S        19

F       06

T        20

G       07

U        21

H       08

V        22

I        09

W        23

J        10

X        24

K       11

Y        25

L        12

Z        26

M       13

 

三、实验原理

1RSA算法

1) 密钥的产生

① 选两个保密的大素数p和q

② 计算n=p×qφ(n)=(p-1)(q-1),其中φ(n)是n的欧拉函数值。

③ 选一整数e满足1<e<φ(n)且gcd(φ(n),e)=1

④ 计算d满足d·e≡1 mod φ(n),即d是e在模φ(n)下的乘法逆元,因e与φ(n)互素,由模运算可知,它的乘法逆元一定存在。

⑤ 以{e,n}为公开钥,{d,n}为秘密钥。

2) 加密

加密时首先将明文比特串分组,使得每个分组对应的十进制数小于n即分组长度小于log2n然后对每个明文分组m作加密运算: c≡me mod n

3) 解密

对密文分组的解密运算为: 

mcd mod n

 

2、涉及的计算

1) 欧几里得(Euclid)算法和扩展的欧几里得(Euclid)算法求乘法逆元

欧几里得(Euclid)算法是数论中的一个基本技术,是求两个正整数的最大公因子的简化过程。而推广的Euclid算法不仅可求两个正整数的最大公因子,而且当两个正整数互素时,还可求出其中一个数关于另一个数的乘法逆元。

欧几里得(Euclid)算法描述如下:

Euclidf, d)  //求最大公因子

1. X←f; Y←d;

2. if Y=0 then return X=gcd(f,d)

3. R=X mod Y

4. X=Y

5. Y=R

6. goto 2

 

扩展的欧几里得(Euclid)算法描述如下:

Extended Euclid(f, d) 设 f >d) //扩展的Euclid算法,求出d-1 mod f ,使得d*d-1≡1modf 

1. (X1,X2,X3)←(1,0,f);(Y1,Y2,Y3)←(0,1,d);

2.  if Y3=0 then return  X3=gcd(f, d)no inverse;

3.  if Y3=1 then return  Y3=gcd(f, d)Y2=d-1 mod f;

4. Q=INT[X3/Y3] 

5. (T1,T2,T3)←(X1-QY1,X2-QY2,X3-QY3);

6. (X1,X2,X3)←(Y1,Y2,Y3);

7. (Y1,Y2,Y3)←(T1,T2,T3);

8. goto 2

 

2) 快速指数算法:给定a,m,n,求d=am mod n, m需要先转换为二进制表示:bkbk-1……b0

算法描述如下:

d=1

For  i=k Downto 0   

DO {

d=(d×d) mod n;

if bi=1 then  {

d=(d×a) mod n

}

}

return d.

 

3) 素性检测,其原理基于以下定理:

费尔玛定理 (Fermat) :若p是素数,a是正整数且gcd(a, p)=1则ap-1≡1 mod p

引理 :如果p为大于2的素数,则方程x2≡1(mod p)的解只有x≡1和x≡-1

引理的逆否命题为:如果方程x2≡1 mod p有一解x0∈{-1,1},那么p不为素数

根据上述定理,得到下面的素性检测算法。

任意选择正整数a ,计算d=a n-1 mod nn-1需要先转换为二进制形式bkbk-1……b0;

为了确定一个数是否素数,此算法需要多次执行,可选择5个不同的a重复执行下列算法,如果每次均返回true 则以很高的几率认为n是素数,否则,不是素数。

 

Witness(a,n)  

for i=k downto 0 do

   {

x←d;

d←(d×d) mod n;

if d=1 and(x≠1)and(x≠n-1)then return False;

if bi=1 then d←(d×a) mod n

   }

if d≠1 then return False;

return True.

 



实现代码一:

//devc++可以直接运行 ,其它编译器运行时可能要修改部分代码 
#include <iostream>
#include <vector>
#include <string.h>
using namespace std;

//n大于a
int Euclid(int a,int n){
	int x,y,r;
	x=n;y=a;
	for(int i=0;;){
		if(y==0)
			return x;
		if(y==1)
			return y;
		r=x%y;
		x=y;
		y=r;
	}
}

//利用扩展的EUCLID计算a mod n的乘法逆元
double extenEuclid(double a,double n){
	double x1=1,x2=0,x3=n,y1=0,y2=1,y3=a,Q;
	double t1,t2,t3;
	for(int i=0;;){
		if(y3==0){
			return x3;
			cout<<"no reverse"<<endl;
		}
		if(y3==1)
			return y2;
		Q=int(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;
	}
}

//Miller-Rabin素性测试算法对一个给定的大数进行测试
bool Rabin(int a,int n){
	vector<int> b;
	unsigned int N=n-1;
	for(int i=0,j=1;; i++){//将n-1表示成二进制形式
		if(j>N)
			break;
		if( (N>> i) & (unsigned int)1 ){
			b.push_back(1);
			return true;
		}
		else{
			b.push_back(0);
			return false;
		}
		j*=2;
	}	
}

void transfer(char cypher[],double c[]){
	int m[100]={0};
	for(int i=0,j=0;cypher[j]!='\0';i+=2){
		if(cypher[j]==' '){
			m[i]=0;m[i+1]=0;
		}
		else{
			m[i]=cypher[j]-64;
			if(m[i]<10){
				m[i+1]=m[i];
				m[i]=0;
			}
			else{
				m[i+1]=m[i]%10;
				m[i]=m[i]/10;
			}
		}
		j++;
	}
	for(int k2=0;k2<2*strlen(cypher);k2++)
		cout<<m[k2];
	cout<<endl;
	//int c[100]={0};
	int n,k;
	for(k=0,n=0;k<2*strlen(cypher);k+=4){
		c[n]=m[k]*1000+m[k+1]*100+m[k+2]*10+m[k+3];
		n++;
	}
	for(;c[n-1]<1000;)//最后一个数填充零,不过此例可要可不要
		c[n-1]*=10;
}

double quickindex1(double a,double m,double n){//实现a^m mod n 的运算 {
	vector<int>b;
	unsigned int N=m;
	for(int ii=0,j=1;;ii++){
		if(j>N)
		break;
		if((N>>ii)& (unsigned int) 1)
			b.push_back(1);			
		else
			b.push_back(0);
		j*=2;
	}
	double c=0,d=1;
	for(int i=b.size()-1;i>=0;i--){
		c*=2;
		d=(d*d)-int((d*d)/n)*n;
		if(b[i]==1){
			c+=1;
			d=(d*a)-int((d*a)/n)*n;
		}
	}
	return d;
}

//主函数
int main(){
	double c[100]={0};
	double a[100]={0};
	double b[100]={0};
	char cypher[]="I LOVE THE PEOPLE'S REPUBLIC OF CHINA";//对“我爱中华人民共和国”加解密
	transfer(cypher,c);//字母变数字的过程
	for(int k1=0;c[k1]!='\0';k1++)
		cout<<c[k1]<<" ";//选取两个素数p=563,q=823
	double n=0, fn=0, p=563,q=823,d=0;
	n=p*q;fn=(q-1)*(p-1);//选e与fn互素
	double e; 
	for(e=2;e<fn;e+=3){
		if(Euclid(e,fn)==1)
			break;
	}
	d=extenEuclid(e,fn);
	cout<<endl<<"密码和密钥e d and n:";
	cout<<e<<" "<<d<<" "<<n<<endl;

	//加密过程
	cout<<endl<<"加密:";
	for(int i=0;c[i]!='\0';i++){
		a[i]=quickindex1(c[i],e,n);
		cout<<a[i]<<" ";
	}
	//解密过程
	cout<<endl<<"解密:";
	for(int j=0;a[j]!='\0';j++){
		b[j]=quickindex1(a[j],d,n);
		cout<<b[j]<<" ";
	}

	cout<<endl;
	return 0;
}

实现代码二:

#include<iostream>
#include<math.h>
#include<stdio.h>
using namespace std;
typedef int Elemtype;
Elemtype p, q, e;
Elemtype fn;
Elemtype m, c;
int flag = 0;
typedef void(*Msghandler)(void);
struct MsgMap
{
    char ch;
    Msghandler handler;
};

/*公钥*/
struct PU
{
    Elemtype e;
    Elemtype n;
} pu;

/*私钥*/
struct PR
{
    Elemtype d;
    Elemtype n;
} pr;

/*判定一个数是否为素数*/
bool test_prime(Elemtype m)
{
    if(m <= 1)
    {
        return false;
    }
    else if(m == 2)
    {
        return true;
    }
    else
    {
        for(int i = 2; i <= sqrt(m); i++)
        {
            if((m % i) == 0)
            {
                return false;
                break;
            }
        }
        return true;
    }
}

/*将十进制数据转化为二进制数组*/
void switch_to_bit(Elemtype b, Elemtype bin[32])
{
    int n = 0;
    while(b > 0)
    {
        bin[n] = b % 2;
        n++;
        b /= 2;
    }
}

/*初始化主界面*/
void Init()
{
    cout << "1.设置密钥" << endl;
    cout << "2.加密" << endl;
    cout << "3.解密" << endl;
    cout << "4.退出" << endl;
    //cout << "输入选择:  " ;
}

/*将两个数排序,大的在前面*/
void order(Elemtype &in1, Elemtype &in2)
{
    Elemtype a = (in1 > in2 ? in1 : in2);
    Elemtype b = (in1 < in2 ? in1 : in2);
    in1 = a;
    in2 = b;
}

/*求最大公约数*/
Elemtype gcd(Elemtype a, Elemtype b)
{
    order(a, b);
    int r;
    if(b == 0)
    {
        return a;
    }
    else
    {
        while(true)
        {
            r = a % b;
            a = b;
            b = r;
            if(b == 0)
            {
                return a;
                break;
            }
        }
    }
}

/*用扩展的欧几里得算法求乘法逆元*/
Elemtype extend_euclid(Elemtype m, Elemtype bin)
{
    order(m, bin);
    Elemtype a[3], b[3], t[3];
    a[0] = 1, a[1] = 0, a[2] = m;
    b[0] = 0, b[1] = 1, b[2] = bin;
    if(b[2] == 0)
    {
        return a[2] = gcd(m, bin);
    }
    if(b[2] == 1)
    {
        return b[2] = gcd(m, bin);
    }
    while(true)
    {
        if(b[2] == 1)
        {
            return b[1];
            break;
        }
        int q = a[2] / b[2];
        for(int i = 0; i < 3; i++)
        {
            t[i] = a[i] - q * b[i];
            a[i] = b[i];
            b[i] = t[i];
        }
    }
}

/*快速模幂算法*/
Elemtype modular_multiplication(Elemtype a, Elemtype b, Elemtype n)
{
    Elemtype f = 1;
    Elemtype bin[32];
    switch_to_bit(b, bin);
    for(int i = 31; i >= 0; i--)
    {
        f = (f * f) % n;
        if(bin[i] == 1)
        {
            f = (f * a) % n;
        }
    }
    return f;
}

/*产生密钥*/
void produce_key()
{
    cout << "输入素数 p 和 q:";
    cin >> p >> q;
    while(!(test_prime(p) && test_prime(q)))
    {
        cout << "输入错误,请重新输入!" << endl;
        cout << "输入素数 p 和 q:";
        cin >> p >> q;
    };
    pr.n = p * q;
    pu.n = p * q;
    fn = (p - 1) * (q - 1);
    cout << "fn为:" << fn << endl;
    cout << "输入随机数e:";
    cin >> e;
    while((gcd(fn, e) != 1))
    {
        cout << "e输入错误,请重新输入!" << endl;
        cout << "输入随机数e:";
        cin >> e;
    }
    pr.d = (extend_euclid(fn, e) + fn) % fn;
    pu.e = e;
    flag = 1;
    cout << "公钥(e,n):" << pu.e << "," << pu.n << endl;
    cout << "私钥d:" << pr.d << endl;
    cout << "请输入下一步操作序号:" << endl;
}

/*加密*/
void encrypt()
{
    if(flag == 0)
    {
        cout << "setkey first:" << endl;
        produce_key();
    }
    cout << "输入明文 m:";
    cin >> m;
    c = modular_multiplication(m, pu.e, pu.n);
    cout << "密文c 为:" << c << endl;
    cout << "请输入下一步操作序号:" << endl;
}

/*解密*/
void decrypt()
{
    if(flag == 0)
    {
        cout << "setkey first:" << endl;
        produce_key();
    }
    cout << "输入密文 c:";
    cin >> c;
    m = modular_multiplication(c, pr.d, pr.n);
    cout << "明文m 为:" << m << endl;
    cout << "请输入下一步操作序号:" << endl;
}

/*消息映射*/
MsgMap Messagemap[] =
{
    {'1', produce_key},
    {'3', decrypt},
    {'2', encrypt},
    {'4', NULL}
};

/*主函数,提供循环*/
int main()
{
    Init();
    char d;
    while((d = getchar()) != '4')
    {
        int i = 0;
        while(Messagemap[i].ch)
        {
            if(Messagemap[i].ch == d)
            {
                Messagemap[i].handler();
                break;
            }
            i++;
        }
    }
    return 0;
}


  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
rsa算法设计程序 #if !defined(AFX_RSAA_H__081D9EE0_1245_11D5_80AC_0000E8810675__INCLUDED_) #define AFX_RSAA_H__081D9EE0_1245_11D5_80AC_0000E8810675__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 // RsaA.h : header file // #include<stdio.h> #include<stdlib.h> #include<string.h> #include<time.h> const DATALENGTH=350; //大数类型的长度 const MLENGTH=10; //质数的长度 const TESTNUM=30; //测试质数时的比较的次数 const SKLENGTH=4; //私钥的长度 typedef signed char byteint[DATALENGTH]; //定义大数类型 typedef signed char mtype[MLENGTH]; //定义质数的大数类型 //extern "C" __declspec(dllexport) void RsaAGenKeys(CString& pk,CString& sk,CString& R); //提供给服务器使用的秘钥产生函数 //extern "C" __declspec(dllexport) int RsaAEncrypt(CString& source,const char* key,const char* R,CStringArray& result);//加密 //extern "C" __declspec(dllexport) CString RsaADecrypt(CStringArray& source,const char* sk,const char* R);//解密 ///////////////////////////////////////////////////////////////////////////// // CRsaA command target //实现RSA算法的类 class CRsaA : public CCmdTarget { DECLARE_DYNCREATE(CRsaA) CRsaA(); // protected constructor used by dynamic creation // 成员函数 private: void InitInt(void); //基本数据常量的初始化 int IntValid(byteint validtemp); //返回大数validtemp的非零位的个数 int IntCmp(byteint A,byteint B); //比较大数A和B是否相等 //自定义类型的基本运算 void Plus(byteint A,byteint B,byteint C); //C=A+B void Substract(byteint SA,byteint SB,byteint SC); //SC=SA-SB void Multiply(byteint A,byteint B,byteint C); //C=A*B void SetMode(byteint A,byteint B,byteint C,byteint D);//C=A%B int PowerMode(byteint A,byteint C,byteint D,signed char flag[400]);//computing A^B mod C-->D void IntRandom(byteint RandomA,int num); //随机产生一个大数 void LoadInt(byteint A,mtype B); //将质数类型转换为大数类型 void TransBi(byteint B,signed char flag[400]); //将大数B转换为二进制形式 void Mdata(); //产生用于生成质数中进行比较的数 int Prime(byteint Prm); //产生一个长度为MLENGTH的质数 int ComputingPK(byteint Rvalue,byteint SK,byteint PK); //计算公钥PK void ComputingR(byteint p,byteint q,byteint R); //计算模值R void ComputingRvalue(byteint p,byteint q,byteint Rvalue); //计算$(r) void IntCpy(byteint A1,byteint B1); //将大数B1的值拷贝到大数A1中 void SetZero(byteint A); //将大数A清零 CString PrtInt(byteint A); //将一个大数类型转换为一个CString类型 int Getinput(byteint result,CString input); //将字符串转换为对应的大数形式 int Getinput1(byteint result,unsigned long input); //将长整形数转换为对应的大数形式 void RsaDo(byteint source,byteint R,byteint key,byteint desti); //实现加解密 unsigned long Os2ip(unsigned char* pstr); CString Ip2os(CString str); public: void GenKeys(CString& pk,CString& sk,CString& R); //提供给服务器使用的秘钥产生函数 int RsaEncrypt(CString& source,const char* key,const char* R,CStringArray& result);//加密 CString RsaDecrypt(CStringArray& source,const char* sk,const char* R);//解密 void GenKeysTable(); //生成秘钥对文件 void LoadKeysFromFile(CString& r,CString& sk,CString& pk); //成员变量 private: byteint ONEVALUE; byteint ZEROVALUE; byteint TWOVALUE; byteint EIGHTVALUE; //O,1,2,8 constant mtype Model[TESTNUM]; //TESTNUM big number to be compared mtype mZEROVALUE,tempModel; //0 constant signed char flag[400]; // Operations public: // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CRsaA) //}}AFX_VIRTUAL // Implementation //protected: virtual ~CRsaA(); // Generated message map functions //{{AFX_MSG(CRsaA) // afx_msg LONG OnComputing(WPARAM wParam, LPARAM lParam); // NOTE - the ClassWizard will add and remove member functions here. //}}AFX_MSG DECLARE_MESSAGE_MAP() }; ///////////////////////////////////////////////////////////////////////////// //{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations im

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值