置换密码代码加详解

0x01 置换密码概要

置换密码(Permutation Cipher)又称为换位密码,总的来说就是明文的字符保持不变,但是对位置进行改变

0x02 周期置换密码

将明文P按固定长度m进行分组,然后对分组后的每个子串按某种顺序重新排序,最后组合成密文

例如我们有一个明文:
The reign of  House Of Cards may be short lived

密码:21635

意思为:

第一个放到第二个

第六个放到第一个

第三个放到第六个

第五个放到第三个

第二个放到第五个

加密后为

0x03 C语言实现

这次写的比较繁琐,目的是为了更好的展示思路,

//
// Created by lmn on 2022/3/2.
//
#include <stdio.h>
#define LEN 50
// 简单置换密码

void Init(void* arr[LEN])
{
    int i = 0;
    for (i = 0; i < LEN; i++) {
        arr[i] = 0;
    }
}

decode()
{
    char plaintext[LEN];
    int key = 0;
    int change[2][LEN];
    int realKey[LEN];
    int realKey2[LEN];
    int i,j=0;

    // 输入明文
    printf("Please input plaintext:>");
    fgets(plaintext, LEN-1, stdin);

    // 去除空格
    // 拆分输入字符
    // The reign of House Of Cards may be short lived
    // ThereignofHouseOfCardsmaybeshortlived
    char *str_c=plaintext;
    int num = 0;
    for(i=0;plaintext[i]!='\0';i++)
    {
        if(plaintext[i]!=' ')
        {
            str_c[j++]=plaintext[i];
            num++;
        }
    }
    str_c[j]='\0';
    printf("去除空格后的字符串:> %s\n", str_c);
    num-=1;
    printf("去除空格后一共有 %d 个字符\n",num);

    // 输入key
    printf("Please input key (eg.21635):>");
    scanf("%d",&key);

    // 找key中最大的一个
    int key2 = key;  // 保留副本
    int tmp = 0;// 最大值,也就是分组数
    int m = 0;
    while(key2)
    {
        if((key2 % 10) > tmp)
        {
            tmp = key2 % 10;
            realKey[m] = key2 % 10; // 倒序
            key2 /= 10;
            m++;
        }
        else
        {
            realKey[m] = key2 % 10; // 倒序
            key2 /= 10;
            m++;
        }
    }
    for (i = 0; i < m; i++) {
        realKey2[i] = realKey[m-i-1];
    }
    printf("realKey2 = %d,%d\n",realKey2[0],realKey2[1]);

    // 生成明文加密的矩阵
    int t = m;
    for (i = 0; i < tmp; i++) {  // m: realKey的数量
        change[0][i] = i+1;  //[0] --> [1,2,3,4,5...realKey]
        for (j = m-1; j >= 0; j--) {  // m: realKey的数量
            if (realKey[j] == i+1) {
                change[1][i] = realKey[t-1]; // 输入21635 得到 216035
                t--;
                break;
            } else
                change[1][i] = i+1;
        }
    }

    // 输出加密矩阵
    printf("输出加密矩阵的运算过程:>\n");
    for (i = 0; i < 2; i++) {
        for (j = 0; j < tmp; j++) {
            printf("%d",change[i][j]);
        }
        printf("\n");
    }

    // 拆分输入字符(按照tmp)
    // ThereignofHouseOfCardsmaybeshortlived
    // 输出 Therei gnofHo useOfC ardsma ybesho rtlive d

    int col = 0; // 分组数
    if(num % tmp != 0)
        col = num/tmp+1;
    else
        col = num/tmp;
    char textGroup[col][tmp];
    char endTextGroup[col][tmp];
    // 初始化
    for (i = 0; i < col; i++) {
        for (j = 0; j < tmp; j++) {
            textGroup[i][j] = ' ';
            endTextGroup[i][j] = ' ';
        }
    }

    int all = 0;
    printf("col = %d",col);
    // 列置换密码
    for (i = 0; i < col; i++) {
        for (j = 0; j < tmp; j++) {
            if(all != num)
            {
                textGroup[i][j] = plaintext[all];
                endTextGroup[i][j] = plaintext[all];
                all++;
            }
            else
                endTextGroup[i][j] = '\0';
        }
    }
    printf("\n输出明文矩阵的运算过程:>\n");
    for (i = 0; i < col; i++) {
        for (j = 0; j < tmp; j++) {
            printf("%c",textGroup[i][j]);
        }
        printf("\n");
    }
    // 列置换密码进行置换
    for (i = 0; i < col; i++) {
        char q = textGroup[i][realKey2[0]-1];
        for (j = 0; j < m-1; j++) {
            endTextGroup[i][realKey2[j]-1] = textGroup[i][realKey2[j+1]-1];
        }
        endTextGroup[i][realKey2[m-1]-1] = q;
    }

    printf("\n输出密文矩阵的运算过程:>\n");
    for (i = 0; i < col; i++) {
        for (j = 0; j < tmp; j++) {
            printf("%c",endTextGroup[i][j]);
        }
        printf("\n");
    }
    printf("\n输出密文:>\n");
    for (i = 0; i < col; i++) {
        for (j = 0; j < tmp; j++) {
            printf("%c",endTextGroup[i][j]);
        }
    }
    return 0;
}

int Permutation()
{
    int a = 1;
    printf("*****  Welcome to Use PermutationTool!  *****\n");
    printf("*****  1.encode 0.exit  *****\n");
    printf("Please make a choice :>");
    scanf("%d",&a);
    return a;
}

int main()
{
    //1. 多次判断+输入信息
    int a = 1;
    while (a)
    {
        a = Permutation();
        if(a == 0)
            break;
        else if(a == 1)
            decode();
    }
    return 0;
}

运行结果

0x04 列置换密码

例如我们有一个明文:
The reign of  House Of Cards may be short lived

我们定加密密钥为:(143)(56)

这里第一眼可能很难看懂,其实意思是:

第一列放到第四列

第四列放到第三列

第三列放到第一列

第五列放到第六列

第六列放到第五列

进行按六位分组

明文P,不足部分用双方约定的进行补充

加密后为

得出最终密文

eoedeI hnsrbt rfOssi TguayrdioCaoe eHFmhv

  • 5
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lmn_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值