Double-SHA-256 in Bash and Python

Being able to calculate Double-SHA-256 hashes (often simply referred to as “DSHA256”) is vital for Bitcoin and other cryptocurrency applications and codes. Bitcoin mining itself is, after all, and somewhat simplified, only a matter of spitting out insane amounts DSHA256 hashes, and hoping your output satisfies the consensus network. DSHA256 is a core function needed for the Bitcoin blockchain. And still, it is not a built-in function in any major Linux distribution that I’m aware of.

The so-called pseudocode is often written as SHA256(SHA256(input)), but you must be very careful when implementing this. To illustrate the problem, say that we need to calculate DSHA256(“hello”), and try this in the terminal:

echo -n "hello" | sha256sum | sha256sum

At first glance, it looks legit, doesn’t it? We are piping the string “hello” into the SHA-256 function twice, aren’t we? Note too that we must always use the -n flag with echo, or otherwise, it will append the newline code “\n” to your input string (so that it, in this case, becomes “hello\n”, which is undesired and will guarantee failure).

Still, this exact command will output the following erroneous 32-byte string:

ec777b992bb0b0678a8737567b348de64ab50b5db3b4b03534f636c456e0a3a7

So, what went wrong here? I’ll tell you what went wrong. The first hash round indeed works as intended, but it outputs a hexadecimal string (plus a stupid trailing ” -“, but we’ll save that for down below), which the second hashing round takes as character string input and not as the intended binary input.

In other words, a hexadecimal number 6f34a2 (an arbitrary example) is not at all the same thing as the word “6f34a2″; a stupid computer interprets these as two completely separate entities until you instruct it exactly how to deal with them. So, to fix this in bash, we need to first remove the trailing ” -” that sha256sum produces, which can be accomplished with a simple cut command (cut out everything after the 32nd character), and we need to convert the first hashing round into real binary data, which can be done with the xxd command. Taken together, the proper command is, therefore:

echo -n "hello" | sha256sum | cut -c1-64 | xxd -r -p | sha256sum | cut -c1-64

which will output the correct DSHA256 hash

9595c9df90075148eb06860365df33584b75bff782a510c6cd4883a419833d50

Pretty cool, huh? But we can do even better! Bash is good enough for simple and smaller tasks, but exceptionally slow compared to for example Python. If you want to process more than a few lines of input, you definitely want to go with Python.

Without further ado, find below a Python script that does the job for you. It can easily read and output hundreds of thousands of DSHA256 hashes on a budget laptop computer in a matter of seconds. Copy this code into a new file:

#!/usr/bin/env python3

import sys, hashlib, binascii

filename=sys.argv[1]
f = open(filename, 'r')
for line in f:
  line = line.replace('\n', '').replace('\r', '')
  round1hex = hashlib.sha256(line.encode('utf-8')).hexdigest().zfill(64)
  round1bin = binascii.unhexlify(round1hex)
  round2hex = hashlib.sha256(round1bin).hexdigest().zfill(64)
  print(round2hex)

… name it “dsha”, save it, and finally issue

chmod +x dsha

so that we are allowed to execute it:

Then prepare a second file, let it contain only only one word – hello – name it “demofile.txt” and save it in the same folder.

What the script does is that it reads the filename passed by the first (and only) argument, reads it line by line, removes both Linux and Windows newline characters, calculates and outputs proper DSHA256 hashes.

Now, to verify that it is working as intended, issue the command

./dsha demofile.txt

It should spit out the exact same string and the bash code above

9595c9df90075148eb06860365df33584b75bff782a510c6cd4883a419833d50

and nothing else.

One thing you can try next is taking a larger wordlist as the input, and see how fast the script can process it. Also, to not completely mess up the terminal, pipe the output to a new file, e.g.

./dsha mywordlist.txt > myhashes.txt

In conclusion, here is how to properly calculate DSHA256 in both bash and Python. And that is useful stuff that you can implement in your own applications.

Feel welcome to borrow these short lines of code. If you use and publish your code elsewhere, I would be grateful for an acknowledgemnt and a link to this page. Many thanks.

Questions and comments?

One more thing!

Consider the donation address at the bottom of the page. We re-invest all contributions into new projects for btcleak.com. Help us create new content and remain ad-free forever. Thank you.

Leave a Reply

Your email address will not be published.