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

欢迎大家的评论和指导。算法请参考: http://en.wikipedia.org/wiki/Playfair_cipher
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define ENCRYPT 1
#define DECRYPT -1
// See in: The Cert C Secure Coding Standard
#define STRINGn) STRING_AGAINn)
#define STRING_AGAINn) #n
#define CHARS_TO_READ 100

FILE *fpSrc = NULL;
FILE *fpDest = NULL;

void flushbuf);
void getkeymatrixchar *)[5], char *); // 通过输入的密钥生成一个密钥矩阵
void printmatrixchar *)[5]);
int encryptchar *)[5]); // 加密函数
int decryptchar *)[5]); // 解密函数
void checkchar *, char *)[5], int); // 查找一对字母在密钥矩阵中对应的字母对

int mainvoid)
{
    int choice;
    char key[CHARS_TO_READ + 1];
    char srcfile[CHARS_TO_READ + 1];
    char destfile[CHARS_TO_READ + 1];
    char keymatrix[5][5];
    memsetkey, 0, CHARS_TO_READ + 1);
    memsetsrcfile, 0, CHARS_TO_READ + 1);
    memsetdestfile, 0, CHARS_TO_READ + 1);
    memsetkeymatrix, 0, 25);
    printf"===============/n"
        "Please select:/n"
        "1.Encrypt/n"
        "2.Decrypt/n"
        "0.Exit/n"
        "Caution: This Program can only apply to ASCII file./n"
        "===============/n");
    do {
        printf"Please input a num between 0 and 2:/n");
        scanf"%d", &choice);
        flushbuf);
    }whilechoice < 0 || choice > 2);
    switchchoice)
    {
    case 0:
        return 0;
    case 1:
        printf"Please input the complete path of the file you want to encrypt:/n");
        break;
    case 2:
        printf"Please input the complete path of the file you want to decrypt:/n");
        break;
    default: break;
    }
    scanf"%"STRINGCHARS_TO_READ)"s", srcfile);
    flushbuf);
    if fpSrc = fopensrcfile, "r") ) == NULL )
    {
        perror"fopen failed to open the file you want to read:");
        exitEXIT_FAILURE);
    }
    printf"Please input the key:/n");
    scanf"%"STRINGCHARS_TO_READ)"[^/n]s", key); // 不忽略空格,读入一整行
    flushbuf);
    getkeymatrixkeymatrix, key);
    printmatrixkeymatrix);
    
    printf"Please input the complete path of the file you want to create:/n");
    scanf"%"STRINGCHARS_TO_READ)"s", destfile);
    flushbuf);
    
    if fpDest = fopendestfile, "w") ) == NULL )
    {
        perror"fopen failed to open the file you want to create:");
        fclosefpSrc);
        exitEXIT_FAILURE);
    }
    
    switchchoice)
    {
    case 1: encryptkeymatrix); break;
    case 2: decryptkeymatrix); break;
    default: break;
    }
    
    fclosefpSrc);
    fclosefpDest);
    system"pause>nul");
    return 0;
}
void flushbuf)
{
    char ch;
    while ch = getchar)) != '/n' && ch != EOF && !feofstdin) );
}

void getkeymatrixchar *p)[5], char *srckey)
{
    // 采用忽略Q的方法
    int i = 0, j = 0;
    char *q = srckey;
    char temp[26];
    memsettemp, 0, 26);
    struprsrckey);
    while*q != '/0')
    {
        if isalpha*q) != 0 && *q != 'Q')
        {
            ifstrchrtemp, *q) == NULL)
            {
                temp[i++] = *q;
            }        
        }
        q++;
    }
    forj = 'A'; j <= 'Z'; j++)
    {
        ifj == 'Q')
            continue;
        if strchrtemp, j) == NULL )
        {
            temp[i++] = j;
        }
    }
    memcpyp, temp, 25);
}

void printmatrixchar *p)[5])
{
    int i, j;
    printf"The final key matrix:/n");
    fori = 0; i < 5; i++)
    {
        forj = 0; j < 5; j++)
        {
            printf"%3c", **p + i) + j));
        }
        printf"/n");
    }
}

int encryptchar *p)[5])
{
    char chs[3];
    char ch;
    int turn = 0;
    memsetchs, 0, 3);
    ch = fgetcfpSrc);
    while!feoffpSrc)) // EOF 是ASCII文件的结束符
    {
        ifisalphach) == 0)
        {
            ch = fgetcfpSrc);
            continue;
        }
        else
        {
            chs[turn] = toupperch);
            turn ^= 1; // 0^1==1 ,1^1 == 0,从而实现给chs[0]和chs[1]轮流赋值
        }
        ifturn == 0) // 如果turn==0 表明已经将一个字母对读入了chs[]
        {
            ifchs[1] == chs[0]) // 如果字母对中两个字母相同 插入X
            {
                chs[1] = 'X';
                fseekfpSrc, -1L, SEEK_CUR);
            }
            checkchs, p, ENCRYPT);
            fprintffpDest, "%s ", chs);
        }
        ch = fgetcfpSrc);
    }
    ifturn == 1) // 如果最后文件中还剩下一个字母 则给chs[1] 赋值 X
    {
        chs[1] = 'X';
        checkchs, p, ENCRYPT);
        fprintffpDest, "%s ", chs);
    }
    return 0;
}

int decryptchar *p)[5])
{
    char chs[3];
    memsetchs, 0, 3);
    fscanffpSrc, "%2s", chs);
    while!feoffpSrc))
    {    
        checkchs, p, DECRYPT);
        fprintffpDest, "%s ", chs);
        fscanffpSrc, "%2s", chs);
    }
    return 0;
}

void checkchar *chs, char *p)[5], int d)
{
    int i, j;
    int row[2];
    int col[2];
    if strchrchs, 'Q') != NULL ) // 如果要加密的字母对中含有Q,则放弃对该字母对加密
    {
        return;
    }
    fori = 0; i < 5; i++)
    {
        forj = 0; j < 5; j++)
        {
            if**p + i) + j) == chs[0])
            {
                row[0] = i;
                col[0] = j;
            }
            else if**p + i) + j) == chs[1])
            {
                row[1] = i;
                col[1] = j;
            }
        }
    }
    ifrow[0] == row[1]) // 加密时同行右移,解密时相反:同行左移
    {
        chs[0] = **p + row[0]) + col[0] + 5 + d) % 5));
        chs[1] = **p + row[1]) + col[1] + 5 + d) % 5));
    }
    else ifcol[0] == col[1]) // 加密时同列下移, 解密时相反:同列上移
    {
        chs[0] = **p + row[0] + 5 + d) % 5)) + col[0]);
        chs[1] = **p + row[1] + 5 + d) % 5)) + col[1]);
    }
    else // 对角线
    {
        chs[0] = **p + row[0]) + col[1]);
        chs[1] = **p + row[1]) + col[0]);
    }
}

Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注