4

I have required:

[clojure.data.codec.base64 :as b64]

I have defined a function:

(defn toHexString [bytes]
  "Convert bytes to a String"
  (apply str (map #(format "%x" %) bytes)))

I run this code to get a result in Clojure:

(toHexString (b64/decode (.getBytes "WR0frsVTzVg8QdA9l45/MuYZ3GUKGynDF7WaEYcjudI")))

I also run this code in PHP for comparison's sake (I am certain that the PHP result is correct):

echo bin2hex(base64_decode("WR0frsVTzVg8QdA9l45/MuYZ3GUKGynDF7WaEYcjudI"));

And I get these results for Clojure and PHP respectively:

591d1faec553cd583c41d03d978e7f32e619dc65a1b29c317b59a118723
591d1faec553cd583c41d03d978e7f32e619dc650a1b29c317b59a118723b9d2

Notice that the result is almost exactly the same. The only difference is the missing 0 in the middle and four missing characters at the end of the Clojure result.

I don't know what I am doing wrong here. Is the base64 decode function in Clojure broken? Or what am I doing wrong? Thanks in advance!

adrianmcli
  • 1,956
  • 3
  • 21
  • 49

1 Answers1

4

Your toHexString needs to 0-pad for bytes that can be represented as a single hexadecimal number:

 (defn to-hex-string [bytes] (apply str (map #(format "%02x" %) bytes)))

Your base64 input has length of 43, so it is either needs to be padded out to a multiple of 4 or decoded with an implementation that does not require padding. Looks like PHP accepts non-padded input and this Clojure does not (truncates). Pad with "=".

(to-hex-string (b64/decode (.getBytes "WR0frsVTzVg8QdA9l45/MuYZ3GUKGynDF7WaEYcjudI=")))

This now gives the expected output.

A. Webb
  • 26,227
  • 1
  • 63
  • 95
  • Thanks! You've solved my headaches! Just a quick question though, how do you know to add an equal sign at the end? – adrianmcli Apr 16 '14 at 08:33
  • 1
    @ibopm The doc-string for decode specifies input length must be in multiples of 4. The `=` padding is standard when padding is used, so I just tried it. – A. Webb Apr 16 '14 at 11:34
  • this might be asking too much, but would you mind showing me an example of how I can make a function that would check if a string input length is a multiple of 4, and if it's not then pad it with "=" until it is? I'm really new to functional programming and would really appreciate an example, thanks! I can create a new question for this if you'd prefer. – adrianmcli Apr 17 '14 at 04:29
  • 1
    `(defn pad-to-multiple [s m pad] (apply str s (repeat (mod (- 0 (count s)) m) pad)))` – A. Webb Apr 17 '14 at 04:43