看起来你需要做的是对消息中的每个字符与密钥中相应的字符进行异或运算。但是,为了做到这一点,你需要使用 ord
和 chr
进行一些转换,因为你只能对数字进行异或运算,而不能对字符串进行操作:
>>> encrypted = [ chr(ord(a) ^ ord(b)) for (a,b) in zip(var, key) ]
>>> encrypted
['\x1b', '\x10', '\x1c', '\t', '\x1d']
>>> decrypted = [ chr(ord(a) ^ ord(b)) for (a,b) in zip(encrypted, key) ]
>>> decrypted
['h', 'e', 'l', 'l', 'o']
>>> "".join(decrypted)
'hello'
请注意,
binascii.a2b_qp("hello")
只是将一个字符串转换为另一个字符串(尽管可能使用不同的编码)。
你的方法和我上面的代码只有在密钥长度至少与消息长度相同的情况下才能工作。然而,如果需要,你可以轻松地重复密钥使用
itertools.cycle
:
>>> from itertools import cycle
>>> var="hello"
>>> key="xy"
>>> encrypted = [ chr(ord(a) ^ ord(b)) for (a,b) in zip(var, cycle(key)) ]
>>> encrypted
['\x10', '\x1c', '\x14', '\x15', '\x17']
>>> decrypted = [ chr(ord(a) ^ ord(b)) for (a,b) in zip(encrypted, cycle(key)) ]
>>> "".join(decrypted)
'hello'
为了解决Unicode /多字节字符的问题(在下面的评论中提出),可以将字符串(和密钥)转换为字节,将它们压缩在一起,然后执行XOR操作,类似于以下方式:
>>> var=u"hello\u2764"
>>> var
'hello❤'
>>> encrypted = [ a ^ b for (a,b) in zip(bytes(var, 'utf-8'),cycle(bytes(key, 'utf-8'))) ]
>>> encrypted
[27, 16, 28, 9, 29, 145, 248, 199]
>>> decrypted = [ a ^ b for (a,b) in zip(bytes(encrypted), cycle(bytes(key, 'utf-8'))) ]
>>> decrypted
[104, 101, 108, 108, 111, 226, 157, 164]
>>> bytes(decrypted)
b'hello\xe2\x9d\xa4'
>>> bytes(decrypted).decode()
'hello❤'