The Go Programming Language

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

release.r60.3. Except as noted, this content is licensed under a Creative Commons Attribution 3.0 License.