A。凯撒密码
题意:
给你k1,k2,和一串明文,一串密文。
明文用k1加密,密文用k2解密。
对于明文要把字母转换成大写字母,非字母全部删除。
额:要考虑到取模可能会变成负数,所以要加一下26再取模。
代码:
代码语言:javascript复制#include<stdio.h>
#define N 85
int k1, k2;
char plain[N], cipher[N];
void init(char s[]) //预处理,转换为大写字母
{
int i;
for(i = 0; s[i]; i )
if(s[i] >= 'a' && s[i] <= 'z')
s[i] = s[i] - 'a' 'A';
}
void encrypt(char s[],int k,int f)//加解密
{
init(s);
int i;
for(i = 0; s[i]; i )
if(s[i] >= 'A' && s[i] <= 'Z')
printf("%c", ((s[i] - 'A' k*f 26) % 26 'A'));
printf("n");
}
int main()
{
scanf("%d,%d ", &k1, &k2);
gets(plain);
gets(cipher);
encrypt(plain,k1,1);
encrypt(cipher,k2,-1);
return 0;
}
B。RSA加密
题意:
给你n,e,和一串明文。用(n,e)加密明文。将明文字母转换成数字,按8位数字分段,不足部分补足0。明文中有非字母删除,A和a转成数字都是00, Z和z转成数字都是25。明文数字8位分段的每一段对应的密文也要求是8位,如果不足8位,前面补足0。
对于明文要把字母转换成大写字母,非字母全部删除。
补充:
RSA加密就是字母转化为两位数字,分段处理,比如每八个一段,M为明文数字段,C为密文数字段,C=Me%n。
代码:
代码语言:javascript复制#include<stdio.h>
#include<string.h>
#define N 1000
#define ll long long
ll n, e;
char plain[N];
ll qpow(ll a, ll b)//快速幂
{
ll k = a % n;
ll ans = 1;
while(b)
{
if(b & 1)
ans = (ans * k ) % n;
k = ( k * k) % n;
b >>= 1;
}
return ans;
}
void init(char s[]) //预处理,转换为大写字母
{
int i;
for(i = 0; s[i]; i )
if(s[i] >= 'a' && s[i] <= 'z')
s[i] = s[i] - 'a' 'A';
}
void encrypt(char s[]) //加密
{
init(s);
int k = 0,i;
ll block = 0;
for(i = 0; s[i]; i )
if(s[i] >= 'A' && s[i] <= 'Z') //如果是字母
{
block = block * 100 (s[i] - 'A') ; //明文对应的数字串
k ;
if(k == 4) //够8位数字时
{
printf("lld", qpow(block, e) % 100000000);//输出密文,这个模不知道是不是必须的,题目没说n的上限
block = 0;
k = 0;
}
}
if(k)//剩下的明文要后面补零
{
while(k != 4)
{
block = block * 100;
k ;
}
printf("lld", qpow(block, e) % 100000000);
}
}
int main()
{
// freopen("in.txt", "r", stdin);
scanf("%lld%lld ", &n, &e);
gets(plain);
encrypt(plain);
return 0;
}
C。RSA解密
题意:
给你n,e,和一串明文。用(n,e)加密明文。将明文字母转换成数字,按8位数字分段,不足部分补足0。明文中有非字母删除,A和a转成数字都是00, Z和z转成数字都是25。明文数字8位分段的每一段对应的密文也要求是8位,如果不足8位,前面补足0。
对于明文要把字母转换成大写字母,非字母全部删除。
补充:
RSA加密就是字母转化为两位数字,分段处理,比如每八个一段,M为明文数字段,C为密文数字段,C=Me%n。
代码:
代码语言:javascript复制#include<stdio.h>
#include<string.h>
#define N 802
#define ll long long
ll n, e, p, q, d, x, y;
char cipher[N << 1], plain[10];
ll exgcd(ll a, ll b)//扩展欧几里德求逆元
{
if(b == 0)
{
x = 1;
y = 0;
return a;
}
ll r = exgcd(b, a % b);
ll tmp = x;
x = y;
y = tmp - a / b * y;
return r;
}
ll qpow(ll a, ll b)//快速幂
{
ll k = a % n;
ll ans = 1;
while(b)
{
if(b & 1)
ans = (ans * k ) % n;
k = ( k * k) % n;
b >>= 1;
}
return ans;
}
void init()//求p和q,和d
{
int i;
for(i = 2; i < n; i )
if(n % i == 0)
{
p = i;
q = n / i;
break;
}
ll M;
M = (p - 1) * (q - 1);
exgcd(e, M);
d = (x % M M) % M;//求e的逆元d
}
void decrypt() //解密
{
ll block = 0;
int k = 0, i, j;
for(i = 0; cipher[i]; i )
{
block = block * 10 cipher[i] - '0';//密文从字符串中取出来
k ;
if(k == 8)//密文达到8位数字时
{
memset(plain, 0, sizeof plain);//清空明文字符串
block = qpow(block, d);//计算明文数字串
for(j = 3; j >= 0; j--)//每次计算两位数字并存在明文字符串中,因为从后面往前取,所以倒过来存
{
plain[j] = block % 100 'A';//取最后面两个数字
block /= 100;//去掉最后面两个数字
}
printf("%s", plain);//输出明文
k = 0;//清空计数器
}
}
}
int main()
{
// freopen("in.txt", "r", stdin);
scanf("%lld%lld ", &n, &e);
gets(cipher);
init();
printf("%dn", d);
decrypt();
return 0;
}