当前位置 : 主页 > 编程语言 > 其它开发 >

古典密码

来源:互联网 收集:自由互联 发布时间:2022-05-30
一系列古典密码 Vigenere 在线解密: https://www.guballa.de/vigenere-solver 已知密钥: http://www.atoolbox.net/Tool.php?Id=856 周期性的移位密码 以 key = cipher 为例 a:0,b:1 key = (2,8,15,7,4,17) 加密时,明文6个一
古典密码 一系列古典密码 Vigenere

在线解密: https://www.guballa.de/vigenere-solver
已知密钥: http://www.atoolbox.net/Tool.php?Id=856

周期性的移位密码

以 key = cipher 为例 a:0,b:1

key = (2,8,15,7,4,17)

加密时,明文6个一组,对应移位

解释时,反向移位

重合指数

在某个密文中随机无放回地抽取其中的两位,这两位字母相同的概率
image
1️⃣利用重合指数可以计算密钥的长度
2️⃣利用在某一取值下的重合指数可以计算密钥
payload [XNUCA2018]baby_crypto为例

from gmpy2 import *

best_index=0.065
sum=0
dic_index={'a': 0.08167,'b': 0.01492,'c': 0.02782,'d':0.04253,'e': 0.12702,'f':0.02228,'g': 0.02015,'h':0.06094,'i':0.06966,'j':0.00153,'k':0.00772,'l':0.04025,'m':0.02406,'n':0.06749,'o':0.07507,'p':0.01929,'q':0.00095,'r':0.05987,'s':0.06327,'t':0.09056,'u':0.02758,'v':0.00978,'w':0.02360,'x':0.00150,'y':0.01974,'z':0.00074}
#计算重合指数
def index_of_coincidence(s):
    '''
    计算字符串的重合指数(所有字母出现频率的平方和)
    :param s: 给定字符串
    :return: 重合指数
    '''
    alpha='abcdefghijklmnopqrstuvwxyz'#给定字母表
    freq={}#统计字母频率(frequency)
    for i in alpha:
        freq[i]=0
    #先全部初始化为0
    for i in s:
        freq[i]=freq[i]+1
    #统计频率
    index=0
    for i in alpha:
        index = index + (freq[i] * (freq[i] - 1)) / (len(s) * (len(s) - 1))
    return index

# 在某一取值下的重合指数
def index_of_coincidence_m(s):
    '''
    计算明文s中的各字母的频率与英文字母中的频率的吻合程度.
    :param s:明文s
    :return:吻合程度
    '''
    alpha = 'abcdefghijklmnopqrstuvwxyz'  # 给定字母表
    freq = {}  # 统计字母频率(frequency)
    for i in alpha:
        freq[i] = 0
    # 先全部初始化为0
    for i in s:
        freq[i] = freq[i] + 1
    # 统计频率
    index = 0
    for i in alpha:
        index = index + freq[i] / len(s) * dic_index[i]
    return index

