DWIM(.nl) - Replicating a JS function in elisp

DWIM(.nl)

Do What I Mean

June 11th, 2021

Replicating a JS function in elisp

I wanted to replicate the following function from Javascript md5 module in Emacs lips:

  function b64_md5(s) { return rstr2b64(rstr_md5(str2rstr_utf8(s))); }

The nested functions are:

  1. str2rstr_utf8 encodes a string as utf-8, assuming it is utf-16
  2. rster_md5 calculates the md5 of a raw string
  3. rstr2b64 converts a raw string to a base-64 string

Outputs:

  str2rstr_utf8("test");      // "test"
  rstr_md5("test");           // "\tkÍF!ÓsÊÞNƒ&'´ö"
  rstr2b64("test");           // "dGVzdA"
  rstr2b64(rstr_md5("test"))  // "CY9rzUYh03PK3k6DJie09g"

I could quite easily find some elisp functions that may be equivalent:

Javascript md5Elisp
str2rstr_utf8encode-coding-string
rster_md5secure-hash
str2b64base64-encode-string

On closer inspection I figured I would not need encode-coding-string because Emacs already uses UTF8 encoding internally, while Javascript uses UTF-16.

It turns out that the other two elisp functions are close matches to their JS counterparts:

   (base64-encode-string "test")   ; "dGVzdA", same as rstr2b64
   (secure-hash 'md5 "test")       ; "098f6bcd4621d373cade4e832627b4f6"
                                   ; which is HEX for "	kÍF!ÓsÊÞNƒ&'´ö"

So, I need a function to decode a HEX string:

  (defun decode-hex-string (hex-string)
    (let ((res nil))
      (dotimes (i (/ (length hex-string) 2) (apply #'concat (reverse res)))
        (let ((hex-byte (substring hex-string (* 2 i) (* 2 (+ i 1)))))
          (push (format "%c" (string-to-number hex-byte 16)) res)))))

  (decode-hex-string (secure-hash 'md5 "test"))    ; "	kÍF!ÓsÊÞNƒ&'´ö" same as rster_md5
  (base64-encode-string
   (decode-hex-string (secure-hash 'md5 "test")))  ; "CY9rzUYh03PK3k6DJie09g"

Et voilá!

tags: emacs, dev

 What is Emacs 
 About me 
Loading script...