3 # shasum: filter for computing SHA digests (analogous to sha1sum)
5 # Copyright (C) 2003-2008 Mark Shelor, All Rights Reserved
8 # Wed Apr 30 04:00:54 MST 2008
12 shasum - Print or Check SHA Checksums
16 Usage: shasum [OPTION] [FILE]...
17 or: shasum [OPTION] --check [FILE]
18 Print or check SHA checksums.
19 With no FILE, or when FILE is -, read standard input.
21 -a, --algorithm 1 (default), 224, 256, 384, 512
22 -b, --binary read files in binary mode (default on DOS/Windows)
23 -c, --check check SHA sums against given list
24 -p, --portable read files in portable mode
25 produces same digest on Windows/Unix/Mac
26 -t, --text read files in text mode (default)
28 The following two options are useful only when verifying checksums:
30 -s, --status don't output anything, status code shows success
31 -w, --warn warn about improperly formatted SHA checksum lines
33 -h, --help display this help and exit
34 -v, --version output version information and exit
36 The sums are computed as described in FIPS PUB 180-2. When checking,
37 the input should be a former output of this program. The default mode
38 is to print a line with checksum, a character indicating type (`*'
39 for binary, `?' for portable, ` ' for text), and name for each FILE.
43 The I<shasum> script provides the easiest and most convenient way to
44 compute SHA message digests. Rather than writing a program, the user
45 simply feeds data to the script via the command line, and waits for
46 the results to be printed on standard output. Data can be fed to
47 I<shasum> through files, standard input, or both.
49 The following command shows how easy it is to compute digests for typical
50 inputs such as the NIST test vector "abc":
52 perl -e "print qw(abc)" | shasum
54 Or, if you want to use SHA-256 instead of the default SHA-1, simply say:
56 perl -e "print qw(abc)" | shasum -a 256
58 Since I<shasum> uses the same interface employed by the familiar
59 I<sha1sum> program (and its somewhat outmoded anscestor I<md5sum>),
60 you can install this script as a convenient drop-in replacement.
64 Copyright (c) 2003-2008 Mark Shelor <mshelor@cpan.org>.
68 shasum is implemented using the Perl module L<Digest::SHA> or
69 L<Digest::SHA::PurePerl>.
80 # Try to use Digest::SHA, since it's faster. If not installed,
81 # use Digest::SHA::PurePerl instead.
83 my $MOD_PREFER = "Digest::SHA";
84 my $MOD_SECOND = "Digest::SHA::PurePerl";
86 my $module = $MOD_PREFER;
87 eval "require $module";
89 $module = $MOD_SECOND;
90 eval "require $module";
91 die "Unable to find $MOD_PREFER or $MOD_SECOND\n" if $@;
95 # Usage statement adapted from Ulrich Drepper's md5sum.
96 # Include an "-a" option for algorithm selection,
97 # and a "-p" option for portable digest computation.
102 $msg = "" unless defined $msg;
104 warn($msg . "Type shasum -h for help\n");
107 print <<'END_OF_USAGE';
108 Usage: shasum [OPTION] [FILE]...
109 or: shasum [OPTION] --check [FILE]
110 Print or check SHA checksums.
111 With no FILE, or when FILE is -, read standard input.
113 -a, --algorithm 1 (default), 224, 256, 384, 512
114 -b, --binary read files in binary mode (default on DOS/Windows)
115 -c, --check check SHA sums against given list
116 -p, --portable read files in portable mode
117 produces same digest on Windows/Unix/Mac
118 -t, --text read files in text mode (default)
120 The following two options are useful only when verifying checksums:
121 -s, --status don't output anything, status code shows success
122 -w, --warn warn about improperly formatted SHA checksum lines
124 -h, --help display this help and exit
125 -v, --version output version information and exit
127 The sums are computed as described in FIPS PUB 180-2. When checking, the
128 input should be a former output of this program. The default mode is to
129 print a line with checksum, a character indicating type (`*' for binary,
130 `?' for portable, ` ' for text), and name for each FILE.
132 Report bugs to <mshelor@cpan.org>.
138 # Collect options from command line
140 my ($alg, $binary, $check, $text, $status, $warn, $help, $version);
143 eval { Getopt::Long::Configure ("bundling") };
145 'b|binary' => \$binary, 'c|check' => \$check,
146 't|text' => \$text, 'a|algorithm=i' => \$alg,
147 's|status' => \$status, 'w|warn' => \$warn,
148 'h|help' => \$help, 'v|version' => \$version,
149 'p|portable' => \$portable
153 # Deal with help requests and incorrect uses
157 usage(1, "shasum: Ambiguous file mode\n")
158 if scalar(grep { defined $_ } ($binary, $portable, $text)) > 1;
159 usage(1, "shasum: --warn option used only when verifying checksums\n")
161 usage(1, "shasum: --status option used only when verifying checksums\n")
162 if $status && !$check;
165 # Default to SHA-1 unless overriden by command line option
167 $alg = 1 unless $alg;
168 grep { $_ == $alg } (1, 224, 256, 384, 512)
169 or usage(1, "shasum: Unrecognized algorithm\n");
172 # Display version information if requested
180 # Try to figure out if the OS is DOS-like. If it is,
181 # default to binary mode when reading files, unless
182 # explicitly overriden by command line "--text" or
183 # "--portable" options.
185 my $isDOSish = ($^O =~ /^(MSWin\d\d|os2|dos|mint|cygwin)$/);
186 if ($isDOSish) { $binary = 1 unless $text || $portable }
188 my $modesym = $binary ? '*' : ($portable ? '?' : ' ');
191 # Read from STDIN (-) if no files listed on command line
193 @ARGV = ("-") unless @ARGV;
196 # sumfile($file): computes SHA digest of $file
201 my $mode = $portable ? 'p' : ($binary ? 'b' : '');
202 my $digest = eval { $module->new($alg)->addfile($file, $mode) };
204 warn "shasum: $file: $!\n";
212 # %len2alg: maps hex digest length to SHA algorithm
214 my %len2alg = (40 => 1, 56 => 224, 64 => 256, 96 => 384, 128 => 512);
217 # Verify checksums if requested
220 my $checkfile = shift(@ARGV);
221 my ($err, $read_errs, $match_errs) = (0, 0, 0);
222 my ($num_files, $num_checksums) = (0, 0);
223 my ($fh, $sum, $fname, $rsp, $digest);
225 die "shasum: $checkfile: $!\n"
226 unless $fh = FileHandle->new($checkfile, "r");
229 ($sum, $modesym, $fname) = /^(\S+) (.)(.*)$/;
230 ($binary, $portable, $text) =
231 map { $_ eq $modesym } ('*', '?', ' ');
232 unless ($alg = $len2alg{length($sum)}) {
233 warn("shasum: $checkfile: $.: improperly " .
234 "formatted SHA checksum line\n") if $warn;
237 $rsp = "$fname: "; $num_files++;
238 unless ($digest = sumfile($fname)) {
239 $rsp .= "FAILED open or read\n";
240 $err = 1; $read_errs++;
244 if (lc($sum) eq $digest) { $rsp .= "OK\n" }
245 else { $rsp .= "FAILED\n"; $err = 1; $match_errs++ }
247 print $rsp unless $status;
251 warn("shasum: WARNING: $read_errs of $num_files listed " .
252 "files could not be read\n") if $read_errs;
253 warn("shasum: WARNING: $match_errs of $num_checksums " .
254 "computed checksums did NOT match\n") if $match_errs;
260 # Compute and display SHA checksums of requested files
265 if ($digest = sumfile($file)) {
266 print "$digest $modesym", "$file\n";