Crystal:如何找到二进制值的SHA256哈希值?

ine*_*sha 4 crystal-lang

我是Crystal的新手.我想尝试找到十六进制字符串的SHA256哈希值.我成功地完成了一些工作:

sha256 = OpenSSL::Digest.new("sha256")
puts sha256.update("abcd")
Run Code Online (Sandbox Code Playgroud)

但我不确定如何将"abcd"的二进制值放入哈希函数中,或者将二进制输出.我基本上希望能够重新创建这个Ruby函数:

def hash256(hex)
  # 1. Convert hex string to array, and pack in to binary
  binary = [hex].pack("H*")

  # 2. Hash the binary value (returns binary)
  hash1 = Digest::SHA256.digest(binary)

  # 3. Hash it again (returns binary)
  hash2 = Digest::SHA256.digest(hash1)

  # 4. Convert back to hex (must unpack as array)
  result = hash2.unpack("H*")[0]

  return result
end
Run Code Online (Sandbox Code Playgroud)

是否可以在Crystal中使用带有二进制值的SHA256?

RX1*_*X14 9

将一串十六进制字符解码为二进制切片目前不是晶体标准库的一部分,所以我自己写了一个解码函数:

def hex_decode(hex)
  return unless hex.size % 2 == 0

  slice = Slice(UInt8).new(hex.size / 2)
  0.step(to: hex.size - 1, by: 2) do |i|
    high_nibble = hex.to_unsafe[i].unsafe_chr.to_u8?(16)
    low_nibble = hex.to_unsafe[i + 1].unsafe_chr.to_u8?(16)
    return unless high_nibble && low_nibble

    slice[i / 2] = (high_nibble << 4) | low_nibble
  end

  slice
end
Run Code Online (Sandbox Code Playgroud)

此函数采用String包含十六进制的字符,然后将其解码为a Slice(UInt8)(nil如果十六进制无效,则返回).

然后,相当于上面粘贴的ruby代码的完整代码将是:

def hash256(hex_string)
  data = hex_decode(hex_string)
  raise "Invalid hexadecimal" unless data

  hash = OpenSSL::Digest.new("SHA256")
  hash.update(data)
  hash1 = hash.digest

  hash = OpenSSL::Digest.new("SHA256")
  hash.update(hash1)

  hash.hexdigest
end
Run Code Online (Sandbox Code Playgroud)

虽然我不得不质疑你为什么要两次使用SHA256.我建议更改哈希函数,如下所示:

def hash256(hex_string)
  data = hex_decode(hex_string)
  raise "Invalid hexadecimal" unless data

  hash = OpenSSL::Digest.new("SHA256")
  hash.update(data)

  hash.hexdigest
end
Run Code Online (Sandbox Code Playgroud)