playfair密码 C语言实现

Playfair密码算法的C语言实现与应用 Playfair密码算法是一种在19世纪末期由英国科学家查尔斯·惠斯通提出的经典加密方法,该算法的名称来源于当时的政治家、科学家和密码学先驱巴特勒·利斯·琼斯男爵(Frederick Charles Francis Abel),他后来被授予“Playfair”男爵称号。该加密算法使用一个5x5的字母矩阵来进行加密,通过替换和重排明文中的字母对来实现加密,相较于传统的单字母替换密码,如凯撒密码,它具有更高的安全性。5x5矩阵是Playfair密码算法的核心组件,用于替代传统的26字母表。 阅读详情

这个学期学校开了应用密码学的课,老师布置的一个作业就是挑选一种置换或者代换密码然后用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  保证明文为偶数位。
/************************************************************************>
**	函数功能:
**		整理明文成为可以加密的格式。
**
**	参数传入:
**		char *text:传入原始明文。
**
**	函数返回:
**		char *sortedText:整理好的明文。
**
**	整理内容: 
**		1>将明文中的非法字符去除。		2>将明文变为全大写。 
**		3>保证成对明文不会相同。		4>将明文中的'J'和'j'替换为'I'。
**		5>保证明文为偶数位。 
**
**	函数说明:
**		传入的原始明文的内容不会被修改,修改后的合法明文的内容存储在一个新
**		的字符串, 并且被返回。 
****************************************************************************/ 
char *sortPlainText(char *text)
{
	int textLength = 0;
	char *tmp = NULL;
	
	textLength = (int)strlen(text);
	
	/* 申请空间 */ 
	tmp = (char *)malloc(sizeof(char) * (textLength + EXTRA_LENGTH));
	/* 判错 */ 
	if (tmp == NULL) {
		
		exit(OVERFLOW);
	}
	/* 初始化 */ 
	memset(tmp, 0, textLength + EXTRA_LENGTH);
	
	/* 通过这个for循环去除非法字符以及将明文字母变为大写,将'J'变为'I' */ 
	int k = 0;
	for (int i = 0; i < textLength; i++) {
		/* 剔除合法字符 */
		if ((text[i] >= 'a' && text[i] <= 'z') || (text[i] >= 'A' && text[i] <= 'Z')) {
			/* 将'J'和'j'变为'I' */ 
			if (text[i] == 'j' || text[i] == 'J') {
				tmp[k++] = 'I';
			}
			/* 普通情况 */ 
			else {
				tmp[k++] = text[i] >= 'a' ? text[i] - 'a' + 'A' : text[i];
			}
		}
	}
	
	for (int i = 1; i < (int)strlen(tmp); i++) {
		/* 分析处理成对字符重复的情况 */
		if ((tmp[i] == tmp[i - 1]) && (i % 2 != 0)) {
			/* 字符串自重复位开始后退一位,在重复位插入缺省字符 */
			for (int j = (int)strlen(tmp); j >i; j--) {
				tmp[j] = tmp[j - 1];
			}
			if (defaultValue != tmp[i - 1]) {
				tmp[i] = defaultValue;
			}
			else {
				/* mod26的原因是如果使用者将缺省字符修改为'Z',则加1可能会溢出 */
				tmp[i] = (defaultValue - 'A' + 1) % 26 + 'A';
			}
		}
	}
	
	/* 保证合法明文为偶数 */
	int len = (int)strlen(tmp);
	if (len % 2 != 0) {
		/* 需要判断与最后一位是否相同 */ 
		if (defaultValue != tmp[len - 1]) {
				tmp[len] = defaultValue;
		}
		else {
			/* mod26的原因是如果使用者将缺省字符修改为'Z',则加1可能会溢出 */
			tmp[len] = (defaultValue - 'A' + 1) % 26 + 'A';
		}
	}
	
	return tmp;
}

3.加密:

