The Go Programming Language

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

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