Python中的随机字节字符串

68

我有一个字符串 buf="\x00\xFF\xFF\xFF\xFF\x00"

如何使其中的"\xFF\xFF\xFF\xFF"随机化?

10个回答

85
>>> import os
>>> "\x00"+os.urandom(4)+"\x00"
'\x00!\xc0zK\x00'

3
我刚刚查看了Python文档... ''.join(chr(random.randint(0,255)) for _ in range(4))有什么不同? - zack
19
除了更有效率之外,randint返回的是伪随机数字。urandom返回适合于加密用途的随机字节。 - John La Rooy
@JohnLaRooy 除非 /dev/urandom 使用某种硬件随机数生成器,否则它的数字也是伪随机的。一个确定性的机器将始终生成伪随机数。 - NullUserException
2
@NullUserException,看这里的urandom(https://docs.python.org/2/library/os.html#miscellaneous-functions),`/dev/random`是更随机的随机源,但在没有足够熵时会阻塞。 - John La Rooy
3
在Linux系统中,/dev/random会使用已知的熵源作为输入,包括(但不限于)人类用户鼠标移动、环境噪音等。虽然内核本身是确定性的,但内核+人类+环境的组合则是不确定性的。 - AnotherSmellyGeek
显示剩余2条评论

38

获取安全随机字节序列的另一种方式是使用自Python 3.6以来可用的标准库secrets模块。

例如,基于所给问题:

import secrets
b"\x00" + secrets.token_bytes(4) + b"\x00"

更多信息可在此处找到: https://docs.python.org/3/library/secrets.html


30
bytearray(random.getrandbits(8) for _ in xrange(size))

比其他解决方案更快,但不具有加密安全性。


24

Python 3.9新增了一个random.randbytes方法,该方法生成随机字节:

from random import randbytes

randbytes(4)

输出:

b'\xf3\xf5\xf8\x98'

但是要小心使用。正如文档中所述,它仅在您不涉及加密时使用:

此方法不应用于生成安全令牌。请改用secrets.token_bytes()


2
这个很酷的事情是,它允许使用random.seed为确定性测试设置种子:https://dev59.com/047ea4cB1Zd3GeqPEKlQ#66018128 - Ciro Santilli OurBigBook.com

8

在 POSIX 平台上:

open("/dev/urandom","rb").read(4)

使用/dev/random来获得更好的随机性。


实际上,如果您在调用之间保持文件描述符打开状态,则此方法的速度约为os.urandom的2.5倍。它对于加密货币散列的随机猜测非常有用。 - jcomeau_ictx
1
如果您不需要加密安全性,为什么要使用os.urandom - 比os.urandom更快的“伪随机数生成器”有很多选择。@jcomeau_ictx - user3467349
@user3467349 公平地说,urandom 可能是真正的随机数生成器,而不仅仅是伪随机数生成器。 - monokrome

7

您是否希望将中间4个字节设置为随机值?

buf = '\x00' + ''.join(chr(random.randint(0,255)) for _ in range(4)) + '\x00'

6

这可以用来生成一串随机字节(替换n为所需的数量):

import random
random_bytes = bytes([random.randrange(0, 256) for _ in range(0, n)])
-or-
random_bytes = bytes([random.randint(0, 255) for _ in range(0, n)])
-or-
random_bytes = bytes([random.getrandbits(8) for _ in range(0, n)])

针对这个具体的问题,答案如下:

import random
buf = b'\x00' + bytes([random.randrange(0, 256) for _ in range(0, 4)]) + b'\x00'
-or-
buf = b'\x00' + bytes([random.randint(0, 255) for _ in range(0, 4)]) + b'\x00'
-or-
buf = b'\x00' + bytes([random.getrandbits(8) for _ in range(0, 4)]) + b'\x00'

正如其他人指出的,这不应该用于密码学,但对于其他所有内容而言,它应该是完全可以接受的。

5

我喜欢使用numpy库进行这项技术。

import numpy as np

X_1KB = 1024
X_256KB = 256 * X_1KB
X_1MB = 1024 * 1024
X_4MB = 4 * X_1MB
X_32MB = 32 * X_1MB
X_64MB = 2 * X_32MB
X_128MB = X_1MB * 128


np.random.bytes( X_1MB )

1

简单:

import functools, random, operator
functools.reduce(operator.add, ('%c' % random.randint(0, 255) for i in range(4)))

这将返回列表的字符串表示,而不是 OP 所要求的字符串。 - yan
3
"".join(...) 是将序列转换为字符串的首选方法。 - John La Rooy

-2
from random import randint 
rstr = ''.join( randint(0, 255) for i in range(4) )

NameError: name 'buf' is not defined - bradley.ayers
3
匿名用户的评论:你不能将除了字符串列表以外的任何东西连接到一个string中,所以将int改为string字符。代码:rstr = "".join( chr(randint(0, 255)) for i in range(4)) - Anne
典型的一个糟糕回答的例子。没有解释功能、代码或者为什么这个解决方案有效的原因。我没有给你投反对票,但我能理解为什么其他人会这样做。然而,你并不孤单,似乎很多人都这样做,我觉得这降低了 Stack Overflow 的质量。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接