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