Siaris
Simple Things
Syndicate: full/short
Siaris
Categories
General0
News2
Programming2
LanguageBits0
Perl50
Ruby10
VersionControl1
Misc1
Article Calendar
<= May, 2008
S M T W T F S
123
45678910
11121314151617
18192021222324
25262728293031
Search this blog

Key links
External Blogs
Brought to you by ...
Ruby
1and1.com

MD5 Checksums with Digest::MD5

Andrew L. Johnson (First published by ItWorld.com 2001-02-01)

MD5 is a one-way hashing algorithm commonly used to create ‘fingerprints’ or ‘signatures’ of strings (often whole files). The Digest::MD5 module (available from CPAN) creates 128 bit signatures of any input string.

MD5 is often used as an encryption method — you can take a password, create the MD5 fingerprint and store it. Later, when a user logs in again you can take their password, create an MD5 digest and compare it to the stored digest. They are also frequently used as file signatures — if you make a file available for download you could also supply an MD5 digest and when a user downloads your file they can create a new digest and check it against yours to make sure the file has not been corrupted. Finally, if you created a database of signatures for all crucial files on your system (say all the system binaries), you could regularly run a script that tested if any files had been modified by creating new digests and comparing them with the ones stored in the database (this could alert you to the fact that your system has been cracked).

Let’s take a quick look at creating a digest from a string or a file (in the first case we’ll use the functional interface and in the second we will use the OO interface):

    #!/usr/bin/perl -w
    use strict;
    use Digest::MD5 qw/md5/;
    my $string = "This is a test";
    my $digest = md5($string);

    my $md5 = Digest::MD5->new();
    open(FILE, "./somefile")||die "Can't $!";
    $md5->addfile(*FILE);
    close FILE;
    my $file_digest = $md5->digest;

If we want to monitor a directory for changes in files we could first create our database of file digests (perhaps using a tied hash with the DB_File module). Now, we periodically wish to run through this directory and test each file against its digest.

    #!/usr/bin/perl -w
    use strict;
    use DB_File;
    use Digest::MD5;

    my %MD5hash;
    tie %MD5hash, 'DB_File', 'md5.db';

    my $dir = './testdir';
    opendir(DIR, $dir)||die "Can't $!";
    my @files = grep{-f} readdir DIR;
    close DIR;

    foreach my $file (@files) {
        my $md5 = Digest::MD5->new();
        open(FILE, "$dir/$file")||die "Can't $!";
        $md5->addfile(*FILE);
        my $digest = $md5->digest();
        close FILE;
        next unless exists $MD5hash{$file};
        if($MD5hash{$file} ne $digest){
            print "Hey, $file has changed!!!\n";
        }
    }

    untie %MD5hash;

You would probably replace the ‘next unless’ line to notify you that a new file has been added to the directory so that you could check to see that it is supposed to be there and rerun your original script to update your database (that original database script is not very different from the one above, it just creates the entries rather than checking them).

*****