65

I have buf="\x00\xFF\xFF\xFF\xFF\x00"

How can I make the "\xFF\xFF\xFF\xFF" randomized?

Community
  • 1
  • 1
zack
  • 681
  • 1
  • 5
  • 7

10 Answers10

82
>>> import os
>>> "\x00"+os.urandom(4)+"\x00"
'\x00!\xc0zK\x00'
John La Rooy
  • 295,403
  • 53
  • 369
  • 502
  • 3
    i just check the python doc.. whats different with ''.join(chr(random.randint(0,255)) for _ in range(4)) – zack Mar 31 '11 at 06:06
  • 19
    @zack, apart from being more efficent, randint returns **pseudo-random** numbers. urandom returns random bytes that are suitable for **cryptographic use** – John La Rooy Mar 31 '11 at 06:12
  • @JohnLaRooy Unless `/dev/urandom` is using some hardware random number generator, its numbers are also pseudo-random. A deterministic machine will always generate pseudo-random numbers. – NullUserException Apr 12 '16 at 21:10
  • 2
    @NullUserException, see `urandom`[here](https://docs.python.org/2/library/os.html#miscellaneous-functions) `/dev/random` is a more random source of randomness, but blocks whenever there is not enough entropy. – John La Rooy Apr 15 '16 at 00:57
  • @JohnLaRooy I don't know how this addresses my comment. I'm just saying `/dev/random` (and also `/dev/urandom`) are pseudorandom number generators, just like `randint`. A CSPRNG is still pseudo-random. See [this question](http://stackoverflow.com/questions/5635277/is-dev-random-considered-truly-random). – NullUserException Apr 15 '16 at 19:49
  • @NullUserException /dev/urandom isn't guaranteed to be pseudo-random since there is hardware to generate random numbers and it will leverage that hardware as a factor in generating the it's resulting strings. If the choice is only between a guaranteed pseudo-random number generator or a potentially truly-random number generator, I'd think we'd always want to go with the potentially truly random one. I think? – monokrome May 19 '18 at 09:17
  • 3
    @NullUserException On Linux, /dev/random uses known sources of entropy as input, including (but not limited to) human users's movements of the mouse, environmental noise, etc. Although the kernel in and of itself is deterministic, the combination kernel+human+environment is not. – AnotherSmellyGeek Sep 13 '18 at 12:31
37

An alternative way to obtaining a secure random sequence of bytes could be to use the standard library secrets module, available since Python 3.6.

Example, based on the given question:

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

More information can be found at: https://docs.python.org/3/library/secrets.html

Tatiana Al-Chueyr
  • 1,065
  • 1
  • 9
  • 11
30
bytearray(random.getrandbits(8) for _ in xrange(size))

Faster than other solutions but not cryptographically secure.

Federico
  • 722
  • 12
  • 12
23

Python 3.9 adds a new random.randbytes method. This method generates random bytes:

from random import randbytes

randbytes(4)

Output:

b'\xf3\xf5\xf8\x98'

Be careful though. It should be used only when you are not dealing with cryptography. As stated in the docs:

This method should not be used for generating security tokens. Use secrets.token_bytes() instead.

Riccardo Bucco
  • 13,980
  • 4
  • 22
  • 50
  • 1
    One cool thing about this is that allows setting a seed for deterministic testing with `random.seed`: https://stackoverflow.com/questions/32329381/generating-random-string-of-seedable-data/66018128#66018128 – Ciro Santilli OurBigBook.com Feb 02 '21 at 21:52
8

On POSIX platforms:

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

Use /dev/random for better randomization.

Janus Troelsen
  • 20,267
  • 14
  • 135
  • 196
  • in practice, this is about 2.5 times faster than os.urandom if you leave the file descriptor open between calls. useful for random guesses at nonces for cryptocurrency hashes. – jcomeau_ictx Jan 03 '14 at 02:14
  • 1
    @jcomeau_ictx Why would you use os.urandom if you don't need it to be cryptographically secure - there are much faster `prng`'s than os.urandom. – user3467349 Jan 25 '15 at 00:54
  • @user3467349 To be fair, urandom is potentially truly random and not only PRNG – monokrome May 19 '18 at 09:34
7

Do you want the middle 4 bytes to be set to a random value?

buf = '\x00' + ''.join(chr(random.randint(0,255)) for _ in range(4)) + '\x00'
yan
  • 20,644
  • 3
  • 38
  • 48
6

This can be used to generate a string of random bytes (replace n with the desired amount):

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)])

The answer to the specific question would then be:

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'

As others pointed out, this should not be used for cryptography, but for everything else it should be perfectly fine.

Fonic
  • 2,625
  • 23
  • 20
5

I like using numpy library for that.

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 )
Saher Ahwal
  • 9,015
  • 32
  • 84
  • 152
1

Simple:

import functools, random, operator
functools.reduce(operator.add, ('%c' % random.randint(0, 255) for i in range(4)))
0xC0000022L
  • 20,597
  • 9
  • 86
  • 152
bradley.ayers
  • 37,165
  • 14
  • 93
  • 99
-2
from random import randint 
rstr = ''.join( randint(0, 255) for i in range(4) )
N 1.1
  • 12,418
  • 6
  • 43
  • 61
  • `NameError: name 'buf' is not defined` – bradley.ayers Mar 31 '11 at 05:03
  • 3
    Comment by anonymous user: You can't join anything but a list of strings into a `string` so change the `int` to `string` character. Code: `rstr = "".join( chr(randint(0, 255)) for i in range(4))`. – Anne Nov 15 '11 at 12:19