实现Playfair密码,C语言

一、算法要求:


二、代码:

#include<windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>//topper函数 
 
// 将密钥中的字母转换成大写
void ConverstAlphabet(char key[]) {
    int keyLen = strlen(key);
    for (int i = 0; i < keyLen; i++)
    {
        key[i] = toupper(key[i]);
        //toupper函数将小写字母转换为大写字母
    }
}
//将密钥的字符去重
int Deduplication(char key[], int keylen1)
{
    //keylen1是原始的密钥的长度
    if (keylen1 <= 1)
    {
        return 0;
    }
    int i = 0;
    int j = 0;
    int count = 1;
    for (i = 1; i < keylen1; i++)
    {
        for (j = 0; j < i; j++)
        {
            if (key[i] == key[j])
            {
                break;
            }
        }
        if (i == j)
        {
            key[count++] = key[i];
        }
    }
    key[count] = '\0';//末尾加一个\0
    return count;//count个 
}
 
 
// 生成密码表
void CreatPassWordTable(char key[], char table[5][5], int keylen2)
{
    char alphabet[] = "ABCDEFGHIKLMNOPQRSTUVWXYZ";
    int alphabetLen = strlen(alphabet);
    int k = 0;
    //这个for循环是把密钥放到密钥表中
    for (int i = 0; i < keylen2; i++) {//keylen2是去重后的密钥的长度
        table[k / 5][k % 5] = key[i];
        k++;
    }
    
    //把未重复的放进密码表 
    for (int i = 0; i < alphabetLen; i++)
    {
        if (alphabet[i] == 'J') {
            // 将字母J转换成I
            continue;
        }
        int flag = 0;
        for (int j = 0; j < keylen2; j++)
		 {
            if (key[j] == alphabet[i])
			 {//判断密钥和25个字母是否相等
                flag = 1;
                break;
            }
         }
        if (!flag) {
            table[k / 5][k % 5] = alphabet[i];//开始把字母存放到密钥表中去
            k++;
        }
    }
}
 /*
 对明文按如下规则一次加密两个字母:
(1) 如果两个字母相同,则中间填充一个字母,如x,balloon-->balxloon-->ba lx lo on。前面的ll变lxl,后面的两个oo就不是一对了,中间无需再加x
(2) 明文去掉空格再加密,如果最终得到明文长度不是偶数的,可填充一个字母。
(2) 落在矩阵同一行中的明文字母对,由其右边的字母代替。如ar-->RM
(3) 落在矩阵同一列中的明文字母对,由其下面的字母代替。如mu-->CM
(4) 其它明文字母对:该字母所在行为密文所在行,另一字母所在列为密文所在列。如hs-->BP,ea-->IM(或JM)
*/ 
// 加密明文
void encrypt(char plaintext[], char table[][5]) {
    int len = strlen(plaintext);
    char p[100] = { 0 };
    int t = 0,z;
    
    
    for (int i = 0; i < len; i += 2) 
    { if(plaintext[i]==plaintext[i+1])
      {  
	  for(z=len;z>=i+2;z--)
	  plaintext[z]=plaintext[z-1]; 
	  len++;
	  if(plaintext[i]!='X') plaintext[i+1]='X';
	  }
	}
	
	
	//printf("加密过程中首先对明文处理为:") ; 
	 //for (int i = 0; i < len; i ++)
//	 printf("%c",plaintext[i]);
	//printf("\n");
    for (int i = 0; i < len; i += 2) {//因为一次找两个字符,所以这里是i+=2
        int row1 = 0, col1 = 0, row2 = 0, col2 = 0;
        // 查找明文字母在密码表中的位置
        for (int j = 0; j < 5; j++) {
            for (int k = 0; k < 5; k++) {
                if (table[j][k] == plaintext[i]) {
                    row1 = j;
                    col1 = k;
                }
                if (table[j][k] == plaintext[i + 1]) {
                    row2 = j;
                    col2 = k;
                }
            }
        }
        // 使用Playfair密码规则加密
        if (row1 == row2) {
            // 如果明文字母在同一行
            col1 = (col1 + 1) % 5;
            col2 = (col2 + 1) % 5;
        }
        else if (col1 == col2) {
            // 如果明文字母在同一列
            row1 = (row1 + 1) % 5;
            row2 = (row2 + 1) % 5;
        }
        else {
            // 如果明文字母不在同一行也不在同一列
            int temp = col1;//找对角线
            col1 = col2;
            col2 = temp;
        }
        //打印加密明文后的密文
        printf("%c%c", table[row1][col1], table[row2][col2]);
    }
}
 
