<p>Short answer: If you are using <code>/dev/urandom</code> as your source of entropy, there is no need to run <code>sha256sum</code> to hash the data. Instead you can use the random data directly to form your key:</p>

<pre><code>dd if=/dev/urandom of=/home/jsmith/private.key bs=1 count=32
</code></pre>

<hr>

<p>Long answer:</p>

<p>The reasoning behind this recommendation is that <code>/dev/urandom</code> is already designed to produce high quality, unpredictable, unbiased random data. Indeed, the most common way to implement such an RNG is to feed raw entropy sources into a cryptographically secure random number generator (CSRNG) algorithm or a cryptographically secure hash function (like SHA-256).</p>

<p>What you are doing by sending urandom's data into <code>sha256sum</code> is almost entirely pointless. If urandom is working correctly, your procedure does not buy you any extra security. If urandom is compromised (e.g. outputting only a few possible sequences), then <code>sha256sum</code> cannot rescue you either, because the hash of a few different sequences is only a few different hashes. However if urandom were unpredictable but badly biased (say it generates 90% zeros and 10% ones), then <code>sha256sum</code>-ing this crappy entropy would help - but this situation is unimaginable for a proper RNG implementation.</p>

<hr>

<p>To respond to kasperd's comment:</p>

<blockquote>
  <p>Due to the internals of SHA256, the resulting key would be slightly stronger if you used <code>count=119</code>. Having <code>count</code> be a multiple of 64 is the worst you can do in terms of entropy of the final output. The optimal values for the input length is 55 plus a multiple of 64, so 55, 119, 183 are good values. But of course what is much more important than the count you specify is the security of the computer you use to generate and store the key.</p>
</blockquote>

<p>This assertion is false, but the reason is not entirely obvious. How the SHA-256 algorithm works is that takes an input message, pads it to a block boundary with some specific numbers, then combines the hash state with each block in sequence.</p>

<p>Suppose <em>S</em><sub>0</sub> is the initial state, <em>B</em><sub><em>i</em></sub> is the <em>i</em><sup>th</sup> message block after padding, and <em>H</em>(<em>S</em>, <em>B</em>) is the hash algorithm's compression function. Then we calculate, <em>S</em><sub>1</sub> = <em>H</em>(<em>S</em><sub>0</sub>, <em>B</em><sub>0</sub>), next <em>S</em><sub>2</sub> = <em>H</em>(<em>S</em><sub>1</sub>, <em>B</em><sub>1</sub>), etc. until all blocks are processed.</p>

<p>The non-obvious fact, however, is that <em>H</em> is an invertible function when <em>B</em> is known. In other words, we can calculate <em>S</em><sub>0</sub> = <em>H</em><sup>−1</sup>(<em>S</em><sub>1</sub>, <em>B</em><sub>0</sub>). Hence we can say that <em>H</em> takes a 512-bit block <em>B</em> and uses it to permute a 256-bit state vector <em>S</em> into another 256-bit state vector <em>S</em>ʹ.</p>

<p>Because of this fact, it doesn't matter if the last block being hashed is highly predictable. If the previous blocks are unpredictable, then the state <em>S</em> will be effectively scrambled by hashing these blocks. Because the block compression function <em>H</em> is invertible, it can't "collapse" multiple states into one state, thus hashing a predictable block will not undo the state scrambling from previous blocks.</p>

CC BY-SA 3.0
2016-05-09T05:41:36.487Z
The compression function is supposed to be collision-resistant. If it could be inverted the way you say it could, then that would be considered a vulnerability in the hash function. The part of the compression function which could not be inverted is the final step which adds the result of processing the message block with the initial state from before processing this block.
kasperd
CC BY-SA 3.0
2016-05-09T16:14:04.037Z
@kasperd I want to understand what you're saying, but don't know what you are referring to when you talk about the "part of the compression function which could not be inverted". Can you elaborate on that in a comment or send me an email?
Nayuki
CC BY-SA 3.0
2016-05-09T16:15:09.797Z
The assertion I made about the compression function *H* being invertible is provably true. In fact it is used by the SHACAL-2 cipher, which I have implemented and tested. Note that the permutation to the *state* is invertible. I never said anything about being able to derive the *block* from the state.
Nayuki
CC BY-SA 3.0
2016-05-09T22:12:34.683Z
I don't know SHACAL-2. You could turn the compression function into a block cipher, if you removed the final addition step. Whether it would be secure is a question I will not even try to address. But if the compression function in SHA-2 really suffered from a vulnerability like the one you describe, it would reduce the trust in SHA-2 enough that people would try to move from SHA-2 to something more secure, and I don't see that happening.
kasperd
CC BY-SA 4.0
2019-06-05T03:01:06.413Z
I'm struggling a bit with your answer. If the RNG is compromised (and by looking at the output I can't know that), I think one would gain a lot if one were to use expensive key extension. If `/dev/random` puts out `hash(someSecret, username, milliseconds)`, the manufacturer would know but the user had no chance of knowing but if I used an expensive key extension to get from seed to mnemonic, similar as mnemonic to masterseed is expensive, an attacker would have a hard time using his backdoor.
Giszmo
CC BY-SA 3.0
2016-05-09T00:05:46.987Z
2016-05-09T00:19:19.603Z
2016-05-09T00:19:19.603Z
Nayuki
<p>From what I've read, a Bitcoin private key is a 32 byte long integer. I take this to mean that to have a valid private key, all I need is 32 random bytes and that, by extension, running</p>

<pre><code>dd if=/dev/urandom bs=1 count=128 | sha256sum
</code></pre>

<p>will give me a perfectly secure private key.</p>

<p>Is this correct or have I missed something important?</p>

