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

这篇具有很好参考价值的文章主要介绍了古典密码之一的Playfair密码的实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一.古典密码

二.Playfair密码的介绍

三.Playfair密码的实现

1.密钥转大写和密钥去重

2.输入密钥并打印密钥表

2.输入明文并加密为密文

3.输入密文并解密为明文

四.全部代码 


一.古典密码

最早的加密方法可以追溯到公元前4000年左右的古代文明时期。埃及人、古希腊人和罗马人都使用了不同的加密方法来保护机密信息。埃及人使用简单的替换密码来隐藏他们的文字,而古希腊人使用了一种称为“斯巴达骑士”的替换密码。罗马人在军事和政治领域中广泛使用替换密码和移位密码,如凯撒密码。
 

古典密码是指在现代密码学发展之前使用的一类加密方法。它们通常基于简单的数学原理和替换、重排、置换等操作来对明文进行加密。

以下是一些常见的古典密码:

  1. 凯撒密码:凯撒密码是最早出现的替换密码,通过将明文中的每个字母按照一个固定的偏移量向后(或向前)替换成另一个字母来实现加密。

  2. 维吉尼亚密码:维吉尼亚密码是一种双重替代密码,它使用了一个关键词作为密钥,在第一次替换时按照关键词的字母顺序对明文进行替换,然后再按照另一个规则进行第二次替换。

  3. 栅栏密码:栅栏密码是一种重排密码,它将明文中的字母按照一定规则排列成多行,并按照特定的顺序读取密文。

  4. 培根密码:培根密码是一种置换密码,它将明文中的每个字母映射到一个五位二进制码,然后将这些二进制码组合成密文。

  5. Playfair密码:Playfair密码是一种混合密码,它使用一个5x5的方阵作为密钥表,将明文中的字母按照特定规则进行替换。

这些古典密码在当时的年代可能用于各种机密文件的加密,随着社会的逐渐发展,这些古典密码在现代密码学中已经不再安全,因为它们的加密原理相对简单,容易被破解。然而,这些古典密码学都是前人的无数智慧所凝结成的。它们仍具有历史和教育意义,并且可以用于了解密码学的基本概念和技术。
而今天我们主要学习的就是Playfair密码的实现。

二.Playfair密码的介绍

Playfair密码是一种经典的对称加密方法,于1854年由英国密码学家查尔斯·维根·威廉姆斯·珀沙普(Charles Wheatstone)发明。它是基于一个5x5的方阵(称为Playfair Square)来进行加密和解密的。

加密过程中,首先需要创建一个密钥表(key table),该表由密钥中的字母组成。通常密钥中没有重复的字母,但是当我们输入密钥中有重复的字符时,我们就可以专门写一个函数,来对密钥进行去重,并且将"J"视为"I"(为了使表格保持为5x5)。因为字母一共有26个,当J被换做I了之后,字母就变成25个了,刚好可以构成5x5的字符表。然后将明文按照一定的规则进行分组和替换。
填充密钥表的规则:
1.如果密钥没有重复的字符,那么就直接使用密钥;如果密钥有重复的字符,使用一个函数来对密钥字符串进行去重。
2.然后把去重后的密钥字符串逐步填入5x5的密钥表,填完之后再把26位的字符中没有出现密钥的字符依次填入密钥表,其中"J"视为"I"。
3.所有字母都必须大写的,如果输入的密钥是小写的字母,我们还是可以使用一个函数把密钥字符串转换为大写的密钥字符串。

我们还是画图来理解一下密钥表是如何实现的:
古典密码之一的Playfair密码的实现,密码学,服务器,运维

加密的规则如下:
1.输入一个大写的明文字符串,然后两两字字符结合,然后找到这个两个字符在密钥表中的位置,如果是同一行的字母,得到的密文就是向右相邻的字符。如果第5列一列的字符的下一个就是第1列的字符,这个操作使用取余来实现。

2.如果这两个字符是同一列的字符,然后加密后的字符就是向下相邻的字符。同样,如果是第5行的字符的下一个字符就是第1行的字符。

3.如果这两个字符既不是同行同列的字符,那么加密后的字符就是它们互为对角线的字符。
古典密码之一的Playfair密码的实现,密码学,服务器,运维

