CTF 栅栏加密解密----python代码实现

目录

文章目录

前言

一、栅栏密码是什么?

二、使用步骤

1.加密过程理解+实现

2.解密过程理解+实现

3.解密过程问题:

总结



前言

最近在学习CTF的密码题目,边做题,边学习用python实现。


提示:全文的明文为IAMMANBUTLIKEWOMEN

在线栅栏密码加密解密,推荐使用这个在线工具,ctf在线工具库里面的,好像有问题。
https://www.qqxiuzi.cn/bianma/zhalanmima.php

一、栅栏密码是什么?

所谓栅栏密码,就是把要加密的明文分成N个一组,然后把每组的第1个字连起来,形成一段无规律的话。 不过栅栏密码本身有一个潜规则,就是组成栅栏的字母一般不会太多。(一般不超过30个,也就是一、两句话) from 百度百科

二、使用步骤

1.加密过程理解+实现

明文为IAMMANBUTLIKEWOMEN      ;加密密钥为3

加密阵列见表

m\n 0列 1列 2列
分组0 I   (0) A   (1) M   (2)
分组1 M   (3) A   (4) N   (5)
分组2 B   (6) U   (7) T   (8)
分组3 L   (9) I   (10) K   (11)
分组4 E   (12) W   (13) O   (14)
分组5 M   (15) E   (16) N   (17)

则:密文为IMBLEM   AAUIWE   MNTKON

解读:将一段字符串(明文)按照(加密密钥)3个一组进行排列,然后将每组的第一列提取,第二列,第三列。分别循环提取。

第0列,下标依次是(0、3、6、9、12、15)        +0

第1列,下标依次是(1、4、7、10、13、16)看作(0、3、6、9、12、15)+1  

第2列,下标依次是(2、5、8、11、14、17)看作(0、3、6、9、12、15)+2

小结:在加密过程中,每次提取string_C明文串中 下标为 [m*Ek+n] 的字符

m为   加密过程中得 第m分组 

取值为0,1,2, ……,len(string_C)/Ek -1

(上例明文长度为18,加密密钥为3,则相除  得6;m=0,1,2,3,4,5) 

注意,当 明文长度 不能被  密钥  整除时,会多出一个分组。

如果长度为18 ,密钥为5,相除得3.6。

这时m得取值为0,1,2, ……,int(len(string_C)/Ek)

但在代码实现过程中,不需要特别区分。 m < len(string_C)/Ek   即可

n为  加密过程中,第n列字符,取值为0,1,2, …… ,Ek-1   (上例n=  0,1,2)

n < Ek

加密函数:

def fun_enCrypto(string_C , Ek):
    string_M = ''     #初始化密文
    n = 0               #提取第n列字符
    while n < Ek:
        m = 0           #第m分组
        while m < len(string_C) / Ek:  #明文长度/加密密钥  即得分组个数
            if (m * Ek+ n) < len(string_C):
                string_M = string_M + string_C[int(m * Ek+ n)]
                m += 1
            else :
                break
        n += 1
    return string_M
 
  

2.解密过程理解+实现

密文为IMBLEMAAUIWEMNTKON

加密密钥为3

求明文,解密密钥为Dk=len(string_M)/Ek  为18/3=6

按照解密规则,得出如下过程。

m\n 0列 1列 2列 3列 4列 5列
分组0 I(0) M(1) B(2) L(3) E(4) M(5)
分组1 A(6) A(7) U(8) I(9) W(10) E(11)
分组2 M(12) N(13) T(14) K(15) O(16) N(17)

明文:IAM MAN BUT LIK EWO MEN

解读:将一段字符串(密文)按照6(解密密钥)个一组进行排列,然后将每组的第一列提取,第二列,第三列,第四列,第五列,第六列。分别循环提取。

0列,第一列下标依次是(0、6、12)        +0

1列,第二列下标依次是(1、7、13)看作(0、6、12)+1  

*

n列,第n+1列下标依次是(0*Dk+n,1*Dk+n,2*Dk+n)

*

5列,第六列下标依次是(5、11、17)看作(0、6、12)+5

小结:在解密过程中,每次提取string_M密文串中 下标为 [m*Dk+n] 的字符

m为   解密过程中得 第m分组 

取值为0,1,2, ……,len(string_M)/Dk -1

(在上例中18/6=3;m=0,1,2);Dk由len(string_M)/Ek得到。

解密过程代码实现:

        n = 0
        while n < Dk:
            m = 0
            while m < Ek:
                if (m * Dk + n) < len(string_M):
                    string_C = string_C + string_M[int(m * Dk + n)]
                    m += 1
                else:
                    break
            n += 1
        return string_C

3.解密过程问题:

用上述代码实现解密的时候,运行程序时,发生问题:

如:已知字符串长度为18,当Ek=5时,解密得到明文就不是我们希望得到的明文。发现,当len(string_M)% Ek != 0 时,上述过程返回明文字符串不正确。

结论:再代码实现时,需判断  len(string_M)% Ek   是否  等于  0

我们对一个余数≠0的实例进行解读:(加密密钥Ek为5;密文:INIMABKEMUENMTWALO)

解密阵列:INIMABKEMUENMTWALO

求明文,解密密钥为Dk=len(string_M)/Ek  为18=Ek*3+3     (18/15=3.5)

0列 1列 2列 3列
分组0 I(0) N(1) I(2) M(3)
分组1 A(4) B(5) K(6) E(7)
分组2 M(8) U(9) E(10) N(11)
分组3 M(12) T(13) W(14)
分组4 A(15) L(16) O(17)

通过观察解密阵列,无法通过m\n进行提取字符。

 这里引入一个概念:步长数组。即解密过程中下一个字符到上一个字符的下标之差组合成一个数组,上例中,步长数组位[4,4,4,3,3] 。数组元素个数为Ek(加密密钥)

1.若len(M)%Ek==0时,Dk=len(M)/Ek,步长=Dk。
2.若len(M)%Ek≠0 时,则步长存在大步长=int(Dk)+1和小布长Dk。相差1.
大步长的个数为  len(M)%Ek  余数。
小布长的个数为 Ek-len(M)%Ek
#Rail-Fence Cipher栅栏解密,输入加密分组中每组中的字符个数
def fun_deCrypto(string_M, Ek):
    Dk = int(len(string_M) / Ek)
    string_C = ''
    yushu = len(string_M) % Ek
    steps = []

    if len(string_M) % Ek == 0:
        print('不存在余数')
        step = Dk
        for i in range(Ek):
            steps.append(step)
        print(steps)

    else:
        print('存在余数')

        big_step = math.ceil(len(string_M) / Ek)
        small_step = int(len(string_M) / Ek)
        for p in range(yushu):
            steps.append(big_step)
        for q in range(Ek - yushu):
            steps.append(small_step)
        print(steps)

    n_column = 0
    while n_column < math.ceil(len(string_M) / Ek):
        count_steps = 0
        for one_step in steps:
            if len(string_C) == len(string_M):
                break
            else:
                string_C += string_M[n_column + count_steps]
                count_steps += one_step
        n_column += 1
    return string_C

总结

栅栏加密解密,即将一个字符串。按照一定的间隔提取单个字符,再按照提取的先后顺序,重组成一个字符串。

加解密都可以通过步长数组实现。如果步长数组为[2,2,1,1],首先提取起始0位,走2步,到第2位,再走2步,到第4位,再走1步到第5位。起始位+1,提取第1位,再走2步,到第3位

 


 


 

你可能感兴趣的:(安全,加密解密)