File: hash-files

package info (click to toggle)
git-lfs 3.6.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 4,808 kB
  • sloc: sh: 21,256; makefile: 507; ruby: 417
file content (59 lines) | stat: -rwxr-xr-x 1,422 bytes parent folder | download | duplicates (2)
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 }