c# equivalent of base64 + UrlTokenEncode in clojure



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

  • 未进行网址编码
  • 与 C# 版本不匹配。

尝试查看 MSDN 文档以获取UrlTokenEncode(),但它没有太多关于它实现的细节,以了解幕后发生了什么。

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

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

  1. 对输入字节进行 Base64 编码
  2. 将任何尾随填充=替换为填充字符数(12
  3. +替换为-,将/替换为_

另一个基本细节是 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))))

解码功能留给读者作为练习。

如果您使用的是 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"

最新更新