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 
#include 
#include 
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"< 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<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<

实现代码二:

#include
#include
#include
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;
}


你可能感兴趣的:(计算机密码学)