我有一段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
库并在(String. (b64/encode (.getBytes email)) "UTF-8")
我得到
V2ludGVyIGlzIGNvbWluZw==
,这是不是url编码的
与C版不匹配。
尝试查看
UrlTokenEncode()
的msdn文档,但是没有太多关于它实现的细节,无法查看引擎盖下发生了什么。我可以在clojure中生成等价的字符串吗?
最佳答案
感谢罗伯特指出UrlTokenEncode
的来源。它执行以下操作:
base64编码输入字节
用填充字符数(=
或1
)替换任何后面的填充2
。
用+
替换-
,用/
替换_
。
另一个重要的细节是c示例对字符串的utf-16表示进行编码(每个字符2个字节)。举例来说,这里有一个来自围棋场的例子: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))))
解码功能留给读者作为练习。