From: Russ Cox Date: Thu, 21 May 2009 01:16:38 +0000 (-0700) Subject: hash reorg. X-Git-Tag: weekly.2009-11-06~1587 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=140aed9ab7a528b98f891c19eafd6db4a2de9c98;p=gostls13.git hash reorg. * new package hash defining interfaces Hash and Hash32. * adler32 and crc32 return Hash32 instead of specific types. * adler32 and crc32 provide non-allocating methods for single slices. * sha1 and md5 move to crypto, return Hash. * sum.go, a simple test program, moves to /usr/rsc. * refresh Make.deps R=r DELTA=1908 (935 added, 923 deleted, 50 changed) OCL=29095 CL=29135 --- diff --git a/src/lib/Make.deps b/src/lib/Make.deps index d75dbf22e5..30083f2631 100644 --- a/src/lib/Make.deps +++ b/src/lib/Make.deps @@ -3,6 +3,8 @@ bufio.install: io.install os.install utf8.install container/vector.install: crypto/aes.install: os.install crypto/block.install: fmt.install io.install os.install +crypto/md5.install: hash.install os.install +crypto/sha1.install: hash.install os.install exec.install: os.install strings.install exvar.install: fmt.install http.install io.install log.install strconv.install sync.install flag.install: fmt.install os.install strconv.install @@ -12,11 +14,9 @@ go/doc.install: container/vector.install fmt.install go/ast.install go/token.ins go/parser.install: container/vector.install fmt.install go/ast.install go/scanner.install go/token.install io.install os.install go/scanner.install: go/token.install strconv.install unicode.install utf8.install go/token.install: strconv.install -hash/adler32.install: os.install -hash/crc32.install: os.install -hash/md5.install: os.install -hash/sha1.install: os.install -hash/sum.install: flag.install fmt.install hash/adler32.install hash/crc32.install hash/md5.install hash/sha1.install io.install os.install +hash.install: io.install +hash/adler32.install: hash.install os.install +hash/crc32.install: hash.install os.install http.install: bufio.install fmt.install io.install log.install net.install os.install path.install strconv.install strings.install utf8.install io.install: os.install sync.install json.install: container/vector.install fmt.install io.install math.install reflect.install strconv.install strings.install utf8.install diff --git a/src/lib/Makefile b/src/lib/Makefile index 75c6758d36..d258e1adbc 100644 --- a/src/lib/Makefile +++ b/src/lib/Makefile @@ -19,6 +19,8 @@ DIRS=\ container/vector\ crypto/aes\ crypto/block\ + crypto/md5\ + crypto/sha1\ exec\ exvar\ flag\ @@ -28,11 +30,9 @@ DIRS=\ go/parser\ go/scanner\ go/token\ + hash\ hash/adler32\ hash/crc32\ - hash/md5\ - hash/sha1\ - hash/sum\ http\ io\ json\ @@ -65,6 +65,9 @@ TEST=\ bufio\ container/vector\ crypto/aes\ + crypto/block\ + crypto/md5\ + crypto/sha1\ exec\ exvar\ flag\ @@ -73,8 +76,6 @@ TEST=\ go/scanner\ hash/adler32\ hash/crc32\ - hash/md5\ - hash/sha1\ http\ io\ json\ diff --git a/src/lib/hash/md5/Makefile b/src/lib/crypto/md5/Makefile similarity index 98% rename from src/lib/hash/md5/Makefile rename to src/lib/crypto/md5/Makefile index f9320faaf5..8867b84a52 100644 --- a/src/lib/hash/md5/Makefile +++ b/src/lib/crypto/md5/Makefile @@ -5,7 +5,7 @@ # DO NOT EDIT. Automatically generated by gobuild. # gobuild -m >Makefile -D=/hash/ +D=/crypto/ O_arm=5 O_amd64=6 diff --git a/src/lib/hash/md5/md5.go b/src/lib/crypto/md5/md5.go similarity index 72% rename from src/lib/hash/md5/md5.go rename to src/lib/crypto/md5/md5.go index de8d34d33f..f8b8dda2fb 100644 --- a/src/lib/hash/md5/md5.go +++ b/src/lib/crypto/md5/md5.go @@ -5,7 +5,13 @@ // This package implements the MD5 hash algorithm as defined in RFC 1321. package md5 -import "os" +import ( + "hash"; + "os"; +) + +// The size of an MD5 checksum in bytes. +const Size = 16; const ( _Chunk = 64; @@ -16,29 +22,35 @@ const ( _Init3 = 0x10325476; ) -// Digest represents the partial evaluation of a checksum. -type Digest struct { +// digest represents the partial evaluation of a checksum. +type digest struct { s [4]uint32; x [_Chunk]byte; nx int; len uint64; } -// NewDigest creates a new Digest. -func NewDigest() *Digest { - d := new(Digest); +func (d *digest) Reset() { d.s[0] = _Init0; d.s[1] = _Init1; d.s[2] = _Init2; d.s[3] = _Init3; +} + +// New returns a Hash computing the SHA1 checksum. +func New() hash.Hash { + d := new(digest); + d.Reset(); return d; } -func _Block(dig *Digest, p []byte) int +func (d *digest) Size() int { + return Size; +} + +func _Block(dig *digest, p []byte) int -// Write updates the Digest with the incremental checksum generated by p. -// It returns the number of bytes written; err is always nil. -func (d *Digest) Write(p []byte) (nn int, err os.Error) { +func (d *digest) Write(p []byte) (nn int, err os.Error) { nn = len(p); d.len += uint64(nn); if d.nx > 0 { @@ -67,9 +79,7 @@ func (d *Digest) Write(p []byte) (nn int, err os.Error) { return; } -// Sum returns the MD5 checksum of the data written to the Digest -// in the form of an array of 16 bytes in big-endian order. -func (d *Digest) Sum() []byte { +func (d *digest) Sum() []byte { // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. len := d.len; var tmp [64]byte; diff --git a/src/lib/hash/md5/md5_test.go b/src/lib/crypto/md5/md5_test.go similarity index 99% rename from src/lib/hash/md5/md5_test.go rename to src/lib/crypto/md5/md5_test.go index 80271978d3..e557742cc7 100644 --- a/src/lib/hash/md5/md5_test.go +++ b/src/lib/crypto/md5/md5_test.go @@ -6,7 +6,7 @@ package md5 import ( "fmt"; - "hash/md5"; + "crypto/md5"; "io"; "testing"; ) @@ -53,7 +53,7 @@ var golden = []md5Test { func TestGolden(t *testing.T) { for i := 0; i < len(golden); i++ { g := golden[i]; - c := NewDigest(); + c := New(); io.WriteString(c, g.in); s := fmt.Sprintf("%x", c.Sum()); if s != g.out { diff --git a/src/lib/hash/md5/md5block.go b/src/lib/crypto/md5/md5block.go similarity index 98% rename from src/lib/hash/md5/md5block.go rename to src/lib/crypto/md5/md5block.go index 0fc210a2cf..2776c8795c 100644 --- a/src/lib/hash/md5/md5block.go +++ b/src/lib/crypto/md5/md5block.go @@ -8,7 +8,7 @@ package md5 -import "hash/md5" +import "crypto/md5" // table[i] = int((1<<32) * abs(sin(i+1 radians))). var table = []uint32 { @@ -90,7 +90,7 @@ var shift2 = []uint { 5, 9, 14, 20 }; var shift3 = []uint { 4, 11, 16, 23 }; var shift4 = []uint { 6, 10, 15, 21 }; -func _Block(dig *Digest, p []byte) int { +func _Block(dig *digest, p []byte) int { a := dig.s[0]; b := dig.s[1]; c := dig.s[2]; diff --git a/src/lib/hash/sha1/Makefile b/src/lib/crypto/sha1/Makefile similarity index 98% rename from src/lib/hash/sha1/Makefile rename to src/lib/crypto/sha1/Makefile index 0f09259b48..f4e1ea0dd5 100644 --- a/src/lib/hash/sha1/Makefile +++ b/src/lib/crypto/sha1/Makefile @@ -5,7 +5,7 @@ # DO NOT EDIT. Automatically generated by gobuild. # gobuild -m >Makefile -D=/hash/ +D=/crypto/ O_arm=5 O_amd64=6 diff --git a/src/lib/hash/sha1/sha1.go b/src/lib/crypto/sha1/sha1.go similarity index 72% rename from src/lib/hash/sha1/sha1.go rename to src/lib/crypto/sha1/sha1.go index 2b83eb9b0c..c5f702264f 100644 --- a/src/lib/hash/sha1/sha1.go +++ b/src/lib/crypto/sha1/sha1.go @@ -5,7 +5,13 @@ // This package implements the SHA1 hash algorithm as defined in RFC 3174. package sha1 -import "os" +import ( + "hash"; + "os"; +) + +// The size of a SHA1 checksum in bytes. +const Size = 20; const ( _Chunk = 64; @@ -17,30 +23,36 @@ const ( _Init4 = 0xC3D2E1F0; ) -// Digest represents the partial evaluation of a checksum. -type Digest struct { +// digest represents the partial evaluation of a checksum. +type digest struct { h [5]uint32; x [_Chunk]byte; nx int; len uint64; } -// NewDigest creates a new Digest. -func NewDigest() *Digest { - d := new(Digest); +func (d *digest) Reset() { d.h[0] = _Init0; d.h[1] = _Init1; d.h[2] = _Init2; d.h[3] = _Init3; d.h[4] = _Init4; +} + +// New returns a Hash computing the SHA1 checksum. +func New() hash.Hash { + d := new(digest); + d.Reset(); return d; } -func _Block(dig *Digest, p []byte) int +func (d *digest) Size() int { + return Size; +} + +func _Block(dig *digest, p []byte) int -// Write updates the Digest with the incremental checksum generated by p. -// It returns the number of bytes written; err is always nil. -func (d *Digest) Write(p []byte) (nn int, err os.Error) { +func (d *digest) Write(p []byte) (nn int, err os.Error) { nn = len(p); d.len += uint64(nn); if d.nx > 0 { @@ -69,9 +81,7 @@ func (d *Digest) Write(p []byte) (nn int, err os.Error) { return; } -// Sum returns the SHA-1 checksum of the data written to the Digest -// in the form of an array of 20 bytes in big-endian order. -func (d *Digest) Sum() []byte { +func (d *digest) Sum() []byte { // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. len := d.len; var tmp [64]byte; diff --git a/src/lib/hash/sha1/sha1_test.go b/src/lib/crypto/sha1/sha1_test.go similarity index 99% rename from src/lib/hash/sha1/sha1_test.go rename to src/lib/crypto/sha1/sha1_test.go index 103b218e9b..3ac9a47ec2 100644 --- a/src/lib/hash/sha1/sha1_test.go +++ b/src/lib/crypto/sha1/sha1_test.go @@ -8,7 +8,7 @@ package sha1 import ( "fmt"; - "hash/sha1"; + "crypto/sha1"; "io"; "testing"; ) @@ -55,7 +55,7 @@ var golden = []sha1Test { func TestGolden(t *testing.T) { for i := 0; i < len(golden); i++ { g := golden[i]; - c := NewDigest(); + c := New(); io.WriteString(c, g.in); s := fmt.Sprintf("%x", c.Sum()); if s != g.out { diff --git a/src/lib/hash/sha1/sha1block.go b/src/lib/crypto/sha1/sha1block.go similarity index 96% rename from src/lib/hash/sha1/sha1block.go rename to src/lib/crypto/sha1/sha1block.go index 51bfd6d092..01ddd9506a 100644 --- a/src/lib/hash/sha1/sha1block.go +++ b/src/lib/crypto/sha1/sha1block.go @@ -8,7 +8,7 @@ package sha1 -import "hash/sha1" +import "crypto/sha1" const ( _K0 = 0x5A827999; @@ -17,7 +17,7 @@ const ( _K3 = 0xCA62C1D6; ) -func _Block(dig *Digest, p []byte) int { +func _Block(dig *digest, p []byte) int { var w [80]uint32; n := 0; diff --git a/src/lib/hash/adler32/adler32.go b/src/lib/hash/adler32/adler32.go index 2b3bd6f85a..fbf9177f89 100644 --- a/src/lib/hash/adler32/adler32.go +++ b/src/lib/hash/adler32/adler32.go @@ -11,28 +11,42 @@ // significant-byte first (network) order. package adler32 -import "os" +import ( + "hash"; + "os"; +) const ( mod = 65521; ) -// Digest represents the partial evaluation of a checksum. -type Digest struct { +// The size of an Adler-32 checksum in bytes. +const Size = 4; + +// digest represents the partial evaluation of a checksum. +type digest struct { // invariant: (a < mod && b < mod) || a <= b // invariant: a + b + 255 <= 0xffffffff a, b uint32; } -// NewDigest creates a new Digest. -func NewDigest() *Digest { - return &Digest{1, 0}; +func (d *digest) Reset() { + d.a, d.b = 1, 0; +} + +// New returns a new Hash32 computing the Adler-32 checksum. +func New() hash.Hash32 { + d := new(digest); + d.Reset(); + return d; +} + +func (d *digest) Size() int { + return Size; } -// Write updates the Digest with the incremental checksum generated by p. -// It returns the number of bytes written; err is always nil. -func (d *Digest) Write(p []byte) (nn int, err os.Error) { - a, b := d.a, d.b; +// Add p to the running checksum a, b. +func update(a, b uint32, p []byte) (aa, bb uint32) { for i := 0; i < len(p); i++ { a += uint32(p[i]); b += a; @@ -45,13 +59,11 @@ func (d *Digest) Write(p []byte) (nn int, err os.Error) { // invariant: a + b + 255 <= 2 * b + 255 <= 0xffffffff } } - d.a, d.b = a, b; - return len(p), nil + return a, b; } -// Sum32 returns the 32-bit Adler-32 checksum of the data written to the Digest. -func (d *Digest) Sum32() uint32 { - a, b := d.a, d.b; +// Return the 32-bit checksum corresponding to a, b. +func finish(a, b uint32) uint32 { if b >= mod { a %= mod; b %= mod; @@ -59,9 +71,16 @@ func (d *Digest) Sum32() uint32 { return b<<16 | a; } -// Sum returns the 32-bit Adler-32 checksum of the data written to the Digest -// in the form of an array of 4 bytes in big-endian order. -func (d *Digest) Sum() []byte { +func (d *digest) Write(p []byte) (nn int, err os.Error) { + d.a, d.b = update(d.a, d.b, p); + return len(p), nil; +} + +func (d *digest) Sum32() uint32 { + return finish(d.a, d.b); +} + +func (d *digest) Sum() []byte { p := make([]byte, 4); s := d.Sum32(); p[0] = byte(s>>24); @@ -70,3 +89,8 @@ func (d *Digest) Sum() []byte { p[3] = byte(s); return p; } + +// Checksum returns the Adler-32 checksum of data. +func Checksum(data []byte) uint32 { + return finish(update(1, 0, data)); +} diff --git a/src/lib/hash/adler32/adler32_test.go b/src/lib/hash/adler32/adler32_test.go index 90c0f6d39e..ce49a110bb 100644 --- a/src/lib/hash/adler32/adler32_test.go +++ b/src/lib/hash/adler32/adler32_test.go @@ -53,7 +53,7 @@ var golden = []_Adler32Test { func TestGolden(t *testing.T) { for i := 0; i < len(golden); i++ { g := golden[i]; - c := NewDigest(); + c := New(); io.WriteString(c, g.in); s := c.Sum32(); if s != g.out { diff --git a/src/lib/hash/crc32/crc32.go b/src/lib/hash/crc32/crc32.go index 57fa6af816..7fc3966aea 100644 --- a/src/lib/hash/crc32/crc32.go +++ b/src/lib/hash/crc32/crc32.go @@ -6,7 +6,13 @@ // See http://en.wikipedia.org/wiki/Cyclic_redundancy_check for information. package crc32 -import "os" +import ( + "hash"; + "os"; +) + +// The size of a CRC-32 checksum in bytes. +const Size = 4; // Predefined polynomials. const ( @@ -26,12 +32,11 @@ const ( ) // Table is a 256-word table representing the polynomial for efficient processing. -// TODO(rsc): Change to [256]uint32 once 6g can handle it. -type Table []uint32 +type Table [256]uint32 // MakeTable returns the Table constructed from the specified polynomial. -func MakeTable(poly uint32) Table { - t := make(Table, 256); +func MakeTable(poly uint32) *Table { + t := new(Table); for i := 0; i < 256; i++ { crc := uint32(i); for j := 0; j < 8; j++ { @@ -49,44 +54,51 @@ func MakeTable(poly uint32) Table { // IEEETable is the table for the IEEE polynomial. var IEEETable = MakeTable(IEEE); -// Digest represents the partial evaluation of a checksum. -type Digest struct { +// digest represents the partial evaluation of a checksum. +type digest struct { crc uint32; - tab Table; + tab *Table; +} + +// New creates a new Hash computing the CRC-32 checksum +// using the polynomial represented by the Table. +func New(tab *Table) hash.Hash32 { + return &digest{0, tab}; +} + +// NewIEEE creates a new Hash computing the CRC-32 checksum +// using the IEEE polynomial. +func NewIEEE() hash.Hash32 { + return New(IEEETable); } -// NewDigest creates a new Digest for the checksum based on -// the polynomial represented by the Table. -func NewDigest(tab Table) *Digest { - return &Digest{0, tab}; +func (d *digest) Size() int { + return Size; } -// NewIEEEDigest creates a new Digest for the checksum based on -// the IEEE polynomial. -func NewIEEEDigest() *Digest { - return NewDigest(IEEETable); +func (d *digest) Reset() { + d.crc = 0; } -// Write updates the Digest with the incremental checksum generated by p. -// It returns the number of bytes written; err is always nil. -func (d *Digest) Write(p []byte) (n int, err os.Error) { - crc := d.crc ^ 0xFFFFFFFF; - tab := d.tab; +func update(crc uint32, tab *Table, p []byte) uint32 { + crc ^= 0xFFFFFFFF; for i := 0; i < len(p); i++ { crc = tab[byte(crc) ^ p[i]] ^ (crc >> 8); } - d.crc = crc ^ 0xFFFFFFFF; + crc ^= 0xFFFFFFFF; + return crc; +} + +func (d *digest) Write(p []byte) (n int, err os.Error) { + d.crc = update(d.crc, d.tab, p); return len(p), nil; } -// Sum32 returns the CRC-32 checksum of the data written to the Digest. -func (d *Digest) Sum32() uint32 { +func (d *digest) Sum32() uint32 { return d.crc } -// Sum returns the CRC-32 checksum of the data written to the Digest -// in the form of an array of 4 bytes in big-endian order. -func (d *Digest) Sum() []byte { +func (d *digest) Sum() []byte { p := make([]byte, 4); s := d.Sum32(); p[0] = byte(s>>24); @@ -96,4 +108,14 @@ func (d *Digest) Sum() []byte { return p; } +// Checksum returns the CRC-32 checksum of data +// using the polynomial represented by the Table. +func Checksum(data []byte, tab *Table) uint32 { + return update(0, tab, data); +} +// ChecksumIEEE returns the CRC-32 checksum of data +// using the IEEE polynomial. +func ChecksumIEEE(data []byte) uint32 { + return update(0, IEEETable, data); +} diff --git a/src/lib/hash/crc32/crc32_test.go b/src/lib/hash/crc32/crc32_test.go index 2d675468d0..c037da600e 100644 --- a/src/lib/hash/crc32/crc32_test.go +++ b/src/lib/hash/crc32/crc32_test.go @@ -52,7 +52,7 @@ var golden = []_Crc32Test { func TestGolden(t *testing.T) { for i := 0; i < len(golden); i++ { g := golden[i]; - c := NewIEEEDigest(); + c := NewIEEE(); io.WriteString(c, g.in); s := c.Sum32(); if s != g.out {