2017-02-17 2 views
4

Je suis nouveau à Crystal. Je voudrais essayer de trouver le SHA256 hachage d'une chaîne hexagonale. J'ai réussi à obtenir quelque chose de travail:Crystal: Comment trouver le hachage SHA256 d'une valeur binaire?

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

Mais je ne sais pas comment mettre la valeur binaire de « ABCD » pour la fonction de hachage, ou obtenir binaire sur. Je voudrais essentiellement être en mesure de recréer cette fonction 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 

Est-il possible d'utiliser SHA256 avec des valeurs binaires en cristal?

Répondre

8

Décodage une chaîne de caractères hexadécimaux dans une tranche binaire n'est pas actuellement partie de la bibliothèque standard de cristal, j'ai donc écrit une fonction de décodage moi-même:

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 

Cette fonction prend un String contenant des caractères hexadécimaux, puis le décode en Slice(UInt8) (ou renvoie nil si l'hex est invalide).

Ensuite, le code complet équivalent au code rubis que vous avez collé ci-dessus serait:

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 

Même si je dois demander pourquoi vous voulez utiliser SHA256 deux fois. Je recommande de changer la fonction de hachage comme ceci:

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

Merci beaucoup. La raison de l'utilisation de SHA256 à deux reprises est parce que j'essaie d'apprendre le cristal en écrivant une bibliothèque Bitcoin, et pour une raison non réelle, les choses ont tendance à être hachées deux fois. – inersha

0

Pour un script Ruby générer un hachage SHA256 avec la gemme digest:

require "digest" 

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

Pour Crystal, vous pouvez exiger openssl et utiliser à la place:

require "openssl" 

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