1  这里没有什么好讲的,直接上代码。
/***********************************************>
**	加密函数:
**		采用playfair加密方式。
**
**	参数传入:
**		char *plaintext:明文,传入字符串首地址。
**		char 	 *key  :密钥,传入字符串首地址。
**
**	函数返回:
**		ciphertext:密文,传回字符串首地址。
**
**	过程简介:
**		1:获取密钥,生成5x5加密矩阵。
**		2:整理明文:
**				使用sortPlainText函数。 
**		3:利用加密矩阵加密明文。 
************************************************/
char *encrypt(char *plainText, char *key)
{
	/* 建立二维数组准备储存矩阵 */
	char matrix[5][5];
	/* 由密钥获取加密矩阵  */
	getKeyMatrix(matrix, key);
	
	/* 由原始明文获取合法明文 */
	char *legalPlnText = sortPlainText(plainText);
	
	/*puts(legalPlnText);		//测试用
	
	for (int i = 0; i < 5; i++) {
		for (int j = 0; j < 5; j++) {
			putchar(matrix[i][j]);
			putchar(' ');
		}
		putchar(10);
	}*/
	
	/* 为密文申请空间 */
	char *cprText = (char *)malloc(sizeof(char) * TEXT_LENGTH);
	
	/* 判断是否申请成功 */
	if (cprText == NULL) {
		exit(OVERFLOW);
	}
	/* 初始化密文空间 */
	memset(cprText, 0, (int)strlen(legalPlnText));
	 
	/* 开始加密 */
	int k = 0;
	for (int i = 0; i < (int)strlen(legalPlnText); i += 2) {
		int tmpPos1 = get_XY_From5x5Matrix(legalPlnText[i], matrix);
		int tmpPos2 = get_XY_From5x5Matrix(legalPlnText[i + 1], matrix);
		
		/* 获取坐标 */
		int x1 = tmpPos1 / 10;
		int x2 = tmpPos2 / 10;
		int y1 = tmpPos1 % 10;
		int y2 = tmpPos2 % 10;
		
		/* 同行不同列的情况 */ 
		if ((x1 == x2) && (y1 != y2)) {
			cprText[k++] = matrix[x1][(y1 + 1) % 5];
			cprText[k++] = matrix[x2][(y2 + 1) % 5];
		}
		/* 同列不同行的情况 */ 
		else  if((x1 != x2) && (y1 == y2)) {
			
			cprText[k++] = matrix[(x1 + 1) % 5][y1];
			cprText[k++] = matrix[(x2 + 1) % 5][y2];
		}
		/* 不同行不同列 */ 
		else  if ((x1 != x2) && (y1 != y2)) {
			cprText[k++] = matrix[x1][y2];
			cprText[k++] = matrix[x2][y1];
		}
		else {
			return NULL;
		}
	}
	/* 末位置为'\0' */ 
	cprText[k] = 0;
	
	return cprText;
}

新人第一次认真地写博客,肯定有不少写得不好的地方,或者说有什么写得错误的地方。欢迎大家指正!
此致,敬礼!

最后粘出所有代码:
1、playfair.c文件

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

