在clojure中c#等效于base64 + UrlTokenEncode

时间:2014-12-01 18:44:31

标签: c# clojure base64

我在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==,这是

  • 不是网址编码
  • 与C#版本不匹配。

尝试查看UrlTokenEncode()的MSDN文档,但它没有详细介绍它的实现,以了解幕后发生了什么。

我可以在clojure中生成等效的字符串吗?

2 个答案:

答案 0 :(得分:3)

感谢Robert指出UrlTokenEncode的来源。它执行以下操作:

  1. Base64编码输入字节
  2. 将任何尾随填充=替换为填充字符数12
  3. +替换为-,将/替换为_
  4. 另一个重要细节是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"