Computing SHA1 hashes on files

Security Briefs

Syndication

Last night I downloaded the SQL Server 2005 Developer Edition DVD ISO image, and as you can probably tell from my last post, I'm trying to get it installed in a VPC. Not having much luck so far. VPC can't mount the ISO image directly, so I burned it to a DVD+RW and tried installing, which gave me an error while installing the .NET Framework 2.0 (I couldn't repro it because after running it a second time the install got past that step smoothly).

Anyway,I wanted to make sure that the image I downloaded matched the ISO that was up on the MSDN site, so I hacked up a little SHA1 hash calculator. I tried using both the managed and unmanaged SHA1 implementations and found (not surprisingly) that the unmanaged version was considerably faster, so I stuck with that.

Anyway, here's the code for the SHA1 calculator if you want one of these for yourself. Post comments if you have improvements, especially perf improvements!

using System;
using System.IO;
using System.Security.Cryptography;
class ComputeSha1ForFiles {
    // this seems to be the sweet spot for perf on my box
    const int BUF_SIZE = 4096 * 10;
    const int PROGESS_INTERVAL_MS = 1000;
     static void Main(string[] args) {
        if (0 == args.Length) {
            Console.Error.WriteLine("Usage: sha1 fname [fname ...]");
        }
        foreach (string fname in args) {
            processFile(fname);
        }
     }
    static void processFile(string fname) {
        SHA1 t = new SHA1CryptoServiceProvider();
        
        using (FileStream fs = File.Open(fname,
            FileMode.Open, FileAccess.Read, FileShare.Read))
        using (CryptoStream cs = new CryptoStream(fs, t,
            CryptoStreamMode.Read)) {
            pumpStream(cs, fs);
        }
        foreach (byte b in t.Hash) {
            Console.Write("{0:X2}", b);
        }
        Console.WriteLine();
    }
    static void pumpStream(Stream s, FileStream fs) {
        DateTime begin = DateTime.Now;
        DateTime beginInterval = begin;
        byte[] buf = new byte[BUF_SIZE];
        for (;;) {
            int c = s.Read(buf, 0, buf.Length);
            if (c != buf.Length) break;
            DateTime now = DateTime.Now;
            if ((now - beginInterval).TotalMilliseconds >
                PROGESS_INTERVAL_MS) {
                double bytesPerSecond = (double)fs.Position /
                    (now - begin).TotalSeconds;
                beginInterval = now;
                Console.Error.WriteLine(
                  "{0}% done ({1:N0} bytes/second)",
                  fs.Position * 100 / fs.Length, bytesPerSecond);
            }
        }
    }
}

Posted Nov 10 2005, 12:17 PM by keith-brown
Filed under:

Comments

Nicole Calinoiu wrote re: Computing SHA1 hashes on files
on 11-10-2005 12:46 PM
'Cause downloading fciv (http://support.microsoft.com/default.aspx?scid=kb;en-us;841290) would have been just too much work, right? ;)
Keith Brown wrote re: Computing SHA1 hashes on files
on 11-10-2005 1:13 PM
Hey Nicole,

Thanks for the tip. Believe me, if I had known about this tool, I'd have downloaded it :)
Keith Brown wrote re: Computing SHA1 hashes on files
on 11-10-2005 4:09 PM
OK, after downloading fciv, I like mine better - at least you have some idea when it's gonna be done ;-)
Matt wrote re: Computing SHA1 hashes on files
on 11-10-2005 4:21 PM
Or, you could have used openssl:

openssl sha1 <filenames>
Christopher Steen wrote Link Listing - November 11, 2005
on 11-11-2005 6:20 AM
A better BackgroundWorker : CancelImmediately and other
goodies [Via: Roy Osherove ]
A better Safe...
Jason Haley wrote Interesting Finds
on 11-11-2005 6:34 AM
Irnis wrote re: Computing SHA1 hashes on files
on 02-12-2006 10:37 PM
Several other checksum utilites for Windows:

http://www.irnis.net/soft/acsv/
http://www.irnis.net/soft/xcsv/
http://www.irnis.net/soft/xcsc/
http://www.accuhash.com