-
Notifications
You must be signed in to change notification settings - Fork 23
/
sm3.go
140 lines (108 loc) · 2.9 KB
/
sm3.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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package sm3
import (
"hash"
)
// The size of an SM3 checksum in bytes.
const Size = 32
// The blocksize of SM3 in bytes.
const BlockSize = 64
// Sum returns the SM3 checksum of the data.
func Sum(data []byte) (sum [Size]byte) {
var h digest
h.Reset()
h.Write(data)
hash := h.Sum(nil)
copy(sum[:], hash)
return
}
// digest represents the partial evaluation of a checksum.
type digest struct {
digest [8]uint32
nblocks uint64
block [BlockSize]byte
num int
}
// New returns a new hash.Hash computing the MD2 checksum.
func New() hash.Hash {
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.digest[0] = 0x7380166F
this.digest[1] = 0x4914B2B9
this.digest[2] = 0x172442D7
this.digest[3] = 0xDA8A0600
this.digest[4] = 0xA96F30BC
this.digest[5] = 0x163138AA
this.digest[6] = 0xE38DEE4D
this.digest[7] = 0xB0FB0E4E
this.nblocks = 0
this.block = [BlockSize]byte{}
this.num = 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.num &= 0x3f
if this.num > 0 {
var left int = BlockSize - this.num
if dataLen < left {
copy(this.block[this.num:], data)
this.num += dataLen
return
} else {
copy(this.block[this.num:], data[:left])
compressBlocks(this.digest[:], this.block[:], 1)
this.nblocks++
data = data[left:]
dataLen -= left
}
}
blocks = dataLen / BlockSize
if blocks > 0 {
compressBlocks(this.digest[:], data, blocks)
this.nblocks += uint64(blocks)
data = data[BlockSize * blocks:]
dataLen -= BlockSize * blocks
}
this.num = dataLen
if dataLen > 0 {
copy(this.block[:], data)
}
return
}
func (this *digest) Sum(in []byte) []byte {
// Make a copy of d so that caller can keep writing and summing.
d := *this
hash := d.checkSum()
return append(in, hash[:]...)
}
func (this *digest) checkSum() [Size]byte {
var i int32
this.num &= 0x3f
this.block[this.num] = 0x80
if this.num <= BlockSize - 9 {
memsetUint8(this.block[this.num + 1:BlockSize - 8], 0)
} else {
memsetUint8(this.block[this.num + 1:BlockSize], 0)
compressBlocks(this.digest[:], this.block[:], 1)
memsetUint8(this.block[:BlockSize - 8], 0)
}
PUTU32(this.block[56:], uint32(this.nblocks >> 23))
PUTU32(this.block[60:], uint32((this.nblocks << 9) + uint64(this.num << 3)))
compressBlocks(this.digest[:], this.block[:], 1)
var digest [Size]byte
for i = 0; i < 8; i++ {
PUTU32(digest[i*4:], this.digest[i])
}
return digest
}