Python 用随机二进制密钥解密二进制序列。什么';我的剧本怎么了?

Python 用随机二进制密钥解密二进制序列。什么';我的剧本怎么了?,python,encryption,linear-algebra,galois-field,Python,Encryption,Linear Algebra,Galois Field,(更新如下) 试图从线性代数的问题文本编码的矩阵由菲利普克莱因。遇到问题,强行对所有可能的密钥执行密文二进制序列。问题1.5.1,第57页: 11个符号的消息已加密如下。每个符号由0到26之间的数字表示(a映射到0,B映射到25,空格映射到26)。每个数字由五位二进制序列表示(0映射到00000,26映射到11010)。最后,生成的55位序列使用有缺陷的一次性pad进行加密:密钥不是55位,而是5个随机位的相同序列的11个副本。密文是: '10101',00100','10101','01011

(更新如下)

试图从线性代数的问题文本编码的矩阵由菲利普克莱因。遇到问题,强行对所有可能的密钥执行密文二进制序列。问题1.5.1,第57页:

11个符号的消息已加密如下。每个符号由0到26之间的数字表示(a映射到0,B映射到25,空格映射到26)。每个数字由五位二进制序列表示(0映射到00000,26映射到11010)。最后,生成的55位序列使用有缺陷的一次性pad进行加密:密钥不是55位,而是5个随机位的相同序列的11个副本。密文是: '10101',00100','10101','01011','11001','00011','01011','10101','00100','11001','11010'

目标是找出明文。 我遇到的问题是:第一,我的解码器函数产生几个大于int 26的5位二进制。该函数的作用是对int 26之前的每一个可能的5位二进制序列(密钥)尝试密文二进制序列,以产生每一个可能的明文序列。第二,我应该使用伽罗瓦域来确保每个二进制序列仍然是二进制的吗?(1+1=0而不是2) 有什么建议吗?我试图通过使用Klein有趣的文本来学习线性代数(并改进我有限的python能力)。这是相当困难的。。。 谢谢大家!

import string

# The Cipher-text
Y = ['10101', '00100', '10101', '01011', '11001', '00011', '01011', '10101', '00100', '11001', '11010']


def trans(bit): # convert the bits into int
    x = ''.join(map(str, bit))
    return int(x, 2)


def decoder(cipher): # Try the ciphertext against each possible 5 bit sequence (up to 11010)
    pos_seq = ["".join("{0:05b}".format(x)) for x in range(27)]
    attempt = []
    for i in pos_seq:
        for j in cipher: # Add ciphertext binary to every possible binary 'key'.
            temp = [(int(i[0])+int(j[0])),(int(i[1])+int(j[1])),(int(i[2])+int(j[2])),
                    (int(i[3])+int(j[3])), (int(i[4])+int(j[4]))]
            attempt.append(temp)
    for i in range(len(attempt)): # Galois Field, 'two' becomes 'one'
        for k in attempt[i]:
            if k == 2:
                attempt[i][attempt[i].index(k)] = 0
    return attempt


new_list = decoder(Y)

decoded = [trans(i) for i in new_list] # translate each 5 digit sequence into int

alph = list(string.ascii_lowercase) # alphabet plus a space
alph.append(' ')

decoded2 = [alph[x] for x in decoded] # Translate int to letter or space

print(decoded2)

更新