// 解密密文
void decrypt(char ciphertext[], char table[][5]) {
    int len = strlen(ciphertext);
    char str[len];
    int t = 0,q,i;
    printf("解密密文之后的明文为:\n");
    for (int i = 0; i < len-1; i += 2) {
        int row1 = 0, col1 = 0, row2 = 0, col2 = 0;
        // 查找密文字母在密码表中的位置
        for (int j = 0; j < 5; j++) {
            for (int k = 0; k < 5; k++) {
                if (table[j][k] == ciphertext[i]) {
                    row1 = j;
                    col1 = k;
                }
                if (table[j][k] == ciphertext[i + 1]) {
                    row2 = j;
                    col2 = k;
                }
            }
        }
        // 使用Playfair密码规则解密
        if (row1 == row2) {
            // 如果密文字母在同一行
            col1 = (col1 + 4) % 5;
            col2 = (col2 + 4) % 5;
        }
        else if (col1 == col2) {
            // 如果密文字母在同一列
            row1 = (row1 + 4) % 5;
            row2 = (row2 + 4) % 5;
        }
        else {
            // 如果密文字母不在同一行也不在同一列
            int temp = col1;
            col1 = col2;
            col2 = temp;
        }
        //打印解密的明文
        str[i]=table[row1][col1];
        str[i+1]=table[row2][col2];
    }
    
    for(i=0;i<len-1;i++)
    {if(str[i]=='X'&&str[i-1]==str[i+1])
     {
     	for(q=i;q<len-1;q++)
     	str[q]=str[q+1];
     	len--;
	 }
	}
    for(i=0;i<len;i++)
    printf("%c",str[i]);
    printf("\n");
}
 
// 打印密码表
void printTable(char table[][5])
{
    printf("打印出Playfair密码表:\n");
    for (int i = 0; i < 5; i++)
    {
        for (int j = 0; j < 5; j++)
        {
            printf("%c ", table[i][j]);
        }
        printf("\n");
    }
    printf("\n");
}
void init(char plaintext[])
{
	    int i,len=strlen(plaintext),p;
	    for(i=0;i<strlen(plaintext);i++)
		if(plaintext[i]==' ')
		{
			for(p=i;p<len-1;p++)
			plaintext[p]=plaintext[p+1];
			len--;
			plaintext[len]='\0';
		}
		  
		//若明文为奇数需要在末尾加入一个无关字符
		if(strlen(plaintext)%2!=0)
		{
		plaintext[len]='M';
		plaintext[len]='\0'; 
    	}
        ConverstAlphabet(plaintext);//把明文中的小写字母转换为大写字母
}
int main() {
		SetConsoleOutputCP(65001);
        char key[100] = { 0 };//密钥
        char plaintext[100] = { 0 };//明文
        char ciphertext[100] = { 0 };//密文
        char table[5][5] = { 0 };
        int input = 0;
        printf("请输入密钥(不超过100个字符):");
        scanf("%s", key);
        ConverstAlphabet(key);//把密钥中的小写字母转换为大写字母
        int keylen1 = strlen(key);//keylen1为去重前的密钥的长度
        int keylen2 = Deduplication(key, keylen1);//把密钥中的字符去重,keylen2为去重后的长度 
        CreatPassWordTable(key, table, keylen2);
        printTable(table);
   
 
        printf("请你输入要加密的明文:\n(若明文有空格,去掉空格,若明文个数为奇数需要在末尾加入一个无关字符)\n");
        scanf("%s", plaintext);
        init(plaintext);
        printf("加密明文后得到的密文为:\n");
        encrypt(plaintext, table);
        printf("\n");
 
 
        printf("请你输入要解密的密文:\n");
        scanf("%s", ciphertext);
        ConverstAlphabet(ciphertext);//把密文中的小写字母转换为大写字母
        printf("\n");
        decrypt(ciphertext, table);
    return 0;
}

