У меня есть сервер, который создает хэш, используя следующий код:
base64_encode(md5("some value", true))
Что мне нужно сделать, так это создать такое же хеш-значение в Clojure (используя взаимодействие с Java). Я создал следующие функции Clojure:
(defn md5-raw [s]
(let [algorithm (java.security.MessageDigest/getInstance "MD5")
size (* 2 (.getDigestLength algorithm))]
(.digest algorithm (.getBytes s))))
(defn bytes-to-base64-string [bytes]
(String. (b64/encode bytes) "UTF-8"))
Затем я использую этот код таким образом:
(bytes-to-base64-string (md5-raw "some value")
Теперь все нормально работает с обычными строками. Однако после обработки нескольких различных примеров я обнаружил, что следующий символ вызывает проблемы:
’
Это UTF-8
персонаж #8217
,
Если я запускаю следующее PHP
код:
base64_encode(md5("’", true))
Что возвращается:
yOy9/y97p/GfapveLVQAHA==
Если я запускаю следующее Clojure
код:
(bytes-to-base64-string (md5-raw "’"))
Я получаю следующее значение:
aF1ZConzUtEGRN2YXaKpoQ==
Это почему? Я подозреваю, что проблема с кодировкой символов, но, кажется, все обрабатывается как UTF-8.
Не все может быть гарантированно UTF-8 в вашем примере, следующее выражение зависит от вашей кодировки по умолчанию:
(.getBytes s)
Вы должны — ну, на самом деле это зависит от вашего варианта использования — use:
(.getBytes s "UTF-8")
Демонстрация:
(defn md5-with-charset
[s charset]
(let [algorithm (java.security.MessageDigest/getInstance "MD5")]
(.digest algorithm (.getBytes s charset))))
(b64 (md5-with-charset "’" "UTF-8")) ;; => "yOy9/y97p/GfapveLVQAHA=="(b64 (md5-with-charset "’" "ASCII")) ;; => "0UV7csP7MjomcRJa7z6rXQ=="(b64 (md5-with-charset "’" "UTF-16")) ;; => "3CLVThylT2KkrocdUpxIpg=="(b64 (md5-with-charset "’" "UTF-32")) ;; => "iHBMMMzkWTbPU+n8GCHitQ=="
(где b64
является этапом кодирования base64)
И я нашел это:
(b64 (md5-with-charset "’" "windows-1250")) ;; => "aF1ZConzUtEGRN2YXaKpoQ=="
Других решений пока нет …