1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
|
#!/usr/bin/env ruby
require "openssl"
# This maps the OpenSSL name to the name used in the output file.
# The order used is the order they should appear in the output file.
DIGESTS = {
'BLAKE2b512' => 'BLAKE2b',
'BLAKE2s256' => 'BLAKE2s',
'SHA256' => 'SHA256',
'SHA384' => 'SHA384',
'SHA512' => 'SHA512',
'SHA512-256' => 'SHA512/256',
'SHA3-256' => 'SHA3-256',
'SHA3-384' => 'SHA3-384',
'SHA3-512' => 'SHA3-512',
}
class Hasher
def initialize(file)
@file = file
@hashers = DIGESTS.map do |openssl, output|
[output, OpenSSL::Digest.new(openssl)]
end.to_h
end
def update(s)
@hashers.values.each { |h| h.update(s) }
end
def to_a
@hashers.map do |name, ctx|
"#{name} (#{@file}) = #{ctx.digest.unpack("H*")[0]}\n"
end.to_a
end
end
results = []
ARGV.each do |file|
f = File.open(file)
h = Hasher.new(file)
while chunk = f.read(65536) do
h.update(chunk)
end
results += h.to_a
end
# Sort entries first by order of algorithm name in DIGESTS, then by filename,
# then print them.
# Create a mapping of output name digest to order in the hash.
names = DIGESTS.values.each_with_index.to_a.to_h
results.sort_by do |s|
# Split into digest name and remainder. The remainder starts with the
# filename.
pair = s.split(' ', 2).to_a
# Order by the index of the digest and then the filename.
[names[pair[0]], pair[1]]
end.each { |l| puts l }
|