感谢曹大方和杰森,我编辑了如下代码,并发现了明文:夏娃是邪恶的

  • 将解码器功能范围增加到32
  • (我还得把脑袋绕在GF(2)和XOR上,包括大方使用的
    x^y&mask
  • 使用将解码器返回的列表切片为11个项目列表
  • chunks=[x:x+11]对范围内的x进行解码(0,len(解码),11)]

    *因为密文由11个“符号”组成

  • 将上述列表映射到大方使用的lambda函数:
  • def解码(编码):
    y=[]
    对于编码中的i:
    如果i<27:
    y、 附加(i)
    返回“”。加入(映射(lambda x:alph[x],y))
    对于我来说,分块:
    decoded2=解码(i)
    打印(解码D2)
    
    使用5位有32个可能的值。知道有效值是0-26,任何大于26的解密值都是一个信号,表明密钥不是加密中使用的密钥。当使用暴力强制时,您可以在遇到此类值时立即跳过该键。事实上,我认为这就是你应该如何消除不正确的钥匙

    同时,没有说明密钥不大于26。你应该尝试所有32种组合

    Re。在伽罗瓦领域,计算机处理器自然是二进制的。您可以利用像XOR这样的逐位操作来加快代码的速度。实际上,XOR是GF(2)中的加法运算。您可以使用
    x^y&mask
    在GF(2)中添加2个向量。当不处理GF(2)时,可以在添加后使用模运算符将值“包装”到有效范围
    x+y%n

    import string
    
    # The Cipher-text
    Y = ['10101', '00100', '10101', '01011', '11001', '00011', '01011', '10101', '00100', '11001', '11010']
    # Parse to binary value
    y = list(map(lambda v: int(v, 2), Y))
    
    max_val = 32
    alphabet_size = 26
    
    # decrypt([0b11111, ...]) = [(key=0b1111, decrpyted=[0b11111, ...]), ...]
    def decrypt(encrypted):
        possible_keys = range(max_val)
        attempt = []
        for key in possible_keys:
            decrypted = []
            for symbol in encrypted:
                # XOR is equivalent to Add in GF(2)
                # If not GF(2), add then wrap around using modulo
                v = symbol ^ key & (max_val - 1)
                print('v = %d' % v)
                if v > alphabet_size:
                    break
                decrypted.append(v)
            if len(decrypted) < len(encrypted):
                print('bad key %d' % key)
                continue
            print('good key %d' % key)
            attempt.append((key, decrypted))
        return attempt
    
    # alphabet plus a space
    alph = list(string.ascii_lowercase)
    alph.append(' ')
    def decode(encoded):
        return ''.join(map(lambda x: alph[x], encoded))
    
    results = decrypt(y)
    
    for (key, encoded) in results:
        decoded = decode(encoded)
        print(decoded)
    
    导入字符串
    #密文
    Y=['10101','00100','10101','01011','11001','00011','01011','10101','00100','11001','11010']
    #解析为二进制值
    y=列表(映射(λv:int(v,2,y))
    最大值=32
    字母表大小=26
    #解密([0b11111,…])=[(密钥=0b1111,解密=[0b11111,…]),…]
    def解密(加密):
    可能的_键=范围(最大值)
    尝试=[]
    对于输入可能的\u键:
    解密=[]
    对于加密中的符号:
    #XOR相当于GF(2)中的外接程序
    #如果不是GF(2),则添加,然后使用模环绕
    v=符号^key&(最大值-1)
    打印('v=%d'%v)
    如果v>字母表大小:
    打破
    已解密。追加(v)
    如果len(解密)
    替代方法:

    # First establish the letter -> binary code:
    digits = set(range(2))
    base = 2
    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', ' ']
    binary_code = {a*base**4 + b*base**3 + c*base**2 + d*base**1 + e*base**0:str(a)+str(b)+str(c)+str(d)+str(e) for a in digits
                              for b in digits
                              for c in digits
                              for d in digits
                              for e in digits if a*base**4 + b*base**3 + c*base**2 + d*base**1 + e*base**0 <= 26}
    letters_to_binary = {k:v for v,k in zip(alphabet,binary_code.values())}
    
    # Now because this one-time pad is flawed, we can make a list of all possible keys - there are only 32
    # These are all the 5 bit binary numbers
    keys = {str(a)+str(b)+str(c)+str(d)+str(e) for a in digits for b in digits
                            for c in digits
                            for d in digits
                            for e in digits}
    
    # We can then apply each key to the cyphertext under 
    # Galois Field 2 addition - GF(2), and see which of 
    # the resulting messages is most sensical
    
    cyphertext = ['10101', '00100', '10101', '01011', '11001', '00011', '01011', '10101', '00100', '11001', '11010']
    results = {}
    for key in keys:
        message = ''
        for text in cyphertext:
            decoded = ''
            for num, t in zip(key, text):
                # The following if else implements GF(2) 
                # addition
                if (int(num) == 1 and int(t) == 0) or (int(num) == 0 and int(t) == 1):
                    decoded = decoded + '1'
                else:
                    decoded = decoded + '0'
            if decoded not in letters_to_binary:
                continue
            else:
                message = message + letters_to_binary[decoded]
        results[key] = message
    
    print(results)
    # From printing the results, using a key of 10001 results in a message of 'EVE IS EVIL', no other messages make sense.
    # Thus the key is 10001
    
    #首先建立字母->二进制代码:
    数字=设置(范围(2))
    基数=2
    字母表=['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’、‘〕
    二进制代码={a*base**4+b*base**3+c*base**2+d*base**1+e*base**0:str(a)+str(b)+str(c)+str(d)+str(e)表示数字形式的a
    以数字表示的b
    对于数字形式的c
    用于数字形式的d
    
    对于数字形式的e,如果a*base**4+b*base**3+c*base**2+d*base**1+e*base**0晚到派对,但我认为这可能是直截了当的:

    message = [0b10101, 0b00100, 0b10101, 0b01011, 0b11001, 0b00011, 
    0b01011, 0b10101, 0b00100, 0b11001, 0b11010]
    
    keys = list(range(0b00000, 0b100000))
    
    letters = ['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', ' ']
    
    for k in keys:
        decrypted = ""
        possible = True
        for m in message:
            if(m^k in range(len(letters))):
                decrypted += letters[m^k]
            else:
                possible = False
                break
        if(possible):
            print(str(k) + ": " + decrypted)
    

    获得大于26的解码值非常好-您可以立即将该解密密钥视为不正确而丢弃。这是一个很好的解决方案,但可能不需要依赖
    map
    lambda
    ,尤其是在为初学者编写时。
    [int(v,2)for v in Y]
    列表(map(lambda v:int(v,2),Y))更简单。
    message = [0b10101, 0b00100, 0b10101, 0b01011, 0b11001, 0b00011, 
    0b01011, 0b10101, 0b00100, 0b11001, 0b11010]
    
    keys = list(range(0b00000, 0b100000))
    
    letters = ['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', ' ']
    
    for k in keys:
        decrypted = ""
        possible = True
        for m in message:
            if(m^k in range(len(letters))):
                decrypted += letters[m^k]
            else:
                possible = False
                break
        if(possible):
            print(str(k) + ": " + decrypted)