2. 程序编写。 (30分钟-3小时)
(书籍P40) 。同学们至少实现2.1 与 2.2;实现RSA完整算法的同学,总成绩的基础上加10分。请大家把编程思想与程序实现(源码),发表在CSDN博文上。
2.1: 判断一个正整数是否为质数的算法。函数签名如下
int isPrime(long a)
输入:一个长整数a
输出:返回1(为质数),返回0(非质数)
2.2: 随机生成一个n bit位的长整数。函数签名如下
long createRndInteger(int n)
输入:随机数bit位的长度为n(解释:3bit位,则最大为111,最小为100;n bit位,则该数字二进制长度为n)
输出:返回该随机数
2.3:随机生成一个n bit位的长质数。函数前面如下
long createRndPrime(int n)
输入:随机质数的bit位长度为n
输出:nbit位长度的质数
关键为使用随机化算法判断一个长整数是否为素数(P33)。
2.4:公开密钥(N,e)的生成算法。 关键为怎样选择一个与(p-1)(q-1)互质的数e。
(p-1)(q-1)的逆元,见书籍25页。
2.6:RSA加密算法。对消息m=25进行加密,生成密文c。
2.7:RSA解密算法。对密文c进行解密。
算法的C++实现如下:
RSA.H:
#ifndef RSA_H
#define RSA_H
class RSA
{
private:
long p;
long q;
long N;
long N2;
double encrypted;
int e;
int d;
public:
RSA();
//求两个数的最大公因数
long GCD(long a, long b);
//求一个数是否为质数,true:是, false:其它
bool IsPrime(long num);
//随机生成一个n bit位长度整数,long为32位,所以bit限制在32位内
long CreateRandInteger(int n);
//随机生成一个n bit位长度的质数
long CreateRandPrime(int n);
//计算public and private keys
void CalKeys(int n);
void RSAEncrypt(int message);
void RSADecrypt();
};
#endif
RSA.CPP
#include "RSA.h"
#include <iostream>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
using namespace std;
RSA::RSA()
{
p = 0;
q = 0;
N = 0;
N2 = 0;
encrypted = 0;
e = 0;
d = 0;
}
//求两个数的最大公因数
long RSA::GCD(long a, long b)
{
long temp;
if (!(a > 0 && b > 0))
{
cout << "Invalid a or b!" << endl;
exit(0);
}
if (b > a)
{
temp = b;
b = a;
a = temp;
}
while ((temp = a % b) != 0)
{
a = b;
b = temp;
}
return b;
}
//求一个数是否为质数,true:是, false:其它
bool RSA::IsPrime(long num)
{
if (num < 1)
{
cout << "Invalid input number:not positive number" << endl;
exit(0);
}
else if (1 == num)
{
cout << "1 is either a prime or a composite number!" << endl;
exit(0);
}
for (int i = 2; i <= sqrt(num); i++)
{
if (0 == num % i)
{
return false;
}
}
return true;
}
//随机生成一个n bit位长度整数,long为32位,所以bit限制在32位内
long RSA::CreateRandInteger(int n)
{
if (n < 1 || n > 32)
{
cout << "Invalid bits!" << endl;
exit(0);
}
int* temp = new int[n];
temp[0] = 1;
//逐位生成整数的各位,数组下标[0--n-1]表示生成的数的最高位到最低位
for (int i = 1; i < n; i++)
{
//因为随机数的产生依赖于系统时间,为了防止在时间单位内CPU做大量的无用重复计算,所以休眠25ms
Sleep(25);
srand(i * (unsigned int)time(NULL));
temp[i] = rand() % 2;
}
//将生成的数以十进制显示
unsigned long bigInt = 0;
for (int j = 0; j < n; j++)
{
if (1 == temp[j])
{
bigInt += temp[j] << (n-j-1);
}
}
delete[] temp;
return bigInt;
}
//随机生成一个n bit位长度的质数
long RSA::CreateRandPrime(int n)
{
unsigned long temp = CreateRandInteger(n);
while (!IsPrime(temp))
{
temp = CreateRandInteger(n);
}
return temp;
}
void RSA::CalKeys(int n)
{
//unsigned long p = 0;
//unsigned long q = 0;
//计算p、q的值
p = CreateRandPrime(n);
q = CreateRandPrime(n);
while (p == q)
{
q = CreateRandPrime(n);
}
N = p * q;
N2 = (p-1) * (q-1);
//unsigned long N = p * q;
//unsigned long N2 = (p-1) * (q-1);
//计算加密指数e
//int e;
for (e = 2; ; e++)
{
if (1 == GCD(e, N2))
{
break;
}
}
//计算解密指数d
//int d;
for (int i = 1; ; i++)
{
if (0 == (N2 * i + 1) % e)
{
d = (N2 * i + 1) / e;
break;
}
}
cout << n << " bits integer number's RSA public and private keys: " << endl;
cout << "PublicKey(" << N << ", " << e << ")" << endl;
cout << "PrivateKey(" << N << ", " << d << ")" << endl;
}
void RSA::RSAEncrypt(int message)
{
encrypted = fmod(pow(message, e), N);
cout << "The original message: " << message << endl;
cout << "After encryption: " << endl;
cout << "The encrypted message: " << encrypted << endl;
}
void RSA::RSADecrypt()
{
encrypted = fmod(pow(encrypted, d), N);
cout << "After decryption: " << endl;
cout << "The original message: " << encrypted << endl;
}
main.cpp:
#include "RSA.h"
void main()
{
//cout << GCD(1035, 759) << endl;
//cout << IsPrime(12) << endl;
//CreateRandInteger(32);
//cout << CreateRandPrime(32) << endl;
RSA rsa;
rsa.CalKeys(4);
rsa.RSAEncrypt(25);
rsa.RSADecrypt();
}
该算法已经能够成功的求出RSA的公钥和私钥,用系统自带的计算器也已经验证成功了,但程序的RSAEncrypt()和RSADecrypt()仍然有一点小问题,不能正常输出加/解密后的结果,这个问题还在解决中。还有,程序要运行比较长的时间才能求出
公钥和私钥,这一点还需要改进。
经过测试发现,当生成的数的位数超过4bit之后,输出结果就显示不正常,调试后发现,是在进行RSA加/解密运算时要执行高次幂运算,产生的运算结果超过64位,导致溢出,所以显示结果不正常,解决方案还在探索中...