A。凯撒密码
题意:
给你k1,k2,和一串明文,一串密文。
明文用k1加密,密文用k2解密。
对于明文要把字母转换成大写字母,非字母全部删除。
额:要考虑到取模可能会变成负数,所以要加一下26再取模。
代码:
#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。
代码:
#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("%08lld", qpow(block, e) % 100000000);//输出密文,这个模不知道是不是必须的,题目没说n的上限 block = 0; k = 0; } } if(k)//剩下的明文要后面补零 { while(k != 4) { block = block * 100; k++; } printf("%08lld", 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。
代码:
#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("%d\n", d); decrypt(); return 0; }
时间: 2024-12-19 13:49:24