我使用os.urandom(8)
生成64位随机字符串。接下来,我想随机更改字符串的一位的值,使该位更改为x = random.getrandbits(6)
并对该位执行XOR操作,如此rand_string ^= 1 << x
,但最后一次操作会给出以下错误:TypeError: unsupported operand type(s) for ^=: 'str' and 'long'
生成随机二进制字符串对我来说很重要,因为我想要对它进行加密cipher.encrypt(rand_string)
并且只接受参数的纯文本。我没有使用random.getrandbits(64)
,因为它返回了一个长的,但它与我想要的64位大小的块不匹配。
此外,我想测量字符串之间的汉明距离(应该给我1,因为我只改变了一位)但我担心我发现的算法对我无效,因为它比较字符表示而不是比较位级:
def hamming_distance(s1, s2):
# Return the Hamming distance between equal-length sequences
if len(s1) != len(s2):
raise ValueError("Undefined for sequences of unequal length")
return sum(ch1 != ch2 for ch1, ch2 in zip(s1, s2))
所以有两个问题:
我怎么能随机改变我的二进制字符串?
上述算法对我的目的有效吗?如果不是,我怎么能在比特级测量汉明距离?
答案 0 :(得分:3)
我认为你的问题中存在拼写错误。正如Jonas Wielicki所说,null
并不存在;大概你的意思是os.random
。是的,使用系统的随机源进行加密工作是一个好主意,但直接使用os.urandom
并不方便。幸运的是,os.urandom
模块提供了random
的接口:os.urandom
类。
在Python中可以对多字节字节对象进行比特操作,尽管它有些繁琐(特别是在Python 2中)。使用Python整数来做这类事情要容易得多。您当然可以使用SystemRandom
方法获得64个随机位,但当然有些前导位可能是零位。
这里有一些在Python 2或Python 3上运行的代码,它们生成一个随机的64位数字,翻转其中一个位,然后计算原始数字和数字之间的汉明距离。翻转位的数字(当然是1)。
getrandbits
典型输出
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))
有更快的方法来计算Python整数中1位的数量,但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
相当快(并且比Kernighan的众所周知的算法的Python实现更快);有关其他方法,请参阅fast way of counting non-zero bits in python。
如果您需要将bincount
转换为Python 3中易于使用的字节对象:只需使用bits0
方法,例如
.to_bytes
如果您需要使用Python 2,将整数转换为字符串并将字符串转换为整数需要更多的工作。这是一个演示,使用上述代码的修改版本。
bytes0 = bits0.to_bytes(8, 'big')
典型输出
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))
答案 1 :(得分:0)
我没有看到获得随机位而不是变换的重点。 randInt应该做得恰到好处。此外,如果您想更改单个位,请尝试xor一个字符而不是字符串。如果这不起作用...=chr(ord(char)^x)