C++实现RSA加密解密

RSA实验要求

实验目的

要求实现RSA的密钥生成、数据加密和解密。

实验要求

  1. 密钥生成包括随机生成两个大素数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。
  2. 数据加密是指用私钥{e, n}对指定的明文进行加密。数据解密是指用公钥{d, n}对指定的明文进行解密。数据加密和解密有一组对应的测试数据,以便检查程序的正确性。要求以命令行的形式,指定明文文件、密钥文件的位置和名称以及加密完成后密文文件的位置和名称。加密时先分别从指定的明文文件、密钥文件中读取有关信息,然后进行加密,最后将密文写入指定的密文文件。注意,密文(一个整数)必须用16进制表示。必须将密文(一个整数)转化成字符串后再写入文件。
  3. 命令行的具体格式如下:
    e3rsa -p plainfile -n nfile [-e efile] [-d dfile] -c cipherfile
    参数:
    -p plainfile 指定明文文件的位置和名称
    -n nfile 指定存放整数n的文件的位置和名称
    -e efile 在数据加密时,指定存放整数e的文件的位置和名称
    -d dfile 在数据解密时,指定存放整数d的文件的位置和名称
    -c cipherfile 指定密文文件的位置和名称
  4. 如果一个分组不足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()
  • 7
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值