-
Notifications
You must be signed in to change notification settings - Fork 0
/
digest.go
118 lines (90 loc) · 1.95 KB
/
digest.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package chaskey
import (
"fmt"
)
// The size of an chaskey checksum in bytes.
const Size = 16
// The blocksize of chaskey in bytes.
const BlockSize = 16
const KeySize = 16
type KeySizeError int
func (k KeySizeError) Error() string {
return fmt.Sprintf("go-hash/chaskey: invalid key size %d", int(k))
}
// digest represents the partial evaluation of a checksum.
type digest struct {
s [4]uint32
x [BlockSize]byte
nx int
len uint64
k1 [4]uint32
k2 [4]uint32
r int
}
func newDigest(key []byte, rounds int) (*digest, error) {
l := len(key)
if l != KeySize {
return nil, KeySizeError(l)
}
d := new(digest)
d.Reset()
d.r = rounds
d.expandKey(key)
return d, nil
}
func (d *digest) Reset() {
d.s = [4]uint32{}
d.x = [BlockSize]byte{}
d.nx = 0
d.len = 0
d.k1 = [4]uint32{}
d.k2 = [4]uint32{}
}
func (d *digest) Size() int {
return Size
}
func (d *digest) BlockSize() int {
return BlockSize
}
func (d *digest) Write(p []byte) (nn int, err error) {
nn = len(p)
d.len += uint64(nn)
if d.nx > 0 {
n := copy(d.x[d.nx:], p)
d.nx += n
if d.nx == BlockSize {
block(d, d.x[:])
d.nx = 0
}
p = p[n:]
}
for ; len(p) > BlockSize; p = p[BlockSize:] {
block(d, p)
d.nx = 0
}
if len(p) > 0 {
d.nx = copy(d.x[:], p)
}
return
}
func (d *digest) Sum(in []byte) []byte {
// Make a copy of d so that caller can keep writing and summing.
d0 := *d
hash := d0.checkSum()
return append(in, hash[:]...)
}
func (d *digest) checkSum() (out [Size]byte) {
lastblock(d)
if d.nx != 0 {
panic("d.nx != 0")
}
digest := uint32sToBytes(d.s[:])
copy(out[:], digest)
return
}
func (d *digest) expandKey(key []byte) {
k := bytesToUint32s(key)
copy(d.s[:], k)
timestwo(d.k1[:], k[:])
timestwo(d.k2[:], d.k1[:])
}