/***********************************************>
**	加密函数:
**		采用playfair加密方式。
**
**	参数传入:
**		char *plaintext:明文,传入字符串首地址。
**		char 	 *key  :密钥,传入字符串首地址。
**
**	函数返回:
**		ciphertext:密文,传回字符串首地址。
**
**	过程简介:
**		1:获取密钥,生成5x5加密矩阵。
**		2:整理明文:
**				使用sortPlainText函数。 
**		3:利用加密矩阵加密明文。 
************************************************/
char *encrypt(char *plainText, char *key)
{
	/* 建立二维数组准备储存矩阵 */
	char matrix[5][5];
	/* 由密钥获取加密矩阵  */
	getKeyMatrix(matrix, key);
	
	/* 由原始明文获取合法明文 */
	char *legalPlnText = sortPlainText(plainText);
	
	/*puts(legalPlnText);		//测试用
	
	for (int i = 0; i < 5; i++) {
		for (int j = 0; j < 5; j++) {
			putchar(matrix[i][j]);
			putchar(' ');
		}
		putchar(10);
	}*/
	
	/* 为密文申请空间 */
	char *cprText = (char *)malloc(sizeof(char) * TEXT_LENGTH);
	
	/* 判断是否申请成功 */
	if (cprText == NULL) {
		exit(OVERFLOW);
	}
	/* 初始化密文空间 */
	memset(cprText, 0, (int)strlen(legalPlnText));
	 
	/* 开始加密 */
	int k = 0;
	for (int i = 0; i < (int)strlen(legalPlnText); i += 2) {
		int tmpPos1 = get_XY_From5x5Matrix(legalPlnText[i], matrix);
		int tmpPos2 = get_XY_From5x5Matrix(legalPlnText[i + 1], matrix);
		
		/* 获取坐标 */
		int x1 = tmpPos1 / 10;
		int x2 = tmpPos2 / 10;
		int y1 = tmpPos1 % 10;
		int y2 = tmpPos2 % 10;
		
		/* 同行不同列的情况 */ 
		if ((x1 == x2) && (y1 != y2)) {
			/*// 需要分析两个字符不相邻时的情况 
			if (abs((y1 - y2)) != 1 && abs((y1 - y2)) != 4) {
				cprText[k++] = matrix[x1][(y1 + 1) % 5];
				cprText[k++] = matrix[x2][(y2 + 1) % 5];
			}
			// 相邻 
			else if (abs(y2 - y1) == 1) {
				cprText[k++] = matrix[x1][(y2 + 1) % 5];
				cprText[k++] = matrix[x2][(y2 + 2) % 5];
			}
			// 分别位于两端 
			else {
				cprText[k++] = matrix[x1][1];
				cprText[k++] = matrix[x2][2];
			}*/
			
			cprText[k++] = matrix[x1][(y1 + 1) % 5];
			cprText[k++] = matrix[x2][(y2 + 1) % 5];
		}
		/* 同列不同行的情况 */ 
		else  if((x1 != x2) && (y1 == y2)) {
			/*
			// 分析两个字符不相邻时的情况  
			if (abs((x1 - x2)) != 1 && abs((x1 - x2)) != 4) {
				cprText[k++] = matrix[(x1 + 1) % 5][y1];
				cprText[k++] = matrix[(x2 + 1) % 5][y2];
			}
			// 相邻 
			else if (abs(x1 - x2) == 1) {
				cprText[k++] = matrix[(x2 + 1) % 5][y1];
				cprText[k++] = matrix[(x2 + 2) % 5][y2];
			}
			// 分别位于两端
			else {
				cprText[k++] = matrix[1][y1];
				cprText[k++] = matrix[2][y2];
			}*/
			cprText[k++] = matrix[(x1 + 1) % 5][y1];
			cprText[k++] = matrix[(x2 + 1) % 5][y2];
		}
		/* 不同行不同列 */ 
		else  if ((x1 != x2) && (y1 != y2)) {
			cprText[k++] = matrix[x1][y2];
			cprText[k++] = matrix[x2][y1];
		}
		else {
			return NULL;
		}
	}
	/* 末位置为'\0' */ 
	cprText[k] = 0;
	
	return cprText;
}