def get_cycle(c):
    '''
    求出最符合统计学的m,n的最小公共周期,方法为通过爆破足够大的周期样本,观察成倍出现的周期.
    计算方法为解出每一个子密文段的重合指数和然后求平均值 再与最佳重合指数相减 误差在0.01以内.
    :param c: 密文
    :return: 公共周期列表
    '''
    cycle=[]
    for i in range(1,100):
        average_index=0#平均重合指数初始化为0
        for j in range(i):
            s = ''.join(c[j+i*x] for x in range(0,len(c)//i))
            index=index_of_coincidence(s)
            average_index+=index
        average_index=average_index/i-best_index
        if abs(average_index)<0.01:
            cycle.append(i)
    return cycle


#修改密钥数量,加密方式
def decrypt(c,i,j):
    '''
    通过i,j解出与之相对应的密文段
    :param c: 密文段
    :param i:与明文相乘的key
    :param j: 位移j(维吉尼亚密码)
    :return: 明文段
    '''
    alpha = 'abcdefghijklmnopqrstuvwxyz'
    m=''
    for x in c:
        m += alpha[((alpha.index(x)-j) * invert(i,26))%26]
    return m

#修改此处 decrypt 传参
def get_key(c):
    '''
    得到某一密文段的单个字符key i j
    方法为暴力枚举所有的可能性,找到最符合统计学规律的 i,j 即该密文段的重合指数与最佳重合指数误差小于0.01
    :param c: 密文段
    :return: i,j
    '''
    for i in range(26):
        if (gcd(i,26)!=1):#i对26的逆元不只一个,造成明文不唯一,因此不符合条件.
            continue
        for j in range(26):
            m=decrypt(c,i,j)
            index=index_of_coincidence_m(m)
            if abs(index-0.065)<0.01:
                return (i,j)

# 得到密钥
def get_all_key(s,cycle):
    '''
    得到一个周期内的所有的密文段的key
    :param s: 原密文
    :param cycle: 周期
    :return: 无
    '''
    for i in range(cycle):
        temps=''.join([s[i+x*cycle] for x in range(0,len(s)//cycle)])
        print(get_key(temps))


'''
c 中特殊字符,换行符去掉,仅为一行字符串文本
'''
c=open('../file/encrypted_message','r').read()
cycle=get_cycle(c)
print(cycle)  #[6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 78, 84, 90, 96]
cycle_select = 6
get_all_key(c,cycle_select)
曼彻斯特密码

manchester

01--->1

10--->0

标准曼彻斯特编码

01--->0

10--->1

差分曼彻斯特编码

0:有跳变

1:无跳变

跳变: 0->1 或者 1->0

是否逆序

[::-1]
image

payload

def manchester(cipher):
    '''
    曼彻斯特编码
    //8位逆序
    '''
    tmp=''
    for i in range(len(cipher)):
        a=bin(eval('0x'+cipher[i]))[2:].zfill(4)
        tmp=tmp+a[1]+a[3]
        # print(tmp)
    plain=[hex(int(tmp[i:i+8][::-1],2))[2:] for i in range(0,len(tmp),8)]
    print(''.join(plain).upper())
单表替换

在线解密: https://quipqiup.com/
image

栅栏解密
  • 千千解密

    不会出现@,不支持批量

https://www.qqxiuzi.cn/bianma/zhalanmima.php

  • bugku

    支持批量解密,有些存在@

polybius

波利比奥斯方阵密码

  • 加密

    两个密文替换一个明文

    i/j占一个格子
    image
    1-5可用随机5个字母代替

payload

from itertools import permutations

def polybius(alphabet,cipher):
    '''
    aphabet:5个字母/数字
    cipher:密文
    '''
    keypossible = []
    numlist = []
    for i in permutations(alphabet,5):
        keypossible.append(''.join(i))

    for i in keypossible:
        t = ""
        for j in cipher:
            t+=str(i.index(j)+1)
        numlist.append(t)
    for i in numlist:
        r = ""
        r2 = ""
        flag = 0
        for j in range(0,len(i),2):
            v = (int(i[j])-1)*5+int(i[j+1])-1+ord('a')  #采用小写,根据情况进行修改
            if(chr(v)=='i'):
                r+='i' 	#只加i
                r2+='j' #只加j
                flag = 1
                continue
            if(v>ord('i')):
                v+=1
            r+=chr(v)
            r2+=chr(v)
        if(flag):
            print(r,r2)
        else:
            print(r)
playfair

playfair Cipher: http://rumkin.com/tools/cipher/playfair.php

双字母单表替换

以key = playfair 为例

  • 根据key生成5x5的矩阵,i/j 为一个元素,key去重后写在前面,其余按顺序摆在后面

    p l a y f i/j r b c d e g h k m n o q s t u v w x z
  • 明文两个字母一组,相同字母插入事先约定的字母 例如 x,不足偶数,填充事先约定的字母

  • p1,p2

    同行,各自取右边

    同列,各自取下边

    不同行不同列,各自取围成的矩阵对角

  • 解密为加密的逆过程

培根密码

替换密码
只要两个不同的属性,代表0和1
image

#example 
..-.-.-.--.......--..-...-..-...--.-.-....-..-..--.-.-..-.-..----
aababababbaaaaaaabbaabaaabaabaaabbababaaaabaabaabbababaababaabbbb
希尔密码

\[C_{n*1}\ =\ K_{n*n}*M_{n*1}\\ M_{n*1}\ =\ K^{'}_{n*n}*C_{n*1} \]

payload

#暴力求解 n = 2 的密钥矩阵
def hill_n_2(m,c):
    m=m.lower()
    c=c.lower()
    m_data=[]
    c_data=[]
    for i in m:
        m_data.append(ord(i) - ord('a'))
    for i in c:
        c_data.append(ord(i) - ord('a'))
    for a in range(26):
        for b in range(26):
            if(((a*m_data[0]+b*m_data[1])%26==c_data[0]) and (a*m_data[2]+b*m_data[3])%26==c_data[2]):
                for c in range(26):
                    for d in range(26):
                        if (((c * m_data[0] + d * m_data[1]) % 26 == c_data[1]) and ((c * m_data[2] + d * m_data[3]) % 26 == c_data[3])):
                            print(a,b,c,d)
                            return a,b,c,d

在线解密: http://practicalcryptography.com/ciphers/hill-cipher/

  • 该网站使用注意事项
    1️⃣密钥输入统一为加密矩阵,不为逆矩阵 --> a11,a12,a21,a22
    2️⃣除字母外的数据均忽略,大小写不管 --> 手动补充特殊字符、数字等,大小写对应
四方密码
  • 密钥生成

    两个密钥,单词去重后,按照字母表排序,去除Q

  • 加密

    两个字母一组

    找出第一个字母在左上角矩阵的位置;
    同样道理,找第二个字母在右下角矩阵的位置;
    找右上角矩阵中,和第一个字母同行,第二个字母同列的字母;
    找左下角矩阵中,和第一个字母同列,第二个字母同行的字母;
    image

网友评论