破解我的密码:Python魔法

破解我的密码:Python魔法,python,Python,我正在尝试编写一个函数decipher(s),它接受一个已加密的字符串,其中字符已被旋转,并返回原始的英文字符串。例如: >>> decipher('Bzdrzq bhogdq? H oqdedq Bzdrzq rzkzc.') 'Caesar ciaapher? I preferr Caesaar saladd.' 它应该只接受字符串作为输入。下面是我编写的所有用于加密的函数。我想知道如何使用rot函数对letter\u prob中所有可能的选项进行评分,然后返回包含所有m

我正在尝试编写一个函数
decipher(s)
,它接受一个已加密的字符串,其中字符已被旋转,并返回原始的英文字符串。例如:

>>> decipher('Bzdrzq bhogdq? H oqdedq Bzdrzq rzkzc.')
'Caesar ciaapher? I preferr Caesaar saladd.'
它应该只接受字符串作为输入。下面是我编写的所有用于加密的函数。我想知道如何使用
rot
函数对
letter\u prob
中所有可能的选项进行评分,然后返回包含所有
max
(最可能)字母出现次数的字符串

def decipher(s):
    lc= [rot for c in s] 
    options = [lc for n in range(26)]
    scored_options = [[letter_prob(c),c] for c in options]
    best_option = max(scored_options)
    return best_option[1]      

如何重写
解密
,使其返回一个包含所有最可能的字符的字符串?

我没有尝试过,但类似的方法应该可以工作:

def decipher(s):
    options = [[rot(c, n) for c in s] for n in range(26)]
    best_option = max(options, key=lambda x: sum(map(letter_prob, x)))
    return ''.join(best_option)
选项将是每个组合的列表,如下所示:

[['B', 'z', 'd', 'r', 'z', 'q', ...], ['C', 'a', 'e', 's', 'a', 'r', ...], ...]
然后我们使用
参数来获得字母概率总和最高的选项<代码>''.join()
将字符列表转换回字符串



我用NumPy制作了一个矢量化版本的代码。我发现这一点更为清楚(尽管如果您之前没有见过NumPy,那么它一开始会有点陌生),对于长字符串,它会更快:

import numpy as np

_a = ord('a')
_z = ord('z')
_A = ord('A')
_Z = ord('Z')

def encipher(s, n):
    arr = np.fromstring(s, np.uint8)
    rawcipher(arr, n)
    return arr.tostring()

def rawcipher(arr, n):
    lower = (arr >= _a) & (arr <= _z)
    upper = (arr >= _A) & (arr <= _Z)
    arr[lower | upper] += n
    arr[lower & (arr > _z)] -= 26
    arr[upper & (arr > _Z)] -= 26

letters = np.ones(128, dtype=np.float32)
letters[ord(' ')] = 0.1904
letters[ord('e')] = 0.1017
letters[ord('t')] = 0.0737
letters[ord('a')] = 0.0661
letters[ord('o')] = 0.0610
letters[ord('i')] = 0.0562
letters[ord('n')] = 0.0557
letters[ord('h')] = 0.0542
letters[ord('s')] = 0.0508
letters[ord('r')] = 0.0458
letters[ord('d')] = 0.0369
letters[ord('l')] = 0.0325
letters[ord('u')] = 0.0228
letters[ord('m')] = 0.0205
letters[ord('c')] = 0.0192
letters[ord('w')] = 0.0190
letters[ord('f')] = 0.0175
letters[ord('y')] = 0.0165
letters[ord('g')] = 0.0161
letters[ord('p')] = 0.0131
letters[ord('b')] = 0.0115
letters[ord('v')] = 0.0088
letters[ord('k')] = 0.0066
letters[ord('x')] = 0.0014
letters[ord('j')] = 0.0008
letters[ord('q')] = 0.0008
letters[ord('z')] = 0.0005
letters[_A:_Z+1] = letters[_a:_z+1]

def score(arr):
    return letters[arr].sum()

def decipher(s):
    arr = np.fromstring(s, np.uint8)
    bestStr = None
    bestScore = 0
    for n in range(0, 26):
        rawcipher(arr, 1)
        thisScore = score(arr)
        if thisScore > bestScore:
            bestScore = thisScore
            bestStr = arr.tostring()

    return bestStr
