技术流丨古典密码学梳理及解密脚本(一)

admin 2022年7月12日21:09:20CTF专场评论2 views8682字阅读28分56秒阅读模式

技术流丨古典密码学梳理及解密脚本(一)


换位加密

换位加密算法是一种较为简单的加密算法,由明文、密钥得出最后的密文,就是通过密钥对明文进行加密,换个位置。


1.栅栏密码

传统型栅栏加密

栅栏密码就是把要加密的明文分成N个一组,然后把每组的第1个字符组合,每组第2个字符组合…每组的第N(最后一个分组可能不足N个)个字符组合,最后把他们全部连接起来就是密文。


案例:

明文:you are goood ctfer

假设栏数为4

分栏:youa rego oodc tfer

去除空格:yrot oeof ugde aocr

密文:yrotoeofugdeaocr


技术流丨古典密码学梳理及解密脚本(一)

传统型栅栏加密又称直型加密,我们通过上面这张图就可以直观看出来。

解密:

解密传统型栅栏密码除了可以使用常见的工具CTFcrack外,笔者这里也提供给大家一个网上收藏的脚本。

# _*_ encoding:utf-8 _*_import math

def buwei(encrypted_str,fence_length): # 比如 14,4 str_len = len(encrypted_str) fence_count = math.ceil(str_len/ fence_length) # 得出4 target_length = fence_count*fence_length jiequ = [] while str_len<target_length: encrypted_str = encrypted_str + '*' jiequ.append(encrypted_str[-fence_count :]) encrypted_str = encrypted_str[:-fence_count] str_len += 1
jiequ.reverse() s = '' for i in jiequ: s = s + i
result = encrypted_str + s return result

def decrypt_fence(encrypted_str,fence_length): encrypted_str = buwei(encrypted_str,fence_length) if fence_length>=len(encrypted_str) or fence_length<1: print("栅栏长度太大或者太小,无需解密") return fence_count = math.ceil(len(encrypted_str)/fence_length) elen=len(encrypted_str)
# b = elen // f # 用字符串实际长度除以上面计算出能整出的数字f result = {x: '' for x in range(fence_count)} for i in range(elen): # 字符串有多少位,就循环多少次 a = i % fence_count result.update({a: result[a] + encrypted_str[i]}) # 字符串截断,并更新数据 d = '' for i in range(len(result)): d += result[i]
d = d.replace("*", '') print(f'假设每栏字数为:{fence_length},解密结果为:{d}') # 输出结果,并开始下一个循环
for i in range(1,48): #通过修改48 设定最高解密的栏数。    decrypt_fence('yrotoeofugdeaocr', i)   #此处填写要解密的密文

技术流丨古典密码学梳理及解密脚本(一)

这个脚本的好处是可以设置最高的解密栏数,从而遍历出最终结果。

W型栅栏加密

W型栅栏密码加密的方法中,明文由上至下顺序写上,当到达最低部时,再回头向上,一直重复直至整篇明文写完为止。此例子中,包含了四栏及一段明文:flag{wzhalanwzhalan}。如下:

['f', '.', '.', '.', '.', '.', 'z', '.', '.', '.', '.', '.', 'w', '.', '.', '.', '.', '.', 'n', '.']['.', 'l', '.', '.', '.', 'w', '.', 'h', '.', '.', '.', 'n', '.', 'z', '.', '.', '.', 'a', '.', '}']['.', '.', 'a', '.', '{', '.', '.', '.', 'a', '.', 'a', '.', '.', '.', 'h', '.', 'l', '.', '.', '.']['.''.''.''g''.''.''.''.''.''l''.''.''.''.''.''a''.''.''.''.']


