这个学期学校开了应用密码学的课,老师布置的一个作业就是挑选一种置换或者代换密码然后用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;
}
1525



被折叠的 条评论
为什么被折叠?



