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