CC BY-SA 3.0
2016-05-08T15:30:04.140Z
Due to the internals of SHA256, the resulting key would be slightly stronger if you used `count=119`. Having `count` be a multiple of 64 is the worst you can do in terms of entropy of the final output. The optimal values for the input length is 55 plus a multiple of 64, so 55, 119, 183 are good values. But of course what is much more important than the count you specify is the security of the computer you use to generate and store the key.
kasperd
CC BY-SA 3.0
2016-05-09T00:19:45.293Z
@kasperd I responded to your comment in my answer.
Nayuki
<private-key>
Will hashing bytes from /dev/urandom yield a secure private key?
yuppity
# Will hashing bytes from /dev/urandom yield a secure private key?

(Asked by: username_0 on 2016-05-07)

From what I've read, a Bitcoin private key is a 32 byte long integer. I take this to mean that to have a valid private key, all I need is 32 random bytes and that, by extension, running

```
dd if=/dev/urandom bs=1 count=128 | sha256sum

```

will give me a perfectly secure private key.

Is this correct or have I missed something important?

**Tags:** private-key

> **Comments:**
> **username_1**: Due to the internals of SHA256, the resulting key would be slightly stronger if you used `count=119`. Having `count` be a multiple of 64 is the worst you can do in terms of entropy of the final output. The optimal values for the input length is 55 plus a multiple of 64, so 55, 119, 183 are good values. But of course what is much more important than the count you specify is the security of the computer you use to generate and store the key.  
> **username_2**: @username_1 I responded to your comment in my answer.  

---

## 1 answers

### Answer by username_2 on 2016-05-09. Score: 0 | Accepted answer

Short answer: If you are using `/dev/urandom` as your source of entropy, there is no need to run `sha256sum` to hash the data. Instead you can use the random data directly to form your key:

```
dd if=/dev/urandom of=/home/jsmith/private.key bs=1 count=32

```

---

Long answer:

The reasoning behind this recommendation is that `/dev/urandom` is already designed to produce high quality, unpredictable, unbiased random data. Indeed, the most common way to implement such an RNG is to feed raw entropy sources into a cryptographically secure random number generator (CSRNG) algorithm or a cryptographically secure hash function (like SHA-256).

What you are doing by sending urandom's data into `sha256sum` is almost entirely pointless. If urandom is working correctly, your procedure does not buy you any extra security. If urandom is compromised (e.g. outputting only a few possible sequences), then `sha256sum` cannot rescue you either, because the hash of a few different sequences is only a few different hashes. However if urandom were unpredictable but badly biased (say it generates 90% zeros and 10% ones), then `sha256sum`-ing this crappy entropy would help - but this situation is unimaginable for a proper RNG implementation.

---

To respond to username_1's comment:

> Due to the internals of SHA256, the resulting key would be slightly stronger if you used `count=119`. Having `count` be a multiple of 64 is the worst you can do in terms of entropy of the final output. The optimal values for the input length is 55 plus a multiple of 64, so 55, 119, 183 are good values. But of course what is much more important than the count you specify is the security of the computer you use to generate and store the key.

This assertion is false, but the reason is not entirely obvious. How the SHA-256 algorithm works is that takes an input message, pads it to a block boundary with some specific numbers, then combines the hash state with each block in sequence.

Suppose *S*0 is the initial state, *B**i* is the *i*th message block after padding, and *H*(*S*, *B*) is the hash algorithm's compression function. Then we calculate, *S*1 = *H*(*S*0, *B*0), next *S*2 = *H*(*S*1, *B*1), etc. until all blocks are processed.

The non-obvious fact, however, is that *H* is an invertible function when *B* is known. In other words, we can calculate *S*0 = *H*−1(*S*1, *B*0). Hence we can say that *H* takes a 512-bit block *B* and uses it to permute a 256-bit state vector *S* into another 256-bit state vector *S*ʹ.

Because of this fact, it doesn't matter if the last block being hashed is highly predictable. If the previous blocks are unpredictable, then the state *S* will be effectively scrambled by hashing these blocks. Because the block compression function *H* is invertible, it can't "collapse" multiple states into one state, thus hashing a predictable block will not undo the state scrambling from previous blocks.

> **Comments:**
> **username_1**: The compression function is supposed to be collision-resistant. If it could be inverted the way you say it could, then that would be considered a vulnerability in the hash function. The part of the compression function which could not be inverted is the final step which adds the result of processing the message block with the initial state from before processing this block.  
> **username_2**: @username_1 I want to understand what you're saying, but don't know what you are referring to when you talk about the "part of the compression function which could not be inverted". Can you elaborate on that in a comment or send me an email?  
> **username_2**: The assertion I made about the compression function *H* being invertible is provably true. In fact it is used by the SHACAL-2 cipher, which I have implemented and tested. Note that the permutation to the *state* is invertible. I never said anything about being able to derive the *block* from the state.  
> **username_1**: I don't know SHACAL-2. You could turn the compression function into a block cipher, if you removed the final addition step. Whether it would be secure is a question I will not even try to address. But if the compression function in SHA-2 really suffered from a vulnerability like the one you describe, it would reduce the trust in SHA-2 enough that people would try to move from SHA-2 to something more secure, and I don't see that happening.  
> **username_3**: I'm struggling a bit with your answer. If the RNG is compromised (and by looking at the output I can't know that), I think one would gain a lot if one were to use expensive key extension. If `/dev/random` puts out `hash(someSecret, username, milliseconds)`, the manufacturer would know but the user had no chance of knowing but if I used an expensive key extension to get from seed to mnemonic, similar as mnemonic to masterseed is expensive, an attacker would have a hard time using his backdoor.  

---

