Skip to content

Package: MD4

MD4

nameinstructionbranchcomplexitylinemethod
FF(int, int, int, int, int, int)
M: 24 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
GG(int, int, int, int, int, int)
M: 28 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
HH(int, int, int, int, int, int)
M: 22 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
MD4()
M: 17 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 6 C: 0
0%
M: 1 C: 0
0%
digest(byte[])
M: 17 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 5 C: 0
0%
M: 1 C: 0
0%
engineUpdate(byte[], int, int)
M: 98 C: 0
0%
M: 18 C: 0
0%
M: 10 C: 0
0%
M: 24 C: 0
0%
M: 1 C: 0
0%
implCompress(byte[], int)
M: 630 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 60 C: 0
0%
M: 1 C: 0
0%
implDigest(byte[], int)
M: 147 C: 0
0%
M: 4 C: 0
0%
M: 3 C: 0
0%
M: 20 C: 0
0%
M: 1 C: 0
0%
implReset()
M: 27 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 7 C: 0
0%
M: 1 C: 0
0%
static {...}
M: 8 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 3 C: 0
0%
M: 1 C: 0
0%

Coverage

1: /*
2: * Copyright (c) 2005, 2023 Oracle and/or its affiliates. All rights reserved.
3: *
4: * This program and the accompanying materials are made available under the
5: * terms of the Eclipse Public License v. 2.0, which is available at
6: * http://www.eclipse.org/legal/epl-2.0.
7: *
8: * This Source Code may also be made available under the following Secondary
9: * Licenses when the conditions for such availability set forth in the
10: * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
11: * version 2 with the GNU Classpath Exception, which is available at
12: * https://www.gnu.org/software/classpath/license.html.
13: *
14: * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15: */
16:
17: /*
18: * Copied from OpenJDK with permission.
19: */
20:
21: package org.eclipse.angus.mail.auth;
22:
23: //import static sun.security.provider.ByteArrayAccess.*;
24:
25: /**
26: * The MD4 class is used to compute an MD4 message digest over a given
27: * buffer of bytes. It is an implementation of the RSA Data Security Inc
28: * MD4 algorithim as described in internet RFC 1320.
29: *
30: * @author Andreas Sterbenz
31: * @author Bill Shannon (adapted for Jakarta Mail)
32: */
33: public final class MD4 {
34:
35: // state of this object
36: private final int[] state;
37: // temporary buffer, used by implCompress()
38: private final int[] x;
39:
40: // size of the input to the compression function in bytes
41: private static final int blockSize = 64;
42:
43: // buffer to store partial blocks, blockSize bytes large
44: private final byte[] buffer = new byte[blockSize];
45: // offset into buffer
46: private int bufOfs;
47:
48: // number of bytes processed so far.
49: // also used as a flag to indicate reset status
50: // -1: need to call engineReset() before next call to update()
51: // 0: is already reset
52: private long bytesProcessed;
53:
54: // rotation constants
55: private static final int S11 = 3;
56: private static final int S12 = 7;
57: private static final int S13 = 11;
58: private static final int S14 = 19;
59: private static final int S21 = 3;
60: private static final int S22 = 5;
61: private static final int S23 = 9;
62: private static final int S24 = 13;
63: private static final int S31 = 3;
64: private static final int S32 = 9;
65: private static final int S33 = 11;
66: private static final int S34 = 15;
67:
68: private static final byte[] padding;
69:
70: static {
71: padding = new byte[136];
72: padding[0] = (byte)0x80;
73: }
74:
75: /**
76: * Standard constructor, creates a new MD4 instance.
77: */
78: public MD4() {
79: state = new int[4];
80: x = new int[16];
81: implReset();
82: }
83:
84: /**
85: * Compute and return the message digest of the input byte array.
86: *
87: * @param        in        the input byte array
88: * @return        the message digest byte array
89: */
90: public byte[] digest(byte[] in) {
91:         implReset();
92:         engineUpdate(in, 0, in.length);
93:         byte[] out = new byte[16];
94:         implDigest(out, 0);
95:         return out;
96: }
97:
98: /**
99: * Reset the state of this object.
100: */
101: private void implReset() {
102: // Load magic initialization constants.
103: state[0] = 0x67452301;
104: state[1] = 0xefcdab89;
105: state[2] = 0x98badcfe;
106: state[3] = 0x10325476;
107: bufOfs = 0;
108: bytesProcessed = 0;
109: }
110:
111: /**
112: * Perform the final computations, any buffered bytes are added
113: * to the digest, the count is added to the digest, and the resulting
114: * digest is stored.
115: */
116: private void implDigest(byte[] out, int ofs) {
117: long bitsProcessed = bytesProcessed << 3;
118:
119: int index = (int)bytesProcessed & 0x3f;
120:• int padLen = (index < 56) ? (56 - index) : (120 - index);
121: engineUpdate(padding, 0, padLen);
122:
123: //i2bLittle4((int)bitsProcessed, buffer, 56);
124: //i2bLittle4((int)(bitsProcessed >>> 32), buffer, 60);
125:         buffer[56] = (byte)bitsProcessed;
126:         buffer[57] = (byte)(bitsProcessed>>8);
127:         buffer[58] = (byte)(bitsProcessed>>16);
128:         buffer[59] = (byte)(bitsProcessed>>24);
129:         buffer[60] = (byte)(bitsProcessed>>32);
130:         buffer[61] = (byte)(bitsProcessed>>40);
131:         buffer[62] = (byte)(bitsProcessed>>48);
132:         buffer[63] = (byte)(bitsProcessed>>56);
133: implCompress(buffer, 0);
134:
135: //i2bLittle(state, 0, out, ofs, 16);
136:•        for (int i = 0; i < state.length; i++) {
137:          int x = state[i];
138:          out[ofs++] = (byte)x;
139:          out[ofs++] = (byte)(x>>8);
140:          out[ofs++] = (byte)(x>>16);
141:          out[ofs++] = (byte)(x>>24);
142:         }
143: }
144:
145: private void engineUpdate(byte[] b, int ofs, int len) {
146:• if (len == 0) {
147: return;
148: }
149:• if ((ofs < 0) || (len < 0) || (ofs > b.length - len)) {
150: throw new ArrayIndexOutOfBoundsException();
151: }
152:• if (bytesProcessed < 0) {
153: implReset();
154: }
155: bytesProcessed += len;
156: // if buffer is not empty, we need to fill it before proceeding
157:• if (bufOfs != 0) {
158: int n = Math.min(len, blockSize - bufOfs);
159: System.arraycopy(b, ofs, buffer, bufOfs, n);
160: bufOfs += n;
161: ofs += n;
162: len -= n;
163:• if (bufOfs >= blockSize) {
164: // compress completed block now
165: implCompress(buffer, 0);
166: bufOfs = 0;
167: }
168: }
169: // compress complete blocks
170:• while (len >= blockSize) {
171: implCompress(b, ofs);
172: len -= blockSize;
173: ofs += blockSize;
174: }
175: // copy remainder to buffer
176:• if (len > 0) {
177: System.arraycopy(b, ofs, buffer, 0, len);
178: bufOfs = len;
179: }
180: }
181:
182: private static int FF(int a, int b, int c, int d, int x, int s) {
183: a += ((b & c) | ((~b) & d)) + x;
184: return ((a << s) | (a >>> (32 - s)));
185: }
186:
187: private static int GG(int a, int b, int c, int d, int x, int s) {
188: a += ((b & c) | (b & d) | (c & d)) + x + 0x5a827999;
189: return ((a << s) | (a >>> (32 - s)));
190: }
191:
192: private static int HH(int a, int b, int c, int d, int x, int s) {
193: a += ((b ^ c) ^ d) + x + 0x6ed9eba1;
194: return ((a << s) | (a >>> (32 - s)));
195: }
196:
197: /**
198: * This is where the functions come together as the generic MD4
199: * transformation operation. It consumes 64
200: * bytes from the buffer, beginning at the specified offset.
201: */
202: private void implCompress(byte[] buf, int ofs) {
203: //b2iLittle64(buf, ofs, x);
204:•        for (int xfs = 0; xfs < x.length; xfs++) {
205:          x[xfs] = (buf[ofs] & 0xff) | ((buf[ofs+1] & 0xff) << 8) |
206:                 ((buf[ofs+2] & 0xff) << 16) | ((buf[ofs+3] & 0xff) << 24);
207:          ofs += 4;
208:         }
209:
210: int a = state[0];
211: int b = state[1];
212: int c = state[2];
213: int d = state[3];
214:
215: /* Round 1 */
216: a = FF (a, b, c, d, x[ 0], S11); /* 1 */
217: d = FF (d, a, b, c, x[ 1], S12); /* 2 */
218: c = FF (c, d, a, b, x[ 2], S13); /* 3 */
219: b = FF (b, c, d, a, x[ 3], S14); /* 4 */
220: a = FF (a, b, c, d, x[ 4], S11); /* 5 */
221: d = FF (d, a, b, c, x[ 5], S12); /* 6 */
222: c = FF (c, d, a, b, x[ 6], S13); /* 7 */
223: b = FF (b, c, d, a, x[ 7], S14); /* 8 */
224: a = FF (a, b, c, d, x[ 8], S11); /* 9 */
225: d = FF (d, a, b, c, x[ 9], S12); /* 10 */
226: c = FF (c, d, a, b, x[10], S13); /* 11 */
227: b = FF (b, c, d, a, x[11], S14); /* 12 */
228: a = FF (a, b, c, d, x[12], S11); /* 13 */
229: d = FF (d, a, b, c, x[13], S12); /* 14 */
230: c = FF (c, d, a, b, x[14], S13); /* 15 */
231: b = FF (b, c, d, a, x[15], S14); /* 16 */
232:
233: /* Round 2 */
234: a = GG (a, b, c, d, x[ 0], S21); /* 17 */
235: d = GG (d, a, b, c, x[ 4], S22); /* 18 */
236: c = GG (c, d, a, b, x[ 8], S23); /* 19 */
237: b = GG (b, c, d, a, x[12], S24); /* 20 */
238: a = GG (a, b, c, d, x[ 1], S21); /* 21 */
239: d = GG (d, a, b, c, x[ 5], S22); /* 22 */
240: c = GG (c, d, a, b, x[ 9], S23); /* 23 */
241: b = GG (b, c, d, a, x[13], S24); /* 24 */
242: a = GG (a, b, c, d, x[ 2], S21); /* 25 */
243: d = GG (d, a, b, c, x[ 6], S22); /* 26 */
244: c = GG (c, d, a, b, x[10], S23); /* 27 */
245: b = GG (b, c, d, a, x[14], S24); /* 28 */
246: a = GG (a, b, c, d, x[ 3], S21); /* 29 */
247: d = GG (d, a, b, c, x[ 7], S22); /* 30 */
248: c = GG (c, d, a, b, x[11], S23); /* 31 */
249: b = GG (b, c, d, a, x[15], S24); /* 32 */
250:
251: /* Round 3 */
252: a = HH (a, b, c, d, x[ 0], S31); /* 33 */
253: d = HH (d, a, b, c, x[ 8], S32); /* 34 */
254: c = HH (c, d, a, b, x[ 4], S33); /* 35 */
255: b = HH (b, c, d, a, x[12], S34); /* 36 */
256: a = HH (a, b, c, d, x[ 2], S31); /* 37 */
257: d = HH (d, a, b, c, x[10], S32); /* 38 */
258: c = HH (c, d, a, b, x[ 6], S33); /* 39 */
259: b = HH (b, c, d, a, x[14], S34); /* 40 */
260: a = HH (a, b, c, d, x[ 1], S31); /* 41 */
261: d = HH (d, a, b, c, x[ 9], S32); /* 42 */
262: c = HH (c, d, a, b, x[ 5], S33); /* 43 */
263: b = HH (b, c, d, a, x[13], S34); /* 44 */
264: a = HH (a, b, c, d, x[ 3], S31); /* 45 */
265: d = HH (d, a, b, c, x[11], S32); /* 46 */
266: c = HH (c, d, a, b, x[ 7], S33); /* 47 */
267: b = HH (b, c, d, a, x[15], S34); /* 48 */
268:
269: state[0] += a;
270: state[1] += b;
271: state[2] += c;
272: state[3] += d;
273: }
274: }