Revision history for Perl extension Digest::SHA.
+5.42 Mon Jul 24 04:04:40 MST 2006
+ - minor code changes suggested by Perl::Critic
+ -- e.g. no bareword filehandles, no 2-argument open's
+ - updated public key (ref. B538C51C)
+ -- previous one (0AF563FE) expired July 2, 2006
+ - added documentation to warn that Base64 digests are NOT padded
+ -- padding must be done by user if interoperability
+ with other software is required
+
5.41 Sat Jun 3 01:50:46 MST 2006
- corrected addfile
-- process $file argument as a filehandle unless passed
-Digest::SHA version 5.41
+Digest::SHA version 5.42
========================
Digest::SHA is a complete implementation of the NIST Secure Hash
use warnings;
use integer;
-our $VERSION = '5.41';
+our $VERSION = '5.42';
require Exporter;
our @ISA = qw(Exporter);
my ($binary, $portable) = map { $_ eq $mode } ("b", "p");
my $text = -T $file;
- local *F;
- _bail("Open failed") unless open(F, "<$file");
- binmode(F) if $binary || $portable;
+ open(my $fh, q{<}, $file) or _bail("Open failed");
+ binmode($fh) if $binary || $portable;
unless ($portable && $text) {
- $self->_addfile(*F);
- close(F);
+ $self->_addfile($fh);
+ close($fh);
return($self);
}
my ($n1, $n2);
my ($buf1, $buf2) = ("", "");
- while (($n1 = read(F, $buf1, 4096))) {
+ while (($n1 = read($fh, $buf1, 4096))) {
while (substr($buf1, -1) eq "\015") {
- $n2 = read(F, $buf2, 4096);
+ $n2 = read($fh, $buf2, 4096);
_bail("Read failed") unless defined $n2;
last unless $n2;
$buf1 .= $buf2;
$self->add($buf1);
}
_bail("Read failed") unless defined $n1;
- close(F);
+ close($fh);
$self;
}
ref. L<http://www.csrc.nist.gov/pki/HashWorkshop/NIST%20Statement/Burr_Mar2005.html>
+=head1 BASE64 DIGESTS
+
+By convention, CPAN Digest modules do not pad their Base64 output.
+This means that Base64 digests contain no trailing "=" characters.
+Unfortunately, problems can occur when feeding such digests to other
+software that expects properly padded Base64 encodings.
+
+For the time being, any necessary padding must be done by the user.
+Fortunately, the rule for accomplishing it is straightforward: if the
+length of a Base64-encoded digest isn't a multiple of 4, simply append
+1 or more "=" characters to the end of the digest until it is:
+
+ while (length($b64_digest) % 4) {
+ $b64_digest .= '=';
+ }
+
+To illustrate, I<sha256_base64("abc")> is computed to be
+
+ ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0
+
+which has a length of 43. So, the properly padded version is
+
+ ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0=
+
=head1 EXPORT
None by default.
Logically joins the arguments into a single string, and returns
its SHA-1/224/256/384/512 digest encoded as a Base64 string.
+It's important to note that the resulting string does B<not> contain
+the padding characters typical of Base64 encodings. This omission is
+deliberate, and is done to maintain compatibility with the family of
+CPAN Digest modules. See L</"BASE64 DIGESTS"> for details.
+
=back
I<OOP style>
This method is inherited if L<Digest::base> is installed on your
system. Otherwise, a functionally equivalent substitute is used.
+It's important to note that the resulting string does B<not> contain
+the padding characters typical of Base64 encodings. This omission is
+deliberate, and is done to maintain compatibility with the family of
+CPAN Digest modules. See L</"BASE64 DIGESTS"> for details.
+
=back
I<HMAC-SHA-1/224/256/384/512>
arguments are allowed, provided that I<$key> is the last argument
in the list.
+It's important to note that the resulting string does B<not> contain
+the padding characters typical of Base64 encodings. This omission is
+deliberate, and is done to maintain compatibility with the family of
+CPAN Digest modules. See L</"BASE64 DIGESTS"> for details.
+
=back
=head1 SEE ALSO
#
# Copyright (C) 2003-2006 Mark Shelor, All Rights Reserved
#
- # Version: 5.41
- # Sat Jun 3 01:50:46 MST 2006
+ # Version: 5.42
+ # Mon Jul 24 04:04:40 MST 2006
=head1 NAME
-b, --binary read files in binary mode (default on DOS/Windows)
-c, --check check SHA sums against given list
-p, --portable read files in portable mode
- produces same digest on Windows/Unix/MacOS 9
+ produces same digest on Windows/Unix/Mac
-t, --text read files in text mode (default)
The following two options are useful only when verifying checksums:
use strict;
use Getopt::Long;
-my $VERSION = "5.41";
+my $VERSION = "5.42";
# Try to use Digest::SHA, since it's faster. If not installed,
my $MOD_SECOND = "Digest::SHA::PurePerl";
my $module = $MOD_PREFER;
-eval "require $module";
+eval "require $module"; ## no critic
if ($@) {
$module = $MOD_SECOND;
- eval "require $module";
+ eval "require $module"; ## no critic
die "Unable to find $MOD_PREFER or $MOD_SECOND\n" if $@;
}
-b, --binary read files in binary mode (default on DOS/Windows)
-c, --check check SHA sums against given list
-p, --portable read files in portable mode
- produces same digest on Windows/Unix/MacOS 9
+ produces same digest on Windows/Unix/Mac
-t, --text read files in text mode (default)
The following two options are useful only when verifying checksums:
my ($fh, $sum, $fname, $rsp);
die "shasum: $checkfile: $!\n"
- unless open($fh, "<$checkfile");
+ unless open($fh, q{<}, $checkfile);
while (<$fh>) {
s/\s+$//;
($sum, $modesym, $fname) = /^(\S+) (.)(.*)$/;
*
* Copyright (C) 2003-2006 Mark Shelor, All Rights Reserved
*
- * Version: 5.41
- * Sat Jun 3 01:50:46 MST 2006
+ * Version: 5.42
+ * Mon Jul 24 04:04:40 MST 2006
*
*/
*
* Copyright (C) 2003-2006 Mark Shelor, All Rights Reserved
*
- * Version: 5.41
- * Sat Jun 3 01:50:46 MST 2006
+ * Version: 5.42
+ * Mon Jul 24 04:04:40 MST 2006
*
*/
*
* Copyright (C) 2003-2006 Mark Shelor, All Rights Reserved
*
- * Version: 5.41
- * Sat Jun 3 01:50:46 MST 2006
+ * Version: 5.42
+ * Mon Jul 24 04:04:40 MST 2006
*
*/
*
* Copyright (C) 2003-2006 Mark Shelor, All Rights Reserved
*
- * Version: 5.41
- * Sat Jun 3 01:50:46 MST 2006
+ * Version: 5.42
+ * Mon Jul 24 04:04:40 MST 2006
*
*/
use Test;
+use strict;
BEGIN {
if ($ENV{PERL_CORE}) {
# test OO methods using first two SHA-256 vectors from NIST
-my $temp = File::Spec->catfile(dirname($0), "oo.tmp");
-my $file = File::Spec->canonpath($temp);
-open(FILE, ">$file");
-binmode(FILE);
-print FILE "bcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
-close(FILE);
+my $file = File::Spec->catfile(dirname($0), "oo.tmp");
+open(my $fh, q{>}, $file);
+binmode($fh);
+print $fh "bcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
+close($fh);
my $ctx = Digest::SHA->new()->reset("SHA-256")->new();
$ctx->add_bits("a", 5)->add_bits("001");
ok($ctx->clone->add("b", "c")->b64digest, $rsp);
$rsp = shift(@vec);
-open(FILE, "<$file");
-binmode(FILE);
-ok($ctx->clone->addfile(*FILE)->hexdigest, $rsp);
-close(FILE);
- # use indirect filehandle
+ # test addfile with bareword filehandle
+
+open(FILE, "<$file"); ## no critic
+binmode(FILE); ## no critic
+ok($ctx->clone->addfile(*FILE)->hexdigest, $rsp); ## no critic
+close(FILE); ## no critic
-open(my $fh, "<$file");
+ # test addfile with indirect filehandle
+
+undef($fh); open($fh, q{<}, $file);
binmode($fh);
ok($ctx->clone->addfile($fh)->hexdigest, $rsp);
close($fh);
# test addfile portable mode
-open(FILE, ">$file");
-binmode(FILE);
-print FILE "abc\012" x 2048; # using UNIX newline
-close(FILE);
+undef($fh); open($fh, q{>}, $file);
+binmode($fh);
+print $fh "abc\012" x 2048; # using UNIX newline
+close($fh);
ok($ctx->new(1)->addfile($file, "p")->hexdigest,
"d449e19c1b0b0c191294c8dc9fa2e4a6ff77fc51");
-open(FILE, ">$file");
-binmode(FILE);
-print FILE "abc\015\012" x 2048; # using DOS/Windows newline
-close(FILE);
+undef($fh); open($fh, q{>}, $file);
+binmode($fh);
+print $fh "abc\015\012" x 2048; # using DOS/Windows newline
+close($fh);
ok($ctx->new(1)->addfile($file, "p")->hexdigest,
"d449e19c1b0b0c191294c8dc9fa2e4a6ff77fc51");
-open(FILE, ">$file");
-binmode(FILE);
-print FILE "abc\015" x 2048; # using Apple/Mac newline
-close(FILE);
+undef($fh); open($fh, q{>}, $file);
+binmode($fh);
+print $fh "abc\015" x 2048; # using Apple/Mac newline
+close($fh);
ok($ctx->new(1)->addfile($file, "p")->hexdigest,
"d449e19c1b0b0c191294c8dc9fa2e4a6ff77fc51");
BEGIN {
my $file = File::Spec->catfile(dirname($0), "nist", "bit-hashes.sha1");
- my $datafile = File::Spec->canonpath($file);
- open(F, $datafile);
- while (<F>) {
+ open(my $fh, q{<}, $file);
+ while (<$fh>) {
next unless (/^[0-9A-F]/);
s/[\r\n]+$//;
if (/\^$/) {
push(@hashes, $_);
}
}
- close(F);
+ close($fh);
plan tests => scalar(@hashes);
}
my $ctx = Digest::SHA->new(1);
my $file = File::Spec->catfile(dirname($0), "nist", "bit-messages.sha1");
-my $datafile = File::Spec->canonpath($file);
-open(F, $datafile);
-while (<F>) {
+open(my $fh, q{<}, $file);
+while (<$fh>) {
$type3 = 1 if (/Type 3/);
$type3 = 0 if (/^<D/);
next unless (/^[0-9^ ]/);
$line = "";
}
}
-close(F);
+close($fh);
BEGIN {
my $file = File::Spec->catfile(dirname($0), "nist", "byte-hashes.sha1");
- my $datafile = File::Spec->canonpath($file);
- open(F, $datafile);
- while (<F>) {
+ open(my $fh, q{<}, $file);
+ while (<$fh>) {
next unless (/^[0-9A-F]/);
s/[\r\n]+$//;
if (/\^$/) {
push(@hashes, $_);
}
}
- close(F);
+ close($fh);
plan tests => scalar(@hashes);
}
my $ctx = Digest::SHA->new(1);
my $file = File::Spec->catfile(dirname($0), "nist", "byte-messages.sha1");
-my $datafile = File::Spec->canonpath($file);
-open(F, $datafile);
-while (<F>) {
+open(my $fh, q{<}, $file);
+while (<$fh>) {
$type3 = 1 if (/Type 3/);
$type3 = 0 if (/^<D/);
next unless (/^[0-9^ ]/);
$line = "";
}
}
-close(F);
+close($fh);
plan tests => scalar(@vec110) / 2 + scalar(@vec011) / 2;
}
-my $fileSTATE110 = File::Spec->catfile(dirname($0), "gillogly", "state.110");
-my $fileSTATE011 = File::Spec->catfile(dirname($0), "gillogly", "state.011");
-
-my $STATE110 = File::Spec->canonpath($fileSTATE110);
-my $STATE011 = File::Spec->canonpath($fileSTATE011);
+my $STATE110 = File::Spec->catfile(dirname($0), "gillogly", "state.110");
+my $STATE011 = File::Spec->catfile(dirname($0), "gillogly", "state.011");
my $reps = 1 << 14;
my $loops = int(1431655764 / $reps);
my @ext = (1, 256, 384, 512);
my $data = "a" x 990000;
my $skip;
-my $tmpname = File::Spec->catfile(dirname($0), "dumpload.tmp");
-my $tmpfile = File::Spec->canonpath($tmpname);
+my $tmpfile = File::Spec->catfile(dirname($0), "dumpload.tmp");
for (my $i = 0; $i < @sharsp; $i++) {
$skip = 0;
my $digest;
unless ($skip) {
my $state;
- my $file;
- my $filename;
- $filename = File::Spec->catfile(dirname($0),
+ my $file = File::Spec->catfile(dirname($0),
"state", "state.$ext[$i]");
- $file = File::Spec->canonpath($filename);
unless ($state = Digest::SHA->load($file)) {
$state = Digest::SHA->new($ext[$i]);
$state->add($data);
BEGIN { plan tests => 1 }
-my $filename = File::Spec->catfile(dirname($0), "ireland.tmp");
-my $file = File::Spec->canonpath($filename);
-open(F, ">$file"); while (<DATA>) { print F $_ } close(F);
+my $file = File::Spec->catfile(dirname($0), "ireland.tmp");
+open(my $fh, q{>}, $file); while (<DATA>) { print $fh $_ } close($fh);
my $data = "a" x 1000000;
my $vec = "b9045a713caed5dff3d3b783e98d1ce5778d8bc331ee4119d707072312af06a7";