python中的字节操作(XOR)

时间:2015-04-02 08:17:38

标签: python encryption byte type-conversion operation

    #!/usr/bin/env python3

import binascii


var=binascii.a2b_qp("hello")
key=binascii.a2b_qp("supersecretkey")[:len(var)]

print(binascii.b2a_qp(var))
print(binascii.b2a_qp(key))


#here i want to do an XOR operation on the bytes in var and key and place them in 'encryption': encryption=var XOR key

print(binascii.b2a_qp(encrypted))

如果有人可以告诉我如何实现这一目标,我将非常高兴。对于整个数据类型的转换来说是非常新的所以是的...阅读python wiki并不像我想的那样清晰:(。

2 个答案:

答案 0 :(得分:19)

两个python3解决方案的比较

第一个基于zip

def encrypt1(var, key):
    return bytes(a ^ b for a, b in zip(var, key))

第二个使用int.from_bytesint.to_bytes

def encrypt2(var, key):
    key = key[:len(var)]
    int_var = int.from_bytes(var, sys.byteorder)
    int_key = int.from_bytes(key, sys.byteorder)
    int_enc = int_var ^ int_key
    return int_enc.to_bytes(len(var), sys.byteorder)

简单测试:

assert encrypt1(b'hello', b'supersecretkey') == b'\x1b\x10\x1c\t\x1d'
assert encrypt2(b'hello', b'supersecretkey') == b'\x1b\x10\x1c\t\x1d'

varkey长度为1000字节的性能测试:

$ python3 -m timeit \
  -s "import test_xor;a=b'abcdefghij'*100;b=b'0123456789'*100" \
  "test_xor.encrypt1(a, b)"
10000 loops, best of 3: 100 usec per loop

$ python3 -m timeit \
  -s "import test_xor;a=b'abcdefghij'*100;b=b'0123456789'*100" \
  "test_xor.encrypt2(a, b)"
100000 loops, best of 3: 5.1 usec per loop

整数方法似乎要快得多。

答案 1 :(得分:12)

看起来您需要做的是将消息中的每个字符与密钥中的相应字符进行异或。但是,要做到这一点,您需要使用ordchr进行一些相互转换,因为您只能编号而不是字符串:

>>> 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❤'