github.com/goproxy0/go@v0.0.0-20171111080102-49cc0c489d2c/src/crypto/sha1/sha1.go (about)

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