Upgrade Digest-SHA from 5.86 to 5.87
authorSteve Hay <steve.m.hay@googlemail.com>
Tue, 18 Feb 2014 08:51:49 +0000 (08:51 +0000)
committerSteve Hay <steve.m.hay@googlemail.com>
Tue, 18 Feb 2014 08:51:49 +0000 (08:51 +0000)
12 files changed:
MANIFEST
Porting/Maintainers.pl
cpan/Digest-SHA/SHA.xs
cpan/Digest-SHA/lib/Digest/SHA.pm
cpan/Digest-SHA/shasum
cpan/Digest-SHA/src/sha.c
cpan/Digest-SHA/src/sha.h
cpan/Digest-SHA/t/gglong.t
cpan/Digest-SHA/t/hmacsha.t
cpan/Digest-SHA/t/ireland.t
cpan/Digest-SHA/t/state.t [moved from cpan/Digest-SHA/t/dumpload.t with 85% similarity]
pod/perldelta.pod

index de0b0c9..f704a71 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -740,7 +740,6 @@ cpan/Digest-SHA/src/sha.h           Digest::SHA extension
 cpan/Digest-SHA/t/allfcns.t            See if Digest::SHA works
 cpan/Digest-SHA/t/base64.t             See if Digest::SHA works
 cpan/Digest-SHA/t/bitbuf.t             See if Digest::SHA works
-cpan/Digest-SHA/t/dumpload.t           See if Digest::SHA works
 cpan/Digest-SHA/t/fips180-4.t          See if Digest::SHA works
 cpan/Digest-SHA/t/fips198.t            See if Digest::SHA works
 cpan/Digest-SHA/t/gglong.t             See if Digest::SHA works
@@ -756,6 +755,7 @@ cpan/Digest-SHA/t/sha224.t          See if Digest::SHA works
 cpan/Digest-SHA/t/sha256.t             See if Digest::SHA works
 cpan/Digest-SHA/t/sha384.t             See if Digest::SHA works
 cpan/Digest-SHA/t/sha512.t             See if Digest::SHA works
+cpan/Digest-SHA/t/state.t              See if Digest::SHA works
 cpan/Digest-SHA/t/unicode.t
 cpan/Digest-SHA/t/woodbury.t           See if Digest::SHA works
 cpan/Digest-SHA/typemap                        Typemap for Digest::SHA
