0

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?

  • 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 May 8 '16 at 15:30
  • @kasperd I responded to your comment in my answer. – Nayuki May 9 '16 at 0:19
0

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 kasperd'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 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.

  • 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 May 9 '16 at 5:41
  • @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 May 9 '16 at 16:14
  • 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 May 9 '16 at 16:15
  • 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 May 9 '16 at 22:12
  • 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 Jun 5 at 3:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.