日常篇:程序设计实验报告——异或加密,凯撒密码(不是完整代码)
在头歌平台上超过最大字符限制,无法提交。用博客网,语法一样。欢迎来我的园子逛逛~
第一部分
描述你的实验过程,包括代码编写、编译和运行。
略
第二部分(说明都在代码注释里)
提供加密和解密的不同示例,并说明测试结果。注意测试用例的选择,要涵盖不同情况。
2.1异或加密
//=====begin=====
int p_len = strlen(p_data); // 有效长度
int key_len = strlen(key);
if (key_len == 0) {
key_len = 1;
key[0] = '0'; // 空密钥默认设为二进制位0
}
// 循环条件i < p_len
for (int i = 0; i < p_len; i++) {
int p_bit = p_data[i] - '0'; // 明文位(0或1)
int key_bit = key[i % key_len] - '0'; // 密钥位(循环使用)
Encrypt[i] = (p_bit ^ key_bit) + '0';
}
Encrypt[p_len] = '\0';
for (int i = 0; i < p_len; i++) {
int encrypt_bit = Encrypt[i] - '0'; // 密文位转数字(0或1)
int key_bit = key[i % key_len] - '0';
Decrypt[i] = (encrypt_bit ^ key_bit) + '0';
}
Decrypt[p_len] = '\0';
// 输出
printf("Initial string: %s\n", p_data);
printf("key string: %s\n", key);
printf("Encrypt string: ");
for (int k = 0; k < p_len; k++)
{
printf("%c", Encrypt[k]);
}
printf("\n解密后的文本: ");
for (int k = 0; k < p_len; k++) // 遍历明文长度,匹配解密结果
{
printf("%c", Decrypt[k]);
}
//======end======
测试结果
Initial string: 10101110000
key string: 00000110101
Encrypt string: 10101000101
解密后的文本: 10101110000
2.2凯撒密码
// 加密函数,plaintext明文串,ci密文串,key密钥
/*凯撒密码的数学表示为:
加密公式:𝐶=(𝑃+𝐾)mod 26
解密公式:𝑃=(𝐶−𝐾+26)mod 26
其中:
𝐶:是密文字符的位置。
𝑃:是明文字符的位置。
𝐾:是密钥(移位量)。
26 是字母表的长度。
**补充**:
非字母字符不移位
200太大,遇到\0停止,条件判断
大小写区分函数
*/
void caesar_encrypt(const char plaintext[], char ciphertext[], int key) {
//=====begin=====
int i=0;
key=(key%26+26)%26;
while(plaintext[i]!='\0')
{
if(isupper(plaintext[i]))
{
ciphertext[i]=(plaintext[i]-'A'+key)%26+'A';
}
else if(islower(plaintext[i]))
{
ciphertext[i]=(plaintext[i]-'a'+key)%26+'a';
}
else
{
ciphertext[i]=plaintext[i];
}
i++;
}
ciphertext[i]='\0';
//======end======
}
// 解密函数
void caesar_decrypt(const char ciphertext[], char plaintext[], int key) {
//=====begin=====
int i=0;
key=(key%26+26)%26;
while(ciphertext[i]!='\0')
{
if(isupper(ciphertext[i]))
{
plaintext[i]=(ciphertext[i]-'A'-key+26)%26+'A';
}
else if(islower(ciphertext[i]))
{
plaintext[i]=(ciphertext[i]-'a'-key+26)%26+'a';
}
else
{
plaintext[i]=ciphertext[i];
}
i++;
}
plaintext[i]='\0';
//======end======
}
// 暴力破解函数,key从0~25变化,双层循环
void caesar_brute_force(const char ciphertext[]) {
//=====begin=====
int key;
// 外层循环
for (key = 0; key <= 25; key++) {
char res[200];
int i = 0;
// 内层循环
while (ciphertext[i] != '\0') {
if (isupper(ciphertext[i])) {
res[i] = (ciphertext[i] - 'A' - key + 26) % 26 + 'A';
} else if (islower(ciphertext[i])) {
res[i] = (ciphertext[i] - 'a' - key + 26) % 26 + 'a';
} else {
res[i] = ciphertext[i];
}
i++;
}
res[i] = '\0'; // 添加结束符
//Shift 0: Mjqqt Btwqi!
printf("Shift %d: %s\n", key, res);
}
//======end======
}
测试结果
Encrypted: PQ34ERo;,#orusodrs
Decrypted: EF34TGd;,#dgjhdsgh
Shift 0: PQ34ERo;,#orusodrs
Shift 1: OP34DQn;,#nqtrncqr
Shift 2: NO34CPm;,#mpsqmbpq
Shift 3: MN34BOl;,#lorplaop
Shift 4: LM34ANk;,#knqokzno
Shift 5: KL34ZMj;,#jmpnjymn
Shift 6: JK34YLi;,#ilomixlm
Shift 7: IJ34XKh;,#hknlhwkl
Shift 8: HI34WJg;,#gjmkgvjk
Shift 9: GH34VIf;,#filjfuij
Shift 10: FG34UHe;,#ehkiethi
Shift 11: EF34TGd;,#dgjhdsgh
Shift 12: DE34SFc;,#cfigcrfg
Shift 13: CD34REb;,#behfbqef
Shift 14: BC34QDa;,#adgeapde
Shift 15: AB34PCz;,#zcfdzocd
Shift 16: ZA34OBy;,#ybecynbc
Shift 17: YZ34NAx;,#xadbxmab
Shift 18: XY34MZw;,#wzcawlza
Shift 19: WX34LYv;,#vybzvkyz
Shift 20: VW34KXu;,#uxayujxy
Shift 21: UV34JWt;,#twzxtiwx
Shift 22: TU34IVs;,#svywshvw
Shift 23: ST34HUr;,#ruxvrguv
Shift 24: RS34GTq;,#qtwuqftu
Shift 25: QR34FSp;,#psvtpest
第三部分
在AI帮助下,了解更多对称加密算法
在博客网上写有一篇关于密码的报告,其中实验关于国密sm234
练习篇:密码学基础
第四部分
报告最后一部分,要清晰阐述在实验过程中是如何使用AI工具的,以及AI在报告中的具体贡献
4.1在实验过程中
int key_bit = key[i % key_len] - '0'; // 密钥位(循环使用),查询ai为什么key不能运行,因为key是输入流。
fgets(p_data, sizeof(p_data), stdin); //那就不得不提到下一个问题,输入流是什么?stdin强制输入?吗?scanf?,sizeof(char)一个字符一字节,相当于个数。
//fgets(p_data, sizeof(p_data), stdin)的含义是:从stdin这个输入流中读取数据,存入p_data指向的内存,最多读取sizeof(p_data)-1个字符(因为fgets会自动在末尾加\0字符串结束符)。
//当程序执行到这行代码时,如果stdin流中没有可用数据(比如用户还没输入),程序会阻塞等待用户从键盘输入,直到用户按下回车键 —— 这是输入流的特性,而非 “强制输入”,只是程序需要等待输入才能继续执行。
//这就不难解释这几行是干什么的了:
//移除fgets可能读取的换行符
if (p_data[strlen(p_data) - 1] == '\n') {
p_data[strlen(p_data) - 1] = '\0';
}
//这几行ASCII的操作
Encrypt[i] = (p_bit ^ key_bit) + '0'; //+ '0'定义了起始位置
ciphertext[i]=(plaintext[i]-'A'+key)%26+'A';//plaintext[i]-'A'计算相对位置,+'A'同上
//每个输入后,为什么要加\0
ciphertext[i]='\0';//C 语言没有原生的 “字符串类型”,而是通过 **“字符数组 + '\0' 结束符”来模拟字符串。该实验没有规定**到底要输入多少个字符**,为了防止内存读取溢出,一定要加一个\0。
//实验最后是输出字符串%s,那么用for输出,和用%s输出的输入要求?
printf("Shift %d: %s\n", key, res);//简单一点
//使用%s一次性输出,数组类型必用char,,输入%c,后续要加\0;输入%s,不用加
//普通printf
for(int i=0;i<200;i++)
{
printf("Shift %d: ", key);
for (int k = 0; res[k] != '\0'; k++) {
printf("%c", res[k]);
}
// 换行,保证每个key的结果占一行
printf("\n");
}
4.2在报告中
回顾markdown语法

浙公网安备 33010602011771号