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