Commit 140aed9a authored by Russ Cox's avatar Russ Cox

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
parent b89a54e5
...@@ -3,6 +3,8 @@ bufio.install: io.install os.install utf8.install ...@@ -3,6 +3,8 @@ bufio.install: io.install os.install utf8.install
container/vector.install: container/vector.install:
crypto/aes.install: os.install crypto/aes.install: os.install
crypto/block.install: fmt.install io.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 exec.install: os.install strings.install
exvar.install: fmt.install http.install io.install log.install strconv.install sync.install exvar.install: fmt.install http.install io.install log.install strconv.install sync.install
flag.install: fmt.install os.install strconv.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 ...@@ -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/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/scanner.install: go/token.install strconv.install unicode.install utf8.install
go/token.install: strconv.install go/token.install: strconv.install
hash/adler32.install: os.install hash.install: io.install
hash/crc32.install: os.install hash/adler32.install: hash.install os.install
hash/md5.install: os.install hash/crc32.install: hash.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
http.install: bufio.install fmt.install io.install log.install net.install os.install path.install strconv.install strings.install utf8.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 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 json.install: container/vector.install fmt.install io.install math.install reflect.install strconv.install strings.install utf8.install
......
...@@ -19,6 +19,8 @@ DIRS=\ ...@@ -19,6 +19,8 @@ DIRS=\
container/vector\ container/vector\
crypto/aes\ crypto/aes\
crypto/block\ crypto/block\
crypto/md5\
crypto/sha1\
exec\ exec\
exvar\ exvar\
flag\ flag\
...@@ -28,11 +30,9 @@ DIRS=\ ...@@ -28,11 +30,9 @@ DIRS=\
go/parser\ go/parser\
go/scanner\ go/scanner\
go/token\ go/token\
hash\
hash/adler32\ hash/adler32\
hash/crc32\ hash/crc32\
hash/md5\
hash/sha1\
hash/sum\
http\ http\
io\ io\
json\ json\
...@@ -65,6 +65,9 @@ TEST=\ ...@@ -65,6 +65,9 @@ TEST=\
bufio\ bufio\
container/vector\ container/vector\
crypto/aes\ crypto/aes\
crypto/block\
crypto/md5\
crypto/sha1\
exec\ exec\
exvar\ exvar\
flag\ flag\
...@@ -73,8 +76,6 @@ TEST=\ ...@@ -73,8 +76,6 @@ TEST=\
go/scanner\ go/scanner\
hash/adler32\ hash/adler32\
hash/crc32\ hash/crc32\
hash/md5\
hash/sha1\
http\ http\
io\ io\
json\ json\
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
# DO NOT EDIT. Automatically generated by gobuild. # DO NOT EDIT. Automatically generated by gobuild.
# gobuild -m >Makefile # gobuild -m >Makefile
D=/hash/ D=/crypto/
O_arm=5 O_arm=5
O_amd64=6 O_amd64=6
......
...@@ -5,7 +5,13 @@ ...@@ -5,7 +5,13 @@
// This package implements the MD5 hash algorithm as defined in RFC 1321. // This package implements the MD5 hash algorithm as defined in RFC 1321.
package md5 package md5
import "os" import (
"hash";
"os";
)
// The size of an MD5 checksum in bytes.
const Size = 16;
const ( const (
_Chunk = 64; _Chunk = 64;
...@@ -16,29 +22,35 @@ const ( ...@@ -16,29 +22,35 @@ const (
_Init3 = 0x10325476; _Init3 = 0x10325476;
) )
// Digest represents the partial evaluation of a checksum. // digest represents the partial evaluation of a checksum.
type Digest struct { type digest struct {
s [4]uint32; s [4]uint32;
x [_Chunk]byte; x [_Chunk]byte;
nx int; nx int;
len uint64; len uint64;
} }
// NewDigest creates a new Digest. func (d *digest) Reset() {
func NewDigest() *Digest {
d := new(Digest);
d.s[0] = _Init0; d.s[0] = _Init0;
d.s[1] = _Init1; d.s[1] = _Init1;
d.s[2] = _Init2; d.s[2] = _Init2;
d.s[3] = _Init3; d.s[3] = _Init3;
}
// New returns a Hash computing the SHA1 checksum.
func New() hash.Hash {
d := new(digest);
d.Reset();
return d; 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. func (d *digest) Write(p []byte) (nn int, err os.Error) {
// It returns the number of bytes written; err is always nil.
func (d *Digest) Write(p []byte) (nn int, err os.Error) {
nn = len(p); nn = len(p);
d.len += uint64(nn); d.len += uint64(nn);
if d.nx > 0 { if d.nx > 0 {
...@@ -67,9 +79,7 @@ func (d *Digest) Write(p []byte) (nn int, err os.Error) { ...@@ -67,9 +79,7 @@ func (d *Digest) Write(p []byte) (nn int, err os.Error) {
return; return;
} }
// Sum returns the MD5 checksum of the data written to the Digest func (d *digest) Sum() []byte {
// in the form of an array of 16 bytes in big-endian order.
func (d *Digest) Sum() []byte {
// Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
len := d.len; len := d.len;
var tmp [64]byte; var tmp [64]byte;
......
...@@ -6,7 +6,7 @@ package md5 ...@@ -6,7 +6,7 @@ package md5
import ( import (
"fmt"; "fmt";
"hash/md5"; "crypto/md5";
"io"; "io";
"testing"; "testing";
) )
...@@ -53,7 +53,7 @@ var golden = []md5Test { ...@@ -53,7 +53,7 @@ var golden = []md5Test {
func TestGolden(t *testing.T) { func TestGolden(t *testing.T) {
for i := 0; i < len(golden); i++ { for i := 0; i < len(golden); i++ {
g := golden[i]; g := golden[i];
c := NewDigest(); c := New();
io.WriteString(c, g.in); io.WriteString(c, g.in);
s := fmt.Sprintf("%x", c.Sum()); s := fmt.Sprintf("%x", c.Sum());
if s != g.out { if s != g.out {
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
package md5 package md5
import "hash/md5" import "crypto/md5"
// table[i] = int((1<<32) * abs(sin(i+1 radians))). // table[i] = int((1<<32) * abs(sin(i+1 radians))).
var table = []uint32 { var table = []uint32 {
...@@ -90,7 +90,7 @@ var shift2 = []uint { 5, 9, 14, 20 }; ...@@ -90,7 +90,7 @@ var shift2 = []uint { 5, 9, 14, 20 };
var shift3 = []uint { 4, 11, 16, 23 }; var shift3 = []uint { 4, 11, 16, 23 };
var shift4 = []uint { 6, 10, 15, 21 }; 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]; a := dig.s[0];
b := dig.s[1]; b := dig.s[1];
c := dig.s[2]; c := dig.s[2];
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
# DO NOT EDIT. Automatically generated by gobuild. # DO NOT EDIT. Automatically generated by gobuild.
# gobuild -m >Makefile # gobuild -m >Makefile
D=/hash/ D=/crypto/
O_arm=5 O_arm=5
O_amd64=6 O_amd64=6
......
...@@ -5,7 +5,13 @@ ...@@ -5,7 +5,13 @@
// This package implements the SHA1 hash algorithm as defined in RFC 3174. // This package implements the SHA1 hash algorithm as defined in RFC 3174.
package sha1 package sha1
import "os" import (
"hash";
"os";
)
// The size of a SHA1 checksum in bytes.
const Size = 20;
const ( const (
_Chunk = 64; _Chunk = 64;
...@@ -17,30 +23,36 @@ const ( ...@@ -17,30 +23,36 @@ const (
_Init4 = 0xC3D2E1F0; _Init4 = 0xC3D2E1F0;
) )
// Digest represents the partial evaluation of a checksum. // digest represents the partial evaluation of a checksum.
type Digest struct { type digest struct {
h [5]uint32; h [5]uint32;
x [_Chunk]byte; x [_Chunk]byte;
nx int; nx int;
len uint64; len uint64;
} }
// NewDigest creates a new Digest. func (d *digest) Reset() {
func NewDigest() *Digest {
d := new(Digest);
d.h[0] = _Init0; d.h[0] = _Init0;
d.h[1] = _Init1; d.h[1] = _Init1;
d.h[2] = _Init2; d.h[2] = _Init2;
d.h[3] = _Init3; d.h[3] = _Init3;
d.h[4] = _Init4; d.h[4] = _Init4;
}
// New returns a Hash computing the SHA1 checksum.
func New() hash.Hash {
d := new(digest);
d.Reset();
return d; 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. func (d *digest) Write(p []byte) (nn int, err os.Error) {
// It returns the number of bytes written; err is always nil.
func (d *Digest) Write(p []byte) (nn int, err os.Error) {
nn = len(p); nn = len(p);
d.len += uint64(nn); d.len += uint64(nn);
if d.nx > 0 { if d.nx > 0 {
...@@ -69,9 +81,7 @@ func (d *Digest) Write(p []byte) (nn int, err os.Error) { ...@@ -69,9 +81,7 @@ func (d *Digest) Write(p []byte) (nn int, err os.Error) {
return; return;
} }
// Sum returns the SHA-1 checksum of the data written to the Digest func (d *digest) Sum() []byte {
// in the form of an array of 20 bytes in big-endian order.
func (d *Digest) Sum() []byte {
// Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
len := d.len; len := d.len;
var tmp [64]byte; var tmp [64]byte;
......
...@@ -8,7 +8,7 @@ package sha1 ...@@ -8,7 +8,7 @@ package sha1
import ( import (
"fmt"; "fmt";
"hash/sha1"; "crypto/sha1";
"io"; "io";
"testing"; "testing";
) )
...@@ -55,7 +55,7 @@ var golden = []sha1Test { ...@@ -55,7 +55,7 @@ var golden = []sha1Test {
func TestGolden(t *testing.T) { func TestGolden(t *testing.T) {
for i := 0; i < len(golden); i++ { for i := 0; i < len(golden); i++ {
g := golden[i]; g := golden[i];
c := NewDigest(); c := New();
io.WriteString(c, g.in); io.WriteString(c, g.in);
s := fmt.Sprintf("%x", c.Sum()); s := fmt.Sprintf("%x", c.Sum());
if s != g.out { if s != g.out {
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
package sha1 package sha1
import "hash/sha1" import "crypto/sha1"
const ( const (
_K0 = 0x5A827999; _K0 = 0x5A827999;
...@@ -17,7 +17,7 @@ const ( ...@@ -17,7 +17,7 @@ const (
_K3 = 0xCA62C1D6; _K3 = 0xCA62C1D6;
) )
func _Block(dig *Digest, p []byte) int { func _Block(dig *digest, p []byte) int {
var w [80]uint32; var w [80]uint32;
n := 0; n := 0;
......
...@@ -11,28 +11,42 @@ ...@@ -11,28 +11,42 @@
// significant-byte first (network) order. // significant-byte first (network) order.
package adler32 package adler32
import "os" import (
"hash";
"os";
)
const ( const (
mod = 65521; mod = 65521;
) )
// Digest represents the partial evaluation of a checksum. // The size of an Adler-32 checksum in bytes.
type Digest struct { const Size = 4;
// digest represents the partial evaluation of a checksum.
type digest struct {
// invariant: (a < mod && b < mod) || a <= b // invariant: (a < mod && b < mod) || a <= b
// invariant: a + b + 255 <= 0xffffffff // invariant: a + b + 255 <= 0xffffffff
a, b uint32; a, b uint32;
} }
// NewDigest creates a new Digest. func (d *digest) Reset() {
func NewDigest() *Digest { d.a, d.b = 1, 0;
return &Digest{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. // Add p to the running checksum a, b.
// It returns the number of bytes written; err is always nil. func update(a, b uint32, p []byte) (aa, bb uint32) {
func (d *Digest) Write(p []byte) (nn int, err os.Error) {
a, b := d.a, d.b;
for i := 0; i < len(p); i++ { for i := 0; i < len(p); i++ {
a += uint32(p[i]); a += uint32(p[i]);
b += a; b += a;
...@@ -45,13 +59,11 @@ func (d *Digest) Write(p []byte) (nn int, err os.Error) { ...@@ -45,13 +59,11 @@ func (d *Digest) Write(p []byte) (nn int, err os.Error) {
// invariant: a + b + 255 <= 2 * b + 255 <= 0xffffffff // invariant: a + b + 255 <= 2 * b + 255 <= 0xffffffff
} }
} }
d.a, d.b = a, b; return a, b;
return len(p), nil
} }
// Sum32 returns the 32-bit Adler-32 checksum of the data written to the Digest. // Return the 32-bit checksum corresponding to a, b.
func (d *Digest) Sum32() uint32 { func finish(a, b uint32) uint32 {
a, b := d.a, d.b;
if b >= mod { if b >= mod {
a %= mod; a %= mod;
b %= mod; b %= mod;
...@@ -59,9 +71,16 @@ func (d *Digest) Sum32() uint32 { ...@@ -59,9 +71,16 @@ func (d *Digest) Sum32() uint32 {
return b<<16 | a; return b<<16 | a;
} }
// Sum returns the 32-bit Adler-32 checksum of the data written to the Digest func (d *digest) Write(p []byte) (nn int, err os.Error) {
// in the form of an array of 4 bytes in big-endian order. d.a, d.b = update(d.a, d.b, p);
func (d *Digest) Sum() []byte { return len(p), nil;
}
func (d *digest) Sum32() uint32 {
return finish(d.a, d.b);
}
func (d *digest) Sum() []byte {
p := make([]byte, 4); p := make([]byte, 4);
s := d.Sum32(); s := d.Sum32();
p[0] = byte(s>>24); p[0] = byte(s>>24);
...@@ -70,3 +89,8 @@ func (d *Digest) Sum() []byte { ...@@ -70,3 +89,8 @@ func (d *Digest) Sum() []byte {
p[3] = byte(s); p[3] = byte(s);
return p; return p;
} }
// Checksum returns the Adler-32 checksum of data.
func Checksum(data []byte) uint32 {
return finish(update(1, 0, data));
}
...@@ -53,7 +53,7 @@ var golden = []_Adler32Test { ...@@ -53,7 +53,7 @@ var golden = []_Adler32Test {
func TestGolden(t *testing.T) { func TestGolden(t *testing.T) {
for i := 0; i < len(golden); i++ { for i := 0; i < len(golden); i++ {
g := golden[i]; g := golden[i];
c := NewDigest(); c := New();
io.WriteString(c, g.in); io.WriteString(c, g.in);
s := c.Sum32(); s := c.Sum32();
if s != g.out { if s != g.out {
......
...@@ -6,7 +6,13 @@ ...@@ -6,7 +6,13 @@
// See http://en.wikipedia.org/wiki/Cyclic_redundancy_check for information. // See http://en.wikipedia.org/wiki/Cyclic_redundancy_check for information.
package crc32 package crc32
import "os" import (
"hash";
"os";
)
// The size of a CRC-32 checksum in bytes.
const Size = 4;
// Predefined polynomials. // Predefined polynomials.
const ( const (
...@@ -26,12 +32,11 @@ const ( ...@@ -26,12 +32,11 @@ const (
) )
// Table is a 256-word table representing the polynomial for efficient processing. // 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 [256]uint32
type Table []uint32
// MakeTable returns the Table constructed from the specified polynomial. // MakeTable returns the Table constructed from the specified polynomial.
func MakeTable(poly uint32) Table { func MakeTable(poly uint32) *Table {
t := make(Table, 256); t := new(Table);
for i := 0; i < 256; i++ { for i := 0; i < 256; i++ {
crc := uint32(i); crc := uint32(i);
for j := 0; j < 8; j++ { for j := 0; j < 8; j++ {
...@@ -49,44 +54,51 @@ func MakeTable(poly uint32) Table { ...@@ -49,44 +54,51 @@ func MakeTable(poly uint32) Table {
// IEEETable is the table for the IEEE polynomial. // IEEETable is the table for the IEEE polynomial.
var IEEETable = MakeTable(IEEE); var IEEETable = MakeTable(IEEE);
// Digest represents the partial evaluation of a checksum. // digest represents the partial evaluation of a checksum.
type Digest struct { type digest struct {
crc uint32; 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 func (d *digest) Size() int {
// the polynomial represented by the Table. return Size;
func NewDigest(tab Table) *Digest {
return &Digest{0, tab};
} }
// NewIEEEDigest creates a new Digest for the checksum based on func (d *digest) Reset() {
// the IEEE polynomial. d.crc = 0;
func NewIEEEDigest() *Digest {
return NewDigest(IEEETable);
} }
// Write updates the Digest with the incremental checksum generated by p. func update(crc uint32, tab *Table, p []byte) uint32 {
// It returns the number of bytes written; err is always nil. crc ^= 0xFFFFFFFF;
func (d *Digest) Write(p []byte) (n int, err os.Error) {
crc := d.crc ^ 0xFFFFFFFF;
tab := d.tab;
for i := 0; i < len(p); i++ { for i := 0; i < len(p); i++ {
crc = tab[byte(crc) ^ p[i]] ^ (crc >> 8); 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; 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 return d.crc
} }
// Sum returns the CRC-32 checksum of the data written to the Digest func (d *digest) Sum() []byte {
// in the form of an array of 4 bytes in big-endian order.
func (d *Digest) Sum() []byte {
p := make([]byte, 4); p := make([]byte, 4);
s := d.Sum32(); s := d.Sum32();
p[0] = byte(s>>24); p[0] = byte(s>>24);
...@@ -96,4 +108,14 @@ func (d *Digest) Sum() []byte { ...@@ -96,4 +108,14 @@ func (d *Digest) Sum() []byte {
return p; 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);
}
...@@ -52,7 +52,7 @@ var golden = []_Crc32Test { ...@@ -52,7 +52,7 @@ var golden = []_Crc32Test {
func TestGolden(t *testing.T) { func TestGolden(t *testing.T) {
for i := 0; i < len(golden); i++ { for i := 0; i < len(golden); i++ {
g := golden[i]; g := golden[i];
c := NewIEEEDigest(); c := NewIEEE();
io.WriteString(c, g.in); io.WriteString(c, g.in);
s := c.Sum32(); s := c.Sum32();
if s != g.out { if s != g.out {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment