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