From 7123ec762fc9cd4e725f2217f832991d62f8fd68 Mon Sep 17 00:00:00 2001 From: Steve Hay Date: Tue, 18 Feb 2014 08:51:49 +0000 Subject: [PATCH] Upgrade Digest-SHA from 5.86 to 5.87 --- MANIFEST | 2 +- Porting/Maintainers.pl | 2 +- cpan/Digest-SHA/SHA.xs | 96 +++++++++---- cpan/Digest-SHA/lib/Digest/SHA.pm | 152 +++++++++++++++----- cpan/Digest-SHA/shasum | 6 +- cpan/Digest-SHA/src/sha.c | 224 ++++++------------------------ cpan/Digest-SHA/src/sha.h | 24 +--- cpan/Digest-SHA/t/gglong.t | 88 +++--------- cpan/Digest-SHA/t/hmacsha.t | 6 +- cpan/Digest-SHA/t/ireland.t | 21 +-- cpan/Digest-SHA/t/{dumpload.t => state.t} | 26 ++-- pod/perldelta.pod | 6 +- 12 files changed, 283 insertions(+), 370 deletions(-) rename cpan/Digest-SHA/t/{dumpload.t => state.t} (85%) diff --git a/MANIFEST b/MANIFEST index de0b0c9..f704a71 100644 --- 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 diff --git a/Porting/Maintainers.pl b/Porting/Maintainers.pl index 44770d4..36bf0c6 100755 --- a/Porting/Maintainers.pl +++ b/Porting/Maintainers.pl @@ -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 diff --git a/cpan/Digest-SHA/SHA.xs b/cpan/Digest-SHA/SHA.xs index 3caf8ef..743337f 100644 --- a/cpan/Digest-SHA/SHA.xs +++ b/cpan/Digest-SHA/SHA.xs @@ -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); diff --git a/cpan/Digest-SHA/lib/Digest/SHA.pm b/cpan/Digest-SHA/lib/Digest/SHA.pm index d8c9aec..c13e30d 100644 --- a/cpan/Digest-SHA/lib/Digest/SHA.pm +++ b/cpan/Digest-SHA/lib/Digest/SHA.pm @@ -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('', ); + 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, 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 method generates -portable, human-readable text describing the current state of -computation. You can subsequently retrieve the file with I -to resume where the calculation left off. +The module also lets you save intermediate SHA states to a string. The +I method generates portable, human-readable text describing +the current state of computation. You can subsequently restore that +state with I 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 method. +=item B + +Returns a string containing a portable, human-readable representation +of the current SHA state. + +=item B + +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. 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 -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 to I<$filename>. If the argument is +missing, or equal to the empty string, the state information will be +written to STDOUT. =item B -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 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 diff --git a/cpan/Digest-SHA/shasum b/cpan/Digest-SHA/shasum index 0026a25..606393e 100644 --- a/cpan/Digest-SHA/shasum +++ b/cpan/Digest-SHA/shasum @@ -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 diff --git a/cpan/Digest-SHA/src/sha.c b/cpan/Digest-SHA/src/sha.c index 9554c25..a848072 100644 --- a/cpan/Digest-SHA/src/sha.c +++ b/cpan/Digest-SHA/src/sha.c @@ -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) { diff --git a/cpan/Digest-SHA/src/sha.h b/cpan/Digest-SHA/src/sha.h index a50b25e..f79deb0 100644 --- a/cpan/Digest-SHA/src/sha.h +++ b/cpan/Digest-SHA/src/sha.h @@ -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 * */ @@ -106,26 +106,6 @@ #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 diff --git a/cpan/Digest-SHA/t/gglong.t b/cpan/Digest-SHA/t/gglong.t index 12f7e5d..044799f 100644 --- a/cpan/Digest-SHA/t/gglong.t +++ b/cpan/Digest-SHA/t/gglong.t @@ -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 = ; 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 = ; $STATE110 .= $line } +for (1 .. 8) { my $line = ; $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 diff --git a/cpan/Digest-SHA/t/hmacsha.t b/cpan/Digest-SHA/t/hmacsha.t index 593b2b1..47e65fe 100644 --- a/cpan/Digest-SHA/t/hmacsha.t +++ b/cpan/Digest-SHA/t/hmacsha.t @@ -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) { diff --git a/cpan/Digest-SHA/t/ireland.t b/cpan/Digest-SHA/t/ireland.t index 7de04f1..4649995 100644 --- a/cpan/Digest-SHA/t/ireland.t +++ b/cpan/Digest-SHA/t/ireland.t @@ -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 () { print $fh $_ } close($fh); - my $rsp = "b9045a713caed5dff3d3b783e98d1ce5778d8bc331ee4119d707072312af06a7"; my $sha; -if ($sha = $MODULE->load($tempfile)) { +if ($sha = $MODULE->putstate(join('', ))) { $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 diff --git a/cpan/Digest-SHA/t/dumpload.t b/cpan/Digest-SHA/t/state.t similarity index 85% rename from cpan/Digest-SHA/t/dumpload.t rename to cpan/Digest-SHA/t/state.t index a1f1cf4..83e2540 100644 --- a/cpan/Digest-SHA/t/dumpload.t +++ b/cpan/Digest-SHA/t/state.t @@ -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 = ; print $fh $line } - $fh->close; -} -my $tmpfile = "dumpload.tmp"; -push @tempfiles, $tmpfile; +my($state001, $state256, $state384, $state512) = ('', '', '', ''); +for (1 .. 8) { my $line = ; $state001 .= $line } +for (1 .. 8) { my $line = ; $state256 .= $line } +for (1 .. 8) { my $line = ; $state384 .= $line } +for (1 .. 8) { my $line = ; $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"; diff --git a/pod/perldelta.pod b/pod/perldelta.pod index 2854b58..0934ede 100644 --- a/pod/perldelta.pod +++ b/pod/perldelta.pod @@ -283,9 +283,11 @@ specified by its prototype. =item * -L has been upgraded from version 5.85 to 5.86. +L 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/C). =item * -- 2.7.4