将numpy导入为np
_a=ord('a')
_z=ord('z')
_A=ord('A')
_Z=ord('Z')
def加密(s,n):
arr=np.fromstring(s,np.uint8)
rawcipher(arr,n)
返回arr.tostring()
def RAWCHIPER(arr,n):
较低=(arr>=(arr=)和(arr=(arr=)和(arr=)]-=26
arr[上和(arr>_Z)]-=26
字母=np.one(128,dtype=np.float32)
字母[ord(“”)]=0.1904
字母[ord('e')]=0.1017
字母[ord('t')]=0.0737
字母[ord('a')]=0.0661
字母[ord('o')]=0.0610
字母[ord('i')]=0.0562
字母[ord('n')]=0.0557
字母[ord('h')]=0.0542
字母[ord('s')]=0.0508
字母[ord('r')]=0.0458
字母[ord('d')]=0.0369
字母[ord('l')]=0.0325
字母[ord('u')]=0.0228
字母[ord('m')]=0.0205
字母[ord('c')]=0.0192
字母[ord('w')]=0.0190
字母[ord('f')]=0.0175
字母[ord('y')]=0.0165
字母[ord('g')]=0.0161
字母[ord('p')]=0.0131
字母[ord('b')]=0.0115
字母[ord('v')]=0.0088
字母[ord('k')]=0.0066
字母[ord('x')]=0.0014
字母[ord('j')]=0.0008
字母[ord('q')]=0.0008
字母[ord('z')]=0.0005
字母[_A:_Z+1]=字母[_A:_Z+1]
def分数(arr):
返回字母[arr].sum()
def解密程序:
arr=np.fromstring(s,np.uint8)
bestStr=None
最佳分数=0
对于范围(0,26)内的n:
rawcipher(arr,1)
此分数=分数(arr)
如果thisScore>bestScore:
最佳分数=此分数
bestStr=arr.tostring()
返回最佳STR
请注意,在尝试所有可能的解密距离时,Python中唯一的循环是从0到26

我对它进行了计时,我的矢量化Encrypher()需要3.6秒来处理122MB的数据,而原始版本需要永远的时间(40分钟后我放弃了)

import numpy as np

_a = ord('a')
_z = ord('z')
_A = ord('A')
_Z = ord('Z')

def encipher(s, n):
    arr = np.fromstring(s, np.uint8)
    rawcipher(arr, n)
    return arr.tostring()

def rawcipher(arr, n):
    lower = (arr >= _a) & (arr <= _z)
    upper = (arr >= _A) & (arr <= _Z)
    arr[lower | upper] += n
    arr[lower & (arr > _z)] -= 26
    arr[upper & (arr > _Z)] -= 26

letters = np.ones(128, dtype=np.float32)
letters[ord(' ')] = 0.1904
letters[ord('e')] = 0.1017
letters[ord('t')] = 0.0737
letters[ord('a')] = 0.0661
letters[ord('o')] = 0.0610
letters[ord('i')] = 0.0562
letters[ord('n')] = 0.0557
letters[ord('h')] = 0.0542
letters[ord('s')] = 0.0508
letters[ord('r')] = 0.0458
letters[ord('d')] = 0.0369
letters[ord('l')] = 0.0325
letters[ord('u')] = 0.0228
letters[ord('m')] = 0.0205
letters[ord('c')] = 0.0192
letters[ord('w')] = 0.0190
letters[ord('f')] = 0.0175
letters[ord('y')] = 0.0165
letters[ord('g')] = 0.0161
letters[ord('p')] = 0.0131
letters[ord('b')] = 0.0115
letters[ord('v')] = 0.0088
letters[ord('k')] = 0.0066
letters[ord('x')] = 0.0014
letters[ord('j')] = 0.0008
letters[ord('q')] = 0.0008
letters[ord('z')] = 0.0005
letters[_A:_Z+1] = letters[_a:_z+1]

def score(arr):
    return letters[arr].sum()

def decipher(s):
    arr = np.fromstring(s, np.uint8)
    bestStr = None
    bestScore = 0
    for n in range(0, 26):
        rawcipher(arr, 1)
        thisScore = score(arr)
        if thisScore > bestScore:
            bestScore = thisScore
            bestStr = arr.tostring()

    return bestStr