001: package org.bouncycastle.crypto.digests;
002:
003: import org.bouncycastle.crypto.*;
004:
005: /**
006: * implementation of MD2
007: * as outlined in RFC1319 by B.Kaliski from RSA Laboratories April 1992
008: */
009: public class MD2Digest implements ExtendedDigest {
010: private static final int DIGEST_LENGTH = 16;
011:
012: /* X buffer */
013: private byte[] X = new byte[48];
014: private int xOff;
015: /* M buffer */
016: private byte[] M = new byte[16];
017: private int mOff;
018: /* check sum */
019: private byte[] C = new byte[16];
020: private int COff;
021:
022: public MD2Digest() {
023: reset();
024: }
025:
026: public MD2Digest(MD2Digest t) {
027: System.arraycopy(t.X, 0, X, 0, t.X.length);
028: xOff = t.xOff;
029: System.arraycopy(t.M, 0, M, 0, t.M.length);
030: mOff = t.mOff;
031: System.arraycopy(t.C, 0, C, 0, t.C.length);
032: COff = t.COff;
033: }
034:
035: /**
036: * return the algorithm name
037: *
038: * @return the algorithm name
039: */
040: public String getAlgorithmName() {
041: return "MD2";
042: }
043:
044: /**
045: * return the size, in bytes, of the digest produced by this message digest.
046: *
047: * @return the size, in bytes, of the digest produced by this message digest.
048: */
049: public int getDigestSize() {
050: return DIGEST_LENGTH;
051: }
052:
053: /**
054: * close the digest, producing the final digest value. The doFinal
055: * call leaves the digest reset.
056: *
057: * @param out the array the digest is to be copied into.
058: * @param outOff the offset into the out array the digest is to start at.
059: */
060: public int doFinal(byte[] out, int outOff) {
061: // add padding
062: byte paddingByte = (byte) (M.length - mOff);
063: for (int i = mOff; i < M.length; i++) {
064: M[i] = paddingByte;
065: }
066: //do final check sum
067: processCheckSum(M);
068: // do final block process
069: processBlock(M);
070:
071: processBlock(C);
072:
073: System.arraycopy(X, xOff, out, outOff, 16);
074:
075: reset();
076:
077: return DIGEST_LENGTH;
078: }
079:
080: /**
081: * reset the digest back to it's initial state.
082: */
083: public void reset() {
084: xOff = 0;
085: for (int i = 0; i != X.length; i++) {
086: X[i] = 0;
087: }
088: mOff = 0;
089: for (int i = 0; i != M.length; i++) {
090: M[i] = 0;
091: }
092: COff = 0;
093: for (int i = 0; i != C.length; i++) {
094: C[i] = 0;
095: }
096: }
097:
098: /**
099: * update the message digest with a single byte.
100: *
101: * @param in the input byte to be entered.
102: */
103: public void update(byte in) {
104: M[mOff++] = in;
105:
106: if (mOff == 16) {
107: processCheckSum(M);
108: processBlock(M);
109: mOff = 0;
110: }
111: }
112:
113: /**
114: * update the message digest with a block of bytes.
115: *
116: * @param in the byte array containing the data.
117: * @param inOff the offset into the byte array where the data starts.
118: * @param len the length of the data.
119: */
120: public void update(byte[] in, int inOff, int len) {
121: //
122: // fill the current word
123: //
124: while ((mOff != 0) && (len > 0)) {
125: update(in[inOff]);
126: inOff++;
127: len--;
128: }
129:
130: //
131: // process whole words.
132: //
133: while (len > 16) {
134: System.arraycopy(in, inOff, M, 0, 16);
135: processCheckSum(M);
136: processBlock(M);
137: len -= 16;
138: inOff += 16;
139: }
140:
141: //
142: // load in the remainder.
143: //
144: while (len > 0) {
145: update(in[inOff]);
146: inOff++;
147: len--;
148: }
149: }
150:
151: protected void processCheckSum(byte[] m) {
152: int L = C[15];
153: for (int i = 0; i < 16; i++) {
154: C[i] ^= S[(m[i] ^ L) & 0xff];
155: L = C[i];
156: }
157: }
158:
159: protected void processBlock(byte[] m) {
160: for (int i = 0; i < 16; i++) {
161: X[i + 16] = m[i];
162: X[i + 32] = (byte) (m[i] ^ X[i]);
163: }
164: // encrypt block
165: int t = 0;
166:
167: for (int j = 0; j < 18; j++) {
168: for (int k = 0; k < 48; k++) {
169: t = X[k] ^= S[t];
170: t = t & 0xff;
171: }
172: t = (t + j) % 256;
173: }
174: }
175:
176: // 256-byte random permutation constructed from the digits of PI
177: private static final byte[] S = { (byte) 41, (byte) 46, (byte) 67,
178: (byte) 201, (byte) 162, (byte) 216, (byte) 124, (byte) 1,
179: (byte) 61, (byte) 54, (byte) 84, (byte) 161, (byte) 236,
180: (byte) 240, (byte) 6, (byte) 19, (byte) 98, (byte) 167,
181: (byte) 5, (byte) 243, (byte) 192, (byte) 199, (byte) 115,
182: (byte) 140, (byte) 152, (byte) 147, (byte) 43, (byte) 217,
183: (byte) 188, (byte) 76, (byte) 130, (byte) 202, (byte) 30,
184: (byte) 155, (byte) 87, (byte) 60, (byte) 253, (byte) 212,
185: (byte) 224, (byte) 22, (byte) 103, (byte) 66, (byte) 111,
186: (byte) 24, (byte) 138, (byte) 23, (byte) 229, (byte) 18,
187: (byte) 190, (byte) 78, (byte) 196, (byte) 214, (byte) 218,
188: (byte) 158, (byte) 222, (byte) 73, (byte) 160, (byte) 251,
189: (byte) 245, (byte) 142, (byte) 187, (byte) 47, (byte) 238,
190: (byte) 122, (byte) 169, (byte) 104, (byte) 121, (byte) 145,
191: (byte) 21, (byte) 178, (byte) 7, (byte) 63, (byte) 148,
192: (byte) 194, (byte) 16, (byte) 137, (byte) 11, (byte) 34,
193: (byte) 95, (byte) 33, (byte) 128, (byte) 127, (byte) 93,
194: (byte) 154, (byte) 90, (byte) 144, (byte) 50, (byte) 39,
195: (byte) 53, (byte) 62, (byte) 204, (byte) 231, (byte) 191,
196: (byte) 247, (byte) 151, (byte) 3, (byte) 255, (byte) 25,
197: (byte) 48, (byte) 179, (byte) 72, (byte) 165, (byte) 181,
198: (byte) 209, (byte) 215, (byte) 94, (byte) 146, (byte) 42,
199: (byte) 172, (byte) 86, (byte) 170, (byte) 198, (byte) 79,
200: (byte) 184, (byte) 56, (byte) 210, (byte) 150, (byte) 164,
201: (byte) 125, (byte) 182, (byte) 118, (byte) 252, (byte) 107,
202: (byte) 226, (byte) 156, (byte) 116, (byte) 4, (byte) 241,
203: (byte) 69, (byte) 157, (byte) 112, (byte) 89, (byte) 100,
204: (byte) 113, (byte) 135, (byte) 32, (byte) 134, (byte) 91,
205: (byte) 207, (byte) 101, (byte) 230, (byte) 45, (byte) 168,
206: (byte) 2, (byte) 27, (byte) 96, (byte) 37, (byte) 173,
207: (byte) 174, (byte) 176, (byte) 185, (byte) 246, (byte) 28,
208: (byte) 70, (byte) 97, (byte) 105, (byte) 52, (byte) 64,
209: (byte) 126, (byte) 15, (byte) 85, (byte) 71, (byte) 163,
210: (byte) 35, (byte) 221, (byte) 81, (byte) 175, (byte) 58,
211: (byte) 195, (byte) 92, (byte) 249, (byte) 206, (byte) 186,
212: (byte) 197, (byte) 234, (byte) 38, (byte) 44, (byte) 83,
213: (byte) 13, (byte) 110, (byte) 133, (byte) 40, (byte) 132,
214: 9, (byte) 211, (byte) 223, (byte) 205, (byte) 244,
215: (byte) 65, (byte) 129, (byte) 77, (byte) 82, (byte) 106,
216: (byte) 220, (byte) 55, (byte) 200, (byte) 108, (byte) 193,
217: (byte) 171, (byte) 250, (byte) 36, (byte) 225, (byte) 123,
218: (byte) 8, (byte) 12, (byte) 189, (byte) 177, (byte) 74,
219: (byte) 120, (byte) 136, (byte) 149, (byte) 139, (byte) 227,
220: (byte) 99, (byte) 232, (byte) 109, (byte) 233, (byte) 203,
221: (byte) 213, (byte) 254, (byte) 59, (byte) 0, (byte) 29,
222: (byte) 57, (byte) 242, (byte) 239, (byte) 183, (byte) 14,
223: (byte) 102, (byte) 88, (byte) 208, (byte) 228, (byte) 166,
224: (byte) 119, (byte) 114, (byte) 248, (byte) 235, (byte) 117,
225: (byte) 75, (byte) 10, (byte) 49, (byte) 68, (byte) 80,
226: (byte) 180, (byte) 143, (byte) 237, (byte) 31, (byte) 26,
227: (byte) 219, (byte) 153, (byte) 141, (byte) 51, (byte) 159,
228: (byte) 17, (byte) 131, (byte) 20 };
229:
230: public int getByteLength() {
231: return 16;
232: }
233: }
|