C# 中与 base64 + UrlTokenEncode 等价的 Clojure 代码是什么?

4

我有一段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#版本不匹配。
尝试查看MSDN文档中的 UrlTokenEncode(),但是它没有详细说明其实现方式,无法确定内部发生了什么。
我能否在Clojure中生成等效字符串?

您可以在此处找到UrlTokenEncode的源代码:http://www.dotnetframework.org/default.aspx/Dotnetfx_Win7_3@5@1/Dotnetfx_Win7_3@5@1/3@5@1/DEVDIV/depot/DevDiv/releases/whidbey/NetFXspW7/ndp/fx/src/xsp/System/Web/httpserverutility@cs/1/httpserverutility@cs - Robert Harvey
确认。不知道为什么链接无法使用。请在Google上搜索urltokenencode源代码,并单击dotnetframework.org链接。 - Robert Harvey
@RobertHarvey 哦,好酷啊,我当然是在看错地方了!谢谢。 - LocustHorde
回滚此更改,因为该问题特别涉及在Clojure中复制特定C#功能。不是关于在Clojure中进行B64编码。请在编辑之前阅读问题。 - LocustHorde
2个回答

3
感谢Robert指出了UrlTokenEncode的来源。它执行以下操作:
  1. 对输入字节进行Base64编码
  2. 将任何尾部填充的=替换为填充字符数(12
  3. +替换为-,将/替换为_
另一个重要细节是C#示例对字符串进行UTF-16编码(每个字符2个字节)。为了说明这一点,这里有一个来自Go playground的示例: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))))

读者需要自行完成解码函数。

一个小的改进是处理空字符串情况。 - Mike Fikes

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"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接