From b9f26c32c39156ab654457fecdb5f73fb69e4064 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Tue, 19 Jan 2010 10:50:04 -0800 Subject: [PATCH] hash: document that Sum does not change hash state crypto/*: implement and test proper Sum Fixes #216. R=agl1 CC=golang-dev https://golang.org/cl/186210 --- src/pkg/crypto/md4/md4.go | 6 +++++- src/pkg/crypto/md4/md4_test.go | 13 +++++++++---- src/pkg/crypto/md5/md5.go | 6 +++++- src/pkg/crypto/md5/md5_test.go | 13 +++++++++---- src/pkg/crypto/sha1/sha1.go | 6 +++++- src/pkg/crypto/sha1/sha1_test.go | 13 +++++++++---- src/pkg/crypto/sha256/sha256.go | 6 +++++- src/pkg/crypto/sha256/sha256_test.go | 13 +++++++++---- src/pkg/hash/hash.go | 13 ++++++++++--- 9 files changed, 66 insertions(+), 23 deletions(-) diff --git a/src/pkg/crypto/md4/md4.go b/src/pkg/crypto/md4/md4.go index 6096ab9975..793cb16fda 100644 --- a/src/pkg/crypto/md4/md4.go +++ b/src/pkg/crypto/md4/md4.go @@ -76,7 +76,11 @@ func (d *digest) Write(p []byte) (nn int, err os.Error) { return } -func (d *digest) Sum() []byte { +func (d0 *digest) Sum() []byte { + // Make a copy of d0, so that caller can keep writing and summing. + d := new(digest) + *d = *d0 + // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. len := d.len var tmp [64]byte diff --git a/src/pkg/crypto/md4/md4_test.go b/src/pkg/crypto/md4/md4_test.go index 9cab80c63e..b883e64590 100644 --- a/src/pkg/crypto/md4/md4_test.go +++ b/src/pkg/crypto/md4/md4_test.go @@ -53,12 +53,17 @@ func TestGolden(t *testing.T) { for i := 0; i < len(golden); i++ { g := golden[i] c := New() - for j := 0; j < 2; j++ { - io.WriteString(c, g.in) + for j := 0; j < 3; j++ { + if j < 2 { + io.WriteString(c, g.in) + } else { + io.WriteString(c, g.in[0:len(g.in)/2]) + c.Sum() + io.WriteString(c, g.in[len(g.in)/2:]) + } s := fmt.Sprintf("%x", c.Sum()) if s != g.out { - t.Errorf("md4[%d](%s) = %s want %s", j, g.in, s, g.out) - t.FailNow() + t.Fatalf("md4[%d](%s) = %s want %s", j, g.in, s, g.out) } c.Reset() } diff --git a/src/pkg/crypto/md5/md5.go b/src/pkg/crypto/md5/md5.go index fd0984a418..90774af6b7 100644 --- a/src/pkg/crypto/md5/md5.go +++ b/src/pkg/crypto/md5/md5.go @@ -76,7 +76,11 @@ func (d *digest) Write(p []byte) (nn int, err os.Error) { return } -func (d *digest) Sum() []byte { +func (d0 *digest) Sum() []byte { + // Make a copy of d0 so that caller can keep writing and summing. + d := new(digest) + *d = *d0 + // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. len := d.len var tmp [64]byte diff --git a/src/pkg/crypto/md5/md5_test.go b/src/pkg/crypto/md5/md5_test.go index 7d5737b267..f6c2938370 100644 --- a/src/pkg/crypto/md5/md5_test.go +++ b/src/pkg/crypto/md5/md5_test.go @@ -53,12 +53,17 @@ func TestGolden(t *testing.T) { for i := 0; i < len(golden); i++ { g := golden[i] c := New() - for j := 0; j < 2; j++ { - io.WriteString(c, g.in) + for j := 0; j < 3; j++ { + if j < 2 { + io.WriteString(c, g.in) + } else { + io.WriteString(c, g.in[0:len(g.in)/2]) + c.Sum() + io.WriteString(c, g.in[len(g.in)/2:]) + } s := fmt.Sprintf("%x", c.Sum()) if s != g.out { - t.Errorf("md5[%d](%s) = %s want %s", j, g.in, s, g.out) - t.FailNow() + t.Fatalf("md5[%d](%s) = %s want %s", j, g.in, s, g.out) } c.Reset() } diff --git a/src/pkg/crypto/sha1/sha1.go b/src/pkg/crypto/sha1/sha1.go index 7209041ee1..98f0a06675 100644 --- a/src/pkg/crypto/sha1/sha1.go +++ b/src/pkg/crypto/sha1/sha1.go @@ -78,7 +78,11 @@ func (d *digest) Write(p []byte) (nn int, err os.Error) { return } -func (d *digest) Sum() []byte { +func (d0 *digest) Sum() []byte { + // Make a copy of d0 so that caller can keep writing and summing. + d := new(digest) + *d = *d0 + // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. len := d.len var tmp [64]byte diff --git a/src/pkg/crypto/sha1/sha1_test.go b/src/pkg/crypto/sha1/sha1_test.go index 8d4485282f..f18c7b0967 100644 --- a/src/pkg/crypto/sha1/sha1_test.go +++ b/src/pkg/crypto/sha1/sha1_test.go @@ -55,12 +55,17 @@ func TestGolden(t *testing.T) { for i := 0; i < len(golden); i++ { g := golden[i] c := New() - for j := 0; j < 2; j++ { - io.WriteString(c, g.in) + for j := 0; j < 3; j++ { + if j < 2 { + io.WriteString(c, g.in) + } else { + io.WriteString(c, g.in[0:len(g.in)/2]) + c.Sum() + io.WriteString(c, g.in[len(g.in)/2:]) + } s := fmt.Sprintf("%x", c.Sum()) if s != g.out { - t.Errorf("sha1[%d](%s) = %s want %s", j, g.in, s, g.out) - t.FailNow() + t.Fatalf("sha1[%d](%s) = %s want %s", j, g.in, s, g.out) } c.Reset() } diff --git a/src/pkg/crypto/sha256/sha256.go b/src/pkg/crypto/sha256/sha256.go index bacefc5637..df18e5fb26 100644 --- a/src/pkg/crypto/sha256/sha256.go +++ b/src/pkg/crypto/sha256/sha256.go @@ -84,7 +84,11 @@ func (d *digest) Write(p []byte) (nn int, err os.Error) { return } -func (d *digest) Sum() []byte { +func (d0 *digest) Sum() []byte { + // Make a copy of d0 so that caller can keep writing and summing. + d := new(digest) + *d = *d0 + // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. len := d.len var tmp [64]byte diff --git a/src/pkg/crypto/sha256/sha256_test.go b/src/pkg/crypto/sha256/sha256_test.go index 29c0bce601..4d0be6257d 100644 --- a/src/pkg/crypto/sha256/sha256_test.go +++ b/src/pkg/crypto/sha256/sha256_test.go @@ -55,12 +55,17 @@ func TestGolden(t *testing.T) { for i := 0; i < len(golden); i++ { g := golden[i] c := New() - for j := 0; j < 2; j++ { - io.WriteString(c, g.in) + for j := 0; j < 3; j++ { + if j < 2 { + io.WriteString(c, g.in) + } else { + io.WriteString(c, g.in[0:len(g.in)/2]) + c.Sum() + io.WriteString(c, g.in[len(g.in)/2:]) + } s := fmt.Sprintf("%x", c.Sum()) if s != g.out { - t.Errorf("sha256[%d](%s) = %s want %s", j, g.in, s, g.out) - t.FailNow() + t.Fatalf("sha256[%d](%s) = %s want %s", j, g.in, s, g.out) } c.Reset() } diff --git a/src/pkg/hash/hash.go b/src/pkg/hash/hash.go index 470e9a36c0..f5c08d3602 100644 --- a/src/pkg/hash/hash.go +++ b/src/pkg/hash/hash.go @@ -7,13 +7,20 @@ package hash import "io" // Hash is the common interface implemented by all hash functions. -// The Write method never returns an error. -// Sum returns the bytes of integer hash codes in big-endian order. type Hash interface { + // Write adds more data to the running hash. + // It never returns an error. io.Writer + + // Sum returns the current hash, without changing the + // underlying hash state. Sum() []byte + + // Reset resets the hash to one with zero bytes written. Reset() - Size() int // number of bytes Sum returns + + // Size returns the number of bytes Sum will return. + Size() int } // Hash32 is the common interface implemented by all 32-bit hash functions. -- 2.50.0