src/pkg/crypto/sha1/sha1.go - The Go Programming Language

Golang

Source file src/pkg/crypto/sha1/sha1.go

     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 SHA1 hash algorithm as defined in RFC 3174.
     6	package sha1
     7	
     8	import (
     9		"crypto"
    10		"hash"
    11	)
    12	
    13	func init() {
    14		crypto.RegisterHash(crypto.SHA1, New)
    15	}
    16	
    17	// The size of a SHA1 checksum in bytes.
    18	const Size = 20
    19	
    20	// The blocksize of SHA1 in bytes.
    21	const BlockSize = 64
    22	
    23	const (
    24		_Chunk = 64
    25		_Init0 = 0x67452301
    26		_Init1 = 0xEFCDAB89
    27		_Init2 = 0x98BADCFE
    28		_Init3 = 0x10325476
    29		_Init4 = 0xC3D2E1F0
    30	)
    31	
    32	// digest represents the partial evaluation of a checksum.
    33	type digest struct {
    34		h   [5]uint32
    35		x   [_Chunk]byte
    36		nx  int
    37		len uint64
    38	}
    39	
    40	func (d *digest) Reset() {
    41		d.h[0] = _Init0
    42		d.h[1] = _Init1
    43		d.h[2] = _Init2
    44		d.h[3] = _Init3
    45		d.h[4] = _Init4
    46		d.nx = 0
    47		d.len = 0
    48	}
    49	
    50	// New returns a new hash.Hash computing the SHA1 checksum.
    51	func New() hash.Hash {
    52		d := new(digest)
    53		d.Reset()
    54		return d
    55	}
    56	
    57	func (d *digest) Size() int { return Size }
    58	
    59	func (d *digest) BlockSize() int { return BlockSize }
    60	
    61	func (d *digest) Write(p []byte) (nn int, err error) {
    62		nn = len(p)
    63		d.len += uint64(nn)
    64		if d.nx > 0 {
    65			n := len(p)
    66			if n > _Chunk-d.nx {
    67				n = _Chunk - d.nx
    68			}
    69			for i := 0; i < n; i++ {
    70				d.x[d.nx+i] = p[i]
    71			}
    72			d.nx += n
    73			if d.nx == _Chunk {
    74				_Block(d, d.x[0:])
    75				d.nx = 0
    76			}
    77			p = p[n:]
    78		}
    79		n := _Block(d, p)
    80		p = p[n:]
    81		if len(p) > 0 {
    82			d.nx = copy(d.x[:], p)
    83		}
    84		return
    85	}
    86	
    87	func (d0 *digest) Sum(in []byte) []byte {
    88		// Make a copy of d0 so that caller can keep writing and summing.
    89		d := *d0
    90	
    91		// Padding.  Add a 1 bit and 0 bits until 56 bytes mod 64.
    92		len := d.len
    93		var tmp [64]byte
    94		tmp[0] = 0x80
    95		if len%64 < 56 {
    96			d.Write(tmp[0 : 56-len%64])
    97		} else {
    98			d.Write(tmp[0 : 64+56-len%64])
    99		}
   100	
   101		// Length in bits.
   102		len <<= 3
   103		for i := uint(0); i < 8; i++ {
   104			tmp[i] = byte(len >> (56 - 8*i))
   105		}
   106		d.Write(tmp[0:8])
   107	
   108		if d.nx != 0 {
   109			panic("d.nx != 0")
   110		}
   111	
   112		var digest [Size]byte
   113		for i, s := range d.h {
   114			digest[i*4] = byte(s >> 24)
   115			digest[i*4+1] = byte(s >> 16)
   116			digest[i*4+2] = byte(s >> 8)
   117			digest[i*4+3] = byte(s)
   118		}
   119	
   120		return append(in, digest[:]...)
   121	}