1
2
3
4
5
6
7 package sha256
8
9 import (
10 "crypto"
11 "encoding/binary"
12 "errors"
13 "hash"
14 )
15
16 func init() {
17 crypto.RegisterHash(crypto.SHA224, New224)
18 crypto.RegisterHash(crypto.SHA256, New)
19 }
20
21
22 const Size = 32
23
24
25 const Size224 = 28
26
27
28 const BlockSize = 64
29
30 const (
31 chunk = 64
32 init0 = 0x6A09E667
33 init1 = 0xBB67AE85
34 init2 = 0x3C6EF372
35 init3 = 0xA54FF53A
36 init4 = 0x510E527F
37 init5 = 0x9B05688C
38 init6 = 0x1F83D9AB
39 init7 = 0x5BE0CD19
40 init0_224 = 0xC1059ED8
41 init1_224 = 0x367CD507
42 init2_224 = 0x3070DD17
43 init3_224 = 0xF70E5939
44 init4_224 = 0xFFC00B31
45 init5_224 = 0x68581511
46 init6_224 = 0x64F98FA7
47 init7_224 = 0xBEFA4FA4
48 )
49
50
51 type digest struct {
52 h [8]uint32
53 x [chunk]byte
54 nx int
55 len uint64
56 is224 bool
57 }
58
59 const (
60 magic224 = "sha\x02"
61 magic256 = "sha\x03"
62 marshaledSize = len(magic256) + 8*4 + chunk + 8
63 )
64
65 func (d *digest) MarshalBinary() ([]byte, error) {
66 b := make([]byte, 0, marshaledSize)
67 if d.is224 {
68 b = append(b, magic224...)
69 } else {
70 b = append(b, magic256...)
71 }
72 b = appendUint32(b, d.h[0])
73 b = appendUint32(b, d.h[1])
74 b = appendUint32(b, d.h[2])
75 b = appendUint32(b, d.h[3])
76 b = appendUint32(b, d.h[4])
77 b = appendUint32(b, d.h[5])
78 b = appendUint32(b, d.h[6])
79 b = appendUint32(b, d.h[7])
80 b = append(b, d.x[:d.nx]...)
81 b = b[:len(b)+len(d.x)-int(d.nx)]
82 b = appendUint64(b, d.len)
83 return b, nil
84 }
85
86 func (d *digest) UnmarshalBinary(b []byte) error {
87 if len(b) < len(magic224) || (d.is224 && string(b[:len(magic224)]) != magic224) || (!d.is224 && string(b[:len(magic256)]) != magic256) {
88 return errors.New("crypto/sha256: invalid hash state identifier")
89 }
90 if len(b) != marshaledSize {
91 return errors.New("crypto/sha256: invalid hash state size")
92 }
93 b = b[len(magic224):]
94 b, d.h[0] = consumeUint32(b)
95 b, d.h[1] = consumeUint32(b)
96 b, d.h[2] = consumeUint32(b)
97 b, d.h[3] = consumeUint32(b)
98 b, d.h[4] = consumeUint32(b)
99 b, d.h[5] = consumeUint32(b)
100 b, d.h[6] = consumeUint32(b)
101 b, d.h[7] = consumeUint32(b)
102 b = b[copy(d.x[:], b):]
103 b, d.len = consumeUint64(b)
104 d.nx = int(d.len % chunk)
105 return nil
106 }
107
108 func appendUint64(b []byte, x uint64) []byte {
109 var a [8]byte
110 binary.BigEndian.PutUint64(a[:], x)
111 return append(b, a[:]...)
112 }
113
114 func appendUint32(b []byte, x uint32) []byte {
115 var a [4]byte
116 binary.BigEndian.PutUint32(a[:], x)
117 return append(b, a[:]...)
118 }
119
120 func consumeUint64(b []byte) ([]byte, uint64) {
121 _ = b[7]
122 x := uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
123 uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
124 return b[8:], x
125 }
126
127 func consumeUint32(b []byte) ([]byte, uint32) {
128 _ = b[3]
129 x := uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24
130 return b[4:], x
131 }
132
133 func (d *digest) Reset() {
134 if !d.is224 {
135 d.h[0] = init0
136 d.h[1] = init1
137 d.h[2] = init2
138 d.h[3] = init3
139 d.h[4] = init4
140 d.h[5] = init5
141 d.h[6] = init6
142 d.h[7] = init7
143 } else {
144 d.h[0] = init0_224
145 d.h[1] = init1_224
146 d.h[2] = init2_224
147 d.h[3] = init3_224
148 d.h[4] = init4_224
149 d.h[5] = init5_224
150 d.h[6] = init6_224
151 d.h[7] = init7_224
152 }
153 d.nx = 0
154 d.len = 0
155 }
156
157
158
159
160
161 func New() hash.Hash {
162 d := new(digest)
163 d.Reset()
164 return d
165 }
166
167
168 func New224() hash.Hash {
169 d := new(digest)
170 d.is224 = true
171 d.Reset()
172 return d
173 }
174
175 func (d *digest) Size() int {
176 if !d.is224 {
177 return Size
178 }
179 return Size224
180 }
181
182 func (d *digest) BlockSize() int { return BlockSize }
183
184 func (d *digest) Write(p []byte) (nn int, err error) {
185 nn = len(p)
186 d.len += uint64(nn)
187 if d.nx > 0 {
188 n := copy(d.x[d.nx:], p)
189 d.nx += n
190 if d.nx == chunk {
191 block(d, d.x[:])
192 d.nx = 0
193 }
194 p = p[n:]
195 }
196 if len(p) >= chunk {
197 n := len(p) &^ (chunk - 1)
198 block(d, p[:n])
199 p = p[n:]
200 }
201 if len(p) > 0 {
202 d.nx = copy(d.x[:], p)
203 }
204 return
205 }
206
207 func (d *digest) Sum(in []byte) []byte {
208
209 d0 := *d
210 hash := d0.checkSum()
211 if d0.is224 {
212 return append(in, hash[:Size224]...)
213 }
214 return append(in, hash[:]...)
215 }
216
217 func (d *digest) checkSum() [Size]byte {
218 len := d.len
219
220 var tmp [64]byte
221 tmp[0] = 0x80
222 if len%64 < 56 {
223 d.Write(tmp[0 : 56-len%64])
224 } else {
225 d.Write(tmp[0 : 64+56-len%64])
226 }
227
228
229 len <<= 3
230 binary.BigEndian.PutUint64(tmp[:], len)
231 d.Write(tmp[0:8])
232
233 if d.nx != 0 {
234 panic("d.nx != 0")
235 }
236
237 var digest [Size]byte
238
239 binary.BigEndian.PutUint32(digest[0:], d.h[0])
240 binary.BigEndian.PutUint32(digest[4:], d.h[1])
241 binary.BigEndian.PutUint32(digest[8:], d.h[2])
242 binary.BigEndian.PutUint32(digest[12:], d.h[3])
243 binary.BigEndian.PutUint32(digest[16:], d.h[4])
244 binary.BigEndian.PutUint32(digest[20:], d.h[5])
245 binary.BigEndian.PutUint32(digest[24:], d.h[6])
246 if !d.is224 {
247 binary.BigEndian.PutUint32(digest[28:], d.h[7])
248 }
249
250 return digest
251 }
252
253
254 func Sum256(data []byte) [Size]byte {
255 var d digest
256 d.Reset()
257 d.Write(data)
258 return d.checkSum()
259 }
260
261
262 func Sum224(data []byte) (sum224 [Size224]byte) {
263 var d digest
264 d.is224 = true
265 d.Reset()
266 d.Write(data)
267 sum := d.checkSum()
268 copy(sum224[:], sum[:Size224])
269 return
270 }
271
View as plain text