sharplispers / ironclad

A cryptographic toolkit written in Common Lisp
BSD 3-Clause "New" or "Revised" License
166 stars 28 forks source link

Support multiple hashes in one call to `digest-file` #10

Closed phmarek closed 4 years ago

phmarek commented 5 years ago

Hi,

I'd like to ask for a small feature update: Allowing passing a list of digests to digest-file, so that one round of IO produces hashes for all of them at the same time (returning a list of results in the same order as the input specifications?).

Thank you for any feedback (and, possibly, an implementation ;)

glv2 commented 5 years ago

This feature seems to be for a very specific use case. I would rather put it in the program or library that requires it than directly in Ironclad.

If (mapcar (lambda (digest-spec) (crypto:digest-file digest-spec pathname)) digest-specs)) is not a viable option because you have very slow IO accesses and the file can't be put in cache by the OS, you can do the following:

(defun multi-digest-file (digest-specs pathname)
  (with-open-file (file pathname :element-type '(unsigned-byte 8))
    (let ((buffer (make-array 16384 :element-type '(unsigned-byte 8)))
          (digesters (mapcar #'crypto:make-digest digest-specs)))
      (do ((n (read-sequence buffer file) (read-sequence buffer file)))
          ((zerop n))
        (mapc (lambda (digester)
                (crypto:update-digest digester buffer :end n))
              digesters))
      (mapcar #'crypto:produce-digest digesters))))

(multi-digest-file '(:sha256 :blake2/256 :sha3/256) "data.dat")
phmarek commented 5 years ago

Well, I'd have thought that doing multiples hashes at the same time isn't that uncommon - but if you don't want that in ironclad, I'll put it in my app.

Thanks a lot!