CTF古典密码:移位密码

CTF古典密码:移位密码

前言

密码和编码都是加密,但是有着本质区别:那个密码比编码多一个密钥(key)。这里的密码,不是指平常用来登陆奇安信的密码,而是指加密字符串。我们将数据(明文)通过一定规则(秘钥)进行打乱混编(加密)得到字符串(密文),这就是密码的基本流程。密码学中,一般将明文用m表示,将密文用c表示,将秘钥k表示。

移位密码是最简单的密码形式之一,也是最容易理解的密码形式。上述加密基本流程就是针对这种密码形式的最大白话的描述。

简单例子

这里有一个明文“qianxinshequ”,有一个秘钥“4132”,用下面的形式进行书写:

m="qianxinshequ"
k="4132"

当m为qianxinshequ的时候,先按照秘钥长度对其进行分割,已知 len(k)=4 :

qian xins hequ

m被分为了3部分,按照k的数字顺序对每一部分的明文进行移位加密。根据k,每一部分的明文第一位被换到了第四位,第二位被换到了第一位,第三位依旧是第三位,第四位被换到第二位。剩下的两部分,以此类推。

经过变化,m变为:

inaq isnx euqh

合并就变成了密文:

inaqisnxeuqh

一个简单移位密码完成。

曲路密码

将m填入一个表中,按照定向的连贯的顺序进行遍历,对其进行加密,是移位密码的一种。

在这里插入图片描述

此时,k看起来是一个表的形式,但仍然可以用字符串进行表达。因为k就是行列数。如下图所示:修改行列数就可以修改k。

有以下m

m = "qianxinyuanchuang"

k为7行5列,c为:

unihcxnngaaiunayq

加密程序代码:

import re

col = 7
row = 5
m = input()
c = ""
temp = []for i in range(col):
    temp.append([])for index, i in enumerate(m):
    temp[index % col].append(i)
re_temp = list(reversed(temp))for index, i in enumerate(re_temp):
    if index % 2 == 0:
        i = list(reversed(i))
    c += "".join(i)

plaintext = ""
length = len(m)
min_row = length // col       
min_num = col - length % col  

temp = []
index = 0for i in range(col):
    if i < min_num:
        temp.append(m[index:index+min_row])
        index += min_row
    else:
        temp.append(m[index:index+min_row+1])
        index += min_row + 1print(temp)for index, i in enumerate(temp):
    if index % 2 == 0:
        temp[index] = "".join(list(reversed(re.findall(".{1}", temp[index]))))
temp.reverse()for i in range(length):
    plaintext += temp[i % col][i // col]print(f"{plaintext} : {c}")

在这里插入图片描述

栅栏密码

栅栏密码是一种规则比较特殊的移位密码,他的k是一个数字,用来表示栅栏的长度。其具体加密过程为,将要加密的m分成若干组。每组一共有k个字符。然后取每组第一个字符顺次连接,组成第一个字符串。然后再将第二个字符顺次连接,组成第二个字符串。以此类推,直到所有的m加密完毕。最后将加密后的字符串拼接在一起,便是c。

有以下样例

m = "qianxin"
k = "2"

按照k进行分解

qi an xi n

每组首位相加,以此类推

qaxn ini

合并得出c

c = "qaxnini"

加密程序代码:

m = input()
k = 2

c = []
length = len(m)for i in range(k):
    for j in range(i, length, k):
        c.append(m[j])print (''.join(c))

在这里插入图片描述

解密程序代码:

from calendar import c
from msvcrt import kbhit

c = input()
k = 2
m  = [] 
length = len(c)

q, r = divmod(length, k)
n = (q + 1) if r else q 
mid = n * (k - r)for i in range(n - 1):
    for j in range(i, mid, n):
        m.append(c[j])
    for j in range(mid + i, length, n - 1):
        m.append(c[j])for j in range(n - 1, mid, n):
    m.append(c[j])print (''.join(m))

在这里插入图片描述

云影密码

云影密码,他仅包含01248五个数字,其中的0用于分割,其余数字用于加和操作之后转换为m。

m只包含字母(不区分大小写),将字母在字母表的排位分解为若干数字(只包含1248这四个数字)之和,然后将这些数字排列在一起便是一个字母的c。若干字母的c之间用0作分割线。

例如

m = "QIANXIN"

加密之后就是

c = "88108101084208880810842"

解密是这样的

881 81 1 842 888 81 842

各组相加

17 9 1 14 24 9 14

对应

Q I A N X I N

连起来就是m

m = "QIANXIN"

加密程序:

mcode = input()
dic = [chr(i) for i in range(ord("A"), ord("Z") + 1)]
m = [i for i in mcode]
tmp = [];flag = []for i in range(len(m)):
    for j in range(len(dic)):
        if m[i] == dic[j]:
            tmp.append(j + 1)for i in tmp:
    res = ""
    if i >= 8:
         res += int(i/8)*"8"
    if i%8 >=4:
        res += int(i%8/4)*"4"
    if i%4 >=2:
        res += int(i%4/2)*"2"
    if i%2 >= 1:
        res += int(i%2/1)*"1"
    flag.append(res + "0")print ("".join(flag)[:-1])

在这里插入图片描述

解密程序:

c = input () 
c = c.split("0") 
m = ''for i in range(0, len(c)):
    str = c[i]
    sum = 0
    for i in str:
        sum += int(i)
    m += chr(sum + 64)print(m)

在这里插入图片描述

总结

古典密码当中的移位密码在ctf比赛当中最主要出现以上三种形式,其中的k有的是固定的,有的是自定义的(需要爆破)。

固定的是云影密码,自定义的是曲路密码和栅栏密码。其中曲路密码的k的爆破主要是针对行列数的改变和遍历方向的不同。而栅栏密码爆破则主要针对的是k的数值不同。

竞赛当中也有一些小技巧可以使用。

比如已知m为flag{…},那么如果在c可以主要寻找flag不同的组合方式。通过四个字母的组合方式去推断k的可能性。

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值