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
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 kasperd's comment:
Due to the internals of SHA256, the resulting key would be slightly stronger if you used
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 S0 is the initial state, Bi is the ith message block after padding, and H(S, B) is the hash algorithm's compression function. Then we calculate, S1 = H(S0, B0), next S2 = H(S1, B1), 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 S0 = H−1(S1, B0). 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.