如果这两个字符是相等的,那么就在这两个相同字母中间插入一个字符,一般是X字符,然后得到新的明文字符串。如果明文字符串是奇数个字符,那么就在明文字符串后面加一个字符,该字符是X或者Z字符,得到一个新的偶数个字符的明文字符串。
注意:下面要实现加密算法,并没有考虑相同字符和奇数个字符,最开始我实现这个加密的时候,就没有考虑到这些,当写这篇文章的时候,我才知道,加密规则我漏看了两个,这里我也不想改代码了,就这样吧。

三.Playfair密码的实现

1.密钥转大写和密钥去重

关于小写转大写,我们可以不用ASCll值的加减来计算,而可以使用一个函数来实现。
toupper 是 C 语言中的一个函数,用于将小写字母转换为大写字母。它是 ctype.h 头文件中的一个字符处理函数。

// 将密钥中的字母转换成大写
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;
    }
    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)//退出循环,i==j说明该字符和前面的任意字符不相等
        {
            key[count++] = key[i];//count从1开始,因为第一个字符不用管
        }
    }
    key[count] = '\0';//末尾加一个\0
    return count;
}

2.输入密钥并打印密钥表

这里开始我们已经细说了步骤了,只是注意这里存放到密钥表中的操作是怎么样的。行是从0开始的,一行是放5列字母的,所以这里行是k/5,而列是k%5。

// 生成密码表
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++;
        }
    }
}

写了这些部分,我们就可以把密钥表打印出来看一下了。
古典密码之一的Playfair密码的实现,密码学,服务器,运维

红圈的部分就是密钥转大写加去重后的。 

2.输入明文并加密为密文

这是我们前面写的加密的规则:按照规则来写代码也就得心应手了。
1.
输入一个大写的明文字符串,然后两两字字符结合,然后找到这个两个字符在密钥表中的位置,如果是同一行的字母,得到的密文就是向右相邻的字符。如果第5列一列的字符的下一个就是第1列的字符,这个操作使用取余来实现。

2.如果这两个字符是同一列的字符,然后加密后的字符就是向下相邻的字符。同样,如果是第5行的字符的下一个字符就是第1行的字符。

3.如果这两个字符既不是同行同列的字符,那么加密后的字符就是它们互为对角线的字符。

// 加密明文
void encrypt(char plaintext[], char table[][5]) {
    int len = strlen(plaintext);
    char p[100] = { 0 };
    int t = 0;
    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]);
    }
}

3.输入密文并解密为明文

这个逻辑和加密的逻辑大差不差的,只是反着找字符即可。

// 解密密文
void decrypt(char ciphertext[], char table[][5]) {
    int len = strlen(ciphertext);
    char q[100] = { 0 };
    int t = 0;
    printf("解密密文之后的明文为:\n");
    for (int i = 0; i < len; 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;
        }
        //打印解密的明文
        printf("%c%c", table[row1][col1], table[row2][col2]);
    }
    printf("\n");
}

古典密码之一的Playfair密码的实现,密码学,服务器,运维文章来源地址https://www.toymoban.com/news/detail-530866.html

四.全部代码 

#define _CRT_SECURE_NO_WARNINGS 1
#define _CRT_SECURE_NO_WARNINGS 1

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

// 将密钥中的字母转换成大写
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;
    }
    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;
}


// 生成密码表
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++;
        }
    }
}

// 加密明文
void encrypt(char plaintext[], char table[][5]) {
    int len = strlen(plaintext);
    char p[100] = { 0 };
    int t = 0;
    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 q[100] = { 0 };
    int t = 0;
    printf("解密密文之后的明文为:\n");
    for (int i = 0; i < len; 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;
        }
        //打印解密的明文
        printf("%c%c", table[row1][col1], table[row2][col2]);
    }
    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");
}

int main() {
        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);//把密钥中的字符去重
        CreatPassWordTable(key, table, keylen2);//keylen2为密钥去重后的长度
        printTable(table);
   

        printf("请你输入要加密的明文:\n");
        scanf("%s", plaintext);
        printf("加密明文后得到的密文为:\n");
        encrypt(plaintext, table);
        printf("\n");


        printf("请你输入要解密的密文:\n");
        scanf("%s", ciphertext);
        printf("\n");
        decrypt(ciphertext, table);
    return 0;
}

