针对Vigenere密码(弗吉尼亚密码)的频率攻击——python代码实现

主函数

def frequency_attack_Vigenere(c:str):
    
    m=''            #明文
    k_len=0         #破解出的密钥长度
    k_len_max=10    #破解时密钥长度的最大值
    offset=0.01     #密文概率平方和与标准概率平方和的最大差值接受度
    target=0        #标准概率平方和

    standard_frequency=[0.08167, 0.01492, 0.02782, 0.04253, 0.12702, 0.02228, 0.02015, 0.06094, 0.06966, 0.00153, 0.00772, 0.04025, 0.02406, 0.06749, 0.07507, 0.01929, 0.00095, 0.05987, 0.06327, 0.09056, 0.02758, 0.00978, 0.02360, 0.00150, 0.01974, 0.00074]
    # 计算英语字母标准频率的平方和
    for i in standard_frequency:
        target+=i**2
    # 找到加密密钥K的长度
    for i in range(k_len_max):
        sample=c[::i+1]
        sum=0
        frequency=frequency_finding(sample)
        for f in frequency:
            sum+=f**2
        if abs(sum-target)<offset:
            # 找到符合偏移量的密钥长度后终止循环
            k_len=i+1
            break
    if k_len:
        m_list=['']*k_len
        # 将密文按照密钥长度分组
        for i in range(k_len):
            sample=c[i::k_len]
            # 分别对每一组进行移位密码的概率攻击
            m_list[i]=frequency_attack_shift_cipher(sample)
        # 将破解的明文段整合
        for i in range(len(c)):
            m+=m_list[i%k_len][i//k_len]
        return m
    else:
        return 'attack fialed'

完整程序

def frequency_finding(letters:str):
    frequency=[0]*26
    cnt=0
    ord_a=ord('a')
    # 计算每个字母的频数
    for letter in letters:
        frequency[ord(letter)-ord_a]+=1
        cnt+=1
    # 计算每个字母的频率
    for i in range(26):
        frequency[i]/=cnt
    return frequency

def Vigenere_encryption(m: str, k: str):
    c = ''
    m_len = len(m)
    k_len = len(k)
    ord_a = ord('a')
    for i in range(m_len):
        c += chr((ord(m[i])-ord_a+ord(k[i % k_len])-ord_a) % 26+ord_a)
    return c

def frequency_attack_shift_cipher(c:str):
    target=0
    best=0
    margin=1
    best_k=0
    standard_frequency=[0.08167, 0.01492, 0.02782, 0.04253, 0.12702, 0.02228, 0.02015, 0.06094, 0.06966, 0.00153, 0.00772, 0.04025, 0.02406, 0.06749, 0.07507, 0.01929, 0.00095, 0.05987, 0.06327, 0.09056, 0.02758, 0.00978, 0.02360, 0.00150, 0.01974, 0.00074]
    # 计算英语字母标准频率的平方和
    for i in standard_frequency:
        target+=i**2
    frequency=frequency_finding(c)
    # 找到使密文字母频率*标准字母频率最接近标准频率平方和的K
    for k in range(26):
        sum=0
        for f in range(26):
            sum+=frequency[f]*standard_frequency[(f-k)%26]
        if abs(sum-target)<margin:
            margin=abs(sum-target)
            best_k=k
            best=sum
    m=shift_cipher_decryption(c,best_k)
    return m

def shift_cipher_encryption(m:str,k:int):
    cipher=""
    for letter in m:
        cipher+=chr(((ord(letter) - ord('a') + k) % 26) + ord('a'))
    return cipher

def shift_cipher_decryption(c:str,k:int):
    return shift_cipher_encryption(c,-k)

def frequency_attack_Vigenere(c:str):
    
    m=''            #明文
    k_len=0         #破解出的密钥长度
    k_len_max=10    #破解时密钥长度的最大值
    offset=0.01     #密文概率平方和与标准概率平方和的最大差值接受度
    target=0        #标准概率平方和

    standard_frequency=[0.08167, 0.01492, 0.02782, 0.04253, 0.12702, 0.02228, 0.02015, 0.06094, 0.06966, 0.00153, 0.00772, 0.04025, 0.02406, 0.06749, 0.07507, 0.01929, 0.00095, 0.05987, 0.06327, 0.09056, 0.02758, 0.00978, 0.02360, 0.00150, 0.01974, 0.00074]
    # 计算英语字母标准频率的平方和
    for i in standard_frequency:
        target+=i**2
    # 找到加密密钥K的长度
    for i in range(k_len_max):
        sample=c[::i+1]
        sum=0
        frequency=frequency_finding(sample)
        for f in frequency:
            sum+=f**2
        if abs(sum-target)<offset:
            # 找到符合偏移量的密钥长度后终止循环
            k_len=i+1
            break
    if k_len:
        m_list=['']*k_len
        # 将密文按照密钥长度分组
        for i in range(k_len):
            sample=c[i::k_len]
            # 分别对每一组进行移位密码的概率攻击
            m_list[i]=frequency_attack_shift_cipher(sample)
        # 将破解的明文段整合
        for i in range(len(c)):
            m+=m_list[i%k_len][i//k_len]
        return m
    else:
        return 'attack failed'
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值