MD4.java
6.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/*
* Decompiled with CFR 0_118.
*/
package com.day.text;
public class MD4 {
private static final byte[] PADDING = new byte[]{-128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
private static final int S11 = 3;
private static final int S12 = 7;
private static final int S13 = 11;
private static final int S14 = 19;
private static final int S21 = 3;
private static final int S22 = 5;
private static final int S23 = 9;
private static final int S24 = 13;
private static final int S31 = 3;
private static final int S32 = 9;
private static final int S33 = 11;
private static final int S34 = 15;
private int[] state = new int[4];
private int[] count = new int[2];
private byte[] buffer = new byte[64];
public MD4() {
this.init();
}
private void init() {
this.count[1] = 0;
this.count[0] = 0;
this.state[0] = 1732584193;
this.state[1] = -271733879;
this.state[2] = -1732584194;
this.state[3] = 271733878;
}
public void update(byte[] input, int off, int len) {
int i;
int index = this.count[0] >> 3 & 63;
int bitlen = len << 3;
this.count[0] = this.count[0] + bitlen;
if (this.count[0] < bitlen) {
int[] arrn = this.count;
arrn[1] = arrn[1] + 1;
}
int[] arrn = this.count;
arrn[1] = arrn[1] + (len >> 29);
int partlen = 64 - index;
if (len >= partlen) {
System.arraycopy(input, off, this.buffer, index, partlen);
this.transform(this.buffer, 0);
i = partlen;
while (i + 63 < len) {
this.transform(input, off + i);
i += 64;
}
index = 0;
} else {
i = 0;
}
System.arraycopy(input, off + i, this.buffer, index, len - i);
}
public byte[] finish() {
byte[] digest = new byte[16];
byte[] bits = new byte[8];
MD4.encode(this.count, bits, 0, bits.length);
int index = this.count[0] >> 3 & 63;
int padlen = index < 56 ? 56 - index : 120 - index;
this.update(PADDING, 0, padlen);
this.update(bits, 0, bits.length);
MD4.encode(this.state, digest, 0, digest.length);
return digest;
}
private void transform(byte[] block, int offset) {
int a = this.state[0];
int b = this.state[1];
int c = this.state[2];
int d = this.state[3];
int[] x = new int[16];
MD4.decode(block, offset, 64, x);
a = MD4.FF(a, b, c, d, x[0], 3);
d = MD4.FF(d, a, b, c, x[1], 7);
c = MD4.FF(c, d, a, b, x[2], 11);
b = MD4.FF(b, c, d, a, x[3], 19);
a = MD4.FF(a, b, c, d, x[4], 3);
d = MD4.FF(d, a, b, c, x[5], 7);
c = MD4.FF(c, d, a, b, x[6], 11);
b = MD4.FF(b, c, d, a, x[7], 19);
a = MD4.FF(a, b, c, d, x[8], 3);
d = MD4.FF(d, a, b, c, x[9], 7);
c = MD4.FF(c, d, a, b, x[10], 11);
b = MD4.FF(b, c, d, a, x[11], 19);
a = MD4.FF(a, b, c, d, x[12], 3);
d = MD4.FF(d, a, b, c, x[13], 7);
c = MD4.FF(c, d, a, b, x[14], 11);
b = MD4.FF(b, c, d, a, x[15], 19);
a = MD4.GG(a, b, c, d, x[0], 3);
d = MD4.GG(d, a, b, c, x[4], 5);
c = MD4.GG(c, d, a, b, x[8], 9);
b = MD4.GG(b, c, d, a, x[12], 13);
a = MD4.GG(a, b, c, d, x[1], 3);
d = MD4.GG(d, a, b, c, x[5], 5);
c = MD4.GG(c, d, a, b, x[9], 9);
b = MD4.GG(b, c, d, a, x[13], 13);
a = MD4.GG(a, b, c, d, x[2], 3);
d = MD4.GG(d, a, b, c, x[6], 5);
c = MD4.GG(c, d, a, b, x[10], 9);
b = MD4.GG(b, c, d, a, x[14], 13);
a = MD4.GG(a, b, c, d, x[3], 3);
d = MD4.GG(d, a, b, c, x[7], 5);
c = MD4.GG(c, d, a, b, x[11], 9);
b = MD4.GG(b, c, d, a, x[15], 13);
a = MD4.HH(a, b, c, d, x[0], 3);
d = MD4.HH(d, a, b, c, x[8], 9);
c = MD4.HH(c, d, a, b, x[4], 11);
b = MD4.HH(b, c, d, a, x[12], 15);
a = MD4.HH(a, b, c, d, x[2], 3);
d = MD4.HH(d, a, b, c, x[10], 9);
c = MD4.HH(c, d, a, b, x[6], 11);
b = MD4.HH(b, c, d, a, x[14], 15);
a = MD4.HH(a, b, c, d, x[1], 3);
d = MD4.HH(d, a, b, c, x[9], 9);
c = MD4.HH(c, d, a, b, x[5], 11);
b = MD4.HH(b, c, d, a, x[13], 15);
a = MD4.HH(a, b, c, d, x[3], 3);
d = MD4.HH(d, a, b, c, x[11], 9);
c = MD4.HH(c, d, a, b, x[7], 11);
b = MD4.HH(b, c, d, a, x[15], 15);
int[] arrn = this.state;
arrn[0] = arrn[0] + a;
int[] arrn2 = this.state;
arrn2[1] = arrn2[1] + b;
int[] arrn3 = this.state;
arrn3[2] = arrn3[2] + c;
int[] arrn4 = this.state;
arrn4[3] = arrn4[3] + d;
}
private static void encode(int[] input, byte[] output, int off, int len) {
int i = 0;
for (int j = off; j < off + len; j += 4) {
output[j] = (byte)(input[i] & 255);
output[j + 1] = (byte)(input[i] >> 8 & 255);
output[j + 2] = (byte)(input[i] >> 16 & 255);
output[j + 3] = (byte)(input[i] >> 24 & 255);
++i;
}
}
private static void decode(byte[] input, int off, int len, int[] output) {
int i = 0;
for (int j = off; j < off + len; j += 4) {
int ch1 = input[j] & 255;
int ch2 = input[j + 1] & 255;
int ch3 = input[j + 2] & 255;
int ch4 = input[j + 3] & 255;
output[i] = ch1 | ch2 << 8 | ch3 << 16 | ch4 << 24;
++i;
}
}
private static int FF(int a, int b, int c, int d, int x, int s) {
return a << s | (a += (b & c | ~ b & d) + x) >>> 32 - s;
}
private static int GG(int a, int b, int c, int d, int x, int s) {
return a << s | (a += (b & c | b & d | c & d) + x + 1518500249) >>> 32 - s;
}
private static int HH(int a, int b, int c, int d, int x, int s) {
return a << s | (a += (b ^ c ^ d) + x + 1859775393) >>> 32 - s;
}
public static byte[] digest(byte[] input) {
MD4 md4 = new MD4();
md4.update(input, 0, input.length);
return md4.finish();
}
}