File Hash Next to Every Download

Those downloading files over unreliable Internet connection are familiar with the curse of partially or badly downloaded file. For detecting such transmission errors, hash or CRC codes come in really handy. While none will fix your file, they will allow you to check whether bytes you received are the same bytes the server was sending.

I wanted to have SHA-256 hash codes available on my site too but I hated the idea of manually calculating them every time I upload something new. I wanted to have something that would work without any change to my usual workflow.

Solution ended up being a two separate parts. First part was generating SHA-256 hash. For this I simply created bash script to go over the every file in download and download/runtime directories:

for file in ~/www/{download,download/runtime}/*; do
...
#calculate SHA
fileBase=$file
fileHash="$fileBase.sha256"
fileBaseSum=`sha256sum $fileBase | cut --delimiter=' ' -f 1`
if [ -e "$fileHash" ]; then
fileHashSum=`cat $fileHash`
if [ "$fileBaseSum" == "$fileHashSum" ]; then
echo " $fileBase"
else
echo "X $fileBase"
echo "$fileBaseSum" > "$fileHash"
fi
else
echo "+ $fileBase"
echo "$fileBaseSum" > "$fileHash"
fi
...
done

This script I added as a cron job to simply run every day. A new file with .sha256 extension gets magically created after execution is done.

Second part was creating a WordPress plugin. For this I wanted to keep it simple and just make it work as a short-code. Its full duty would be, whenever it finds downhash short code to create a link and, if .sha256 file exists, to set SHA-256 as its title. In practice this means SHA-256 hash would appear as a tooltip when mouse gets over the link. Visible for those who want it, but unobtrusive for normal people. :)

And yes, the code does include a bit of hard-coded styling. In my defense, I don't plan to publish this as an official plugin and it does simplify the code quite a bit:

add_shortcode('downhash', 'snippet_downhash_shortcode_callback');

function snippet_downhash_shortcode_callback($atts, $content = null) {
...

$file = $_SERVER['DOCUMENT_ROOT'] . $content . '.sha256';
if (file_exists($file)) {
$hash = chunk_split(file_get_contents($file), 8, ' ');
}

$html = '<div style="clear:both; font-size:120%; text-align:center;">';
$html .= '&bull; <a href="' . $content . '"';
if (isset($hash)) { $html .= ' title="SHA-256: ' . $hash . '"'; }
$html .= '>' . $title . '</a> &bull;</div>';

return $html;
}

To use this in code, just use downhash shortcode. For example, for my Bimil I used:

[downhash]/download/bimil170.exe[/downhash]

This will result in the following line:

As always, you can download and check code yourself.

PS: And yes, SHA-1 would also be ok for this particular purpose despite it being broken.

One thought to “File Hash Next to Every Download”

  1. Optimization idea: compare modification date on .sha256 and the base file. Only recalculate .sha256 if the base file is newer than the .sha256.

Leave a Reply to Ivan V Cancel reply

Your email address will not be published. Required fields are marked *