RSA实验要求
实验目的
要求实现RSA的密钥生成、数据加密和解密。
实验要求
- 密钥生成包括随机生成两个大素数p,q,计算n=p×q和Φ(n)=(p-1)(q-1),然后选择与Φ(n)互素且小于Φ(n)的整数e,计算d=e-1mod Φ(n),最后得到公钥{e, n}和私钥{d, n}。要求p,q至少均大于1010, 将生成的整数p、q、n、e、d分别写入文件p.txt、q.txt、n.txt、e.txt、d.txt中。注意,所有整数都必须用16进制表示。必须将整数转化成字符串后再写入文件,例如素数p=6B1BCF(用16进制表示),则写入文件的应是字符串"6B1BCF"而非整数6B1BCF。
- 数据加密是指用私钥{e, n}对指定的明文进行加密。数据解密是指用公钥{d, n}对指定的明文进行解密。数据加密和解密有一组对应的测试数据,以便检查程序的正确性。要求以命令行的形式,指定明文文件、密钥文件的位置和名称以及加密完成后密文文件的位置和名称。加密时先分别从指定的明文文件、密钥文件中读取有关信息,然后进行加密,最后将密文写入指定的密文文件。注意,密文(一个整数)必须用16进制表示。必须将密文(一个整数)转化成字符串后再写入文件。
- 命令行的具体格式如下:
e3rsa -p plainfile -n nfile [-e efile] [-d dfile] -c cipherfile
参数:
-p plainfile 指定明文文件的位置和名称
-n nfile 指定存放整数n的文件的位置和名称
-e efile 在数据加密时,指定存放整数e的文件的位置和名称
-d dfile 在数据解密时,指定存放整数d的文件的位置和名称
-c cipherfile 指定密文文件的位置和名称 - 如果一个分组不足64bit,低位补0。
代码
BigInteger.h
#ifndef __BIGINTEGER_H__
#define __BIGINTEGER_H__
#include <string>
#include <vector>
#include <ostream>
class BigInteger {
public:
typedef long long long_t;
typedef unsigned base_t;
BigInteger() : is_negative(false) {
data.push_back(0); }// 默认为0
BigInteger(const BigInteger &); // 利用给定的大整数初始化
BigInteger(const std::string &);// 利用给定的十六进制字符串初始化
BigInteger(const long_t &); // 利用给定的long_t类型数据初始化
~BigInteger() {
}
BigInteger add(const BigInteger &); // 大整数加法
BigInteger subtract(const BigInteger &);// 大整数减法
BigInteger multiply(const BigInteger &) const;// 大整数乘法
BigInteger divide(const BigInteger &); // 大整数整除
BigInteger remainder(const BigInteger &); // 大整数取余
BigInteger mod(const BigInteger &); // 大整数取模
BigInteger divideAndRemainder(const BigInteger &, BigInteger &);// 大整数整除和取余
BigInteger pow(const BigInteger &); // 大整数幂乘
BigInteger modPow(const BigInteger &, const BigInteger &) const;// 大整数幂模运算
BigInteger modInverse(const BigInteger &);// 用扩展欧几里得算法求乘法逆元
BigInteger shiftLeft(const unsigned); // 移位运算,左移
BigInteger shiftRight(const unsigned); // 移位运算,右移
int compareTo(const BigInteger &) const;// 比较运算
bool equals(const BigInteger &) const;// 判断是否等于给定数
static BigInteger valueOf(const long_t &);// 将给定数转换为大整数并返回
std::string toString() const; // 将大整数转换为十六进制字符串
BigInteger abs() const; // 求大整数的绝对值
protected:
// 以下运算符重载函数主要用于像基本类型一样使用大整数类型
friend BigInteger operator + (const BigInteger &, const BigInteger &);
friend BigInteger operator - (const BigInteger &, const BigInteger &);
friend BigInteger operator * (const BigInteger &, const BigInteger &);
friend BigInteger operator / (const BigInteger &, const BigInteger &);
friend BigInteger operator % (const BigInteger &, const BigInteger &);
friend bool operator < (const BigInteger &, const BigInteger &);
friend bool operator > (const BigInteger &, const BigInteger &);
friend bool operator == (const BigInteger &, const BigInteger &);
friend bool operator <= (const BigInteger &, const BigInteger &);
friend bool operator >= (const BigInteger &, const BigInteger &);
friend bool operator != (const BigInteger &, const BigInteger &);
// 重载版本,使其能用于long_t类型
friend BigInteger operator + (const BigInteger &, const long_t &);
friend BigInteger operator - (const BigInteger &, const long_t &);
friend BigInteger operator * (const BigInteger &, const long_t &);
friend BigInteger operator / (const BigInteger &, const long_t &);
friend BigInteger operator % (const BigInteger &, const long_t &);
friend bool operator < (const BigInteger &, const long_t &);
friend bool operator > (const BigInteger &, const long_t &);
friend bool operator == (const BigInteger &, const long_t &);
friend bool operator <= (const BigInteger &, const long_t &);
friend bool operator >= (const BigInteger &, const long_t &);
friend bool operator != (const BigInteger &, const long_t &);
friend std::ostream & operator << (std::ostream &, const BigInteger &);
BigInteger operator = (const std::string & str) {
return (*this) = BigInteger(str); }
BigInteger operator = (const long_t & num) {
return (*this) = BigInteger(num); }
private:
BigInteger trim(); // 去掉高位无用的0
int hexToNum(char); // 十六进制字符转换为十进制数
public:
static const int base_bit = 5; // 2^5=32,大整数每位存储的二进制位数
static const int base_char = 8; // 组成大整数的一位需要的十六进制位数
static const int base_int = 32; // 大整数一位对应的二进制位数
static const int base_num = 0xffffffff;// 截取低位的辅助
static const int base_temp = 0x1f; // 截取模32的余数的辅助
static const BigInteger ZERO; // 大整数常量0
static const BigInteger ONE; // 大整数常量1
static const BigInteger TWO; // 大整数常量2
static const BigInteger TEN; // 大整数常量10
private:
bool is_negative;// 是否为负数
std::vector<base_t> data;// 按位数据存储,高位在后
class bit {
// 便于大整数运算的二进制处理类
public:
bit(const BigInteger &);// 根据大整数初始化
size_t size() {
return length; } // 返回大整数对应的二进制位数
bool at(size_t); // 返回第i位二进制是否为1
private:
std::vector<base_t> bit_vector; // 二进制数据存储,每一个元素对应32位二进制
size_t length; // 二进制的总位数
};
friend class RSA; // RSA为其友元类
};
#endif // __BIGINTEGER_H__#pragma once
BigInteger.cpp
#include <algorithm>
#include <cassert>
#include <cctype>
#include "BigInteger.h"
// 以下表示为静态常量赋值
const BigInteger BigInteger::ZERO = BigInteger(0);
const BigInteger BigInteger::ONE = BigInteger(1);
const BigInteger BigInteger::TWO = BigInteger(2);
const BigInteger BigInteger::TEN = BigInteger(10);
/**
* 函数功能:根据给定的大整数构造一个新的大整数
* 参数含义:val代表给定的大整数
*/
BigInteger::BigInteger(const BigInteger & val) {
*this = val;
}
/**
* 函数功能:根据给定的十六进制字符串数据构造一个大整数
* 参数含义:str代表给定的数据
*/
BigInteger::BigInteger(const std::string & str) : is_negative(false) {
std::string t(str);
if (t.size() && t.at(0) == '-') {
if (t.size() > 1)
is_negative = true;
t = t.substr(1);
}
int cnt = (8 - (t.size() % 8)) % 8;// 数的长度不是8的倍数,补足0
std::string temp;
for (int i = 0; i<cnt; ++i)
temp.push_back('0');
t = temp + t;
for (size_t i = 0; i<t.size(); i += base_char) {
base_t sum = 0;
for (int j = 0; j<base_char; ++j) {
// 8位十六进制组成大整数的一位
char ch = t[i + j];
int num = hexToNum(ch);
sum = ((sum << 4) | (num));
}
data.push_back(sum);
}
reverse(data.begin(), data.end());// 高位在后
*this = trim();// 去除高位的0
}
/**
* 函数功能:根据给定的long_t类型数据构造一个大整数
* 参数含义:num代表给定的数据
*/
BigInteger::BigInteger(const long_t & num) : is_negative(false) {
long_t t = num;
if (t < 0) {
is_negative = true;
t = -t;
}
do {
base_t temp = (t&base_num); // 每次截取低32位
data.push_back(temp);
t >>= base_int;
} while (t);
}
/**
* 函数功能:大整数加法运算
* 参数含义:val代表加数
*/
BigInteger BigInteger::add(const BigInteger & val) {
BigInteger ans(*this);
if (ans.is_negative == val.is_negative) {
// 同号
int len = val.data.size() - ans.data.size();
while ((len--) > 0) // 被加数位数少,高位补0
ans.data.push_back(0);
int carry = 0; // 进位
for (size_t i = 0; i<val.data.size(); ++i) {
base_t temp = ans.data[i];
ans.data[i] += val.data[i] + carry; // 无符号数相加,超出取其余数
// 进位:一种是有无进位都超出,一种是有进位才超出(比如十进制相加,9+9+1,得9,9+0+0,得9)
carry = (temp>ans.data[i] ? 1 : (temp>(temp + val.data[i]) ? 1 : 0));
}
for (size_t i = val.data.size(); i<ans.data.size() && carry != 0; ++i) {
// 还有进位
base_t temp = ans.data[i];
ans.data[i] += carry;
carry = temp > ans.data[i];
}
if (carry) // 还有进位
ans.data.push_back(carry);
}
else {
// 异号
BigInteger a = abs();
BigInteger b = val.abs();
int flag = a.compareTo(b);
// 绝对值相等,则结果为0,否则用绝对值大的减去小的,符号随绝对值大的
if (flag == -1) {
ans = b.subtract(a);
ans.is_negative = val.is_negative;
}
else if (flag == 0)
ans = ZERO;
else {
ans = a.subtract(b);
ans.is_negative = is_negative;
}
}
return ans;
}
/**
* 函数功能:大整数减法运算
* 参数含义:val代表减数
*/
BigInteger BigInteger::subtract(const BigInteger & val) {
BigInteger ans(*this);
BigInteger a = abs();
BigInteger b = val.abs();
if (ans.is_negative == val.is_negative) {
// 同号
int flag = a.compareTo(b);
if (flag == 1) {
// a的绝对值大于b的绝对值,直接减
int borrow = 0; // 借位
// 大数减小数
for (size_t i = 0; i<val.data.size