欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

双向循环链表:维吉尼亚密码

发布时间:2025/3/15 编程问答 44 豆豆
生活随笔 收集整理的这篇文章主要介绍了 双向循环链表:维吉尼亚密码 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

维吉尼亚密码简介


维吉尼亚密码引入了“密钥”的概念,即根据密钥来决定用哪一行的密表来进行替换,以此来对抗字频统计。假如下面图第一行代表明文字母,左面第一列代表密钥字母,对如下明文加密:
TO BE OR NOT TO BE THAT IS THE QUESTION
当选定RELATIONS作为密钥时,加密过程是:明文一个字母为T,第一个密钥字母为R,因此可以找到在R行中代替T的为K,依此类推,得出对应关系如下:
密钥:RELAT IONSR ELATI ONSRE LATIO NSREL
明文:TOBEO RNOTT OBETH ATIST HEQUE STION
密文:KSMEH ZBBLK SMEMP OGAJX SEJCS FLZSY


维吉尼亚密码分析


明文T字符 密钥是R 对应的密文是K?从数学角度 有没有规律可寻呢?我们仔细看图,每一行每一列都是26个连续的字母,不同字母开头反正都是循环一圈,

从明文T到 密文K 是不是经历了17个单元,恰巧是密钥R在26个元素中的下标17

我们将 A—Z密钥看作0—25个数,明文字符在A—Z循环链表走过 密钥个数结点 到密文结点。说的太拗口,举个简单例子,明文是 T ,密钥是B那么 T 走1个位置 是 U ,那么 明文就T的密文 就是U。看图 查看密钥是不是。


循环链表实现方式


#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #define OK 1 #define ERROR 0typedef int Status; typedef char EleType; //双向循环链表 结点数据结构 typedef struct DulNode {EleType data;//数据域struct DulNode* next;//后继结点指针域struct DulNode* prior;//前驱结点指针域 }DulNode, *DulLinkList; //取了别名 DulNode* 相当于DulLInkListDulLinkList list_AZ = NULL;//创建26个英文字母双向循环链表 Status CreatDulLink(DulLinkList* list) {if (list == NULL){return ERROR;}DulNode* head = (DulNode*)malloc(sizeof(DulNode));//创建头结点if (head == NULL){return ERROR;}DulNode* p = head;//p 移动指针,起初指向头结点p->next = p->prior = NULL;for (size_t i = 0; i < 26; i++){DulNode* node = (DulNode*)malloc(sizeof(DulNode));//创建结点node->data = 'A' + i;//下面3步将创建的node结点放到双向循环链表中node->next = p->next;//直接赋值NULL也可以node->prior = p;p->next = node;//p 始终指向链表最后一个结点p = node;}//下2步 将尾结点和第一个结点关联形成双向循环链表,越过头结点。p->next = head->next;head->next->prior = p;//循环链表指向第一个元素*list = p->next;//释放头结点free(head);return OK; } //进行位移 Status Caesar(DulLinkList* list, int num) {DulLinkList tmp = *list;//双向循环链表指针往后移if (num > 0){int i = 0;//num = 1 往后移动1位, temp = temp -> nextwhile (i < num){tmp = tmp->next;i++;}*list = tmp;}//双向循环链表指针往前移if (num < 0){int i = 0;//num = -1 往前移动1位,temp = temp->priorwhile (i < num*-1){tmp = tmp->prior;i++;}*list = tmp;}return OK; }/* 获取密文字符 num 字符移动位数 ch 字符起点 */ char GetCipertext(int num,char ch) {//printf("num=%d", num);DulLinkList list = list_AZ;//移动到字符位置Caesar(&list, ch - 'A');//根据密钥进行偏移Caesar(&list, num);return list->data; }/* 维吉尼亚密码 生成随机密钥 根据随机密钥进行加密 */Status Virginia(char* words,char** keytext,char** cipertext ,int len) {char* key = (char*)malloc(sizeof(char)*len+1);char* ciper = (char*)malloc(sizeof(char)*len+1);memset(key, 0, len + 1);memset(ciper, 0, len + 1);srand((size_t)time(NULL));for (size_t i = 0; i < len; i++){//需要范围为 x ~ y 公式 为 rand()%(y-x)+x //如果需要 1~ 9 公式为 rand()%8+1int num = rand() % 26;key[i] = 'A' + num;ciper[i] = GetCipertext(num,words[i]);}//通过指针返回数据*cipertext = ciper;*keytext = key;return OK; }int main(int argc, char *argv[]) { //创建26个字母的循环链表CreatDulLink(&list_AZ);char temp[1024] = {0};while (1){printf("请输入一段明文(英文大写,0退出):");scanf("%s", temp);if (temp[0] == '0'){break;}char* key = NULL;char* ciper = NULL;Virginia(temp,&key, &ciper, strlen(temp));printf("明文:%s\n", temp);printf("密钥:%s\n", key);printf("密文:%s\n", ciper);}system("pause");return 0; }

运行结果

对照维吉尼亚密码表 没有问题





新人创作打卡挑战赛发博客就能抽奖!定制产品红包拿不停!

总结

以上是生活随笔为你收集整理的双向循环链表:维吉尼亚密码的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。