RSA 算法C++实现

【id:194】【100分】A. 3.RSA算法(不要求支持大数)

时间限制1s

内存限制128MB

题目描述

C++中数据的类型与长度参考:

因此,C++最大能支持的十进制是19位的整数。如果要支持更大的整数,需要实现Big Number类。RSA目前比较安全的密钥长度是2048位二进制,即是617位的十进制。因此,C++自带的数据类型无法实现安全的RSA密钥加解密。

为了降低难度,该题不要求实现大数支持,因此只使用C++自带的long long 数据类型。

该实验主要包含三部分:1. 公私钥的生成。在公私钥生成中,有p、q、e三个参数是随机选择的,其中p、q要求是质数,因此需要实现一个函数检查一个整数是否是质数。由p、q的乘积可以得到n:n=p*q,以及n的欧拉函数: φ(n) = (p-1)*(q-1)。e是在(1, φ(n))之间随机选取的整数,需要满足gcd(e, φ(n)) = 1,因此,需要通过扩展欧几里得算法验证取得的e是与φ(n)互质的。d可以通过扩展欧几里得算法求得 。即。

 

 

公钥为(n, e),私钥为(n,d)检查一个整数是否为质数或或扩展欧几里得算法

2. 加密过程,使用加密算法c = m^e mod n,计算出密文c;

3.解密过程,使用私钥d和解密算法m = c^d mod n, ,计算m;

加密和解密过程需要做幂运算取余,如果直接先做幂运算再取余,则很容易出现溢出,因此,我们需要采用快速幂运算取余算法。

因此,该次实验主要难点在于以下三个算法的理解与实现:

1. Rabin-Miller算法

2. 扩展欧几里得算法

3. 快速幂取余算法

根据前面的算法,我们知道明文和密文都不能大于n,假设n的长度为L,对于明文,我们需要按照L-1的长度对其分组然后再加密,每组的密文长度L。解密的时候使用L的长度对其进行分组然后解密,每组的明文长度为L-1。分组按照整数从低到高(即从右往左)

输入

第一行是p

第二行是q

第三行是e

第四行是待加密数据

第五行是待解密数据

输出

第一行输出p是否是质数

第二行输出q是否是质数

第三行打印n

第四行打印d

第五行显示输入第四行的加密结果

第六行显示输入第五行的解密结果

样例查看模式 

正常显示查看格式

输入样例1

67
43
13
281
2154

输出样例1

Yes
Yes
2881
853
325
54

输入样例2 

67
43
13
54281
3252154

输出样例2

Yes
Yes
2881
853
21540325
281054
 

输入样例3 

9973
9397
4889
2020
53185119

输出样例3

Yes
Yes
93716281
42181817
53185119
2020

首先声明,俺是菜鸟,纯属发着玩哈哈哈

这次的RSA实验主要是分片比较容易错,因为一般的题目输入的密文或者明文都是小于q*p的,但是为了更好地满足用户需求,也要对密文和明文大于n进行处理。代码如下:

#include<iostream>
#include<cmath>
using namespace std;
int main(){
	long jiemi(long ,long ,long);
	long calc_d(long , long);
	long zhishu(long);
	long qumo(long ,long ,long);
	long p,q,e,m,m1;//m是待加密数据 
	long n,d,c;
	long hanshu,noserect;
	int i;
	cin>>p>>q>>e>>m>>noserect;
	if(zhishu(p)==1){
		cout<<"no"<<endl;
	}
	else cout<<"Yes"<<endl;
		if(zhishu(q)==1){
		cout<<"no"<<endl;
	}
	else cout<<"Yes"<<endl;
	n=q*p;
	cout<<n<<endl;
	hanshu=(p-1)*(q-1);
	d=calc_d(e,hanshu);//私钥 
	cout<<d<<endl;  
	c=qumo(m,e,n);
	cout<<c<<endl; 
	m1=jiemi(noserect,d,n);
	cout<<m1<<endl;
	return 0;
	}