/********************************************************>
**	解密函数:
**		采用playfair解密方式。
**
**	参数传入:
**		char *cipherText:明文,传入字符串首地址。
**		char 	 *key   :密钥,传入字符串首地址。
**
**	函数返回:
**		plainText:密文,传回字符串首地址。
**
**	过程简介:
**		1:获取密钥,生成5x5加密矩阵。
**		2:整理密文并且做处理生成合法密文字符串。
**		3:利用解密矩阵解密密文。
**		4:解密过程是加密的逆过程,只需要更改运算符(代码中有标注)。
*******************************************************************/ 
char *decrypt(char *cipherText, char *key)
{
	/* 建立二维数组准备储存矩阵 */ 
	char matrix[5][5];
	/* 由密钥获取加密矩阵  */ 
	getKeyMatrix(matrix, key);
	
	/* 用一个新的字符串去储存密文,防止改变原文 */
	char *cprText = (char *)malloc(sizeof(char) * TEXT_LENGTH);
	if (cprText == NULL) {
		exit(OVERFLOW);
	}
	/* 获取合法密文 */ 
	int k = 0;
	for (int i = 0; i < (int)strlen(cipherText); i++) {
		if ((cipherText[i] >= 'a' && cipherText[i] <= 'z') || (cipherText[i] >= 'A' && cipherText[i] <= 'Z')) {
			cprText[k++] = cipherText[i] >= 'a' ? cipherText[i] - 'a' + 'A' : cipherText[i];
		}
	}
	/* 末位置为'\0' */ 
	cprText[k] = '\0';
	
	/* 为明文申请空间 */ 
	char *plnText = (char *)malloc(sizeof(char) * TEXT_LENGTH);
	
	/* 初始化明文空间 */
	memset(plnText, 0, (int)strlen(plnText));
	
	/*for (int i = 0; i < 5; i++) {		//调试用 
		for (int j = 0; j < 5; j++) {
			putchar(matrix[i][j]);
		}
		putchar(10);
	}
	
	puts(cprText);*/
	 
	/* 开始解密 */
	k = 0;
	for (int i = 0; i < (int)strlen(cprText); i += 2) {
		int tmpPos1 = get_XY_From5x5Matrix(cprText[i], matrix);
		int tmpPos2 = get_XY_From5x5Matrix(cprText[i + 1], matrix);
		
		/* 获取坐标 */ 
		int x1 = tmpPos1 / 10;
		int x2 = tmpPos2 / 10;
		int y1 = tmpPos1 % 10;
		int y2 = tmpPos2 % 10;
		
		/* 同行不同列的情况 */ 
		if ((x1 == x2) && (y1 != y2)) {
			/*
			// 需要分析两个字符不相邻时的情况
			if (abs((y1 - y2)) != 1 && abs((y1 - y2)) != 4) {
				// !!!模数之前加5的原因是C语言中的模和代数中的模运算不全相同,
				//-3 % 5 == -3 而不是代数中的2,故在此应该加 5 保证为正
				plnText[k++] = matrix[x1][(y1 - 1 + 5) % 5];
				plnText[k++] = matrix[x2][(y2 - 1 + 5) % 5];
			}
			// 相邻
			else if (abs(y1 - y2) == 1) {
				plnText[k++] = matrix[x1][(y1 - 2 + 5) % 5];
				plnText[k++] = matrix[x2][(y1 - 1 + 5) % 5];
			}
			// 分别位于两端 
			else {
				plnText[k++] = matrix[x1][2];
				plnText[k++] = matrix[x2][3];
			}*/
			plnText[k++] = matrix[x1][(y1 - 1 + 5) % 5];
			plnText[k++] = matrix[x2][(y2 - 1 + 5) % 5];
		}
		/* 同列不同行的情况 */ 
		else  if((x1 != x2) && (y1 == y2)) {
			/*
			// 分析两个字符不相邻时的情况 
			if (abs((x1 - x2)) != 1 && abs((x1 - x2)) != 4) {
				plnText[k++] = matrix[(x1 - 1 + 5) % 5][y1];
				plnText[k++] = matrix[(x2 - 1 + 5) % 5][y2];
			}
			// 相邻
			else if (abs(x1 - x2) == 1) {
				plnText[k++] = matrix[(x1 - 2 + 5) % 5][y1];
				plnText[k++] = matrix[(x1 - 1 + 5) % 5][y2];
			}
			// 分别位于两端 
			else {
				plnText[k++] = matrix[2][y1];
				plnText[k++] = matrix[3][y2];
			}*/
			plnText[k++] = matrix[(x1 - 1 + 5) % 5][y1];
			plnText[k++] = matrix[(x2 - 1 + 5) % 5][y2];
		}
		/* 不同行不同列 */ 
		else  if ((x1 != x2) && (y1 != y2)) {
			plnText[k++] = matrix[x1][y2];
			plnText[k++] = matrix[x2][y1];
		}
		else {
			return NULL;
		}
	}
	/* 末位置为'\0' */ 
	plnText[k] = 0;
	
	return plnText;
}

/*********************************************>
**	函数功能:
**		修改缺省字符。
**
**	参数传入:
**		char ch:一个字母字符。
**
**	函数返回:
**		无返回值。
**
**	函数说明:
**		无论输入是否为大写,都会转为大写。
************************************************/ 
status changeDeaultValue(char ch)
{
	if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
		/* 保证为大写 */
		defaultValue = (ch >= 'a' ? ch - 'a' + 'A' : ch);
		
		return SUCCESS;
	}
	else {
		return ERROR;
	}
}
/*******************************>
**	函数功能:
**		返回缺省字符。
**
**	参数传入:
**		无。 
**
**	函数返回:
**		返回缺省值:char型字符。 
**********************************/ 
char getDefaultValue()
{
	return defaultValue;
}

