Преобразование функции С# CUSTOM getSHA512 в Ruby

Мне было интересно, может ли кто-нибудь помочь мне преобразовать этот метод в рубин, возможно ли это вообще?

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;
}

заранее спасибо


ОБНОВИТЬ:

Я просто хотел бы прояснить, что, к сожалению, этот метод предназначен не только для генерации SHA512, но и для пользовательского. Я считаю, что Digest::SHA512.hexdigest будет просто экземпляром SHHast, но если вы внимательно посмотрите на этот метод, вы увидите, что он немного отличается от простой генерации хэша. Следует за результатом обеих функций.

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

# in Ruby
Digest::SHA512.hexdigest("hello") || Digest::SHA2 => "9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043" 

person zanona    schedule 23.06.2010    source источник
comment
Что вы пробовали до сих пор?   -  person Sjoerd    schedule 23.06.2010


Ответы (2)


require 'digest/sha2'

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

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

Как и во всех моих фрагментах кода на StackOverflow, я всегда использую последнюю версию Ruby. Вот тот, который также работает с 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'

Обратите внимание, что в этом случае вы должны знать и явно сообщать Ruby о кодировке, в которой находится строка. В Ruby 1.9 Ruby всегда знает, в какой кодировке находится строка, и при необходимости преобразует ее соответствующим образом. Я выбрал UTF-8 в качестве кодировки по умолчанию, потому что она обратно совместима с ASCII, является стандартной кодировкой в ​​Интернете, а также широко используется в других целях. Однако, например, и .NET, и Java используют UTF-16LE, а не UTF-8. Если ваша строка не имеет кодировку UTF-8 или ASCII, вам нужно будет передать имя кодировки в метод sha512.


Не по теме: 9 строк кода сокращены до 1. Я люблю Ruby!

Ну, на самом деле это немного несправедливо. Вы могли бы написать это примерно так:

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

Это на самом деле всего 3 строки (разбитые на 5 для макета StackOverflow) и, что наиболее важно, избавление от этого уродливого явного цикла for в стиле 1950-х годов для красивого сгиба в стиле 1960-х (иначе. reduce ака. inject ака. Aggregate ака. inject:into: это все то же).

Возможно, есть еще более элегантный способ написать это, но а) я на самом деле не знаю C# и .NET и б) этот вопрос касается Ruby. Сосредоточься, Йорг, сосредоточься! :-)

Ааанд нашел это:

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

Я знал, что где-то должен быть эквивалент Ruby Enumerable#join, просто я искал не в том месте.

person Jörg W Mittag    schedule 23.06.2010
comment
Привет, Йорг, к сожалению, это не так просто :( это всего лишь экземпляр SHhash, как и рекомендовал Сьорд. Я обновил свой вопрос примерами. Так что вы можете увидеть разницу между ними :) - person zanona; 23.06.2010
comment
@ludicco: Извините, я пропустил тот факт, что вы сначала перекодируете в UTF-16LE. Исправлено сейчас. - person Jörg W Mittag; 23.06.2010
comment
еще раз извините за невежество, Йорг, но я получаю это при использовании вашего метода NoMethodError: неопределенный метод `encode' для hello:String, как я могу правильно использовать это кодирование? - person zanona; 23.06.2010
comment
@ludicco: Похоже, вы используете более старую версию Ruby. Поддержка многоязычия была значительно улучшена в Ruby 1.9. Точнее: до Ruby 1.9 не было поддержки m17n, все m17n должны были обрабатываться программистом явно. В Ruby 1.8 вам придется использовать библиотеку iconv из стандартной библиотеки. - person Jörg W Mittag; 23.06.2010
comment
Ха! Спасибо, Йорг, ты молодец! И много знает о программировании, я поражен. - person zanona; 23.06.2010
comment
Отличный ответ. Подчеркивается, что основной причиной того, что два хэша по OP были разными, является отсутствие преобразования в UTF16-LE сначала, как это делал Unicode.GetBytes(). Кроме того, бонусные баллы за дальнейшее объяснение различий между Ruby 1.8/1.9 и предоставление современного примера исходной проблемы на C#. - person maxwellb; 23.06.2010

Используйте Digest::SHA2. класс.

person Sjoerd    schedule 23.06.2010
comment
привет Sjoerd Боюсь, я уже использовал Digest::SHA512.digest, но я понятия не имею, как использовать другие классы, такие как UnicodeEncoding, GetBytes, ComputeHash :(. В этом методе Digest::SHA512.digest будет быть просто экземпляром SHhash. - person zanona; 23.06.2010