long zhishu(long a){//判断素数 
	int i,flag=0;
	for(i=2;i<a;i++){
		if(a%i==0)
		flag=1;
		break;
	}
	if(a%i!=0) flag=0;
	return flag;
}
long calc_d(long e, long n) {//私钥计算方法 
	if (e == 1||n==1) return 1;
	int d1 = calc_d(e%n, n%e);
	return d1 - n / e * ((1 - e * d1) / (n%e));
}
long qumo(long a,long e,long n){//取模运算 
    long n0=n;long a1;;
    long temp=a;
	long count=0;
	long long ans = 1;
    long long ans1=1;
	for(;n0!=0;count++){
		n0/=10;
	}
	if(a>n){
		a=a/(pow(10,count-1));
		a=temp-a*pow(10,count-1);
		temp=temp/pow(10,(count-1));
    a %= n; 
    temp%=n;
    while(e){
    	if(e % 2){
    		ans = (ans * a) % n;
    		ans1 = (ans1*temp) %n;
		}
		e /= 2;
		a = (a * a) % n; 
		temp =(temp*temp)%n;
	}
	long result=ans1*pow(10,count)+ans;
    return result;
	}
   else if(a<n){
   	a%=n;
   	for(int i=1;i<=e;i++){
   		ans=(ans*a)%n;
	   }
	   ans=ans%n;
	   return ans;
   }
}
long jiemi(long a,long b,long p){
	long p0=p;long a1;;
    long temp=a;
	long count=0;
	long long ans = 1;
    long long ans1=1;
	for(;p0!=0;count++){
		p0/=10;
	}
	if(a>p){
		a=a/(pow(10,count));
		a=temp-a*pow(10,count);
		temp=temp/pow(10,(count));
    a %= p; 
    temp%=p;
    while(b){
    	if(b % 2){
    		ans = (ans * a) % p;
    		ans1 = (ans1*temp) %p;
		}
		b /= 2;
		a = (a * a) % p; 
		temp =(temp*temp)%p;
	}
	long result=ans1*pow(10,count-1)+ans;
    return result;
	}
   else if(a<p){
   	a%=p;
   	for(int i=1;i<=b;i++){
   		ans=(ans*a)%p;
	   }
	   ans=ans%p;
	   return ans;
   }
}

最后的结果是ac的,也可根据具体题目去修改一下。

 

  • 3
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
为了保证数据传输的安全性,RSA算法是一种非常常见的加密算法。在C语言中,可以使用以下代码实现RSA算法: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <openssl/rsa.h> #include <openssl/pem.h> #include <openssl/err.h> #define KEY_LENGTH 2048 #define PUB_EXP 3 int main(int argc, char *argv[]) { char *pub_key_path = "public.pem"; // 公钥路径 char *pri_key_path = "private.pem"; // 私钥路径 char *plain_text = "Hello, RSA!"; // 明文 char cipher_text[256] = {0}; // 密文 char decrypt_text[256] = {0}; // 解密后的明文 // 1. 生成密钥对 RSA *rsa = RSA_generate_key(KEY_LENGTH, PUB_EXP, NULL, NULL); if (rsa == NULL) { printf("RSA_generate_key error.\n"); return -1; } // 2. 保存公钥和私钥 FILE *fp = NULL; fp = fopen(pub_key_path, "wb+"); if (fp == NULL) { printf("fopen public key error.\n"); return -1; } PEM_write_RSAPublicKey(fp, rsa); fclose(fp); fp = fopen(pri_key_path, "wb+"); if (fp == NULL) { printf("fopen private key error.\n"); return -1; } PEM_write_RSAPrivateKey(fp, rsa, NULL, NULL, 0, NULL, NULL); fclose(fp); // 3. 使用公钥加密 fp = fopen(pub_key_path, "rb"); if (fp == NULL) { printf("fopen public key error.\n"); return -1; } RSA *public_key = RSA_new(); if (public_key == NULL) { printf("RSA_new public_key error.\n"); return -1; } public_key = PEM_read_RSAPublicKey(fp, &public_key, NULL, NULL); fclose(fp); int rsa_len = RSA_public_encrypt(strlen(plain_text), (unsigned char *)plain_text, (unsigned char *)cipher_text, public_key, RSA_PKCS1_PADDING); if (rsa_len == -1) { printf("RSA_public_encrypt error.\n"); return -1; } printf("cipher text: %s\n", cipher_text); // 4. 使用私钥解密 fp = fopen(pri_key_path, "rb"); if (fp == NULL) { printf("fopen private key error.\n"); return -1; } RSA *private_key = RSA_new(); if (private_key == NULL) { printf("RSA_new private_key error.\n"); return -1; } private_key = PEM_read_RSAPrivateKey(fp, &private_key, NULL, NULL); fclose(fp); rsa_len = RSA_private_decrypt(rsa_len, (unsigned char *)cipher_text, (unsigned char *)decrypt_text, private_key, RSA_PKCS1_PADDING); if (rsa_len == -1) { printf("RSA_private_decrypt error.\n"); return -1; } printf("decrypt text: %s\n", decrypt_text); return 0; } ``` 注意,在使用该代码时需要安装openssl库。可以使用以下命令在Ubuntu上安装openssl: ```shell sudo apt-get install libssl-dev ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值