Calculating Hashes

  • published on February 26th, 2008

    The MD5 and SHA1 cryptographic hashes are commonly used to verify the integrity of files or create a fixed length digital representation of a string or file. PHP has some very easy functions to create hashes of both strings and files.

    Like most utility functions, generating these hashes is not part of the core Ruby objects. Instead, the Ruby Standard Library includes the Digest library. Let’s take a look at the equivalents to PHP’s common cryptographic hash functions in the Ruby universe.

    Comparing Functions/Methods

    md5 vs. Digest::MD5

    In PHP, we use the md5 function to calculate an MD5 hash. In Ruby, we use Digest::MD5.

    PHP

    print md5("my string");
    // => 2ba81a47c5512d9e23c435c1f29373cb

    Ruby

    require "digest"
     
    print Digest::MD5.hexdigest("my string")
    # => 2ba81a47c5512d9e23c435c1f29373cb

    Above, we first required the Digest library using require "digest". This is similar to using require_once to include a class in PHP. To get the equivalent of the hash we’d generate using md5(), we use the hexdigest method.

    md5_file vs. Digest::MD5

    There are generally two different ways in Ruby to generate a cryptographic hash of a file. The first and easiest way is to use File.read to read the entire file contents into memory. We can then use the same MD5.hexdigest method on the contents to generate the hash.

    PHP

    print md5_file("my_file.jpg");
    // => 14b6a00b1a4eb40542cfecdc4d64940d

    Ruby

    require "digest"
     
    print Digest::MD5.hexdigest(File.read("my_file.jpg"))
    # => 14b6a00b1a4eb40542cfecdc4d64940d

    The code above works for many cases but for larger files, there’s a risk of consuming large amounts of memory. For these cases, we can initialize a new digest with Digest::MD5.new and then read the file in smaller chunks, incrementally building the digest with MD5#update.

    Ruby

    require "digest"
     
    digest = Digest::MD5.new
    File.open("my_file.jpg", "r") do |f|
      digest.update f.read(8192) until f.eof
    end
     
    print digest.hexdigest
    # => 14b6a00b1a4eb40542cfecdc4d64940d

    sha1 vs. Digest::SHA1

    We use the Digest::SHA1 class to build the equivalent cryptographic hash to PHP’s sha1 function. This works the same as the Digest::MD5 class mentioned above, and needs to require the Digest library using require "digest".

    PHP

    print sha1("my string");
    // => e19343e6c6c76f8f634a685eba7c0880648b1389

    Ruby

    require "digest"
     
    print Digest::SHA1.hexdigest("my string")
    # => e19343e6c6c76f8f634a685eba7c0880648b1389

    sha1_file vs. Digest::SHA1

    Just like with MD5, we can generate the SHA1 hash of a file in a couple different ways. We can generate the hash of the entire entire file with File.read

    PHP

    print sha1_file("my_file.jpg");
    // => 5de1a26c24b0d176c6cafd11bf1f03017bcc767b

    Ruby

    require "digest"
     
    print Digest::SHA1.hexdigest(File.read("my_file.jpg"))
    # => 5de1a26c24b0d176c6cafd11bf1f03017bcc767b

    We can take the same chunked approach we used for MD5 to generate a hash for larger files.

    Ruby

    require "digest"
     
    digest = Digest::SHA1.new
    File.open("my_file.jpg", "r") do |f|
      digest.update f.read(8192) until f.eof
    end
     
    print digest.hexdigest
    # => 5de1a26c24b0d176c6cafd11bf1f03017bcc767b

    crypt vs. String#crypt

    Finally we have PHP’s crypt function, which returns an encrypted string using a standard Unix DES-based encryption or an alternate based on the system. This operation has very similar usage in PHP and Ruby. Ruby uses the String#crypt method with a single salt parameter to get the same result.

    PHP

    print crypt("my string", "salt");
    // => saGMxKJ.nmUhU

    Ruby

    print "my string".crypt("salt")
    # => saGMxKJ.nmUhU

4 comments

  • comment by lifewithryan 29 Feb 08

    Just curious, as this is my first time seeing such comparisons…but is it just me or does PHP seem to do the same things, with less code?

    Not that “less code” is necessarily better or anything but what does ruby/rails buy me over PHP/CodeIgniter/Cake, insert php framework here?

    You always hear the code comparisons between Rails and other frameworks in lines of code, etc…this doesn’t seem to be any more efficient.

    (Granted the closures save alot of lines of code and we’re not seeing that here…just a question…)

  • comment by Mike 29 Feb 08

    As you see many more of these examples, sometimes you’re going to feel like PHP comes out ahead and sometimes you’ll feel like Ruby does. It sounds like you’re pretty open minded, and that’s great. People that are polarized completely one way or another just aren’t being objective.

    We spent a lot of time in the book talking about where we think Ruby and Rails shine, without trying to be over the top about it. We’ll continue to do that here in future articles. We definitely like Ruby a lot, and Rails works very well for many of the things we need to do. Many, but certainly not all.

    Whether you’ll like Ruby or Rails depends mostly on your needs and how well they fit into them. It’s very situational. We can’t really say “these are the reasons you’ll love Ruby”. All we can do is be positive and objective, and let you learn and figure out what works for you. One thing that’s for sure is Ruby certainly isn’t a replacement for PHP, that PHP isn’t a replacement for Ruby, and there’s quite a bit of overlap.

    I hope that you’ll keep reading our future articles as we get deeper into
    these topics, have some fun experimenting with Ruby, and continue to build an informed opinion.

  • comment by Matthew Weier O'Phinney 29 Feb 08

    Learning another language can also inform you about areas of your language of expertise that you may not have been aware of. For instance, in learning about hashing algorithms in Ruby, you may stumble across the fact that PHP 5 has added a ‘hash’ extension that does general purpose hashing using a variety of algorithms (and that md5() and sha1() are no longer the only ways of hashing using those algorithms, and the extension adds a ton more possibilities for hashing).

    Learning another language also can show you areas in your language of expertise that could be improved. You note Ruby closures, for example — PHP does not have closures (create_function() is a bear to work with, in comparison). Would you like them in PHP? Do they make sense for PHP?

    I’ve found learning another language helps make my usage of my language of proficiency — PHP — stronger and more efficient. It’s not necessarily a question of one being better than the other — it’s a question of learning the various tools available — including other languages — and how to wield them effectively.

  • pingback by Ruby和PHP加密函数 @ jiaogen 27 Jul 10

    [...] md5 [...]

Post a comment


We welcome your participation but please note we reserve the right to remove any comments that we think are not relevant or do not contribute to the discussion.