我在C#中有一段代码对字符串进行编码并返回URL安全字符串(稍后解码)
string stringToEncrypt = "Winter is coming";
byte[] bytes = new byte[stringToEncrypt.Length * sizeof(char)];
System.Buffer.BlockCopy(stringToEncrypt.ToCharArray(), 0, bytes, 0, bytes.Length);
System.Web.HttpServerUtility.UrlTokenEncode(bytes).Dump();
Dump
来自LinqPad。我用它来快速测试C#的各个部分
执行时返回VwBpAG4AdABlAHIAIABpAHMAIABjAG8AbQBpAG4AZwA1
。
我正在尝试从clojure服务中做同样的事情。使用encode
库并经过this answer当我有
(String. (b64/encode (.getBytes email)) "UTF-8")
我得到V2ludGVyIGlzIGNvbWluZw==
,这是
尝试查看UrlTokenEncode()
的MSDN文档,但它没有详细介绍它的实现,以了解幕后发生了什么。
我可以在clojure中生成等效的字符串吗?
答案 0 :(得分:3)
感谢Robert指出UrlTokenEncode
的来源。它执行以下操作:
=
替换为填充字符数1
或2
)+
替换为-
,将/
替换为_
另一个重要细节是C#示例对字符串的UTF-16表示进行编码(每个字符2个字节)。为了说明,这里是Go操场的一个例子:http://play.golang.org/p/UlKMa7_OwV
此代码生成测试输入的预期输出:
(ns blah.core
(:require [clojure.data.codec.base64 :as b64])
(:require [clojure.string :as string])
(:gen-class))
(defn encode [original]
(let [bytes_in (.getBytes original "UTF-16LE")
bytes_enc (b64/encode bytes_in)
bytes_len (alength bytes_enc)
pad_count (b64/pad-length bytes_enc 0 bytes_len)
enc_string (String. bytes_enc 0 (- bytes_len pad_count) "UTF-8")
enc_string (string/replace enc_string \+ \-)
enc_string (string/replace enc_string \/ \_)]
(str enc_string pad_count)))
(defn -main
[& args]
(let [message "Winter is coming"]
(println message)
(println (encode message))))
解码功能留给读者练习。
答案 1 :(得分:2)
如果您使用的是Java 8,则新的Base64
类以及一个用于填充计数的模块化算术可以实现:
(defn url-token-encode [bytes]
(let [byte-count (count bytes)]
(if (pos? byte-count)
(str (.. (java.util.Base64/getUrlEncoder) (withoutPadding) (encodeToString bytes))
(mod (- byte-count) 3))
"")))
(defn encode [s]
(url-token-encode (.getBytes s "UTF-16LE")))
(encode "Winter is coming")
;=>"VwBpAG4AdABlAHIAIABpAHMAIABjAG8AbQBpAG4AZwA1"