Crystal: How can I find the SHA256 hash of a binary value?

I am new to Crystal. I would like to try to find the SHA256 hash of the hexadecimal string. I managed to do something:

sha256 = OpenSSL::Digest.new("sha256")
puts sha256.update("abcd")

But I'm not sure how to put the binary value "abcd" in a hash function or get the binary code. Basically, I would like to recreate this Ruby function:

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

Is it possible to use SHA256 with binary values ​​in Crystal?

+4
source share
2 answers

Decoding a string of hexadecimal characters into a binary fragment is currently not part of the standard crystal library, so I wrote the decoding function myself:

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

String, , Slice(UInt8) ( nil, ).

, , :

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

, 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
+8

Ruby script, SHA256 digest:

require "digest"

def calc_hash
  sha = Digest::SHA256.new
  sha.update(@index.to_s + @timestamp.to_s + @data + @previous_hash)
  sha.hexdigest
end

Crystal openssl :

require "openssl"

def calc_hash
  hash = OpenSSL::Digest.new("SHA256")
  hash.update(@index.to_s + @timestamp.to_s + @data + @previous_hash)
  hash.hexdigest
end
0

Source: https://habr.com/ru/post/1670070/


All Articles