Python 用随机二进制密钥解密二进制序列。什么';我的剧本怎么了?
(更新如下) 试图从线性代数的问题文本编码的矩阵由菲利普克莱因。遇到问题,强行对所有可能的密钥执行密文二进制序列。问题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能力)。这是相当困难的。。。 谢谢大家!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
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)
更新
感谢曹大方和杰森,我编辑了如下代码,并发现了明文:夏娃是邪恶的
x^y&mask
)chunks=[x:x+11]对范围内的x进行解码(0,len(解码),11)]
*因为密文由11个“符号”组成
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)