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