到了这里,关于古典密码之一的Playfair密码的实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 密码学——古典密码中的基本加密运算附简单例题

    本篇文章将对古典密码中使用到的基本加解密运算进行总结,并展示个别加减密运算的简单例题,从而使读者更加容易理解古典密码中的基本加减密运算的原理。 首先引入密码学中的几个基本定义: M:明文空间,明文的集合 C:密文空间,密文的集合 K:密钥空间(也称密钥

    2024年02月12日
    浏览(75)
  • java 实现区块链的密码学

    java 实现区块链的密码学今天分享,首先区块链行业相关的密码学有几个思路,比如对称加解密、非对称加解密、数字签名算法、散列hash相关的SHA-256加解密、Merkle树相关算法等等。今天我们主要采用java语言分享非对称加密和数字签名。 1、相关jar等配置,配置JDK1.8版本加上下

    2024年02月11日
    浏览(53)
  • 密码学之DES,3DES与Python实现AES

    最近项目中需要用到DES,3DES解密算法,所以了解一下。正好CSDN上有关于DES,3DES的资料。边看边写一下总结。 密码学之DES,3DES详解与Python实现 DES(Data Encryption Standard-数据加密标准)属于对称加密,即使用相同的密钥来完成加密和解密。分组长度为8个字节64bit(密钥每个字节的最

    2024年02月08日
    浏览(37)
  • DES的加密与解密(C语言实现)——大三密码学实验

    目录 DES的描述 Feistel体制 密钥扩展函数 F函数 总流程  代码 get函数的构建 yihuo函数的构建 fuck函数的构建 left_move函数的构建 exchange函数的构建 erzhuanshi函数的构建 shizhuaner函数的构建 s_box函数的构建 主函数的构建 总函数 运行结果示例 DES: 16 轮, Feistel 型结构 明文长度:

    2024年02月07日
    浏览(44)
  • 密码学与人工智能的融合:如何实现更高级别的安全保障

    随着人工智能技术的不断发展,我们的生活、工作和社会都在不断变得更加智能化和自动化。然而,随着这种变革的推进,我们也面临着更多的安全挑战。密码学是一种数学性质的科学,它主要研究如何保护信息免受未经授权的访问和篡改。在这篇文章中,我们将探讨密码学

    2024年04月11日
    浏览(49)
  • 【11.10】现代密码学1——密码学发展史:密码学概述、安全服务、香农理论、现代密码学

    参考:密码学发展简史 骆婷老师的《现代密码学(32H)》课程,笔记+查找的资料补充 期末为闭卷考试的形式 密码学早在公元前400多年就已经产生,人类使用密码的历史几乎与使用文字的时间一样长,密码学的发展大致可以分为 3 个阶段: 1949年之前的古典密码学阶段; 1949 年

    2024年02月04日
    浏览(48)
  • 【网络安全】【密码学】【北京航空航天大学】实验三、数论基础(下)【C语言实现】

    1、中国剩余定理(Chinese Remainder Theorem) (1)、算法原理 m1 , m2 , … mk 是一组 两两互素 的正整数,且 M = m1 · m2 · … · mk 为它们的乘积, 则如下的同余方程组: x == a1 (mod m1) x == a2 (mod m2) … x == ak (mod mk) 对于 模M 有唯一的解 x = (M · e1 · a1 / m1 + M · e2 · a2 / m2 + … + M · ek ·

    2024年02月02日
    浏览(48)
  • 【密码学】高级密码学-2

    🍬第⑤部分由L3H_CoLin编写,有一些修改。🍬 Song, Dawn Xiaoding, David Wagner, and Adrian Perrig. “Practical techniques for searches on encrypted data.” Proceeding 2000 IEEE Symposium on Security and Privacy. SP 2000. IEEE, 2000. 数据的安全外包存储 利用密码算法加密明文数据,使得云平台无法获得额外信息 解决

    2024年02月16日
    浏览(33)
  • 【密码学】高级密码学-1

      通信双方使用 同一个密钥 ,通过使用加密算法配合上密钥来加密,解密过程采用加密过程的逆过程配合密钥即可。   常见的对称加密算法有DES、AES等。   对称加密的缺点:不能在不安全的网络上传输密钥,一旦密钥泄露则加密通信失败。   非对称加密使用了一

    2024年02月05日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包