ElGamal 密码算法(不要求大数)

ElGamal加密体制的公私密钥生成过程如下:

 

1.加密过程

 

2.解密过程

 

输入

加密:

第一行输入0,表示加密操作

第二行输入素数p

第三行输入生成元g

第四行输入私钥

第五行输入明文(明文中的字母按照英文字母表a=00,b=01,…,z=25编码)

第六行输入对应的随机数

解密:

第一行输入1,表示解密操作

第一行输入素数p

第二行输入私钥x

第三行输入密文

输出

加密:

第一行输出公钥中的y

第二行输出密文

解密:

 输出明文

输入样例1 <-复制

0
13171
2
23
bupt
31 16

输出样例1

11852
(4782,8218) (12852,4511)

输入样例2 <-复制

1
13171
23
(4782,8218) (12852,4511)

输出样例2

bupt

提示

 数据格式为十进制

#include <iostream>
#include <string>
#include <stack>
using namespace std;
int getlen(int num_1) {
	int num = num_1;
	int count = 0;
	while (num != 0) {
		num /= 10;
		count++;
	}
	return count;
}
void extend_gcd(long long a, long long b, long long& x, long long& y) { //求逆元的调用方法
	if (b == 0) {
		x = 1, y = 0;
		return;
	}
	extend_gcd(b, a % b, x, y);
	long long tmp = x;
	x = y;
	y = tmp - (a / b) * y;
}
long long mod_inverse(long long a, long long mod) {//求逆元的外部调用函数
	long long x, y;
	extend_gcd(a, mod, x, y);
	while (x < 0) {
		x = x + mod;
	}
	return x;
}
int main() {
	int operate, p, g, x, y, c1, c2;
	string ming;
	cin >> operate;
	if (operate == 0) {
		cin >> p >> g >> x >> ming;
		y = g;
		for (int i = 1; i < x; i++) {
			y = y * g;
			y %= p;
		}
		cout << y << endl;
		int len_1 = ming.length();
		int len = getlen(p) - 1;
		int group = len_1 * 2 / len;
		int* r = new int[group];
		for (int i = 0; i < group; i++) {
			cin >> r[i];
		}
		for (int i = 0; i < group; i++) {
			int c, c_1, c_2;
			c = 0;
			for (int j = i * len / 2; j < (i + 1) * len / 2; j++) {
				int num = ming[j] - 'a';
				c = c * 100 + num;
			}
			c_1 = g;
			for (int j = 1; j < r[i]; j++) {
				c_1 = c_1 * g;
				c_1 %= p;
			}
			c_2 = c * y;
			c_2 %= p;
			for (int j = 1; j < r[i]; j++) {
				c_2 = c_2 * y;
				c_2 %= p;
			}
			if (i != group) {
				cout << "(" << c_1 << "," << c_2 << ") ";
			}
			else {
				cout << "(" << c_1 << "," << c_2 << ")";
			}
		}
	}
	else if (operate == 1) {
		string Miwen;
		cin >> p >> x;
		getchar();
		getline(cin, Miwen);
		int len = Miwen.length();
		int len_1 = getlen(p) - 1;
		int flag = 0;
		int num = 0;
		int c1, c2;
		for (int i = 0; i < len; i++) {
			if (Miwen[i] >= '0' && Miwen[i] <= '9') {
				num = num * 10 + (Miwen[i] - '0');
			}
			if (Miwen[i] == ',') {
				c1 = num;
				num = 0;
			}
			if (Miwen[i] == ')') {
				c2 = num;
				num = 0;
				int fenmu = c1;
				for (int j = 1; j < x; j++) {
					fenmu = fenmu * c1;
					fenmu %= p;
				}
				fenmu = mod_inverse(fenmu, p);
				int m = (c2 * fenmu) % p;
				string newmi = to_string(m);
				int newlen = newmi.length();
				stack<char> chnum;
				for (int i = newlen - 1; i >= 0; i-=2) {
					if (i != 0) {
						int number = 0;
						number = (newmi[i-1] - '0') * 10 + (newmi[i] - '0');
						char ch = 'a' + number;
						chnum.push(ch);
						if (i == 1) {
							while (!chnum.empty()) {
								char ch = chnum.top();
								chnum.pop();
								cout << ch;
							}
						}
					}
					else if(i==0){
						int number = 0;
						number = newmi[i] - '0';
						char ch = 'a' + number;
						chnum.push(ch);
						while (!chnum.empty()) {
							char ch = chnum.top();
							chnum.pop();
							cout << ch;
						}
					}
				}
			}
		}
	}
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值