SHA2 и управление байтами в Ruby

В качестве задания по программированию в курсе криптографии у меня есть следующая проблема:

Прочитайте видеофайл, разделите его на блоки по 1 КБ, возьмите последний блок, получите его сумму SHA256, добавьте эту сумму к предпоследнему блоку, получите сумму SHA256 результирующего блока и так далее и тому подобное... ответом на проблему является последняя сумма SHA256, которую вы получаете из этой цепочки. Ответ, полученный этим алгоритмом применительно к определенному видео, представляет собой сумму SHA256: «5b96aece304a1422224f9a41b228416028f9ba26b0d1058f400200f06a589949».

Я понимаю проблему, но не могу решить ее с помощью Ruby.

Это мой код Руби:

require 'digest/sha2'

def chunker
  video, array = File.new('video.mp4', 'r'), []
  (0..video.size/1024).each { |i| array[i] = video.read 1024 }
  array
end

video_chunks, sha, digest = chunker, '', Digest::SHA2.new

video_chunks.reverse_each { |chunk| sha = (digest << chunk+sha).to_s }

puts sha

Я в основном делю видео на куски по 1024 байта, затем просматриваю его в обратном порядке, получаю сумму SHA256 (currentBlock + lastSha) и сохраняю ее в переменной, которую я вывожу в конце этого обратного обхода.

Это не работает.

Сумма SHA256 первого фрагмента (к которому не добавлен какой-либо прошлый sha) равна «f2e208617302c6b089f52b6f27f78a7171b4424c1191989bbf86ed5ab0cbccee», я знаю это из программы Java, которая решает точно такую ​​же проблему. Эта сумма верна. Но вторая сумма SHA256, которая является результатом SHA265 добавления "f2e2..." к предпоследнему блоку, должна быть "34b6...", и она выводит другое. Проблема возникает в коде "дайджест ‹‹ чанк+ша". Почему-то при добавлении что-то происходит и получается ша неверный. Любые идеи? :(


person acib708    schedule 18.10.2013    source источник
comment
Убедитесь, что вы добавляете необработанные байты хэша, а не представление в шестнадцатеричном коде (или наоборот; я не знаю, какой способ правильный).   -  person ntoskrnl    schedule 18.10.2013


Ответы (1)


sha не следует генерировать через .to_s, вам нужна версия двоичной строки. Кроме того, вы загружаете все больше и больше блоков в один и тот же дайджест, в то время как ваше упражнение посвящено процессу выполнения одних и тех же действий, но под вашим собственным контролем (то есть в вашем собственном коде).

Таким образом, вместо того, чтобы поддерживать объект digest и вызывать для него .to_s для извлечения каждого вложенного хеша, вы должны каждый раз вычислять хэш заново, используя метод класса Digest::SHA2.digest( data ).

Попробуйте это вместо этого:

video_chunks, sha = chunker, ''

video_chunks.reverse_each { |chunk| sha = Digest::SHA2.digest( chunk+sha ) }

# Convert to hex:
puts sha.unpack('H*').first
person Neil Slater    schedule 18.10.2013
comment
Я не знал о методе класса дайджеста, поэтому я вызывал reset для объекта на каждой итерации. Я все еще рубиновый нуб, но ваш ответ многое прояснил. Спасибо!! - person acib708; 19.10.2013