/*****************************************************************>
**	函数功能:
**		生成一个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);
}

/************************************************************************>
**	函数功能:
**		整理明文成为可以加密的格式。
**
**	参数传入:
**		char *text:传入原始明文。
**
**	函数返回:
**		char *sortedText:整理好的明文。
**
**	整理内容: 
**		1>将明文中的非法字符去除。		2>将明文变为全大写。 
**		3>保证成对明文不会相同。		4>将明文中的'J'和'j'替换为'I'。
**		5>保证明文为偶数位。 
**
**	函数说明:
**		传入的原始明文的内容不会被修改,修改后的合法明文的内容存储在一个新
**		的字符串, 并且被返回。 
****************************************************************************/ 
char *sortPlainText(char *text)
{
	int textLength = 0;
	char *tmp = NULL;
	
	textLength = (int)strlen(text);
	
	/* 申请空间 */ 
	tmp = (char *)malloc(sizeof(char) * (textLength + EXTRA_LENGTH));
	/* 判错 */ 
	if (tmp == NULL) {
		
		exit(OVERFLOW);
	}
	/* 初始化 */ 
	memset(tmp, 0, textLength + EXTRA_LENGTH);
	
	/* 通过这个for循环去除非法字符以及将明文字母变为大写,将'J'变为'I' */ 
	int k = 0;
	for (int i = 0; i < textLength; i++) {
		/* 剔除合法字符 */
		if ((text[i] >= 'a' && text[i] <= 'z') || (text[i] >= 'A' && text[i] <= 'Z')) {
			/* 将'J'和'j'变为'I' */ 
			if (text[i] == 'j' || text[i] == 'J') {
				tmp[k++] = 'I';
			}
			/* 普通情况 */ 
			else {
				tmp[k++] = text[i] >= 'a' ? text[i] - 'a' + 'A' : text[i];
			}
		}
	}
	
	for (int i = 1; i < (int)strlen(tmp); i++) {
		/* 分析处理成对字符重复的情况 */
		if ((tmp[i] == tmp[i - 1]) && (i % 2 != 0)) {
			/* 字符串自重复位开始后退一位,在重复位插入缺省字符 */
			for (int j = (int)strlen(tmp); j >i; j--) {
				tmp[j] = tmp[j - 1];
			}
			if (defaultValue != tmp[i - 1]) {
				tmp[i] = defaultValue;
			}
			else {
				/* mod26的原因是如果使用者将缺省字符修改为'Z',则加1可能会溢出 */
				tmp[i] = (defaultValue - 'A' + 1) % 26 + 'A';
			}
		}
	}
	
	/* 保证合法明文为偶数 */
	int len = (int)strlen(tmp);
	if (len % 2 != 0) {
		/* 需要判断与最后一位是否相同 */ 
		if (defaultValue != tmp[len - 1]) {
				tmp[len] = defaultValue;
		}
		else {
			/* mod26的原因是如果使用者将缺省字符修改为'Z',则加1可能会溢出 */
			tmp[len] = (defaultValue - 'A' + 1) % 26 + 'A';
		}
	}
	
	return tmp;
}

/************************************************************************>
**	函数功能:
**		从矩阵找到对应字符并且返回其位置。
**
**	参数传入:
**		char	 ch		 :传入待查找字符。
**		char (*matrix)[5]:传入矩阵。 
**
**	函数返回:
**		ushort类型的变量:x位于十位,y位于个位。 
**
**	函数说明:
**		传回的是一个unsigned short变量,下标 x 储存在十位,下标 y 储存在个位。
******************************************************************************/ 
ushort get_XY_From5x5Matrix(char ch, char (*matrix)[5])
{
	/* 遍历矩阵 */
	for (int x = 0; x < 5; x++) {
		for (int y = 0; y < 5; y++) {
			if (matrix[x][y] == ch) {
				/* 利用一个变量同时返回下标x, y */ 
				return (x * 10 + y);
			}
		}
	}
}

