1
2
3
4
5
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
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
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
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
83 d := new(digest)
84 *d = *d0
85
86
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
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 }