密码学实验之Playfair密码(看这一篇就足够)

从键盘上接收明文输入,密钥输入。

1.密钥的处理过程:

①将密钥输入全部转换成大写

②并且遇到J字母替换成I字母

③将密钥中重复出现的字母剔除

④按照字母表顺序将密钥未出现的字母进行填充

⑤按照5*5的矩阵输出密钥

2.明文的处理过程:

①将密钥输入全部转换成大写

②并且遇到J字母替换成I字母

③将明文两两一组,如果出现两个字母一样则插入Z如果相同的字母是Z则依次A-Y的顺序递推到不相等

④经过处理的字符串如果是奇数长度则最后一个字母补充字母,如果最后一个字母是Z则依次A-Y的顺序递推到不相等

3.加密过程

明文两两一组,比如NA TZ TE RI AC KT OA DZ,经过填充处理的密钥是STANDERCHBKFGILMOPQUVWXYZ。每次获取两个字母,则有三种处理方式:

第一种:处于同一行情况

比如NA字母在密钥中的位置分别是第3和第2,

row1=3/5=0,col1=3%5=3,可知N字母在5*5的矩阵中是处于0行3列,同理

row2=2/5=0,col2=2%5=2,可知A字母在5*5的矩阵中是处于0行2列,

此时有行相等,故只用列向右挪动1列,即col1=(col1+1)%5计算出挪动1列后新的列,此时保持row1不变的情况下组成新的位置(row1, col1),然后row1*5+co1计算出在密钥中的新位置

第二种:处于同一列情况

比如AC字母在密钥中的位置分别是第2和第7,

row1=2/5=0,col1=2%5=2,可知A字母在5*5的矩阵中是处于0行2列,同理

row2=7/5=1,col2=7%5=2,可知C字母在5*5的矩阵中是处于1行2列,

此时有列相等,故只用行向下挪动1行,即row1=(row1+1)%5计算出挪动1行后新的行,此时保持col1不变的情况下组成新的位置(row1, col1),然后row1*5+co1计算出在密钥中的新位置

第三种:不在同一列或者同一行需要绘制矩形框

S

T

A

N

D

E

R

C

H

B

K

F

G

I

L

M

O

P

Q

U

V

W

X

Y

Z

比如KT字母在密钥中的位置分别是第10和第1,

row1=10/5=2,col1=10%5=0,可知K字母在5*5的矩阵中是处于2行0列,同理

row2=1/5=0,col2=1%5=1,可知T字母在5*5的矩阵中是处于0行1列,行列都不等,故需要绘制矩形框,经过观察可以发现,K的对应点F的坐标就是K的行+T的列,T的对应的S的坐标就是K的行+T的列构成