我们按行读取后密文:fzwnlwhnza}a{aahlgla

W型的加密密钥就不只能是字符串长度的因子,小于其长度的任何一个数都可能是其key值,所以第一步也是确定密钥,也就是栏数。

解密:

在这里也分享一个笔者在网上收藏的脚本:

# -*- coding: utf-8 -*-
def enc(plain, num): matrix = [([0] * len(plain)) for i in range(num)]
# 获取i的取值序列 i_s = [] for a in range(num): i_s.append(a) for a in range(num - 2, 0, -1): i_s.append(a) i_s_len = len(i_s)
# 按规则写入 i = 0 for c in plain: matrix[i_s[i % i_s_len]][i] = c i += 1
# 排除空值,从头到尾取出 encrypted = '' for i in range(num): for j in range(len(plain)): if matrix[i][j]: encrypted += matrix[i][j]
# 临时输出 # for i in range(num): # for j in range(len(plain)): # print (matrix[i][j], ' ') # print()
return encrypted

def dec(encrypted, num): matrix = [([0] * len(encrypted)) for i in range(num)] cur = 0 for i in range(num): # 按行来填 # 生成每行空格个数的取值序列 if i == 0: # 第1行和最后一行,只需要一个取值就好了 pair = [(num - (i + 1)) * 2 - 1] elif i == num - 1: pair = [i * 2 - 1] else: pair = [(num - (i + 1)) * 2 - 1, i * 2 - 1]
# 按规则填入 pair_i = 0 j = i while True: if cur < len(encrypted): matrix[i][j] = encrypted[cur] cur += 1 j += pair[pair_i % len(pair)] + 1 # 这里要加1,直接加间隔是不够的 pair_i += 1 if j >= len(encrypted): break
# 临时输出 # for i in range(num): # for j in range(len(encrypted)): # print (matrix[i][j], ' ') # print()
# 获取i的取值序列 i_s = [] for a in range(num): i_s.append(a) for a in range(num - 2, 0, -1): i_s.append(a) i_s_len = len(i_s) # 按规则取出 decrypted = '' for j in range(len(encrypted)): decrypted += matrix[i_s[j % i_s_len]][j] return decrypted

encrypted = 'fzwnlwhnza}a{aahlgla'num = 5for i in range(2, len(encrypted)): print('分为' + str(i) + '栏时,解密结果为:' + dec(encrypted, i))

'''

readme:encrypted = 'fzwnlwhnza}a{aahlgla'中修改自己要解密的密文.脚本会自动识别字符串个数,列出所有栏数的可能

'''

技术流丨古典密码学梳理及解密脚本(一)

这个脚本的好处就是会自动识别字符串个数,列出所有栏数的可能。得到最终结果。


2.曲路密码

曲路密码也是换位密码的一种,需要加密方与解密方约定加解密路径(也就是曲路路径)。


下面我来举个例子:

我是加密方A,我想要发一段文字给解密方B

未加密文段为:Welcome to the DedSec

然后按照事先约定的序列填入3X6的列表里


技术流丨古典密码学梳理及解密脚本(一)


加密方与解密方互相约定加密路线

技术流丨古典密码学梳理及解密脚本(一)


这样加密的密文:cem ohe stc lod ete wed


解密:

这里分享给大家一个曲路密码的解密脚本,不过是c语言。而且这个脚本适用的曲路路径也是上图所示的路径。

#include <iostream>#include <algorithm>#include <vector>using namespace std;
string encrypt(const string &text, const int &rows, const int &cols) {//加密算法 int length = text.length(); if (length != rows * cols) return "wrong matrix";//保证矩阵matrix恰好装下text string matrix[rows]; for (int i = 0; i < rows; ++i) { matrix[i] = text.substr(i * cols, cols); } //矩阵计算完毕,开始曲路取字符 string encrypted; int x = cols - 1; int y = rows - 1; //当前x,y坐标位置 int director = -1;//竖直方向上有向下和向上两种方向,需要一个director变量记录方向 bool turn_flag = 0;//拐弯标记 for (int i = 0; i < length; i++) { encrypted += matrix[y][x]; if (y == 0 || y == rows - 1) {//y=0或者y=rows-1时需要拐弯 if (turn_flag == 0) { //考虑拐弯有两种,一种是竖直方向转向水平,一种是水平方向转向数值,需要分类讨论 //但是两种转向方式是交替出现的,因此用一个只有两个状态的开关trun_flag来记录区别就可以 turn_flag = 1;//如果本次是水平方向转向竖直方向,那么下一次一定是从竖直方向转向水平方向 y += director;//此种情况是水平方向转向竖直方向,需要在竖直方向上向director方向迈出一步 } else { turn_flag = 0; --x;//此种情况是竖直方向转水平方向,需要水平向左迈出一步 } if (y == 0 ) director = 1;//如果y处在最高处,那么以后的竖直方向一定是下降的 else if (y == rows - 1) director = -1;//如果y处在最低处,那么以后的竖直方向一定是上升的 } else y += director;//此处else判断的是在竖直半路上位置,不需要考虑x的变化,只需要无脑听从director的指示 } return encrypted;}
string decrypt(const string &encrypted, const int &rows, const int &cols) { int length = encrypted.length(); if (length != rows * cols) return "wrong matrix"; string matrix[rows]; for (int i = 0; i < rows; i++) { matrix[i].resize(cols); } int x = cols - 1; int y = rows - 1; //当前x,y坐标位置 int director = -1; int turn_flag = 0;//拐弯标记 for (int i = 0; i < length; i++) { matrix[y][x] = encrypted[i]; if (y == 0 || y == rows - 1) {//y=0或者y=rows-1时需要拐弯 if (turn_flag == 0) { turn_flag = 1; y += director; } else { turn_flag = 0; --x; } if (y == 0 ) director = 1; else if (y == rows - 1) director = -1; } else y += director; } string text; for (int i = 0; i < rows; i++) { text += matrix[i]; } return text;}
int main() { string text = "WelcometotheDedSec"; string encrypted = encrypt(text, 3, 6); string decrypted = decrypt(encrypted, 3, 6); cout << encrypted << endl; cout << decrypted << endl; return 0;}

技术流丨古典密码学梳理及解密脚本(一)

最终得到结果WelcometotheDedSec。



替换加密

替换加密法,是一种用一个字符替换另一个字符的加密方法。

1.恺撒密码
恺撒密码,密码学中最经典的密码之一了。
恺撒密码,或称恺撒加密、恺撒变换、变换加密,它是一种替换加密的技术,明文中的所有字母都在字母表上向后(或向前)按照一个固定数目进行偏移后被替换成密文。例如,当偏移量是3的时候,所有的字母A将被替换成D,B变成E,以此类推。


技术流丨古典密码学梳理及解密脚本(一)


而根据偏移量的不同,还存在若干特定的恺撒密码名称:

偏移量为10: Avocat(A→K)

偏移量为13:ROT13

偏移量为-5: Cassis (K6)

偏移量为-6: Cassette (K7)

由此可知我们要解密一段恺撒加密后的密文,最重要的就是确定偏移量。

下面我们解密这段密文:iodj{YHQLYLGLYLFL}


解密:

这里我们直接使用工具CTFcrack解密即可。

技术流丨古典密码学梳理及解密脚本(一)


2.ROT13

rot13是恺撒密码的一种变体。

rot13是自身的逆反。即:要还原成原文只要使用同一算法即可得,故同样的操作可用于加密与解密。该算法并没有提供真正密码学上的保全,故它不应该被用于需要保全的用途上。它常常被当作弱加密示例的典型。


案例:

再加密一次你就得到flag啦~

synt{IRAVIVQVIVPV}


解密:

#coding:utf-8#python2
import string
def decoder(crypt_str,shift): crypt_list = list(crypt_str) plain_str = "" num = int(shift) for ch in crypt_list: ch = ord(ch) if ord('a') <= ch and ch <= ord('z'): ch = ch + num if ch > ord('z'): ch -= 26 if ord('A') <= ch and ch <= ord('Z'): ch = ch +num if ch > ord('Z'): ch -= 26 a=chr(ch) plain_str += a
print(plain_str)
crypt_str = raw_input("Crypto_text:")print "!------decode------!"shift=13 #修改数字确定位移量。选择13 则为ROT13加密 ROT13是它自身的逆反,即:要还原成原文只要使用同一算法即可得,故同样的操作可用于加密与解密。decoder(crypt_str,shift)

技术流丨古典密码学梳理及解密脚本(一)

最终得到flag{VENIVIDIVICI}。


3.猪圈密码

比起叫猪圈密码,笔者更喜欢叫他共济会密码。是一种以格子为基础的简单替代式密码。即使使用符号,也不会影响密码分析,亦可用在其它替代式的方法。


下面的图片就是猪圈密码与26个字母的对应表。

技术流丨古典密码学梳理及解密脚本(一)


如果不方便理解可以结合猪圈密码设计图。

技术流丨古典密码学梳理及解密脚本(一)


解密:

解密的话目前没有脚本,可以通过在线解密网站进行解密。当无法联网时需要通过对照图进行解密。


猪圈密码在线转换:http://moersima.00cha.net/zhuquan.asp

技术流丨古典密码学梳理及解密脚本(一)


4.培根密码

培根密码(Baconian Cipher)是一种替换密码,每个明文字母被一个由5字符组成的序列替换。

原理:最初的加密方式就是由‘A’和‘B’组成序列替换明文,比如字母‘D’替换成“aaabb”。


大家注意俩个映射表的区别不止大小写。大小写在培根密码中不区分。我们注意第二个映射表i和j,u和v对应的是同一个密码。从映射表我们也可以知道培根密码只对字母进行加密。

技术流丨古典密码学梳理及解密脚本(一)

技术流丨古典密码学梳理及解密脚本(一)


案例:

AAAAB AAAAA AAABA ABBBA ABBAB ABAAA BAABA AAAAA ABBAB AABBA BAAAB BBAAA


解密:

这个脚本,算是我从网上收藏的一个脚本,可以加密也可以解密,而且俩种映射表都会有。

# coding:utf8# python2.Ximport re
alphabet = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
first_cipher = ["aaaaa","aaaab","aaaba","aaabb","aabaa","aabab","aabba","aabbb","abaaa","abaab","ababa","ababb","abbaa","abbab","abbba","abbbb","baaaa","baaab","baaba","baabb","babaa","babab","babba","babbb","bbaaa","bbaab"]
second_cipher = ["aaaaa","aaaab","aaaba","aaabb","aabaa","aabab","aabba","aabbb","abaaa","abaaa","abaab","ababa","ababb","abbaa","abbab","abbba","abbbb","baaaa","baaab","baaba","baabb","baabb","babaa","babab","babba","babbb"]
def encode(): upper_flag = False # 用于判断输入是否为大写 string = raw_input("please input string to encode:n") if string.isupper(): upper_flag = True string = string.lower() e_string1 = "" e_string2 = "" for index in string: for i in range(0,26): if index == alphabet[i]: e_string1 += first_cipher[i] e_string2 += second_cipher[i] break if upper_flag: e_string1 = e_string1.upper() e_string2 = e_string2.upper() print "first encode method result is:n"+e_string1 print "second encode method result is:n"+e_string2 return

def decode(): upper_flag = False # 用于判断输入是否为大写 e_string = raw_input("please input string to decode:n") if e_string.isupper(): upper_flag = True e_string = e_string.lower() e_array = re.findall(".{5}",e_string) d_string1 = "" d_string2 = "" for index in e_array: for i in range(0,26): if index == first_cipher[i]: d_string1 += alphabet[i] if index == second_cipher[i]: d_string2 += alphabet[i] if upper_flag: d_string1 = d_string1.upper() d_string2 = d_string2.upper() print "first decode method result is:n"+d_string1 print "second decode method result is:n"+d_string2 return

if __name__ == '__main__': print "ttcoding by qux" while True: print "t*******Bacon Encode_Decode System*******" print "input should be only lowercase or uppercase,cipher just include a,b(or A,B)" print "1.encoden2.decode(解密的密文需要去掉空格)n3.exit" s_number = raw_input("please input number to choosen") if s_number == "1": encode() raw_input() elif s_number == "2": decode() raw_input() elif s_number == "3": break else:            continue

技术流丨古典密码学梳理及解密脚本(一)


参考链接:

https://www.bilibili.com/read/cv6496295


技术流丨古典密码学梳理及解密脚本(一)

原文始发于微信公众号(小草培养创研中心):技术流丨古典密码学梳理及解密脚本(一)

特别标注: 本站(CN-SEC.COM)所有文章仅供技术研究,若将其信息做其他用途,由用户承担全部法律及连带责任,本站不承担任何法律及连带责任,请遵守中华人民共和国安全法.
  • 我的微信
  • 微信扫一扫
  • weinxin
  • 我的微信公众号
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年7月12日21:09:20
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                  技术流丨古典密码学梳理及解密脚本(一) http://cn-sec.com/archives/1173296.html

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: