문제

I was wondering if someone could help me to get this method converted to ruby, is this possible at all?

public static string getSHA512(string str){
    UnicodeEncoding UE = new UnicodeEncoding();
    byte[] HashValue = null;
    byte[] MessageBytes = UE.GetBytes(str);
    System.Security.Cryptography.SHA512Managed SHhash = new System.Security.Cryptography.SHA512Managed();
    string strHex = "";
    HashValue = SHhash.ComputeHash(MessageBytes);
    foreach (byte b in HashValue){
        strHex += string.Format("{0:x2}", b);
    }
    return strHex;
}

Thanks in advance


UPDATE:

I just would like to make it clear that unfortunately it's method is not just for SHA512 generation but a custom one. I believe that the Digest::SHA512.hexdigest would be just the SHHast instance, but if you carefully look for the method you can see that it differs a bit from a simple hash generation. Follows the result of both functions.

# in C#
getSHA512("hello") => "5165d592a6afe59f80d07436e35bd513b3055429916400a16c1adfa499c5a8ce03a370acdd4dc787d04350473bea71ea8345748578fc63ac91f8f95b6c140b93"

# in Ruby
Digest::SHA512.hexdigest("hello") || Digest::SHA2 => "9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043" 
도움이 되었습니까?

해결책

require 'digest/sha2'

class String
  def sha512
    Digest::SHA2.new(512).hexdigest(encode('UTF-16LE'))
  end
end

'hello'.sha512 # => '5165d592a6afe59f80d07436e35bd…5748578fc63ac91f8f95b6c140b93'

As with all my code snippets on StackOverflow, I always assume the latest version of Ruby. Here's one that also works with Ruby 1.8:

require 'iconv'
require 'digest/sha2'

class String
  def sha512(src_enc='UTF-8')
    Digest::SHA2.new(512).hexdigest(Iconv.conv(src_enc, 'UTF-16LE', self))
  end
end

'hello'.sha512 # => '5165d592a6afe59f80d07436e35bd…5748578fc63ac91f8f95b6c140b93'

Note that in this case, you have to know and tell Ruby about the encoding the string is in explicitly. In Ruby 1.9, Ruby always knows what encoding a string is in, and will convert it accordingly, when required. I chose UTF-8 as default encoding because it is backwards-compatible with ASCII, is the standard encoding on the internet and also otherwise widely used. However, for example both .NET and Java use UTF-16LE, not UTF-8. If your string is not UTF-8 or ASCII-encoded, you will have to pass in the encoding name into the sha512 method.


Off-Topic: 9 lines of code reduced to 1. I love Ruby!

Well, actually that is a little bit unfair. You could have written it something like this:

var messageBytes = new UnicodeEncoding().GetBytes(str);
var hashValue = new System.Security.Cryptography.SHA512Managed().
    ComputeHash(messageBytes);
return hashValue.Aggregate<byte, string>("",
    (s, b) => s += string.Format("{0:x2}", b)
);

Which is really only 3 lines (broken into 5 for StackOverflow's layout) and most importantly gets rid of that ugly 1950s-style explicit for loop for a nice 1960s-style fold (aka. reduce aka. inject aka. Aggregate aka. inject:into: … it's all the same).

There's probably an even more elegant way to write this, but a) I don't actually know C# and .NET and b) this question is about Ruby. Focus, Jörg, focus! :-)

Aaand … found it:

return string.Join("", from b in hashValue select string.Format("{0:x2}", b));

I knew there had to be an equivalent to Ruby's Enumerable#join somewhere, I just was looking in the wrong place.

다른 팁

Use the Digest::SHA2 class.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top