May 8, 2008
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(9)
Babel is portable and recently became asdf-installable.
There’s also a STRING-TO-OCTETS (and OCTETS-TO-STRING, for that matter, too) in Arnesi.
babel is the answer. it’s fast and behaves the same on each platform.
Yeah, you want babel:string-to-octets.
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.
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.
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.
It works for me as long as I don’t use any non-ASCII character :)
This is SBCL 1.0.15.
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.