Ironclad hashes in SBCL

Getting a SHA1 digest from Ironclad turned out to be a quite bumpy ride; its “convenience functions” are not convenient enough to take a string, they only operate on octets.

There’s a helper function that converts an ASCII string to octets, but I needed to be able to supply Unicode strings as well. I ended up finding STRING-TO-OCTETS:

(defun sha1 (str)
  (ironclad:byte-array-to-hex-string
    (ironclad::digest-sequence :sha1 (SB-EXT:STRING-TO-OCTETS str))))

If someone knows an easier or more portable way, I’m all for it. I’m also interested in other free implementations’ functions to convert their strings to octets.

Comments

  1. frob
    May 8th, 2008 | 10:58 am

    Babel is portable and recently became asdf-installable.

  2. May 8th, 2008 | 11:06 am

    There’s also a STRING-TO-OCTETS (and OCTETS-TO-STRING, for that matter, too) in Arnesi.

  3. attila
    May 8th, 2008 | 11:10 am

    babel is the answer. it’s fast and behaves the same on each platform.

  4. May 8th, 2008 | 12:18 pm

    Yeah, you want babel:string-to-octets.

  5. May 8th, 2008 | 1:55 pm

    The convenience functions are that way because Ironclad doesn’t want to be in the unicode business. There are plenty of excellent ways to convert strings to octets.

    I suppose it might be reasonable to add a :HEX keyword to DIGEST-SEQUENCE and company.

  6. May 8th, 2008 | 6:59 pm

    Interestingly enough I just needed the same thing for my chat software (shamless plug: http://mr-co.de/projects/klatschbase/) and also decided to use ironclad. I came up with this:

    (defun sha256 (str)
    (ironclad:digest-sequence :sha256 (ironclad:ascii-string-to-byte-array str)))

    Since I completely rely on UTF-8, this seems to work just fine for me.

  7. May 8th, 2008 | 7:32 pm

    My bad. This of course only works with ASCII (which is all I needed at that point). So just ignore my previous post. That’s what you get for commenting in a hurry.

  8. May 8th, 2008 | 7:36 pm

    It works for me as long as I don’t use any non-ASCII character :)

    CL-USER(2): (ironclad:digest-sequence :sha256 (ironclad:ascii-string-to-byte-array "’"))
    ; test single typographical apostrophe
     
    debugger invoked on a SIMPLE-ERROR in thread #<thread "initial thread" {A725541}>:
      ’ is not an ASCII character
    </thread>

    This is SBCL 1.0.15.

  9. May 9th, 2008 | 7:32 pm

    I changed my method to use babel, as suggested in the other comments. However, I want to avoid further dependencies. So I looked into Edi’s flexi-streams:

    (defun sha256 (str)
    (let* ((utf8 (flexi-streams:make-external-format :utf-8))
    (str* (flexi-streams:string-to-octets str :external-format utf8)))
    (ironclad:digest-sequence :sha256 str*)))

    This might be interesting for hunchentoot users, because they already depend on flexi-stream.

Leave a reply