双向循环链表:维吉尼亚密码
2018-01-20 02:12
309 查看
维吉尼亚密码简介
维吉尼亚密码引入了“密钥”的概念,即根据密钥来决定用哪一行的密表来进行替换,以此来对抗字频统计。假如下面图第一行代表明文字母,左面第一列代表密钥字母,对如下明文加密: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 0 typedef int Status; typedef char EleType; //双向循环链表 结点数据结构 typedef struct DulNode { EleType data;//数据域 struct DulNode* next;//后继结点指针域 struct DulNode* prior;//前驱结点指针域 }DulNode, *DulLinkList; //取了别名 DulNode* 相当于DulLInkList DulLinkList 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 -> next while (i < num) { tmp = tmp->next; i++; } *list = tmp; } //双向循环链表指针往前移 if (num < 0) { int i = 0; //num = -1 往前移动1位,temp = temp->prior while (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+1 int 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; }
运行结果
对照维吉尼亚密码表 没有问题相关文章推荐
- 循环链表、双向链表
- 双向约瑟夫(C语言双向循环链表实…
- 带哨兵的双向循环链表的C语言实现
- 线性表续——双向、循环链表
- C语言数据结构之双向循环链表的实例
- 带头结点的双向循环链表
- JavaScript数据结构之双向链表和双向循环链表的实现
- 双向循环链表实践---学生管理系统
- java与数据结构(4)---java实现双向循环链表
- 双向循环链表
- 2016年12月23日学习总结----双向循环链表操作程序(头插、尾插、中间插入、删除)
- c语言实现双向循环链表
- 数据结构与算法(五)-线性表之双向链表与双向循环链表
- 带表头结点的双向循环链表
- 带表头结点的双向循环链表
- (学习java)双向循环链表
- 双向链表(4) - 排序二叉树转换为循环双向链表
- java实现双向循环链表和单链表
- 双向循环链表的插入与删除
- 链表的C语言实现之循环链表及双向链表