Skip Menu |

This queue is for tickets about the SHA256 CPAN distribution.

Report information
The Basics
Id: 24659
Status: new
Priority: 0/
Queue: SHA256

People
Owner: Nobody in particular
Requestors: ohcamacnahtanoj [...] comcast.net
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: (no value)



Subject: sha256-hash(a x 256) neq sha256-hash(a x 16 x 16)
Date: Mon, 29 Jan 2007 09:25:43 -0500
To: bug-SHA256 [...] rt.cpan.org
From: Jonathan <ohcamacnahtanoj [...] comcast.net>
Problem: The perl code below prints out "02d7160d 77e18c64 47be80c2 e355c7ed 43885452 71702c50 253b0914 c65ce5fe" "69f0a9fc 8364d2f7 887ab151 c3fce25e 82a084e0 3b297efa 48cefbaa 87689d3d" instead of printing out "02d7160d 77e18c64 47be80c2 e355c7ed 43885452 71702c50 253b0914 c65ce5fe" "02d7160d 77e18c64 47be80c2 e355c7ed 43885452 71702c50 253b0914 c65ce5fe" Versions of everything Digest::SHA256: v0.01b PERL: 5.8.3, i386-linux-thread-multi Machine: 32-bit i686 linux system. Code: #!/usr/bin/perl -w use strict; use Digest::SHA256; #Sample program to show how Digest::SHA256 is flawed. my $ctx = Digest::SHA256::new(256); #Add 256 bytes of "a", 16 bytes at a time. for(1..16){ $ctx->add("a" x 16); } print("The hash of 'a' x 256 (as obtained through 'a' x 16 x 16) is\n " . $ctx->hexdigest() . "\n\n"); $ctx->reset(); #Add 256 bytes all at once. $ctx->add("a" x 256); print("The hash of 'a' x 256 (as obtained through 'a' x 256 x 1) is\n " . $ctx->hexdigest() . "\n\n"); Writing a C version, and stepping through with GDB, the problem appears to be line 175: clo = TRUNC32(sha_info->count_lo + ((Uint8) count << 3)); The problem is the cast to Uint8, which truncates most of the length information when the size of each chunk is > 255 bytes. Replacing this cast with a something that preserves more information, such as Uint32, fixes the problem. If overflow is the reason for the cast, then it could be replaced with clo = TRUNC32(sha_info->count_lo + ( (count & 0x1FFFFFFF) << 3)); And the next line, sha_info->count_hi += (Uint8) count >> 29; is probably also wrong, although I can't test it.
#include <stdio.h> #include <stdlib.h> #include <string.h> //for memset() #include "sha.h" int main(int argc, char ** argv){ char data [300]; int i; memset(data, 'a', 299); data[299] = 0; SHA_INFO sha_struct; sha_init(&sha_struct); for(i = 0; i < 8; i++){ sha_update(&sha_struct, data, 16); } sha_final(&sha_struct); printf("The hash of 'a' x 128 (as obtained through 'a' x 16 x 8) is\n "); sha_print(&sha_struct); printf("\n"); sha_init(&sha_struct); sha_update(&sha_struct, data, 128); sha_final(&sha_struct); printf("The hash of 'a' x 128 (as obtained through 'a' x 128 x 1)is\n "); sha_print(&sha_struct); printf("\n"); sha_init(&sha_struct); for(i = 0; i < 16; i++){ sha_update(&sha_struct, data, 16); } sha_final(&sha_struct); printf("The hash of 'a' x 256 (as obtained through 'a' x 16 x 16) is\n "); sha_print(&sha_struct); printf("\n"); sha_init(&sha_struct); sha_update(&sha_struct, data, 256); sha_final(&sha_struct); printf("The hash of 'a' x 256 (as obtained through 'a' x 256 x 1) is\n "); sha_print(&sha_struct); printf("\n"); return 0; }
#!/usr/bin/perl -w use strict; use Digest::SHA256; #Sample program to show how Digest::SHA256 is flawed. my $ctx = Digest::SHA256::new(256); #Add 128 bytes of "a", 16 bytes at a time. for(1..8){ $ctx->add("a" x 16); } print("The hash of 'a' x 128 (as obtained through 'a' x 16 x 8) is\n " . $ctx->hexdigest() . "\n\n"); $ctx->reset(); #Add 128 bytes all at once. $ctx->add("a" x 128); print("The hash of 'a' x 128 (as obtained through 'a' x 128 x 1) is\n " . $ctx->hexdigest() . "\n\n"); #Note how the 2 values are identical. $ctx->reset(); #Add 256 bytes of "a", 16 bytes at a time. for(1..16){ $ctx->add("a" x 16); } print("The hash of 'a' x 256 (as obtained through 'a' x 16 x 16) is\n " . $ctx->hexdigest() . "\n\n"); $ctx->reset(); #Add 256 bytes all at once. $ctx->add("a" x 256); print("The hash of 'a' x 256 (as obtained through 'a' x 256 x 1) is\n " . $ctx->hexdigest() . "\n\n"); #Note the difference.