2.3 置换密码 – lmn-【密码学】小世界-安全文库-NGC660安全实验室

2.3 置换密码 – lmn

2.3 置换密码 – lmn

1646290006888-01236d19-e80c-479b-ac88-7acd7f16b880

0x01 置换密码概要

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

0x02 周期置换密码

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

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

1646290018558-f56d4508-11ed-42b6-90de-98e2de33a78e

密码:21635
意思为:
第一个放到第二个
第六个放到第一个
第三个放到第六个
第五个放到第三个
第二个放到第五个

1646290029968-0cbb6208-7909-4898-bc96-8eab3bc10f40

加密后为

1646290041076-7fe55e65-9d37-45ef-9c25-b17d8abb0963

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;
}

运行结果

1646290096328-a59a08a4-7f02-4c64-bc54-490694174d89

0x04 列置换密码

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

1646290109256-c2ebea73-0ea9-4694-84c5-c96629f4c8c4

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

这里第一眼可能很难看懂,其实意思是:
第一列放到第四列
第四列放到第三列
第三列放到第一列
第五列放到第六列
第六列放到第五列

1646290118298-341b2825-9c8d-4432-96b7-1fb96d2e5d1e

进行按六位分组

1646290126316-69924a87-9906-4a23-9933-6c5b2723bb16

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

1646290134598-30fd9cb3-e4e8-4f77-b989-4852b5aa0bfe

加密后为

1646290142986-7a100145-ba5b-45e6-ab9c-aa4c0bb761e6

得出最终密文
eoedeI hnsrbt rfOssi TguayrdioCaoe eHFmhv

请登录后发表评论

    请登录后查看回复内容