当然可以实现Playfair密码C语言程序。Playfair密码是一种替换密码,它使用一个5x5的矩阵来加密和解密文本。以下是一个简单的Playfair密码C语言实现示例: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #define SIZE 5 // 去除重复字符并将J替换为I void sanitizeKey(char *key) { int i, j; int len = strlen(key); int exists[26] = {0}; for (i = 0, j = 0; i < len; i++) { if (key[i] == 'J') { key[i] = 'I'; } if (!exists[key[i] - 'A']) { exists[key[i] - 'A'] = 1; key[j++] = key[i]; } } key[j] = '\0'; } // 生成密钥矩阵 void generateKeyMatrix(char key[], char keyMatrix[][SIZE]) { int i, j, k = 0; int len = strlen(key); for (i = 0; i < SIZE; i++) { for (j = 0; j < SIZE; j++) { keyMatrix[i][j] = key[k++]; } } } // 查找字符位置 void findPosition(char keyMatrix[][SIZE], char ch, int *row, int *col) { int i, j; if (ch == 'J') { ch = 'I'; } for (i = 0; i < SIZE; i++) { for (j = 0; j < SIZE; j++) { if (keyMatrix[i][j] == ch) { *row = i; *col = j; return; } } } } // 加密 void encrypt(char keyMatrix[][SIZE], char plaintext[], char ciphertext[]) { int i, j; int row1, col1, row2, col2; int len = strlen(plaintext); for (i = 0; i < len; i += 2) { findPosition(keyMatrix, plaintext[i], &row1, &col1); findPosition(keyMatrix, plaintext[i + 1], &row2, &col2); if (row1 == row2) { // 同一行 ciphertext[i] = keyMatrix[row1][(col1 + 1) % SIZE]; ciphertext[i + 1] = keyMatrix[row2][(col2 + 1) % SIZE]; } else if (col1 == col2) { // 同一列 ciphertext[i] = keyMatrix[(row1 + 1) % SIZE][col1]; ciphertext[i + 1] = keyMatrix[(row2 + 1) % SIZE][col2]; } else { // 不同行不同列 ciphertext[i] = keyMatrix[row1][col2]; ciphertext[i + 1] = keyMatrix[row2][col1]; } } ciphertext[len] = '\0'; } int main() { char key[26]; char keyMatrix[SIZE][SIZE]; char plaintext[100]; char ciphertext[100]; printf("请输入密钥:"); scanf("%s", key); printf("请输入明文:"); scanf("%s", plaintext); sanitizeKey(key); generateKeyMatrix(key, keyMatrix); encrypt(keyMatrix, plaintext, ciphertext); printf("密文:%s\n", ciphertext); return 0; } ``` 在上面的代码中,我们首先实现了去除重复字符并将字母"J"替换为"I"的函数`sanitizeKey`。然后,我们使用给定的密钥生成密钥矩阵的函数`generateKeyMatrix`。接下来,我们实现了一个辅助函数`findPosition`来查找字符在密钥矩阵中的位置。最后,我们实现了加密函数`encrypt`来对明文进行加密。 在`main`函数中,我们首先获取用户输入的密钥和明文。然后,我们调用适当的函数来执行加密操作,并打印出密文。 请注意,上述代码只是一个简单的示例,仅用于演示Playfair密码的基本思想。在实际应用中,还需要考虑更多的细节和错误处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值