4.下面是源码(纯c语言代码):

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
void Encryption() {
	char MingWen[40];//定义明文字符串
	printf("请输入明文");
	scanf("%s", MingWen);
	for (int i = 0; i < strlen(MingWen); i++) {//将明文字符串小写字母转换为大写字母
		if(MingWen[i]>='a'){
			MingWen[i] = MingWen[i] - 32;
		}
	}
	for (int i = 0; i <= strlen(MingWen); i++) {//将明文字符串中的J代换为I
		if (MingWen[i] == 'J') {
			MingWen[i] = 'I';
		}
	}
	for (int i = 0; i < strlen(MingWen); i=i+2) {//遇见两两重复字母情况
		if (MingWen[i] == MingWen[i + 1]) {
			if (MingWen[i + 1] == 'Z') {//遇见重复字母为Z
				for (int j = strlen(MingWen); j >= i; j--) {
					MingWen[j+1] = MingWen[j];
				}
				MingWen[i + 1] = 'A';//在两个Z之间添加个A
			}
			else {//将重复字母不为Z的两字母之间加Z
				for (int j = strlen(MingWen); j > i; j--) {
					MingWen[j + 1] = MingWen[j];
				}
				MingWen[i + 1] = 'Z';
			}
		}
	}
	if (strlen(MingWen) % 2 == 1) {//判断新明文是否为奇数,若为奇数且最后一位不为Z,在明文最后一位加Z,
		//若为Z,则在最后添加A-Y中不会出现重复情况的字母
		if (MingWen[strlen(MingWen)] == "Z"){
			MingWen[strlen(MingWen) + 1] = MingWen[strlen(MingWen)];
			MingWen[strlen(MingWen)] = 'A';
		}
		MingWen[strlen(MingWen)+1]=MingWen[strlen(MingWen)];
		MingWen[strlen(MingWen)] = 'Z';
	}
	char MiYue[30];//定义密钥
	printf("请输入密钥");
	scanf("%s", MiYue);
	for (int i = 0; i < strlen(MiYue); i++) {
		MiYue[i] = MiYue[i] - 32;
	}//将密钥全部转换为大写
	for (int i = 0; i <= strlen(MiYue); i++) {//将密钥中的J代换为I
		if (MiYue[i] == 'J') {
			MiYue[i] = 'I';
		}
	}
	printf("把J替换成I后的key为:%s\n", MiYue);
	for (int i = 0; i <= strlen(MiYue); i++) {
		for (int j = 1 + i; j <= strlen(MiYue); j++) {
			if (MiYue[j] == MiYue[i]) {
				for (int n = j; n < strlen(MiYue); n++) {
					MiYue[n] = MiYue[n + 1];
				}
				i = i - 1;
			}
		}
	}
	printf("去重后的key为:%s\n", MiYue);
	char Biao[5][5];//定义表
	char OtherChar[25] = "ABCDEFGHIKLMNOPQRSTUVWXYZ";
	for (int j = 0; j <= strlen(MiYue); j++){
		for (int i = 0; i < 26; i++){ 
			if (MiYue[j] == OtherChar[i]) {//去除26字母表中密钥出现过的字母
				for (int n = i; n <= 25; n++) {
					OtherChar[n] = OtherChar[n + 1];
				}
			}
		}
	}
	int o = 0;
	for (int i = 0; i < 5; i++) {
		for (int j = 0; j < 5; j++) {
			if (j + i * 5 < strlen(MiYue)) {
				Biao[i][j] = MiYue[j + i * 5];//先往表中填入密钥字母
			}
			else {
				Biao[i][j] = OtherChar[o];//再填入其他字母
				o = o + 1;
			}
		}
	}
	printf("填充后的key为:");//打填充的key
	for (int i = 0; i < 5; i++) {
		for (int j = 0; j < 5; j++) {
			printf("%c", Biao[i][j]);
		}
	}
	printf("\n");
	printf("key形成的矩阵是\n");
	for (int i = 0; i < 5; i++) {//打印表
		for (int j = 0; j < 5; j++) {
			printf("%c ", Biao[i][j]);
		}
		printf("\n");
	}
	char MiWen[30];//定义密文
	int indexX[2];//表的横坐标
	int indexY[2];//表的纵坐标
	for (int n = 0; n < strlen(MingWen); n=n+2) {//匹配找到明文字母1对应坐标
		for (int i = 0; i < 5; i++) {
			for (int j = 0; j < 5; j++) {
				if (MingWen[n] == Biao[i][j]) {
					indexX[0] = j;
					indexY[0] = i;
				}
			}
		}
		for (int i = 0; i < 5; i++) {//匹配找到明文字母2对应的坐标
			for (int j = 0; j < 5; j++) {
				if (MingWen[n + 1] == Biao[i][j]) {
					indexX[1] = j;
					indexY[1] = i;
				}
			}
		}
		if (indexY[0] == indexY[1]) {//纵坐标相同时横坐标向右移动
			MiWen[n] = Biao[indexY[0]][(indexX[0]+1)%5];
			MiWen[n+1] = Biao[indexY[1]][(indexX[1]+1)%5];
		}
		else if (indexX[0] == indexX[1]) {//横坐标相同时纵坐标向下移动
			MiWen[n] = Biao[(indexY[0]+1)%5][indexX[0]];
			MiWen[n + 1] = Biao[(indexY[1]+1)%5][indexX[1]];
		}
		else {//横纵坐标都不同用对角线字母代换
			MiWen[n] = Biao[indexY[0]][indexX[1]];
			MiWen[n + 1] = Biao[indexY[1]][indexX[0]];
		}
	}
	printf("J替换成I后的明文是");//打印J替换成I后的明文
	for (int i = 0; i < strlen(MingWen)-1; i++) {
		printf("%c", MingWen[i]);
	}
	printf("\n加密后密文为:");//打印密文
	for (int i = 0; i < strlen(MingWen); i++) {
		printf("%c", MiWen[i]);
	}
}
void Declassify() {
	printf("还未开发\n");
}
void menu() {
	printf("******************\n\n");
	printf("1.Playfair加密\n");
	printf("2.Playfair解密\n");
	printf("0.退出程序\n");
	printf("\n******************\n");
	int c;
	scanf("%d", &c);
	getchar();
	switch (c) {
	case 1: Encryption(); break;
	case 2:Declassify(); break;
	case 0:exit();
	}
}
int main() {
	while (1) {
		menu();
	}
	return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
void Encryption() {
	char MingWen[40];//定义明文字符串
	printf("请输入明文");
	scanf("%s", MingWen);
	for (int i = 0; i < strlen(MingWen); i++) {//将明文字符串小写字母转换为大写字母
		if(MingWen[i]>='a'){
			MingWen[i] = MingWen[i] - 32;
		}
	}
	for (int i = 0; i <= strlen(MingWen); i++) {//将明文字符串中的J代换为I
		if (MingWen[i] == 'J') {
			MingWen[i] = 'I';
		}
	}
	for (int i = 0; i < strlen(MingWen); i=i+2) {//遇见两两重复字母情况
		if (MingWen[i] == MingWen[i + 1]) {
			if (MingWen[i + 1] == 'Z') {//遇见重复字母为Z
				for (int j = strlen(MingWen); j >= i; j--) {
					MingWen[j+1] = MingWen[j];
				}
				MingWen[i + 1] = 'A';//在两个Z之间添加个A
			}
			else {//将重复字母不为Z的两字母之间加Z
				for (int j = strlen(MingWen); j > i; j--) {
					MingWen[j + 1] = MingWen[j];
				}
				MingWen[i + 1] = 'Z';
			}
		}
	}
	if (strlen(MingWen) % 2 == 1) {//判断新明文是否为奇数,若为奇数且最后一位不为Z,在明文最后一位加Z,
		//若为Z,则在最后添加A-Y中不会出现重复情况的字母
		if (MingWen[strlen(MingWen)] == "Z"){
			MingWen[strlen(MingWen) + 1] = MingWen[strlen(MingWen)];
			MingWen[strlen(MingWen)] = 'A';
		}
		MingWen[strlen(MingWen)+1]=MingWen[strlen(MingWen)];
		MingWen[strlen(MingWen)] = 'Z';
	}
	char MiYue[30];//定义密钥
	printf("请输入密钥");
	scanf("%s", MiYue);
	for (int i = 0; i < strlen(MiYue); i++) {
		MiYue[i] = MiYue[i] - 32;
	}//将密钥全部转换为大写
	for (int i = 0; i <= strlen(MiYue); i++) {//将密钥中的J代换为I
		if (MiYue[i] == 'J') {
			MiYue[i] = 'I';
		}
	}
	printf("把J替换成I后的key为:%s\n", MiYue);
	for (int i = 0; i <= strlen(MiYue); i++) {
		for (int j = 1 + i; j <= strlen(MiYue); j++) {
			if (MiYue[j] == MiYue[i]) {
				for (int n = j; n < strlen(MiYue); n++) {
					MiYue[n] = MiYue[n + 1];
				}
				i = i - 1;
			}
		}
	}
	printf("去重后的key为:%s\n", MiYue);
	char Biao[5][5];//定义表
	char OtherChar[25] = "ABCDEFGHIKLMNOPQRSTUVWXYZ";
	for (int j = 0; j <= strlen(MiYue); j++){
		for (int i = 0; i < 26; i++){ 
			if (MiYue[j] == OtherChar[i]) {//去除26字母表中密钥出现过的字母
				for (int n = i; n <= 25; n++) {
					OtherChar[n] = OtherChar[n + 1];
				}
			}
		}
	}
	int o = 0;
	for (int i = 0; i < 5; i++) {
		for (int j = 0; j < 5; j++) {
			if (j + i * 5 < strlen(MiYue)) {
				Biao[i][j] = MiYue[j + i * 5];//先往表中填入密钥字母
			}
			else {
				Biao[i][j] = OtherChar[o];//再填入其他字母
				o = o + 1;
			}
		}
	}
	printf("填充后的key为:");//打填充的key
	for (int i = 0; i < 5; i++) {
		for (int j = 0; j < 5; j++) {
			printf("%c", Biao[i][j]);
		}
	}
	printf("\n");
	printf("key形成的矩阵是\n");
	for (int i = 0; i < 5; i++) {//打印表
		for (int j = 0; j < 5; j++) {
			printf("%c ", Biao[i][j]);
		}
		printf("\n");
	}
	char MiWen[30];//定义密文
	int indexX[2];//表的横坐标
	int indexY[2];//表的纵坐标
	for (int n = 0; n < strlen(MingWen); n=n+2) {//匹配找到明文字母1对应坐标
		for (int i = 0; i < 5; i++) {
			for (int j = 0; j < 5; j++) {
				if (MingWen[n] == Biao[i][j]) {
					indexX[0] = j;
					indexY[0] = i;
				}
			}
		}
		for (int i = 0; i < 5; i++) {//匹配找到明文字母2对应的坐标
			for (int j = 0; j < 5; j++) {
				if (MingWen[n + 1] == Biao[i][j]) {
					indexX[1] = j;
					indexY[1] = i;
				}
			}
		}
		if (indexY[0] == indexY[1]) {//纵坐标相同时横坐标向右移动
			MiWen[n] = Biao[indexY[0]][(indexX[0]+1)%5];
			MiWen[n+1] = Biao[indexY[1]][(indexX[1]+1)%5];
		}
		else if (indexX[0] == indexX[1]) {//横坐标相同时纵坐标向下移动
			MiWen[n] = Biao[(indexY[0]+1)%5][indexX[0]];
			MiWen[n + 1] = Biao[(indexY[1]+1)%5][indexX[1]];
		}
		else {//横纵坐标都不同用对角线字母代换
			MiWen[n] = Biao[indexY[0]][indexX[1]];
			MiWen[n + 1] = Biao[indexY[1]][indexX[0]];
		}
	}
	printf("J替换成I后的明文是");//打印J替换成I后的明文
	for (int i = 0; i < strlen(MingWen)-1; i++) {
		printf("%c", MingWen[i]);
	}
	printf("\n加密后密文为:");//打印密文
	for (int i = 0; i < strlen(MingWen); i++) {
		printf("%c", MiWen[i]);
	}
}
void Declassify() {
	printf("还未开发\n");
}
void menu() {
	printf("******************\n\n");
	printf("1.Playfair加密\n");
	printf("2.Playfair解密\n");
	printf("0.退出程序\n");
	printf("\n******************\n");
	int c;
	scanf("%d", &c);
	getchar();
	switch (c) {
	case 1: Encryption(); break;
	case 2:Declassify(); break;
	case 0:exit();
	}
}
int main() {
	while (1) {
		menu();
	}
	return 0;
}

5.运行结果:

 

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值