/*************************************>
**	函数功能:
**		计算绝对值。 
**
**	参数传入:
**		int num:需要求绝对值的整型数。 
**
**	函数返回:
**		num绝对值。 
***************************************/ 
int abs(int num)
{
	return (num > 0 ? num : -num);
}

2、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

3、我自己写的main.c文件

#include <stdio.h>
#include <string.h>
#include "playfair.h"

int main()
{
	char plainText[100] = "";
	char cipherText[100] = "";
	char key[100] = "";
	
	printf("****************playfair加密函数*********V1.0*****\n");
	int sel = -1;
	
	while (1) {
		printf("请输入(0-退出、1-加密、2-解密):" ); 
		scanf("%d", &sel);

		switch(sel) {
			case 0: return 0; break;
			case 1: {
				printf("\t请输入明文:");
				scanf("%s", plainText);
				printf("\t请输入密钥:");
				scanf("%s", key);
				char *cprText = encrypt(plainText, key);
				puts(cprText);
				break;
			}
			case 2: {
				printf("\t请输入密文:");
				scanf("%s", cipherText);
				printf("\t请输入密钥:");
				scanf("%s", key);
				char *plnText = decrypt(cipherText, key);
				puts(plnText);
				break;
			}
			default: break;
		}
	}
	
	return 0;
}
Playfair加密算法 C语言 C语言实现Playfair密码,在Windows平台的VC和Linux平台的gcc上均测试通过 C语言实现Playfair密码,在Windows平台的VC和Linux平台的gcc上均测试通过<<隐藏 立即下载

相关推荐

playfair多码代换加密解密的C语言实现

这是一段c语言实现的playfair多码代换算法的简单程序。

playfair密钥矩阵加密--c语言

//playfair #include<stdio.h> #include<string.h> int main() { char pf[5][5]={'c','a','l','m','d','o','w','n','b','e','f','g','h','i','k','p','q','r','s' ,'t','u','v','x','y','z'}; printf("输入明文:\n"); char ms[20]; gets(ms); int len =strlen.

qq_52875323的博客 1525

playfair密码C语言实现

是我自己写的C语言算法,可以实现playfair加解密。 需要后续文档什么的可以找我,免费。 不过其实代码里面的注释完全可以帮助大家看懂了

Playfair密码(波雷费密码)的C语言实现

#include #include #include #include #define ENCRYPT 1 #define DECRYPT -1 // See in: The Cert C Secure Coding Standard #define STRING(n) STRING_AGAIN(n) #define STRING_AGAIN(n) #n #define CHARS_TO_READ 100 FILE *fpSrc = NULL; FILE *fpDest = N

8990

playfair 算法及其C语言模拟实现

playfair 算法及其C语言模拟实现

playfair密码的C++实现的实验报告,及源码

该文件包含了playfair密码的详细实验报告,以及可以直接在DEV或VC++里面可以直接运行的代码

Playfair加密算法(C 实现)

