目标:在emacs中进行base64url的编解码
现状:
- 原字符串:d93a4fae-4f9d-44c2-9aa6-34efe9fc66f7
- base64url编码结果:2TpPrk-dRMKapjTv6fxm9w
使用python的base64结果没问题:
但是elisp的结果不对:
怎样让elisp的编码、解码与python中一致?是跟bytes的大端字节序有关么?
目标:在emacs中进行base64url的编解码
现状:
使用python的base64结果没问题:
但是elisp的结果不对:
怎样让elisp的编码、解码与python中一致?是跟bytes的大端字节序有关么?
看起来是python里面的uuidstring
被UUID
包了一层的缘故,如果直接uuidstring.encode()
就和elisp一致了
使用的 Python的 base64算法和 elisp 的不一致。
>>> import base64
>>> s = "d93a4fae-4f9d-44c2-9aa6-34efe9fc66f7"
>>> bs = s.encode()
>>> s2 = base64.b64encode(bs)
b'ZDkzYTRmYWUtNGY5ZC00NGMyLTlhYTYtMzRlZmU5ZmM2NmY3'
>>> s2.decode()
'ZDkzYTRmYWUtNGY5ZC00NGMyLTlhYTYtMzRlZmU5ZmM2NmY3'
都byte了哪还有什么字节序问题。你的python代码和elisp代码逻辑就不一致,可以看看上面两位的回复。
确实,看起来不是base64算法的问题,而是uuid有不同的二进制编码方式。所以base64-encode-string接受字符串、按照常规方式编码为二进制就会有问题。看来需要研究一下uuid,把它转成正确的bytes,然后传给base64-encode-region,
我感觉这里的特殊之处在于,原字符串是uuid,不能直接用标准方法。
目前发现从base64url解码回来,需要补上==后缀并设置BASE64URL。不过这样得到的结果似乎是bytes。
现在的问题是,怎么在elisp中将其转化为十六进制,即下图红色箭头部分:
你的python代码的逻辑是: d93a4fae-4f9d-44c2-9aa6-34efe9fc66f7 → uuid → base64encode
elisp代码的逻辑是: d93a4fae-4f9d-44c2-9aa6-34efe9fc66f7 → base64encode
我没看错吧?你的代码逻辑不一样啊 二楼的回复也是这意思啊。
我上面字节序可能说得太绝对了,不过我目前打不开维基,能打开了我学习下。
python的base64encode接受的是bytes,emacs的base64-encode接受的是string,所以我原来以为uuid.bytes做的是把string转bytes,相当于emacs的base64-encode中的部分功能,看了二楼的回复才意识到uuid转bytes不是常规按照字符串转bytes,而是去掉-后,当作16进制转bytes😂
elisp貌似没有现成函数处理uuid与slugid之间的转化,我决定这部分就先放在外面处理了。
我对你的原始需求还有点不清楚,不确定你是要用elisp代码复刻你截图里python代码的行为还是说只是达成base64encode字符串就可以。我上面的回复只是针对你两端代码逻辑的差异。你如果还需要讨论,可以再明确一下。
另外说一个我的疑惑点,d93a4fae-4f9d-44c2-9aa6-34efe9fc66f7看着已经是一个uuid字符串了,如果只是string转bytes,python肯定有其它方法,用uuid不合适。
原始需求就是能实现以下二者的互转。
原字符串:d93a4fae-4f9d-44c2-9aa6-34efe9fc66f7
base64url编码结果:2TpPrk-dRMKapjTv6fxm9w
至于为什么非要这么转,因为这也算某种标准吧,youtube等网站就是这么实现的。更多参见 GitHub - tanbro/b64uuid: A small Python library and command-line tool to encode/decode UUID to/from a 22 characters shorter URL safe base64 string. 。 我在用的一个软件的deep link也是用的这种方式,给到的链接是2TpPrk-dRMKapjTv6fxm9w,其对应的文件路径为d93a4fae-4f9d-44c2-9aa6-34efe9fc66f7。
直接string转bytes那就是3楼的方案了,不是我希望的。现在明白问题出在哪一步了,elisp似乎没有现成的函数,就先不在emacs中实现了。
(base64url-encode-string
(apply #'string
(mapcar (lambda (x) (string-to-number x 16))
(seq-partition (remove ?- "d93a4fae-4f9d-44c2-9aa6-34efe9fc66f7") 2))))
;; => "2TpPrk-dRMKapjTv6fxm9w=="
这就是把byte直接写成string了,转回去就好,==
不要就自己去掉。