index 44770d4..36bf0c6 100755 (executable)
@@ -385,7 +385,7 @@ use File::Glob qw(:case);
     },
 
     'Digest::SHA' => {
-        'DISTRIBUTION' => 'MSHELOR/Digest-SHA-5.86.tar.gz',
+        'DISTRIBUTION' => 'MSHELOR/Digest-SHA-5.87.tar.gz',
         'FILES'        => q[cpan/Digest-SHA],
         'EXCLUDED'     => [
             qw( t/pod.t
index 3caf8ef..743337f 100644 (file)
@@ -35,20 +35,11 @@ CODE:
        RETVAL = shaclose(s);
        sv_setiv(SvRV(ST(0)), 0);
 
-int
-shadump(file, s)
-       char *  file
-       SHA *   s
-
 SHA *
 shadup(s)
        SHA *   s
 
 SHA *
-shaload(file)
-       char *  file
-
-SHA *
 shaopen(alg)
        int     alg
 
@@ -88,7 +79,7 @@ ALIAS:
        Digest::SHA::sha512256_base64 = 20
 PREINIT:
        int i;
-       unsigned char *data;
+       UCHR *data;
        STRLEN len;
        SHA *state;
        char *result;
@@ -96,7 +87,7 @@ PPCODE:
        if ((state = shaopen(ix2alg[ix])) == NULL)
                XSRETURN_UNDEF;
        for (i = 0; i < items; i++) {
-               data = (unsigned char *) (SvPVbyte(ST(i), len));
+               data = (UCHR *) (SvPVbyte(ST(i), len));
                while (len > MAX_WRITE_SIZE) {
                        shawrite(data, MAX_WRITE_SIZE << 3, state);
                        data += MAX_WRITE_SIZE;
@@ -107,8 +98,8 @@ PPCODE:
        shafinish(state);
        len = 0;
        if (ix % 3 == 0) {
-               result = (char *) shadigest(state);
-               len = shadsize(state);
+               result = (char *) digcpy(state);
+               len = state->digestlen;
        }
        else if (ix % 3 == 1)
                result = shahex(state);
@@ -144,17 +135,17 @@ ALIAS:
        Digest::SHA::hmac_sha512256_base64 = 20
 PREINIT:
        int i;
-       unsigned char *key;
-       unsigned char *data;
+       UCHR *key;
+       UCHR *data;
        STRLEN len;
        HMAC *state;
        char *result;
 PPCODE:
-       key = (unsigned char *) (SvPVbyte(ST(items-1), len));
+       key = (UCHR *) (SvPVbyte(ST(items-1), len));
        if ((state = hmacopen(ix2alg[ix], key, len)) == NULL)
                XSRETURN_UNDEF;
        for (i = 0; i < items - 1; i++) {
-               data = (unsigned char *) (SvPVbyte(ST(i), len));
+               data = (UCHR *) (SvPVbyte(ST(i), len));
                while (len > MAX_WRITE_SIZE) {
                        hmacwrite(data, MAX_WRITE_SIZE << 3, state);
                        data += MAX_WRITE_SIZE;
@@ -165,8 +156,8 @@ PPCODE:
        hmacfinish(state);
        len = 0;
        if (ix % 3 == 0) {
-               result = (char *) hmacdigest(state);
-               len = shadsize(state->osha);
+               result = (char *) digcpy(state->osha);
+               len = state->osha->digestlen;
        }
        else if (ix % 3 == 1)
                result = hmachex(state);
@@ -186,8 +177,10 @@ PREINIT:
        SHA *state;
        int result;
 PPCODE:
+       if (!sv_isa(self, "Digest::SHA"))
+               XSRETURN_UNDEF;
        state = INT2PTR(SHA *, SvIV(SvRV(SvRV(self))));
-       result = ix ? shaalg(state) : shadsize(state) << 3;
+       result = ix ? state->alg : state->digestlen << 3;
        ST(0) = sv_2mortal(newSViv(result));
        XSRETURN(1);
 
@@ -196,13 +189,15 @@ add(self, ...)
        SV *    self
 PREINIT:
        int i;
-       unsigned char *data;
+       UCHR *data;
        STRLEN len;
        SHA *state;
 PPCODE:
+       if (!sv_isa(self, "Digest::SHA"))
+               XSRETURN_UNDEF;
        state = INT2PTR(SHA *, SvIV(SvRV(SvRV(self))));
        for (i = 1; i < items; i++) {
-               data = (unsigned char *) (SvPVbyte(ST(i), len));
+               data = (UCHR *) (SvPVbyte(ST(i), len));
                while (len > MAX_WRITE_SIZE) {
                        shawrite(data, MAX_WRITE_SIZE << 3, state);
                        data += MAX_WRITE_SIZE;
@@ -224,12 +219,14 @@ PREINIT:
        SHA *state;
        char *result;
 PPCODE:
+       if (!sv_isa(self, "Digest::SHA"))
+               XSRETURN_UNDEF;
        state = INT2PTR(SHA *, SvIV(SvRV(SvRV(self))));
        shafinish(state);
        len = 0;
        if (ix == 0) {
-               result = (char *) shadigest(state);
-               len = shadsize(state);
+               result = (char *) digcpy(state);
+               len = state->digestlen;
        }
        else if (ix == 1)
                result = shahex(state);
@@ -238,3 +235,54 @@ PPCODE:
        ST(0) = sv_2mortal(newSVpv(result, len));
        sharewind(state);
        XSRETURN(1);
+
+void
+_getstate(self)
+       SV *    self
+PREINIT:
+       SHA *state;
+       UCHR buf[256];
+       UCHR *ptr = buf;
+PPCODE:
+       if (!sv_isa(self, "Digest::SHA"))
+               XSRETURN_UNDEF;
+       state = INT2PTR(SHA *, SvIV(SvRV(SvRV(self))));
+       memcpy(ptr, digcpy(state), state->alg <= SHA256 ? 32 : 64);
+       ptr += state->alg <= SHA256 ? 32 : 64;
+       memcpy(ptr, state->block, state->alg <= SHA256 ? 64 : 128);
+       ptr += state->alg <= SHA256 ? 64 : 128;
+       ptr = w32mem(ptr, state->blockcnt);
+       ptr = w32mem(ptr, state->lenhh);
+       ptr = w32mem(ptr, state->lenhl);
+       ptr = w32mem(ptr, state->lenlh);
+       ptr = w32mem(ptr, state->lenll);
+       ST(0) = sv_2mortal(newSVpv((char *) buf, ptr - buf));
+       XSRETURN(1);
+
+void
+_putstate(self, ...)
+       SV *    self
+PREINIT:
+       UINT bc;
+       STRLEN len;
+       SHA *state;
+       UCHR *data;
+PPCODE:
+       if (!sv_isa(self, "Digest::SHA"))
+               XSRETURN_UNDEF;
+       state = INT2PTR(SHA *, SvIV(SvRV(SvRV(self))));
+       data = (UCHR *) SvPV(ST(1), len);
+       if (len != (state->alg <= SHA256 ? 116 : 212))
+               XSRETURN_UNDEF;
+       data = statecpy(state, data);
+       memcpy(state->block, data, state->blocksize >> 3);
+       data += (state->blocksize >> 3);
+       bc = memw32(data), data += 4;
+       if (bc >= (state->alg <= SHA256 ? 512 : 1024))
+               XSRETURN_UNDEF;
+       state->blockcnt = bc;
+       state->lenhh = memw32(data), data += 4;
+       state->lenhl = memw32(data), data += 4;
+       state->lenlh = memw32(data), data += 4;
+       state->lenll = memw32(data);
+       XSRETURN(1);
index d8c9aec..c13e30d 100644 (file)
@@ -7,7 +7,7 @@ use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
 use Fcntl;
 use integer;
 
-$VERSION = '5.86';
+$VERSION = '5.87';
 
 require Exporter;
 require DynaLoader;
@@ -161,12 +161,94 @@ sub Addfile {
        $self;
 }
 
+sub getstate {
+       my $self = shift;
+
+       my $alg = $self->algorithm or return;
+       my $state = $self->_getstate or return;
+       my $nD = $alg <= 256 ?  8 :  16;
+       my $nH = $alg <= 256 ? 32 :  64;
+       my $nB = $alg <= 256 ? 64 : 128;
+       my($H, $block, $blockcnt, $lenhh, $lenhl, $lenlh, $lenll) =
+               $state =~ /^(.{$nH})(.{$nB})(.{4})(.{4})(.{4})(.{4})(.{4})$/s;
+       for ($alg, $H, $block, $blockcnt, $lenhh, $lenhl, $lenlh, $lenll) {
+               return unless defined $_;
+       }
+
+       my @s = ();
+       push(@s, "alg:" . $alg);
+       push(@s, "H:" . join(":", unpack("H*", $H) =~ /.{$nD}/g));
+       push(@s, "block:" . join(":", unpack("H*", $block) =~ /.{2}/g));
+       push(@s, "blockcnt:" . unpack("N", $blockcnt));
+       push(@s, "lenhh:" . unpack("N", $lenhh));
+       push(@s, "lenhl:" . unpack("N", $lenhl));
+       push(@s, "lenlh:" . unpack("N", $lenlh));
+       push(@s, "lenll:" . unpack("N", $lenll));
+       join("\n", @s) . "\n";
+}
+
+sub putstate {
+       my $class = shift;
+       my $state = shift;
+
+       my %s = ();
+       for (split(/\n/, $state)) {
+               s/^\s+//;
+               s/\s+$//;
+               next if (/^(#|$)/);
+               my @f = split(/[:\s]+/);
+               my $tag = shift(@f);
+               $s{$tag} = join('', @f);
+       }
+
+       # H and block may contain arbitrary values, but check everything else
+       grep { $_ == $s{'alg'} } (1,224,256,384,512,512224,512256) or return;
+       length($s{'H'}) == ($s{'alg'} <= 256 ? 64 : 128) or return;
+       length($s{'block'}) == ($s{'alg'} <= 256 ? 128 : 256) or return;
+       {
+               no integer;
+               for (qw(blockcnt lenhh lenhl lenlh lenll)) {
+                       0 <= $s{$_} or return;
+                       $s{$_} <= 4294967295 or return;
+               }
+               $s{'blockcnt'} < ($s{'alg'} <= 256 ? 512 : 1024) or return;
+       }
+
+       my $state_packed = (
+               pack("H*", $s{'H'}) .
+               pack("H*", $s{'block'}) .
+               pack("N", $s{'blockcnt'}) .
+               pack("N", $s{'lenhh'}) .
+               pack("N", $s{'lenhl'}) .
+               pack("N", $s{'lenlh'}) .
+               pack("N", $s{'lenll'})
+       );
+
+       if (ref($class)) {      # instance method
+               if ($$class) { shaclose($$class); $$class = undef }
+               return unless $$class = shaopen($s{'alg'});
+               return $class->_putstate($state_packed);
+       }
+       else {
+               my $sha = shaopen($s{'alg'}) or return;
+               my $self = \$sha;
+               bless($self, $class);
+               return $self->_putstate($state_packed);
+       }
+}
+
 sub dump {
        my $self = shift;
        my $file = shift;
 
-       $file = "" unless defined $file;
-       shadump($file, $$self) || return;
+       my $state = $self->getstate or return;
+       $file = "-" if (!defined($file) || $file eq "");
+
+       local *FH;
+       open(FH, "> $file") or return;
+       print FH $state;
+       close(FH);
+
        return($self);
 }
 
@@ -174,16 +256,14 @@ sub load {
        my $class = shift;
        my $file = shift;
 
-       $file = "" unless defined $file;
-       if (ref($class)) {      # instance method
-               if ($$class) { shaclose($$class); $$class = undef }
-               return unless $$class = shaload($file);
-               return($class);
-       }
-       my $state = shaload($file) || return;
-       my $self = \$state;
-       bless($self, $class);
-       return($self);
+       $file = "-" if (!defined($file) || $file eq "");
+       
+       local *FH;
+       open(FH, "< $file") or return;
+       my $str = join('', <FH>);
+       close(FH);
+
+       $class->putstate($str);
 }
 
 Digest::SHA->bootstrap($VERSION);
@@ -225,9 +305,9 @@ In programs:
        $sha->add_bits($bits);
        $sha->add_bits($data, $nbits);
 
-       $sha_copy = $sha->clone;        # if needed, make copy of
-       $sha->dump($file);              #       current digest state,
-       $sha->load($file);              #       or save it on disk
+       $sha_copy = $sha->clone;        # make copy of digest object
+       $state = $sha->getstate;        # save current state to string
+       $sha->putstate($state);         # restore previous $state
 
        $digest = $sha->digest;         # compute digest
        $digest = $sha->hexdigest;
@@ -302,16 +382,15 @@ Note that for larger bit-strings, it's more efficient to use the
 two-argument version I<add_bits($data, $nbits)>, where I<$data> is
 in the customary packed binary format used for Perl strings.
 
-The module also lets you save intermediate SHA states to disk, or
-display them on standard output.  The I<dump()> method generates
-portable, human-readable text describing the current state of
-computation.  You can subsequently retrieve the file with I<load()>
-to resume where the calculation left off.
+The module also lets you save intermediate SHA states to a string.  The
+I<getstate()> method generates portable, human-readable text describing
+the current state of computation.  You can subsequently restore that
+state with I<putstate()> to resume where the calculation left off.
 
 To see what a state description looks like, just run the following:
 
        use Digest::SHA;
-       Digest::SHA->new->add("Shaw" x 1962)->dump;
+       print Digest::SHA->new->add("Shaw" x 1962)->getstate;
 
 As an added convenience, the Digest::SHA module offers routines to
 calculate keyed hashes using the HMAC-SHA-1/224/256/384/512
@@ -565,21 +644,30 @@ a convenient way to calculate the digest values of partial-byte data by
 using files, rather than having to write programs using the I<add_bits>
 method.
 
+=item B<getstate>
+
+Returns a string containing a portable, human-readable representation
+of the current SHA state.
+
+=item B<putstate($str)>
+
+Returns a Digest::SHA object representing the SHA state contained
+in I<$str>.  The format of I<$str> matches the format of the output
+produced by method I<getstate>.  If called as a class method, a new
+object is created; if called as an instance method, the object is reset
+to the state contained in I<$str>.
+
 =item B<dump($filename)>
 
-Provides persistent storage of intermediate SHA states by writing
-a portable, human-readable representation of the current state to
-I<$filename>.  If the argument is missing, or equal to the empty
-string, the state information will be written to STDOUT.
+Writes the output of I<getstate> to I<$filename>.  If the argument is
+missing, or equal to the empty string, the state information will be
+written to STDOUT.
 
 =item B<load($filename)>
 
-Returns a Digest::SHA object representing the intermediate SHA
-state that was previously dumped to I<$filename>.  If called as a
-class method, a new object is created; if called as an instance
-method, the object is reset to the state contained in I<$filename>.
-If the argument is missing, or equal to the empty string, the state
-information will be read from STDIN.
+Returns a Digest::SHA object that results from calling I<putstate> on
+the contents of I<$filename>.  If the argument is missing, or equal to
+the empty string, the state information will be read from STDIN.
 
 =item B<digest>
 
index 0026a25..606393e 100644 (file)
@@ -4,8 +4,8 @@
        ##
        ## Copyright (C) 2003-2014 Mark Shelor, All Rights Reserved
        ##
-       ## Version: 5.86
-       ## Thu Jan 30 08:24:28 MST 2014
+       ## Version: 5.87
+       ## Mon Feb 17 16:42:02 MST 2014
 
        ## shasum SYNOPSIS adapted from GNU Coreutils sha1sum.
        ## Add an "-a" option for algorithm selection, a "-p"
@@ -97,7 +97,7 @@ use strict;
 use Fcntl;
 use Getopt::Long;
 
-my $VERSION = "5.86";
+my $VERSION = "5.87";
 
 
        ## Try to use Digest::SHA.  If not installed, use the slower
index 9554c25..a848072 100644 (file)
@@ -5,8 +5,8 @@
  *
  * Copyright (C) 2003-2014 Mark Shelor, All Rights Reserved
  *
- * Version: 5.86
- * Thu Jan 30 08:24:28 MST 2014
+ * Version: 5.87
+ * Mon Feb 17 16:42:02 MST 2014
  *
  */
 
@@ -222,18 +222,30 @@ static void sha256(SHA *s, UCHR *block)           /* SHA-224/256 transform */
                        : ((nbytes) / 3) * 4 + ((nbytes) % 3) + 1)
 
 /* w32mem: writes 32-bit word to memory in big-endian order */
-static void w32mem(UCHR *mem, W32 w32)
+static UCHR *w32mem(UCHR *mem, W32 w32)
 {
        int i;
 
        for (i = 0; i < 4; i++)
                *mem++ = (UCHR) (SR32(w32, 24-i*8) & 0xff);
+       return(mem);
+}
+
+/* memw32: returns 32-bit word from memory written in big-endian order */
+static W32 memw32(UCHR *mem)
+{
+       int i;
+       W32 w = 0;
+
+       for (i = 0; i < 4; i++)
+               w = (w << 8) + *mem++;
+       return(w);
 }
 
 /* digcpy: writes current state to digest buffer */
-static void digcpy(SHA *s)
+static UCHR *digcpy(SHA *s)
 {
-       UINT i;
+       int i;
        UCHR *d = s->digest;
        W32 *p32 = (W32 *) s->H;
        W64 *p64 = (W64 *) s->H;
@@ -246,6 +258,24 @@ static void digcpy(SHA *s)
                        w32mem(d, (W32) ((*p64 >> 16) >> 16));
                        w32mem(d+4, (W32) (*p64++ & SHA32_MAX));
                }
+       return(s->digest);
+}
+
+/* statecpy: writes buffer to current state (opposite of digcpy) */
+static UCHR *statecpy(SHA *s, UCHR *buf)
+{
+       int i;
+       W32 *p32 = (W32 *) s->H;
+       W64 *p64 = (W64 *) s->H;
+
+       if (s->alg <= SHA256)
+               for (i = 0; i < 8; i++, buf += 4)
+                       *p32++ = memw32(buf);
+       else
+               for (i = 0; i < 8; i++, buf += 8)
+                       *p64++ = ((W64) memw32(buf) << 32) +
+                                       memw32(buf+4);
+       return(buf);
 }
 
 #define SHA_INIT(algo, transform)                                      \
@@ -416,13 +446,6 @@ static void shafinish(SHA *s)
        s->sha(s, s->block);
 }
 
-/* shadigest: returns pointer to current digest (binary) */
-static UCHR *shadigest(SHA *s)
-{
-       digcpy(s);
-       return(s->digest);
-}
-
 /* xmap: translation map for hexadecimal encoding */
 static char xmap[] =
        "0123456789abcdef";
@@ -434,11 +457,11 @@ static char *shahex(SHA *s)
        char *h;
        UCHR *d;
 
-       digcpy(s);
+       d = digcpy(s);
        s->hex[0] = '\0';
        if (HEXLEN((size_t) s->digestlen) >= sizeof(s->hex))
                return(s->hex);
-       for (i = 0, h = s->hex, d = s->digest; i < s->digestlen; i++) {
+       for (i = 0, h = s->hex; i < s->digestlen; i++) {
                *h++ = xmap[(*d >> 4) & 0x0f];
                *h++ = xmap[(*d++   ) & 0x0f];
        }
@@ -473,11 +496,11 @@ static char *shabase64(SHA *s)
        UCHR *q;
        char out[5];
 
-       digcpy(s);
+       q = digcpy(s);
        s->base64[0] = '\0';
        if (B64LEN((size_t) s->digestlen) >= sizeof(s->base64))
                return(s->base64);
-       for (n = s->digestlen, q = s->digest; n > 3; n -= 3, q += 3) {
+       for (n = s->digestlen; n > 3; n -= 3, q += 3) {
                encbase64(q, 3, out);
                strcat(s->base64, out);
        }
@@ -486,18 +509,6 @@ static char *shabase64(SHA *s)
        return(s->base64);
 }
 
-/* shadsize: returns length of digest in bytes */
-static int shadsize(SHA *s)
-{
-       return(s->digestlen);
-}
-
-/* shaalg: returns which SHA algorithm is being used */
-static int shaalg(SHA *s)
-{
-       return(s->alg);
-}
-
 /* shadup: duplicates current digest object */
 static SHA *shadup(SHA *s)
 {
@@ -510,153 +521,6 @@ static SHA *shadup(SHA *s)
        return(p);
 }
 
-/* shadump: dumps digest object to a human-readable ASCII file */
-static int shadump(char *file, SHA *s)
-{
-       int i, j;
-       SHA_FILE *f;
-       UCHR *p = shadigest(s);
-
-       if (file == NULL || strlen(file) == 0)
-               f = SHA_stdout();
-       else if ((f = SHA_open(file, "w")) == NULL)
-               return(0);
-       SHA_fprintf(f, "alg:%d\nH", s->alg);
-       for (i = 0; i < 8; i++)
-               for (j = 0; j < (s->alg <= 256 ? 4 : 8); j++)
-                       SHA_fprintf(f, "%s%02x", j==0 ? ":" : "", *p++);
-       SHA_fprintf(f, "\nblock");
-       for (i = 0; i < (int) (s->blocksize >> 3); i++)
-               SHA_fprintf(f, ":%02x", s->block[i]);
-       SHA_fprintf(f, "\nblockcnt:%u\n", s->blockcnt);
-       SHA_fprintf(f, "lenhh:%lu\nlenhl:%lu\nlenlh:%lu\nlenll:%lu\n",
-               (ULNG) LO32(s->lenhh), (ULNG) LO32(s->lenhl),
-               (ULNG) LO32(s->lenlh), (ULNG) LO32(s->lenll));
-       if (f != SHA_stdout())
-               SHA_close(f);
-       return(1);
-}
-
-/* fgetstr: reads (and returns pointer to) next line of file */
-static char *fgetstr(char *line, UINT maxsize, SHA_FILE *f)
-{
-       char *p;
-
-       if (SHA_feof(f) || maxsize == 0)
-               return(NULL);
-       for (p = line; !SHA_feof(f) && maxsize > 1; maxsize--)
-               if ((*p++ = SHA_getc(f)) == '\n')
-                       break;
-       *p = '\0';
-       return(line);
-}
-
-/* empty: returns true if line contains only whitespace characters */
-static int empty(char *line)
-{
-       char *p;
-
-       for (p = line; *p; p++)
-               if (!isspace(*p))
-                       return(0);
-       return(1);
-}
-
-/* getval: null-terminates field value, and sets pointer to rest of line */
-static char *getval(char *line, char **pprest)
-{
-       char *p, *v;
-
-       for (v = line; *v == ':' || isspace(*v); v++)
-               ;
-       for (p = v; *p; p++) {
-               if (*p == ':' || isspace(*p)) {
-                       *p++ = '\0';
-                       break;
-               }
-       }
-       *pprest = p;
-       return(p == v ? NULL : v);
-}
-
-/* types of values present in dump file */
-#define T_C 1                  /* character */
-#define T_I 2                  /* normal integer */
-#define T_L 3                  /* 32-bit value */
-#define T_Q 4                  /* 64-bit value */
-
-/* ldvals: checks next line in dump file against tag, and loads values */
-static int ldvals(
-       SHA_FILE *f,
-       const char *tag,
-       int type,
-       void *pval,
-       int reps,
-       int base)
-{
-       char *p, *pr, line[512];
-       UCHR *pc = (UCHR *) pval; UINT *pi = (UINT *) pval;
-       W32  *pl = (W32  *) pval; W64  *pq = (W64  *) pval;
-
-       while ((p = fgetstr(line, sizeof(line), f)) != NULL)
-               if (line[0] != '#' && !empty(line))
-                       break;
-       if (p == NULL || strcmp(getval(line, &pr), tag) != 0)
-               return(0);
-       while (reps-- > 0) {
-               if ((p = getval(pr, &pr)) == NULL)
-                       return(1);
-               switch (type) {
-               case T_C: *pc++ = (UCHR) strtoul(p, NULL, base); break;
-               case T_I: *pi++ = (UINT) strtoul(p, NULL, base); break;
-               case T_L: *pl++ = (W32 ) strtoul(p, NULL, base); break;
-               case T_Q: *pq++ = (W64 ) strto64(p            ); break;
-               }
-       }
-       return(1);
-}
-
-/* closeall: closes dump file and de-allocates digest object */
-static SHA *closeall(SHA_FILE *f, SHA *s)
-{
-       if (f != NULL && f != SHA_stdin())
-               SHA_close(f);
-       if (s != NULL)
-               shaclose(s);
-       return(NULL);
-}
-
-/* shaload: creates digest object corresponding to contents of dump file */
-static SHA *shaload(char *file)
-{
-       int alg;
-       SHA *s = NULL;
-       SHA_FILE *f;
-
-       if (file == NULL || strlen(file) == 0)
-               f = SHA_stdin();
-       else if ((f = SHA_open(file, "r")) == NULL)
-               return(NULL);
-       if (
-               /* avoid parens by exploiting precedence of (type)&-> */
-               !ldvals(f,"alg",T_I,(VP)&alg,1,10)                      ||
-               ((s = shaopen(alg)) == NULL)                            ||
-               !ldvals(f,"H",alg<=SHA256?T_L:T_Q,(VP)s->H,8,16)        ||
-               !ldvals(f,"block",T_C,(VP)s->block,s->blocksize/8,16)   ||
-               !ldvals(f,"blockcnt",T_I,(VP)&s->blockcnt,1,10)         ||
-               (alg <= SHA256 && s->blockcnt >= SHA1_BLOCK_BITS)       ||
-               (alg >= SHA384 && s->blockcnt >= SHA384_BLOCK_BITS)     ||
-               !ldvals(f,"lenhh",T_L,(VP)&s->lenhh,1,10)               ||
-               !ldvals(f,"lenhl",T_L,(VP)&s->lenhl,1,10)               ||
-               !ldvals(f,"lenlh",T_L,(VP)&s->lenlh,1,10)               ||
-               !ldvals(f,"lenll",T_L,(VP)&s->lenll,1,10)
-       )
-               return(closeall(f, s));
-       if (f != SHA_stdin())
-               SHA_close(f);
-       return(s);
-}
-
 /* hmacopen: creates a new HMAC-SHA digest object */
 static HMAC *hmacopen(int alg, UCHR *key, UINT keylen)
 {
@@ -686,7 +550,7 @@ static HMAC *hmacopen(int alg, UCHR *key, UINT keylen)
                }
                shawrite(key, keylen * 8, h->ksha);
                shafinish(h->ksha);
-               memcpy(h->key, shadigest(h->ksha), h->ksha->digestlen);
+               memcpy(h->key, digcpy(h->ksha), h->ksha->digestlen);
                shaclose(h->ksha);
        }
        for (i = 0; i < h->osha->blocksize / 8; i++)
@@ -709,17 +573,11 @@ static ULNG hmacwrite(UCHR *bitstr, ULNG bitcnt, HMAC *h)
 static void hmacfinish(HMAC *h)
 {
        shafinish(h->isha);
-       shawrite(shadigest(h->isha), h->isha->digestlen * 8, h->osha);
+       shawrite(digcpy(h->isha), h->isha->digestlen * 8, h->osha);
        shaclose(h->isha);
        shafinish(h->osha);
 }
 
-/* hmacdigest: returns pointer to digest (binary) */
-static UCHR *hmacdigest(HMAC *h)
-{
-       return(shadigest(h->osha));
-}
-
 /* hmachex: returns pointer to digest (hexadecimal) */
 static char *hmachex(HMAC *h)
 {
index a50b25e..f79deb0 100644 (file)
@@ -5,8 +5,8 @@
  *
  * Copyright (C) 2003-2014 Mark Shelor, All Rights Reserved
  *
- * Version: 5.86
- * Thu Jan 30 08:24:28 MST 2014
+ * Version: 5.87
+ * Mon Feb 17 16:42:02 MST 2014
  *
  */
 
 #define SHA_newz       Newz
 #define SHA_free       Safefree
 
-#ifdef SHA_PerlIO
-       #define SHA_FILE                PerlIO
-       #define SHA_stdin()             PerlIO_stdin()
-       #define SHA_stdout()            PerlIO_stdout()
-       #define SHA_open                PerlIO_open
-       #define SHA_close               PerlIO_close
-       #define SHA_fprintf             PerlIO_printf
-       #define SHA_feof                PerlIO_eof
-       #define SHA_getc                PerlIO_getc
-#else
-       #define SHA_FILE                FILE
-       #define SHA_stdin()             stdin
-       #define SHA_stdout()            stdout
-       #define SHA_open                fopen
-       #define SHA_close               fclose
-       #define SHA_fprintf             fprintf
-       #define SHA_feof                feof
-       #define SHA_getc                fgetc
-#endif
-
 #define SHA1           1
 #define SHA224         224
 #define SHA256         256
index 12f7e5d..044799f 100644 (file)
@@ -1,7 +1,6 @@
 # Test against long bitwise vectors from Jim Gillogly and Francois Grieu
 
 use strict;
-use FileHandle;
 
 my $MODULE;
 
@@ -50,97 +49,42 @@ my @vec011 = (      # 011 rep 1431655764
        "0110", "a3d7438c589b0b932aa91cc2446f06df9abc73f0",
        "01101", "3eee3e1e28dede2ca444d68da5675b2faaab3203"
 );
-print "1..", scalar(@vec110) / 2 + scalar(@vec011) / 2, "\n";
 
-my $STATE110 = "gglong0.tmp";
-my $STATE011 = "gglong1.tmp";
-
-END { 1 while unlink $STATE110, $STATE011 }
-
-for ($STATE011, $STATE110) {
-       my $fh = FileHandle->new($_, "w");
-       for (1 .. 8) { my $line = <DATA>; print $fh $line }
-       $fh->close;
-}
-
-my $reps = 1 << 14;
-my $loops = int(1431655764 / $reps);
-my $rest = 3 * (1431655764 - $loops * $reps);
-
-sub state110 {
-       my $i;
-       my $state;
-       my $bitstr;
-
-       $state = $MODULE->new(1);
-       if (-r $STATE110) {
-               if ($state->load($STATE110)) {
-                       return($state);
-               }
-       }
-       $bitstr = pack("B*", "110" x $reps);
-       $state->reset;
-       for ($i = 0; $i < $loops; $i++) {
-               $state->add_bits($bitstr, 3 * $reps);
-       }
-       $state->add_bits($bitstr, $rest);
-       $state->dump($STATE110);
-       return($state);
-}
-
-sub state011 {
-       my $i;
-       my $state;
-       my $bitstr;
-
-       $state = $MODULE->new(1);
-       if (-r $STATE011) {
-               if ($state->load($STATE011)) {
-                       return($state);
-               }
-       }
-       $bitstr = pack("B*", "011" x $reps);
-       $state->reset;
-       for ($i = 0; $i < $loops; $i++) {
-               $state->add_bits($bitstr, 3 * $reps);
-       }
-       $state->add_bits($bitstr, $rest);
-       $state->dump($STATE011);
-       return($state);
-}
-
-my $i;
+my($STATE110, $STATE011) = ('', '');
+for (1 .. 8) { my $line = <DATA>; $STATE110 .= $line }
+for (1 .. 8) { my $line = <DATA>; $STATE011 .= $line }
 
 my $testnum = 1;
+print "1..", scalar(@vec110)/2 + scalar(@vec011)/2, "\n";
 
-my $state110 = state110();
-for ($i = 0; $i < @vec110/2; $i++) {
+my $state110 = $MODULE->putstate($STATE110);
+while (@vec110) {
        my $state = $state110->clone;
-       $state->add_bits($vec110[2*$i]);
-       print "not " unless $state->hexdigest eq $vec110[2*$i+1];
+       $state->add_bits(shift @vec110);
+       print "not " unless $state->hexdigest eq (shift @vec110);
        print "ok ", $testnum++, "\n";
 }
 
-my $state011 = state011();
-for ($i = 0; $i < @vec011/2; $i++) {
+my $state011 = $MODULE->putstate($STATE011);
+while (@vec011) {
        my $state = $state011->clone;
-       $state->add_bits($vec011[2*$i]);
-       print "not " unless $state->hexdigest eq $vec011[2*$i+1];
+       $state->add_bits(shift @vec011);
+       print "not " unless $state->hexdigest eq (shift @vec011);
        print "ok ", $testnum++, "\n";
 }
 
 __DATA__
 alg:1
-H:7950cbe2:86a45aa0:91ff7dff:29015b42:3912e764:00000000:00000000:00000000
-block:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6
+H:dfc51a14:87b4a4b7:ecf19acd:8cbbe40e:03a435f8:00000000:00000000:00000000
+block:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d
 blockcnt:508
 lenhh:0
 lenhl:0
 lenlh:0
 lenll:4294967292
 alg:1
-H:dfc51a14:87b4a4b7:ecf19acd:8cbbe40e:03a435f8:00000000:00000000:00000000
-block:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d
+H:7950cbe2:86a45aa0:91ff7dff:29015b42:3912e764:00000000:00000000:00000000
+block:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6:db:6d:b6
 blockcnt:508
 lenhh:0
 lenhl:0
index 593b2b1..47e65fe 100644 (file)
@@ -7,7 +7,7 @@ my $MODULE;
 BEGIN {
        $MODULE = (-d "src") ? "Digest::SHA" : "Digest::SHA::PurePerl";
        eval "require $MODULE" || die $@;
-       $MODULE->import(qw(hmac_sha256_hex));
+       $MODULE->import(qw(hmac_sha256 hmac_sha256_hex));
 }
 
 BEGIN {
@@ -51,11 +51,11 @@ my @out = (
        "6355ac22e890d0a3c8481a5ca4825bc884d3e7a1ff98a2fc2ac7d8e064c3b2e6"
 );
 
-       # do the first one using multi-argument data feed
+       # do first one using multi-argument data feed and binary output
 
 my $testnum = 1;
 my @args = split(//, shift @data);
-print "not " unless hmac_sha256_hex(@args, shift @keys) eq shift @out;
+print "not " unless hmac_sha256(@args, shift @keys) eq pack("H*", shift @out);
 print "ok ", $testnum++, "\n";
 
 while (@data) {
index 7de04f1..4649995 100644 (file)
@@ -1,5 +1,4 @@
 use strict;
-use FileHandle;
 
 my $MODULE;
 
@@ -19,20 +18,14 @@ BEGIN {
 # David Ireland's test vector - SHA-256 digest of "a" x 536870912
 
 # Adapted from Julius Duque's original script (t/24-ireland.tmp)
-#      - modified to use state cache via dump()/load() methods
+#      - modified to use state cache via putstate method
 
 print "1..1\n";
 
-my $tempfile = "ireland.tmp";
-END { 1 while unlink $tempfile }
-
-my $fh = FileHandle->new($tempfile, "w");
-while (<DATA>) { print $fh $_ }  close($fh);
-
 my $rsp = "b9045a713caed5dff3d3b783e98d1ce5778d8bc331ee4119d707072312af06a7";
 
 my $sha;
-if ($sha = $MODULE->load($tempfile)) {
+if ($sha = $MODULE->putstate(join('', <DATA>))) {
        $sha->add("aa");
        print "not " unless $sha->hexdigest eq $rsp;
        print "ok 1\n";
@@ -40,11 +33,19 @@ if ($sha = $MODULE->load($tempfile)) {
 else { print "not ok 1\n" }
 
 __DATA__
+
+       # Verify comments/blank lines ignored in state data
+                       
 alg:256
 H:dd75eb45:02d4f043:06b41193:6fda751d:73064db9:787d54e1:52dc3fe0:48687dfa
-block:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
+
+block:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:61:00:00
 blockcnt:496
+                            
 lenhh:0
 lenhl:0
 lenlh:0
+
+# Note: add'ing two more bytes will cause lenll (below) to overflow
+
 lenll:4294967280
similarity index 85%
rename from cpan/Digest-SHA/t/dumpload.t
rename to cpan/Digest-SHA/t/state.t
index a1f1cf4..83e2540 100644 (file)
@@ -1,5 +1,4 @@
 use strict;
-use FileHandle;
 
 my $MODULE;
 
@@ -26,18 +25,12 @@ my @sharsp = (
 my $numtests = scalar @sharsp;
 print "1..$numtests\n";
 
-my @tempfiles;
-END { 1 while unlink @tempfiles }
-
-my @statefiles = ("dl001.tmp", "dl256.tmp", "dl384.tmp", "dl512.tmp");
-for (@statefiles) {
-       push @tempfiles, $_;
-       my $fh = FileHandle->new($_, "w");
-       for (1 .. 8) { my $line = <DATA>; print $fh $line }
-       $fh->close;
-}
-my $tmpfile = "dumpload.tmp";
-push @tempfiles, $tmpfile;
+my($state001, $state256, $state384, $state512) = ('', '', '', '');
+for (1 .. 8) { my $line = <DATA>; $state001 .= $line }
+for (1 .. 8) { my $line = <DATA>; $state256 .= $line }
+for (1 .. 8) { my $line = <DATA>; $state384 .= $line }
+for (1 .. 8) { my $line = <DATA>; $state512 .= $line }
+my @states = ($state001, $state256, $state384, $state512);
 
 my @alg = (1, 256, 384, 512);
 my $data = "a" x 990000;
@@ -47,7 +40,6 @@ while (@sharsp) {
        my $skip = 0;
        my $alg = shift @alg;
        my $rsp = shift @sharsp;
-       my $file = shift @statefiles; push(@statefiles, $file);
        if ($alg == 384) { $skip = sha384_hex("") ? 0 : 1 }
        if ($alg == 512) { $skip = sha512_hex("") ? 0 : 1 }
        if ($skip) {
@@ -56,12 +48,12 @@ while (@sharsp) {
        }
        my $digest;
        my $state;
-       unless ($state = $MODULE->load($file)) {
+       unless ($state = $MODULE->putstate(shift @states)) {
                print "not ok ", $testnum++, "\n";
                next;
        }
-       $state->add_bits($data, 79984)->dump($tmpfile);
-       $state->load($tmpfile)->add_bits($data, 16);
+       my $statestr = $state->add_bits($data, 79984)->getstate;
+       $state->putstate($statestr)->add_bits($data, 16);
        $digest = $state->hexdigest;
        print "not " unless $digest eq $rsp;
        print "ok ", $testnum++, "\n";
index 2854b58..0934ede 100644 (file)
@@ -283,9 +283,11 @@ specified by its prototype.
 
 =item *
 
-L<Digest::SHA> has been upgraded from version 5.85 to 5.86.
+L<Digest::SHA> has been upgraded from version 5.85 to 5.87.
 
-Improved the performance of hexadecimal output functions.
+Improved the performance of hexadecimal output functions and simplified capture
+of intermediate SHA states, which can now be done via strings (see
+C<getstate()>/C<putstate()>).
 
 =item *