2017-02-17 57 views
4

我是Crystal的新手。我想嘗試找到一個十六進制字符串的哈希值SHA256。我已經成功地得到一些工作:Crystal:如何查找二進制值的SHA256哈希值?

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

但我不知道如何把「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 

是否有可能在Crystal中使用SHA256的二進制值?

回答

8

解碼十六進制字符的字符串轉換成二進制片不是目前晶體標準庫的一部分,所以我寫的解碼功能自己:

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)。

然後充分等同於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 

雖然我不得不懷疑你爲什麼會想使用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 
+0

非常感謝。兩次使用SHA256的原因是因爲我試圖通過編寫一個比特幣庫來學習Crystal,而沒有真正的理由,事情往往會被哈希兩次。 – inersha

0

對於Ruby腳本生成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