playfair密码 C语言实现

本文介绍了作者在应用密码学课程中,使用C语言实现Playfair密码加密解密算法的过程。文章详细阐述了Playfair密码的原理、加密规则以及解密规则,并提供了详细的步骤和代码示例。在实现过程中,作者遇到了网上资料不足和规则不一致的问题,最终成功实现了符合书本规则的算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这个学期学校开了应用密码学的课,老师布置的一个作业就是挑选一种置换或者代换密码然后用C语言实现。

刚开始拿到组长分配的任务,觉得playfair很简单,完全可以一个小时搞定,可是真正动手去写,才发现这个算法的复杂。

不是需要多么高深的算法技巧,但是对于明文的整理,生成5x5矩阵的过程,加密的分析,需要用到二维数组,动态内存,等等。关键是网上对于playfair密码的介绍实在是很少啊。(如果大家有好的网站推荐一下,博主在此谢过了,嘿嘿)

当时我去了解这个原理完全是靠百度百科,后来一看,咦!与书上不一样。我去。。白写了大半天,百度百科中对明文的处理,加密的方式和书上差距比较大。

所以在这里我需要啰嗦一下加密的规则。

/**************************************************************************************************>
**	项目声明:本加密算法采用 playfair 加密方式。
**		传入的明(密)文允许出现非法字符(除字母之外的字符),算法可以自动剔除,得到合法明(密)文
**		且算法不会改变原始明(密)文的值。
**
**	使用须知:
**		由于无法对解密密文得到的明文中的缺省值做判断,例如
**		无法判断JKASX中的X是来自于缺省值还是明文中本就有的字符,故明文加密得到的
**		密文再经解密可能会与明文出现差异,并且由于I和J被视为一个字符,故解密得到
**		的明文需要判断I和J,大体上不影响明文翻译。
**
**	加密规则:
**		1、同行不同列:依次取右一位。
**		2、同列不同行:依次取下一位。
**		3、不同行且不同列:依次取对应的角。
**
**	解密规则:
**		1、同行不同列:依次取左一位。
**		2、同列不同行:依次取上一位。
**		3、不同行且不同列:依次取对应的角。
**
*******************************************************************************************/

下面是头文件playfair.h的内容

#ifndef _PLAYFAIR_H_
#define _PLAYFAIR_H_

typedef unsigned int status;
typedef unsigned short ushort;

#define ERROR 1
#define SUCCESS 0
#define OVERFLOW -1

#define EXTRA_LENGTH 20
#define TEXT_LENGTH 100

char *encrypt(char *plaintext, char *key);
char *decrypt(char *code, char *key);
status changeDeaultValue(char ch);
void getKeyMatrix(char (*matrix)[5], char *srckey);
char *sortPlainText(char *text);
char getDefaultValue();
ushort get_XY_From5x5Matrix(char ch, char (*matrix)[5]);
int abs(int num);

#endif

一、playfair密码:

  • Playfair密码是查尔斯▪惠斯通于1854年发明的一种加密方式,属于代换密码。

  • Playfair加密得到的密文有一个特征,位数必然为偶数,任意同组(两个一组,后面会介绍)的字母都是不一样的。

  • Playfair密码使用方便,并且可以很好地抵抗频度分析法的攻击。但是在1915年的一战被破译了。
    二、加密规则:

  • 值得吐槽的是,我的教材上和网上的规则是不一样的,一度导致我写完算法之后测试,诶,这个怎么不对,,,,我去,又错了?!后来发现,我用网上的标准去给书上的明文加密,得到的密文和书上不一样。然后改为了书上的规则,发现又对不上网上的答案了。好吧,我当时肯定是写算法写晕了。

  • 吐槽完毕,开始讲规则!

  • 加密规则:

    0、两个一组进行加密。

    1、同行不同列:依次取右一位。

    2、同列不同行:依次取下一位。

    3、不同行且不同列:依次取对应的角。

  • 解密规则:

    1、同行不同列:依次取左一位。

    2、同列不同行:依次取上一位。

    3、不同行且不同列:依次取对应的角。

  • 举例:

    n 见下面矩阵,如果根据这个矩阵对HEYDDYLMOT进行加密,那么HE得到的密文是RY,,YD加密得到HC,DY加密得到CH,LM加密得到MN,OT加密得到PO。(声明一下,我这个规则可能不是标准的,但是我代码写好了,修改加密规则之后,我只要改几条语句就OK,当然,主要还是因为我现在还没找到传说中的标准-,如果大家有资源,推荐一下,感激不尽!)

  • 详细步骤:

    1.首先需要根据密钥生成5x5字母矩阵,这里我们规定矩阵中的字母都是大写的,而且因为5x5==25,所以有一个字母得被舍弃掉。我们把密钥依次加到矩阵里面,重复的字母忽略,密钥添加完毕之后,开始添加26字母中密钥之外的字母,例如我们的密钥是keyhere,那么得到的矩阵应该是:

K E Y H R
A B C D F
G I L M N
O P Q S T
U V W X Z

/*****************************************************************>
**	函数功能:
**		生成一个5x5大小,符合playfair规则的加密矩阵,并且返回。 
**
**	参数传入:
**		char martix[5][5]:一个5x5的矩阵(二维数组实现)
**		char    *key  :密钥
**
**	函数返回:
**		无返回值。 
****************************************************************/
void getKeyMatrix(char (*matrix)[5], char *key)
{
	/* 生成5X5加密矩阵 */
	int k = 0;
	char temp[26];
	memset(temp, 0, 26);
	
	/* 将密钥加入到矩阵中 */
	while (*key != 0) {
		/* strchr的功能是判断一个字符串中是否有某个字符,
			如果有,返回下标,没有则返回NULL */
		if (strchr(temp, *key) == NULL) {
			if ((*key >='a' && *key <= 'z') || (*key >= 'A' && *key <= 'Z')) {
				temp[k++] = *key;
			}
		}
		/* 指针后移 */ 
		key++;
	}
	
	/* 将字符数组中的字母变为大写,由于是字符数组,所以不能使用strupr函数 */
	int i = 0;
	while (temp[i] != '\0') {
		temp[i] = temp[i] >= 'a' ? temp[i] - 'a' + 'A' : temp[i];
		i++;
	}
	
	/* 填充矩阵 */ 
	for (int i = 'A'; i <= 'Z'; i++) {
		if (i == 'J') {
			continue;
		}
		/* 仍然需要查重 */ 
		else {
			if (strchr(temp, i) == NULL) {
				temp[k++] = i;
			}
		}
	}
	/* 将temp中的数据转存到二维数组中 */
	memcpy(matrix, temp, 25);
}

检查是否正确的方法很简单,只需要看一下最后一位是不是’Z’就行。这里需要注意的是,矩阵中是没有’J’的,在playfair密码中,把’I’和’J’视为同一个字母,在我的算法里面直接就把所有明文或者密文或者密钥中的’J’变为’I’。

2.接下来需要做的是整理明文,需要做的有五步:

1  去掉非法字符(字母以外都是非法字符)。

2  将明文变为大写(便于后续加密)。

3  保证每两个一组的明文不会重复。

4  把明文中的’J’替换为’I’。

5  保证明文为偶数位。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值