我认为您的问题中有一个错字。正如 Jonas Wielicki 所说,os.random 不存在;大概你的意思是os.urandom。是的,使用系统的随机源进行加密工作是个好主意,但是直接使用os.urandom 不是那么方便。幸运的是,random 模块提供了到os.urandom 的接口:SystemRandom 类。
在 Python 中可以对多字节字节对象进行位旋转,尽管它有些繁琐(尤其是在 Python 2 中)。用 Python 整数做这种事情要容易得多。您当然可以使用getrandbits 方法获得 64 个随机位,当然其中一些前导位可能是零位。
这里有一些在 Python 2 或 Python 3 上运行的代码,它生成一个随机的 64 位数字,翻转其中一个位,然后计算原始数字与翻转位的数字之间的汉明距离(当然是1)。
import random
# SystemRandom uses os.urandom()
sysrandom = random.SystemRandom()
def bincount(n):
return bin(n).count("1")
for _ in range(5):
bits0 = sysrandom.getrandbits(64)
print('bits0: {:016x}'.format(bits0))
bitnum = sysrandom.randint(0, 64)
print('bitnum: {}'.format(bitnum))
bits1 = bits0 ^ (1 << bitnum)
print('bits1: {:016x}'.format(bits1))
hamming = bincount(bits0 ^ bits1)
print('Hamming distance: {}\n'.format(hamming))
典型输出
bits0: a508c77693a0e7d7
bitnum: 32
bits1: a508c77793a0e7d7
Hamming distance: 1
bits0: 9608e25db458a350
bitnum: 3
bits1: 9608e25db458a358
Hamming distance: 1
bits0: f485bd53af91e2dc
bitnum: 62
bits1: b485bd53af91e2dc
Hamming distance: 1
bits0: 18f6749bc260fcd1
bitnum: 17
bits1: 18f6749bc262fcd1
Hamming distance: 1
bits0: 51b35142c99b6814
bitnum: 54
bits1: 51f35142c99b6814
Hamming distance: 1
有更快的方法来计算 Python 整数中 1 的位数,但 bincount 相当快(并且比 Kernighan 的著名算法的 Python 实现更快);其他方法见fast way of counting non-zero bits in python。
如果您需要将bits0 转换为在Python 3 中很容易的字节对象:只需使用.to_bytes 方法,例如
bytes0 = bits0.to_bytes(8, 'big')
如果您需要使用 Python 2,将整数转换为字符串以及将字符串转换为整数需要更多的工作。这是一个演示,使用上述代码的修改版本。
from __future__ import print_function
import random
from binascii import hexlify
# SystemRandom uses os.urandom()
sysrandom = random.SystemRandom()
def bincount(n):
return bin(n).count("1")
def int_to_bytes(n, size):
result = []
for _ in range(size):
result.append(chr(n & 0xff))
n >>= 8
return ''.join(result[::-1])
def bytes_to_int(bs):
n = 0
for b in bs:
n = (n << 8) | ord(b)
return n
for _ in range(4):
bits0 = sysrandom.getrandbits(64)
print('bits0: {0:016x}'.format(bits0))
bs = int_to_bytes(bits0, 8)
print('bytes:', repr(bs))
print('hex: ', hexlify(bs))
n = bytes_to_int(bs)
print('int: {0:016x}, {1}\n'.format(n, n == bits0))
典型输出
bits0: 69831968a1b0aff8
bytes: 'i\x83\x19h\xa1\xb0\xaf\xf8'
hex: 69831968a1b0aff8
int: 69831968a1b0aff8, True
bits0: c2c77e02969d3ebc
bytes: '\xc2\xc7~\x02\x96\x9d>\xbc'
hex: c2c77e02969d3ebc
int: c2c77e02969d3ebc, True
bits0: e87c78eb3929a76f
bytes: '\xe8|x\xeb9)\xa7o'
hex: e87c78eb3929a76f
int: e87c78eb3929a76f, True
bits0: 0d5d796c986ba329
bytes: '\r]yl\x98k\xa3)'
hex: 0d5d796c986ba329
int: 0d5d796c986ba329, True