1 package org.metricshub.winrm.service.client.encryption;
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 public class MD4 {
35
36 private int a = 0x67452301;
37 private int b = 0xefcdab89;
38 private int c = 0x98badcfe;
39 private int d = 0x10325476;
40 private long count = 0L;
41 private final byte[] dataBuffer = new byte[64];
42
43 void update(final byte[] input) {
44
45
46
47 int curBufferPos = (int) (count & 63L);
48 int inputIndex = 0;
49 while (input.length - inputIndex + curBufferPos >= dataBuffer.length) {
50
51
52
53 final int transferAmt = dataBuffer.length - curBufferPos;
54 System.arraycopy(input, inputIndex, dataBuffer, curBufferPos, transferAmt);
55 count += transferAmt;
56 curBufferPos = 0;
57 inputIndex += transferAmt;
58 processBuffer();
59 }
60
61
62
63 if (inputIndex < input.length) {
64 final int transferAmt = input.length - inputIndex;
65 System.arraycopy(input, inputIndex, dataBuffer, curBufferPos, transferAmt);
66 count += transferAmt;
67 curBufferPos += transferAmt;
68 }
69 }
70
71 byte[] getOutput() {
72
73
74 final int bufferIndex = (int) (count & 63L);
75 final int padLen = (bufferIndex < 56) ? (56 - bufferIndex) : (120 - bufferIndex);
76 final byte[] postBytes = new byte[padLen + 8];
77
78
79 postBytes[0] = (byte) 0x80;
80
81 for (int i = 0; i < 8; i++) {
82 postBytes[padLen + i] = (byte) ((count * 8) >>> (8 * i));
83 }
84
85
86 update(postBytes);
87
88
89 final byte[] result = new byte[16];
90 writeULong(result, a, 0);
91 writeULong(result, b, 4);
92 writeULong(result, c, 8);
93 writeULong(result, d, 12);
94 return result;
95 }
96
97 private static void writeULong(final byte[] buffer, final int value, final int offset) {
98 buffer[offset] = (byte) (value & 0xff);
99 buffer[offset + 1] = (byte) ((value >> 8) & 0xff);
100 buffer[offset + 2] = (byte) ((value >> 16) & 0xff);
101 buffer[offset + 3] = (byte) ((value >> 24) & 0xff);
102 }
103
104 private void processBuffer() {
105
106 final int[] d = new int[16];
107
108 for (int i = 0; i < 16; i++) {
109 d[i] =
110 (dataBuffer[i * 4] & 0xff) +
111 ((dataBuffer[i * 4 + 1] & 0xff) << 8) +
112 ((dataBuffer[i * 4 + 2] & 0xff) << 16) +
113 ((dataBuffer[i * 4 + 3] & 0xff) << 24);
114 }
115
116
117 final int aa = a;
118 final int bb = b;
119 final int cc = c;
120 final int dd = this.d;
121 round1(d);
122 round2(d);
123 round3(d);
124 a += aa;
125 b += bb;
126 c += cc;
127 this.d += dd;
128 }
129
130 private void round1(final int[] d) {
131 a = rotintlft((a + f(b, c, this.d) + d[0]), 3);
132 this.d = rotintlft((this.d + f(a, b, c) + d[1]), 7);
133 c = rotintlft((c + f(this.d, a, b) + d[2]), 11);
134 b = rotintlft((b + f(c, this.d, a) + d[3]), 19);
135
136 a = rotintlft((a + f(b, c, this.d) + d[4]), 3);
137 this.d = rotintlft((this.d + f(a, b, c) + d[5]), 7);
138 c = rotintlft((c + f(this.d, a, b) + d[6]), 11);
139 b = rotintlft((b + f(c, this.d, a) + d[7]), 19);
140
141 a = rotintlft((a + f(b, c, this.d) + d[8]), 3);
142 this.d = rotintlft((this.d + f(a, b, c) + d[9]), 7);
143 c = rotintlft((c + f(this.d, a, b) + d[10]), 11);
144 b = rotintlft((b + f(c, this.d, a) + d[11]), 19);
145
146 a = rotintlft((a + f(b, c, this.d) + d[12]), 3);
147 this.d = rotintlft((this.d + f(a, b, c) + d[13]), 7);
148 c = rotintlft((c + f(this.d, a, b) + d[14]), 11);
149 b = rotintlft((b + f(c, this.d, a) + d[15]), 19);
150 }
151
152 private void round2(final int[] d) {
153 a = rotintlft((a + g(b, c, this.d) + d[0] + 0x5a827999), 3);
154 this.d = rotintlft((this.d + g(a, b, c) + d[4] + 0x5a827999), 5);
155 c = rotintlft((c + g(this.d, a, b) + d[8] + 0x5a827999), 9);
156 b = rotintlft((b + g(c, this.d, a) + d[12] + 0x5a827999), 13);
157
158 a = rotintlft((a + g(b, c, this.d) + d[1] + 0x5a827999), 3);
159 this.d = rotintlft((this.d + g(a, b, c) + d[5] + 0x5a827999), 5);
160 c = rotintlft((c + g(this.d, a, b) + d[9] + 0x5a827999), 9);
161 b = rotintlft((b + g(c, this.d, a) + d[13] + 0x5a827999), 13);
162
163 a = rotintlft((a + g(b, c, this.d) + d[2] + 0x5a827999), 3);
164 this.d = rotintlft((this.d + g(a, b, c) + d[6] + 0x5a827999), 5);
165 c = rotintlft((c + g(this.d, a, b) + d[10] + 0x5a827999), 9);
166 b = rotintlft((b + g(c, this.d, a) + d[14] + 0x5a827999), 13);
167
168 a = rotintlft((a + g(b, c, this.d) + d[3] + 0x5a827999), 3);
169 this.d = rotintlft((this.d + g(a, b, c) + d[7] + 0x5a827999), 5);
170 c = rotintlft((c + g(this.d, a, b) + d[11] + 0x5a827999), 9);
171 b = rotintlft((b + g(c, this.d, a) + d[15] + 0x5a827999), 13);
172 }
173
174 private void round3(final int[] d) {
175 a = rotintlft((a + h(b, c, this.d) + d[0] + 0x6ed9eba1), 3);
176 this.d = rotintlft((this.d + h(a, b, c) + d[8] + 0x6ed9eba1), 9);
177 c = rotintlft((c + h(this.d, a, b) + d[4] + 0x6ed9eba1), 11);
178 b = rotintlft((b + h(c, this.d, a) + d[12] + 0x6ed9eba1), 15);
179
180 a = rotintlft((a + h(b, c, this.d) + d[2] + 0x6ed9eba1), 3);
181 this.d = rotintlft((this.d + h(a, b, c) + d[10] + 0x6ed9eba1), 9);
182 c = rotintlft((c + h(this.d, a, b) + d[6] + 0x6ed9eba1), 11);
183 b = rotintlft((b + h(c, this.d, a) + d[14] + 0x6ed9eba1), 15);
184
185 a = rotintlft((a + h(b, c, this.d) + d[1] + 0x6ed9eba1), 3);
186 this.d = rotintlft((this.d + h(a, b, c) + d[9] + 0x6ed9eba1), 9);
187 c = rotintlft((c + h(this.d, a, b) + d[5] + 0x6ed9eba1), 11);
188 b = rotintlft((b + h(c, this.d, a) + d[13] + 0x6ed9eba1), 15);
189
190 a = rotintlft((a + h(b, c, this.d) + d[3] + 0x6ed9eba1), 3);
191 this.d = rotintlft((this.d + h(a, b, c) + d[11] + 0x6ed9eba1), 9);
192 c = rotintlft((c + h(this.d, a, b) + d[7] + 0x6ed9eba1), 11);
193 b = rotintlft((b + h(c, this.d, a) + d[15] + 0x6ed9eba1), 15);
194 }
195
196 private static int f(final int x, final int y, final int z) {
197 return ((x & y) | (~x & z));
198 }
199
200 private static int g(final int x, final int y, final int z) {
201 return ((x & y) | (x & z) | (y & z));
202 }
203
204 private static int h(final int x, final int y, final int z) {
205 return (x ^ y ^ z);
206 }
207
208 private static int rotintlft(final int val, final int numbits) {
209 return ((val << numbits) | (val >>> (32 - numbits)));
210 }
211 }