在 Clojure 中将 40 字节 SHA 打包为 20 字节

发布于 2025-01-15 08:48:51 字数 919 浏览 4 评论 0原文

为了将 40 字节 SHA 打包为 20 字节,我们这样做:

(defn pack-sha-1 [sha-1] 
  (->> sha-1
       (partition 2)
       (map (partial apply str)) ;; To convert back to list of strings
       (map (fn [hex] (-> hex
                         (Integer/parseInt 16)
                         char)))
       (apply str)))             ;; To convert back to string

首先我们按 2 进行分区,然后将其转换为单个字符。

这本质上是打包步骤,其中 2 个十六进制字符被转换为一个 单个字符。

当我们尝试将打包字符串转换回其 40 字节 SHA 时(使用 https://www.rapidtables.com/convert/number/ascii- to-hex.html),它没有给出 在所有情况下返回相同的 SHA。

它适用于:“5e4fb7a0afe4f2ec9768a9ddd2c476dab7fd449b”

,但不适用于:“00c35422185bf1dca594f699084525e8d0b8569f”

只要范围内有一对十六进制(“08” - “0d”),它就不会 工作。

这里出了什么问题?

这是在 Clojure 中实现 James Coglan 的书“Building Git”的一部分。

感谢您的帮助!

To pack a 40 byte SHA in 20 bytes, we are doing this:

(defn pack-sha-1 [sha-1] 
  (->> sha-1
       (partition 2)
       (map (partial apply str)) ;; To convert back to list of strings
       (map (fn [hex] (-> hex
                         (Integer/parseInt 16)
                         char)))
       (apply str)))             ;; To convert back to string

First we partition by 2 and then convert that into a single character.

This is essentially the packing step where 2 hex characters are converted into a
single character.

When we try to convert the packed string back to its 40 bytes SHA (using
https://www.rapidtables.com/convert/number/ascii-to-hex.html), it does not give
the same SHA back in all the cases.

It works for: "5e4fb7a0afe4f2ec9768a9ddd2c476dab7fd449b"

But it does not work for: "00c35422185bf1dca594f699084525e8d0b8569f"

Whenever there is a pair of hex in the range ("08" - "0d"), it does not work.

What is going wrong here?

This is done as part of implementing James Coglan's book "Building Git" in Clojure.

Thanks for your help!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

夜灵血窟げ 2025-01-22 08:48:51

一般来说,不可能以可逆的方式将40字节打包成20字节。您将会丢失包装中的信息。我还没有读过《Building Git》一书,所以不太清楚他们到底想做什么。也许您可以编辑您的问题来澄清。

SHA-1 始终为 20 个字节。为了打印这 20 个字节,您可以使用 40 个十六进制字符来显示它们,其中每个字节显示为 2 个十六进制字符。这不是 40 个字节,而是 40 个用于显示的字符。

可以有其他方式来显示 20 个字节。例如,您可以将每个字节视为 000 到 255(1-3 个字符)之间的无符号整数,并且它们之间有一个空格。在这种情况下,您的第一个示例 SHA 将显示为
“0 195 84 34 24 91 241 220 165 148 246 153 8 69 37 232 208 184 86 159”

以十六进制显示为 08 的字节是退格字符。我尝试在您提供的 ASCII 到十六进制转换器中输入退格键,但失败了。因此,我不相信该转换器能够对所有字符正常工作。

In general, it is not possible to pack 40 bytes into 20 bytes in a reversible manner. You will lose information in the packing. I have not read the "Building Git" book, so not quite sure what exactly they are trying to do. Perhaps you can edit your question to clarify.

A SHA-1 is always 20 bytes. In order to print those 20 bytes, you can display them using 40 hex characters, where each byte is displayed as 2 hex characters. That is not 40 bytes, but 40 characters for the display.

There can be other ways to display the 20 bytes. For example, you could consider each byte as an unsigned integer between 000 and 255 (1-3 characters) and a space between them. In that case, your first example SHA would be displayed as
"0 195 84 34 24 91 241 220 165 148 246 153 8 69 37 232 208 184 86 159".

The byte that displays as 08 in hex is the backspace character. I tried typing a backspace into the ASCII-to-Hex converter you provided and was not able to. So, I would not trust that converter to work correctly for all characters.

薄荷港 2025-01-22 08:48:51

实际上,我认为它有效 - 您可能在复制/粘贴 pack-sha-1 输出的字符串时遇到问题。

如果你这样做:
(def Packed-sha-1 (pack-sha-1 "00c35422185bf1dca594f699084525e8d0b8569f"))

然后使用这里的答案:Clojure相当于python的encode hex和decodehex你把它转换回来:

(hexify (map short (seq packed-sha-1)))

你回来“00c35422185bf1dca594f699084525e8d0b8569f” 细绳。

(=  "00c35422185bf1dca594f699084525e8d0b8569f" (hexify (map short (seq packed-sha-1 ))))
true

Actually, I think it works - you may have trouble with copy/pasting the string that the pack-sha-1 is outputting.

If you do:
(def packed-sha-1 (pack-sha-1 "00c35422185bf1dca594f699084525e8d0b8569f"))

and then using the answer from here: Clojure's equivalent to python's encode hex and decodehex you convert it back:

(hexify (map short (seq packed-sha-1)))

you get back the "00c35422185bf1dca594f699084525e8d0b8569f" string.

(=  "00c35422185bf1dca594f699084525e8d0b8569f" (hexify (map short (seq packed-sha-1 ))))
true
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文