主要函数 1、Creat_Key(char* s,int L, char Matrix[5][5]) 生成密钥Matrix矩阵 2、Encrypt(char Matrix[5][5],int L, char* s, char *s0, bool reverse) 根据密钥矩阵加密或解密 加密:s为明文,s0为密文字符串存储位置,reverse=0 解密:s为密文,s0为明文字符串存储位置,reverse=1 注意事项 1、字符串只能含有字母 2、已禁用字母j/J 3、字符均以大写形式处理(已自动转换,输入时

dc12499574的博客 4623

大模型呼叫中心场景分享之六:大模型外呼IT运维告警——智能监控与自动化响应的未来

在数字化运维(IT Operations)中,实时监控系统健康状态并及时响应告警是保障业务连续性的关键。传统的IT告警方式(如邮件、短信、钉钉/企业微信通知)存在信息过载、响应延迟、人工处理效率低等问题。而大模型(LLM)与语音技术(TTS/ASR)的结合,为IT运维告警提供了更智能的解决方案——大模型外呼告警系统。大模型外呼告警系统正在重新定义IT运维的效率和体验。通过实时语音交互+智能自动化,企业能够将平均故障修复时间(MTTR)从小时级缩短至分钟级。

开源呼叫中心系统FreeIPCC的博客 922

古典密码之一的Playfair密码的实现

古典密码之一的Playfair密码的实现

adcxhw的博客 5014

手教你如何使用Simulink和相关工具箱模拟和实现无人机的多机接力信号中继的建模

扩大通信范围:单架无人机的通信能力有限,通过多机接力的方式可以显著扩展通信覆盖范围。提高可靠性:当某架无人机出现故障或电量不足时,其他无人机可以接管其任务,确保通信不中断。适应复杂环境:在山区、森林等复杂地形中,多机接力可以绕过障碍物,建立稳定的通信链路。使用Communications Toolbox中的模块来模拟无线通信链路。例如,可以使用模块模拟噪声信道,或者使用模块计算信号衰减。matlab深色版本。

MHD0815的博客 767

基于分段线性近似的Softmax硬件加速器设计

本文深入探讨了基于分段线性近似的Softmax硬件加速器设计。针对深度学习模型中Softmax函数在硬件实现时指数运算成本高昂的问题,提出用分段线性拟合替代传统泰勒展开,通过一次乘加操作高效完成计算,并详细分析了输入范围压缩、精度与硬件资源权衡、以及包含地址生成、参数查找、乘加计算和归一化的完整硬件架构。该方法在保证精度的同时,显著提升了AI边缘芯片的推理速度和能效。

weixin_28278377的博客 312

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

密码学作业:Playfair密码(普莱费尔密码)c语言源码,不想自己变成,源码(纯c语言代码)复杂粘贴就能用。(看这一篇就够了)

qq_55961330的博客 1690

海康工业相机LabVIEW二次开发实战——参数配置优化与图像高效存储

本文详细介绍了海康工业相机在LabVIEW平台上的二次开发实战,重点解析了相机参数配置的优化方法与图像高效存储策略。通过剖析曝光、增益、触发模式等核心参数的设置逻辑,并结合生产者-消费者设计模式,指导开发者构建稳定、高效的图像采集与异步存储流程,有效提升工业视觉项目的开发效率与系统稳定性。

weixin_29306317的博客 221

实现Playfair密码,C语言

【代码】实现Playfair密码,C语言。

fighting_xr1的博客 650

Wonderware Intouch 2014R2 SP1 安装教程

下载Wonderware System Platform 2014R2 SP1 and Intouch 2014R2 SP1的安装压缩包,如下 软件的下载连接地址如下: https://pan.baidu.com/s/1a2GnI_nfT3vK1l49B94FIQ, 提取码:6ec6 或者直接微信扫描下面的二维码 管理员运行下面的setup.exe可执行程序, 进入安装,选择Product Based Selection, 自定义选择需要安装的程序,如下: 普通的Into

工控先生 3万+

【肌电处理】肌电信号EMG积分肌电值+均方根值+中值频率+平均功率频率【含Matlab源码 3386期】

肌电信号EMG积分肌电值+均方根值+中值频率+平均功率频率 完整的代码,方可运行;可提供运行操作视频!适合小白!

订阅付费专栏Matlab(奶茶价版),可赠送奶茶价版付费专栏指定代码1份; 822

c语言 修改密码源码,Playfair密码C语言源代码.doc

Playfair密码C语言源代码//PLAYFAIR.H头文件#ifndef _PLAY_FAIR_H_#define _PLAY_FAIR_H_void cst_playfair_table (char *in_key);void prnt_playfair_table ();int playfair_encrypt (char *plain_txt, char *cipher_txt);int...

weixin_39610468的博客 487

AI自瞄原理剖析(四)从Yolo推理坐标到屏幕坐标:基于FOV视角与焦距的坐标变换与精准瞄准

从Yolo推理框架得到的坐标到屏幕坐标的转换是一个涉及到FOV视角、焦距以及分辨率的复杂过程。通过数学公式,我们可以将推理框坐标反推为游戏内的实际坐标,并最终映射到屏幕坐标系中。利用这些信息,AI自瞄系统能够精确计算出准星从当前位置移动到敌人位置的距离,实现精准的自动瞄准。通过这种方法,AI自瞄系统能够在不同的游戏环境下灵活应对,提供高度精确的操作体验。在AI自瞄系统中,目标检测仅仅是第一步,获取到预测框的坐标后,我们还需要将这些坐标转换为实际屏幕上的精确位置。

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 1334

Playfair 加密

题目真的好长但是意思很简单 89.加密 (15分)C时间限制:3 毫秒 | C内存限制:3000 Kb题目内容:一种Playfair密码变种加密方法如下:首先选择一个密钥单词(称为pair)(字母不重复,且都为小写字母),然后与字母表中其他字母一起填入至一个5x5的方阵中,填入方法如下:1.首先按行填入密钥串。2.紧接其后,按字母序按行填入不在密钥串中的字母。3.由于方阵中只有25个位置,...

weixin_30645617的博客 422

第11.4节 混合储能系统能量管理

混合储能系统(HESS)的能量管理策略采用分层架构实现多时间尺度优化:调度层(小时级)进行经济优化,协调层(秒级)基于频率分解分配功率,执行层(毫秒级)实现快速跟踪。深度强化学习(DRL)方法通过定义状态空间、动作空间和多目标奖励函数,能有效处理系统不确定性和多目标优化问题。HESS性能评估需综合技术指标(如调节性能Kp值、设备寿命指标)和经济指标(净现值NPV、平准化储能成本LCOS),并遵循"建模-仿真-实验"的闭环流程。

技术工作者 245

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

使用Playfair密码变种加密字符串

一种Playfair密码变种加密方法如下:首先选择一个密钥单词(称为pair)(字母不重复,且都为小写字母),然后与字母表中其他字母一起填入至一个5x5的方阵中,填入方法如下: 1.首先按行填入密钥串。 2.紧接其后,按字母序按行填入不在密钥串中的字母。 3.由于方阵中只有25个位置,最后剩下的那个字母则不需变换。 如果密钥为youandme,则该方阵如下:  y o u a n d

xtgyt的专栏 1667

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

playfair加密算法c语言,二古典密码算法Playfair密码.doc

PAGE《密码学基础》实验指导20 / 20 学年 第 学期班 级:组 号:组 长:实验地点:指导教师:计算机科学与工程学院2009年10月PAGE I实验目录TOC \o "1-3" \h \z \u 实验一、熟悉CAP4 1实验二 古典密码算法Playfair密码 3实验三 古典密码算法仿射密码 5实验四 古典密码算法Vigenère密码 7实验五、对称密...

weixin_32825955的博客 945

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

蓝桥杯 程序设计_7

一种Playfair密码变种加密方法如下:首先选择一个密钥单词(称为pair)(字母不重复,且都为小写字母),然后与字母表中其他字母一起填入至一个5x5的方阵中,填入方法如下: 1.首先按行填入密钥串。 2.紧接其后,按字母序按行填入不在密钥串中的字母。 3.由于方阵中只有25个位置,最后剩下的那个字母则不需变换。 如果密钥为youandme,则该方阵如下:   y o u a n d

ll_0520的专栏 1075

标准字头密码体制c语言,关于Playfair密码体制

第一步,你需要一个密钥,当然是英文的了,一句话或者几个单词,比如HOW ARE YOU。然后把这组密钥里重复的字母去掉,只留第一次出现的,自然,空格也要去掉,于是变成HOWAREYU。把密钥记下来,或者传给你要发送密码过去的人,然后开始下一步。第二步,做一5*5矩阵,把密钥每5个字母断开,作为一行,直到密钥每个字母都排在矩阵中,然后紧接着密钥最后一个字母,以“除去密钥中的字母的字母表”(是残缺的字...

weixin_36319281的博客 693

每日一题-加密

title: 每日一题–加密 date: 2019-10-31 11:13:59 tags: 每日一题 算法 89.加密 (15分) C时间限制:3 毫秒 | C内存限制:3000 Kb 题目内容: 一种Playfair密码变种加密方法如下:首先选择一个密钥单词(称为pair)(字母不重复,且都为小写字母),然后与字母表中其他字母一起填入至一个5x5的方阵中,填入方法如下: 1.首先...

qq_42266398的博客 1042
DLPointer
博客等级 码龄10年 6粉丝 1原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值