57

I'd like to put together a command that will print out a string of 32 hexadecimal digits. I've got a Python script that works:

python -c 'import random ; print "".join(map(lambda t: format(t, "02X"), [random.randrange(256) for x in range(16)]))'

This generates output like:

6EF6B30F9E557F948C402C89002C7C8A 

Which is what I need.

On a Mac, I can even do this:

uuidgen | tr -d '-'

However, I don't have access to the more sophisticated scripting languages ruby and python, and I won't be on a Mac (so no uuidgen). I need to stick with more bash'ish tools like sed, awk, /dev/random because I'm on a limited platform. Is there a way to do this?

Ana
  • 11,726
  • 5
  • 49
  • 101

6 Answers6

91

If you have hexdump then:

hexdump -n 16 -e '4/4 "%08X" 1 "\n"' /dev/random

should do the job.

Explanation:

  • -n 16 to consume 16 bytes of input (32 hex digits = 16 bytes).
  • 4/4 "%08X" to iterate four times, consume 4 bytes per iteration and print the corresponding 32 bits value as 8 hex digits, with leading zeros, if needed.
  • 1 "\n" to end with a single newline.

Note: this solution uses /dev/random but it could as well use /dev/urandom. The choice between the two is a complex question and out of the scope of this answer. If you are not sure, have a look maybe at this other question.

Renaud Pacalet
  • 13,638
  • 2
  • 26
  • 38
  • 1
    Right. And `%08X` is even better if exactly 32 hex digits are needed when there are leading zeros. I modified my answer accordingly. – Renaud Pacalet Dec 17 '15 at 07:54
  • @Renauld_Pacalet How would I be able to do the same thing and produce a 32 digit hex like this from a python code. When I do it on command line it works fast 1st time, then after that it takes like 30 seconds or longer for some reason. – Norman Bird Apr 12 '16 at 17:14
  • 2
    @NormanBird It takes time because `/dev/random` is slow. You cannot read from it with a ultra-high throughput. [This question](http://stackoverflow.com/questions/4819359/dev-random-extremely-slow) explains why. It is not a matter of what language you use. Python would have the same problem. If you do not care too much about the quality of the random generator try `/dev/urandom` instead. But be sure you understand the difference first. – Renaud Pacalet Apr 13 '16 at 13:11
  • 2
    @RenaudPacalet: I suggest you change your answer to use `/dev/urandom`. To say that it is "lower quality" is a myth. See https://www.2uo.de/myths-about-urandom/ – Jay Sullivan Apr 13 '19 at 16:39
  • @JaySullivan: thanks for this suggestion. I edited the answer to mention `/dev/urandom`. However, without knowing what use will be made of this, I prefer not to recommend one or the other. It is a more complex question than what most people usually think. – Renaud Pacalet Apr 13 '19 at 20:03
  • @RenaudPacalet then, default to urandom. I have just emptied my entropy pool because of copypasting. I should have reviewed, true, but still, suggesting a solution that consumes this much entropy is not common at all. I strongly suggesto to change your answer example command to urandom (and of course still mention both) . – jjmontes Oct 20 '20 at 04:21
48

If you are looking for a single command and have openssl installed, see below. Generate random 16 bytes (32 hex symbols) and encode in hex (also -base64 is supported).

openssl rand -hex 16
Community
  • 1
  • 1
touzoku
  • 581
  • 4
  • 2
  • 2
    Nice, short solution, but it is pseudo-random and uses seed files. It may not be the most secure solution. See: https://www.openssl.org/docs/man1.0.2/man1/openssl-rand.html. – justinpc Feb 07 '19 at 11:13
  • could you please tell me how to find the -K value, i used this for encrypt and now need to decrypt it but no way for find it. i made a question for it here: https://stackoverflow.com/questions/67131597/how-to-find-k-value-for-hex-16-generated-in-openssl – Mina Magdy Apr 16 '21 at 20:33
18

There three ways that I know of:

#!/bin/bash

n=16 

# Read n bytes from urandom (in hex):
xxd -l "$n" -p                    /dev/urandom | tr -d " \n" ; echo
od  -vN "$n" -An -tx1             /dev/urandom | tr -d " \n" ; echo
hexdump -vn "$n" -e ' /1 "%02x"'  /dev/urandom ; echo

Use one, comment out the other two.

  • 4
    In my experience `od` is the most common. MacOS had `hexdump`, `xdd`, and `od`. Git Bash (MinGW) had `xxd` and `od`. Docker image based on Alpine Linux had `od` (and `tr` of course). And all three platforms had `/dev/urandom`. So if you are looking for the most portable then stick with the `od` flavor. – Tim Lewis Oct 25 '17 at 09:34
10

Here are a few more options, all of which have the nice property of providing an obvious and easy way to directly select the length of the output string. In all the cases below, changing the '32' to your desired string length is all you need to do.

#works in bash and busybox, but not in ksh
tr -dc 'A-F0-9' < /dev/urandom | head -c32

#works in bash and ksh, but not in busybox
tr -dc 'A-F0-9' < /dev/urandom | dd status=none bs=1 count=32

#works in bash, ksh, AND busybox! w00t!
tr -dc 'A-F0-9' < /dev/urandom | dd bs=1 count=32 2>/dev/null

EDIT: Tested in different shells.

caveman
  • 101
  • 1
  • 4
  • The other ones here all let you specify the length too, except as number of bytes = half the number of characters. And you could easily pipe them into `head -c` to trim it down to an odd number. – Rup Mar 14 '18 at 17:41
5

Try:

xxd -u -l 16 -p /dev/urandom

Example output:

C298212CD8B55F2E193FFA16165E95E3

And to convert it back to binary:

echo -n C298212CD8B55F2E193FFA16165E95E3 | xxd -r -p
Jay Sullivan
  • 14,694
  • 8
  • 54
  • 79
0

If you want to generate output of arbitrary length, including even/odd number of characters:

cat /dev/urandom | hexdump --no-squeezing -e '/1 "%x"' | head -c 31

Or to maximize efficiency over readability/composeability:

hexdump --no-squeezing -e '/1 "%x"' -n 15 /dev/urandom
VasiliNovikov
  • 7,845
  • 2
  • 38
  • 49