OSDN Git Service

848d9552df55a0ed1620f9be978e716ec9263b75
[pf3gnuchains/gcc-fork.git] / libgo / go / 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 }