您的位置:首页 > 其它

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

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;
}


运行结果

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

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: