当前位置: 首页 > news >正文

如何使用C语言实现Vigenre密码加解密

如何使用C语言实现Vigenère密码加解密

在洛谷看到这题,觉得有意思,遂写。

参考文章:C语言实现Vigenere加解密算法(附带源码)

1. Vigenère密码简介与原理

Vigenère密码是一种多表密码,使用一系列凯撒密码(Caesar cipher)来实现加密。在Vigenère密码中,明文中的每个字符都被替换为密文中的对应字符,而密钥用于确定使用哪个凯撒密码表。具体来说,明文中的每个字符都会根据密钥中的字符进行位移,从而生成密文。如图:img
加密例子:明文:HELLO,密钥:KEY,加密后:RIJVS

对照表中,先将密钥填充至与明文长度相同:KEYKE。然后在对照表中找到明文字符对应的密文字符,如第一个字符在对照表中的K行找到H列,对应的字符是R,于是第一个字符就被加密成R。以此类推,直到明文全部加密完成。

实际操作中,其实就是一系列的不同的凯撒密码加密,而密钥决定了使用哪个凯撒密码表,这里不赘述。我们把字母转换成数字(A = 0,B = 1,……),写成公式可以表达成:

加密:C = (P + K)% 26

其中C为密文字符,P为明文字符,K为密钥字符。同样可以得到解密公式:

解密:P = (C - K + 26)% 26

2.具体实现

这里仅给出函数实现,以及省略了引入string.h和ctype.h头文件。

我们可以考虑先忽略字母的大小写,解密后再对照原文判断是否转换大小写。先实现字母转数字、数字转字母的函数:

int Char_to_Number(char c)
{return c - 'A';
}char Number_to_Char(int num, char origin)
{char c = 'A' + num;//* 对照原文if (islower(origin)){return tolower(c);}return c;
}

解码:

char *Decode(char *key, char *C, char *M)
{for (int i = 0, j = 0; i < strlen(C); i++){if (isalpha(C[i])){int keyNum = Char_to_Number(key[j % strlen(key)]); // 填充密钥int CNum = Char_to_Number(C[i]);int MNum = (CNum - keyNum + 26) % 26;M[i] = Number_to_Char(MNum, C[i]);// 不能在循环体里面写j++😡,否则遇到非字母字符j也会增加j++; }else{M[i] = C[i];}}return M;
}

加密:

char *Encode(char *key, char *M, char *C)
{for (int i = 0, j = 0; i < strlen(M); i++){if (isalpha(M[i])){int keyNum = Char_to_Number(key[j % strlen(key)]);int MNum = Char_to_Number(M[i]);int CNum = (MNum + keyNum) % 26;C[i] = Number_to_Char(CNum, M[i]);j++;}else{C[i] = M[i];}}
}

完整测试用例代码:

#include <stdio.h>
#include <string.h>
#include <ctype.h>int Char_to_Number(char c);
char Number_to_Char(int num, char origin);
char *Decode(char *key, char *C, char *M);
char *Encode(char *key, char *M, char *C);int main()
{char key[101];char C[1001];char M[1001];fgets(key, sizeof(key), stdin);fgets(C, sizeof(C), stdin);key[strcspn(key, "\n")] = '\0';C[strcspn(C, "\n")] = '\0';Decode(key, C, M);printf("%s\n", M);// Encode(key, M, C);// printf("%s\n", C);return 0;
}int Char_to_Number(char c)
{return toupper(c) - 'A';
}char Number_to_Char(int num, char origin)
{char c = 'A' + num;//* 对照原文if (islower(origin)){return tolower(c);}return c;
}char *Decode(char *key, char *C, char *M)
{for (int i = 0, j = 0; i < strlen(C); i++){if (isalpha(C[i])){int keyNum = Char_to_Number(key[j % strlen(key)]); // 填充密钥int CNum = Char_to_Number(C[i]);int MNum = (CNum - keyNum + 26) % 26;M[i] = Number_to_Char(MNum, C[i]);j++; // 不能在循环体里面写j++😡,否则遇到非字母字符j也会增加}else{M[i] = C[i];}}return M;
}char *Encode(char *key, char *M, char *C)
{for (int i = 0, j = 0; i < strlen(M); i++){if (isalpha(M[i])){int keyNum = Char_to_Number(key[j % strlen(key)]);int MNum = Char_to_Number(M[i]);int CNum = (MNum + keyNum) % 26;C[i] = Number_to_Char(CNum, M[i]);j++;}else{C[i] = M[i];}}
}

3. 总结

知道了加解密公式,实现起来就很简单,以及注意需要对照原文判断转换字母的大小写。

介绍和图片来源于网络,侵删。

http://www.hskmm.com/?act=detail&tid=14563

相关文章:

  • 【F#学习】列表 List
  • Trae与Gitee MCP深度集成:AI编程工具链迎来重大升级
  • 【2025-09-22】加班感悟
  • OpenAI Codex 使用 智谱 API
  • 嵌入式ARM架构学习9——IIC - 教程
  • Day04---数据类型及面试题详解
  • 记-一次H3C交换机版本升级
  • 客服系统中的定时任务设计与实现
  • 使用Go语言实现高效定时任务功能
  • JavaScript获取NHK的附件文件
  • 承兑 背书 贴现区别
  • 洛谷题单指南-进阶数论-P3811 【模板】模意义下的乘法逆元
  • Interlocked.Increment学习
  • 基于解析法的四轴SCARA机器人正逆运动学代码
  • .Net-IIS 文件上传安全漏洞问题
  • 【F#学习】记录 Record
  • 【光照】[高光反射specular]以UnityURP为例
  • 游戏性能优化与逆向分析技术
  • 使用 feign 调用时对微服务实例进行选择
  • EI目录今年第3次更新!55本中国期刊被收录,附完整版下载
  • 程序员的未来:从技术岗位到全栈思维的进化之路 - 实践
  • envoy和nginx的区别
  • 基于自适应差分进化算法的MATLAB实现
  • 【SPIE出版、主题宽泛、快速检索】2025年可持续发展与数字化转型国际学术会议(SDDT 2025)
  • langfuse使用的postgresql异机备份和恢复(docker)并进行langfuse版本升级
  • 国产化Excel处理组件Spire.XLS教程:Java在 Excel 表格中轻松添加下标
  • tips图解复杂数组、指针声明
  • 通过perl或awk实现剪切功能
  • java列队多种实现方式,
  • Ashampoo Music Studio 12.0.3 音频编辑处理