/
digest.go
119 lines (89 loc) · 2.32 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
119
package sm3
// The size of an SM3 checksum in bytes.
const Size = 32
// The blocksize of SM3 in bytes.
const BlockSize = 64
// digest represents the partial evaluation of a checksum.
type digest struct {
s [8]uint32
x [BlockSize]byte
nx uint64
len int
}
func newDigest() *digest {
d := new(digest)
d.Reset()
return d
}
func (this *digest) Size() int {
return Size
}
func (this *digest) BlockSize() int {
return BlockSize
}
func (this *digest) Reset() {
this.s = iv
this.x = [BlockSize]byte{}
this.nx = 0
this.len = 0
}
// Write is the interface for IO Writer
func (this *digest) Write(data []byte) (nn int, err error) {
nn = len(data)
var blocks int
dataLen := len(data)
this.len &= 0x3f
if this.len > 0 {
var left int = BlockSize - this.len
if dataLen < left {
copy(this.x[this.len:], data)
this.len += dataLen
return
} else {
copy(this.x[this.len:], data[:left])
compressBlocks(this.s[:], this.x[:], 1)
this.nx++
data = data[left:]
dataLen -= left
}
}
blocks = dataLen / BlockSize
if blocks > 0 {
compressBlocks(this.s[:], data, blocks)
this.nx += uint64(blocks)
data = data[BlockSize * blocks:]
dataLen -= BlockSize * blocks
}
this.len = dataLen
if dataLen > 0 {
copy(this.x[:], data)
}
return
}
func (this *digest) Sum(in []byte) []byte {
// Make a copy of d so that caller can keep writing and summing.
d := *this
sum := d.checkSum()
return append(in, sum[:]...)
}
func (this *digest) checkSum() [Size]byte {
var i int32
this.len &= 0x3f
this.x[this.len] = 0x80
zeros := make([]byte, BlockSize)
if this.len <= BlockSize - 9 {
copy(this.x[this.len + 1:BlockSize - 8], zeros)
} else {
copy(this.x[this.len + 1:BlockSize], zeros)
compressBlocks(this.s[:], this.x[:], 1)
copy(this.x[:BlockSize - 8], zeros)
}
PUTU32(this.x[56:], uint32(this.nx >> 23))
PUTU32(this.x[60:], uint32((this.nx << 9) + uint64(this.len << 3)))
compressBlocks(this.s[:], this.x[:], 1)
var digest [Size]byte
for i = 0; i < 8; i++ {
PUTU32(digest[i*4:], this.s[i])
}
return digest
}