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 sha1 implements the SHA-1 hash algorithm as defined in RFC 3174.
6//
7// SHA-1 is cryptographically broken and should not be used for secure
8// applications.
9package sha1
10
11import (
12	"crypto"
13	"crypto/internal/boring"
14	"errors"
15	"hash"
16	"internal/byteorder"
17)
18
19func init() {
20	crypto.RegisterHash(crypto.SHA1, New)
21}
22
23// The size of a SHA-1 checksum in bytes.
24const Size = 20
25
26// The blocksize of SHA-1 in bytes.
27const BlockSize = 64
28
29const (
30	chunk = 64
31	init0 = 0x67452301
32	init1 = 0xEFCDAB89
33	init2 = 0x98BADCFE
34	init3 = 0x10325476
35	init4 = 0xC3D2E1F0
36)
37
38// digest represents the partial evaluation of a checksum.
39type digest struct {
40	h   [5]uint32
41	x   [chunk]byte
42	nx  int
43	len uint64
44}
45
46const (
47	magic         = "sha\x01"
48	marshaledSize = len(magic) + 5*4 + chunk + 8
49)
50
51func (d *digest) MarshalBinary() ([]byte, error) {
52	b := make([]byte, 0, marshaledSize)
53	b = append(b, magic...)
54	b = byteorder.BeAppendUint32(b, d.h[0])
55	b = byteorder.BeAppendUint32(b, d.h[1])
56	b = byteorder.BeAppendUint32(b, d.h[2])
57	b = byteorder.BeAppendUint32(b, d.h[3])
58	b = byteorder.BeAppendUint32(b, d.h[4])
59	b = append(b, d.x[:d.nx]...)
60	b = b[:len(b)+len(d.x)-d.nx] // already zero
61	b = byteorder.BeAppendUint64(b, d.len)
62	return b, nil
63}
64
65func (d *digest) UnmarshalBinary(b []byte) error {
66	if len(b) < len(magic) || string(b[:len(magic)]) != magic {
67		return errors.New("crypto/sha1: invalid hash state identifier")
68	}
69	if len(b) != marshaledSize {
70		return errors.New("crypto/sha1: invalid hash state size")
71	}
72	b = b[len(magic):]
73	b, d.h[0] = consumeUint32(b)
74	b, d.h[1] = consumeUint32(b)
75	b, d.h[2] = consumeUint32(b)
76	b, d.h[3] = consumeUint32(b)
77	b, d.h[4] = consumeUint32(b)
78	b = b[copy(d.x[:], b):]
79	b, d.len = consumeUint64(b)
80	d.nx = int(d.len % chunk)
81	return nil
82}
83
84func consumeUint64(b []byte) ([]byte, uint64) {
85	return b[8:], byteorder.BeUint64(b)
86}
87
88func consumeUint32(b []byte) ([]byte, uint32) {
89	return b[4:], byteorder.BeUint32(b)
90}
91
92func (d *digest) Reset() {
93	d.h[0] = init0
94	d.h[1] = init1
95	d.h[2] = init2
96	d.h[3] = init3
97	d.h[4] = init4
98	d.nx = 0
99	d.len = 0
100}
101
102// New returns a new hash.Hash computing the SHA1 checksum. The Hash also
103// implements [encoding.BinaryMarshaler] and [encoding.BinaryUnmarshaler] to
104// marshal and unmarshal the internal state of the hash.
105func New() hash.Hash {
106	if boring.Enabled {
107		return boring.NewSHA1()
108	}
109	d := new(digest)
110	d.Reset()
111	return d
112}
113
114func (d *digest) Size() int { return Size }
115
116func (d *digest) BlockSize() int { return BlockSize }
117
118func (d *digest) Write(p []byte) (nn int, err error) {
119	boring.Unreachable()
120	nn = len(p)
121	d.len += uint64(nn)
122	if d.nx > 0 {
123		n := copy(d.x[d.nx:], p)
124		d.nx += n
125		if d.nx == chunk {
126			block(d, d.x[:])
127			d.nx = 0
128		}
129		p = p[n:]
130	}
131	if len(p) >= chunk {
132		n := len(p) &^ (chunk - 1)
133		block(d, p[:n])
134		p = p[n:]
135	}
136	if len(p) > 0 {
137		d.nx = copy(d.x[:], p)
138	}
139	return
140}
141
142func (d *digest) Sum(in []byte) []byte {
143	boring.Unreachable()
144	// Make a copy of d so that caller can keep writing and summing.
145	d0 := *d
146	hash := d0.checkSum()
147	return append(in, hash[:]...)
148}
149
150func (d *digest) checkSum() [Size]byte {
151	len := d.len
152	// Padding.  Add a 1 bit and 0 bits until 56 bytes mod 64.
153	var tmp [64 + 8]byte // padding + length buffer
154	tmp[0] = 0x80
155	var t uint64
156	if len%64 < 56 {
157		t = 56 - len%64
158	} else {
159		t = 64 + 56 - len%64
160	}
161
162	// Length in bits.
163	len <<= 3
164	padlen := tmp[:t+8]
165	byteorder.BePutUint64(padlen[t:], len)
166	d.Write(padlen)
167
168	if d.nx != 0 {
169		panic("d.nx != 0")
170	}
171
172	var digest [Size]byte
173
174	byteorder.BePutUint32(digest[0:], d.h[0])
175	byteorder.BePutUint32(digest[4:], d.h[1])
176	byteorder.BePutUint32(digest[8:], d.h[2])
177	byteorder.BePutUint32(digest[12:], d.h[3])
178	byteorder.BePutUint32(digest[16:], d.h[4])
179
180	return digest
181}
182
183// ConstantTimeSum computes the same result of [Sum] but in constant time
184func (d *digest) ConstantTimeSum(in []byte) []byte {
185	d0 := *d
186	hash := d0.constSum()
187	return append(in, hash[:]...)
188}
189
190func (d *digest) constSum() [Size]byte {
191	var length [8]byte
192	l := d.len << 3
193	for i := uint(0); i < 8; i++ {
194		length[i] = byte(l >> (56 - 8*i))
195	}
196
197	nx := byte(d.nx)
198	t := nx - 56                 // if nx < 56 then the MSB of t is one
199	mask1b := byte(int8(t) >> 7) // mask1b is 0xFF iff one block is enough
200
201	separator := byte(0x80) // gets reset to 0x00 once used
202	for i := byte(0); i < chunk; i++ {
203		mask := byte(int8(i-nx) >> 7) // 0x00 after the end of data
204
205		// if we reached the end of the data, replace with 0x80 or 0x00
206		d.x[i] = (^mask & separator) | (mask & d.x[i])
207
208		// zero the separator once used
209		separator &= mask
210
211		if i >= 56 {
212			// we might have to write the length here if all fit in one block
213			d.x[i] |= mask1b & length[i-56]
214		}
215	}
216
217	// compress, and only keep the digest if all fit in one block
218	block(d, d.x[:])
219
220	var digest [Size]byte
221	for i, s := range d.h {
222		digest[i*4] = mask1b & byte(s>>24)
223		digest[i*4+1] = mask1b & byte(s>>16)
224		digest[i*4+2] = mask1b & byte(s>>8)
225		digest[i*4+3] = mask1b & byte(s)
226	}
227
228	for i := byte(0); i < chunk; i++ {
229		// second block, it's always past the end of data, might start with 0x80
230		if i < 56 {
231			d.x[i] = separator
232			separator = 0
233		} else {
234			d.x[i] = length[i-56]
235		}
236	}
237
238	// compress, and only keep the digest if we actually needed the second block
239	block(d, d.x[:])
240
241	for i, s := range d.h {
242		digest[i*4] |= ^mask1b & byte(s>>24)
243		digest[i*4+1] |= ^mask1b & byte(s>>16)
244		digest[i*4+2] |= ^mask1b & byte(s>>8)
245		digest[i*4+3] |= ^mask1b & byte(s)
246	}
247
248	return digest
249}
250
251// Sum returns the SHA-1 checksum of the data.
252func Sum(data []byte) [Size]byte {
253	if boring.Enabled {
254		return boring.SHA1(data)
255	}
256	var d digest
257	d.Reset()
258	d.Write(data)
259	return d.checkSum()
260}
261