1    package org.bouncycastle.crypto.digests;
2    
3    import org.bouncycastle.crypto.Digest;
4    /**
5     * implementation of MD2
6     * as outlined in RFC1319 by B.Kaliski from RSA Laboratories April 1992
7     */
8    public class MD2Digest
9        implements Digest
10   {
11       private static final int DIGEST_LENGTH = 16;
12   
13       /* X buffer */
14       private byte[]   X = new byte[48];
15       private int     xOff;
16       /* M buffer */
17       private byte[]   M = new byte[16];
18       private int     mOff;
19       /* check sum */
20       private byte[]   C = new byte[16];
21       private int COff;
22   
23       public MD2Digest()
24       {
25           reset();
26       }
27           public MD2Digest(MD2Digest t)
28           {
29                   System.arraycopy(t.X, 0, X, 0, t.X.length);
30                   xOff = t.xOff;
31                   System.arraycopy(t.M, 0, M, 0, t.M.length);
32                   mOff = t.mOff;
33                   System.arraycopy(t.C, 0, C, 0, t.C.length);
34                   COff = t.COff;
35           }
36       /**
37        * return the algorithm name
38        *
39        * @return the algorithm name
40        */
41       public String getAlgorithmName()
42       {
43           return "MD2";
44       }
45       /**
46        * return the size, in bytes, of the digest produced by this message digest.
47        *
48        * @return the size, in bytes, of the digest produced by this message digest.
49        */
50           public int getDigestSize()
51       {
52           return DIGEST_LENGTH;
53       }
54       /**
55        * close the digest, producing the final digest value. The doFinal
56        * call leaves the digest reset.
57        *
58        * @param out the array the digest is to be copied into.
59        * @param outOff the offset into the out array the digest is to start at.
60        */
61           public int doFinal(byte[] out, int outOff)
62       {
63           // add padding
64           byte paddingByte = (byte)(M.length-mOff);
65           for (int i=mOff;i<M.length;i++)
66           {
67               M[i] = paddingByte;
68           }
69           //do final check sum
70           processCheckSum(M);
71           // do final block process
72           processBlock(M);
73   
74           processBlock(C);
75   
76           System.arraycopy(X,xOff,out,outOff,16);
77   
78           reset();
79   
80           return DIGEST_LENGTH;
81       }
82       /**
83        * reset the digest back to it's initial state.
84        */
85       public void reset()
86       {
87           xOff = 0;
88           for (int i = 0; i != X.length; i++)
89           {
90               X[i] = 0;
91           }
92           mOff = 0;
93           for (int i = 0; i != M.length; i++)
94           {
95               M[i] = 0;
96           }
97           COff = 0;
98           for (int i = 0; i != C.length; i++)
99           {
100              C[i] = 0;
101          }
102      }
103      /**
104       * update the message digest with a single byte.
105       *
106       * @param in the input byte to be entered.
107       */
108          public void update(byte in)
109      {
110          M[mOff++] = in;
111  
112          if (mOff == 16)
113          {
114              processCheckSum(M);
115              processBlock(M);
116              mOff = 0;
117          }
118      }
119  
120      /**
121       * update the message digest with a block of bytes.
122       *
123       * @param in the byte array containing the data.
124       * @param inOff the offset into the byte array where the data starts.
125       * @param len the length of the data.
126       */
127          public void update(byte[] in, int inOff, int len)
128      {
129          //
130          // fill the current word
131          //
132          while ((mOff != 0) && (len > 0))
133          {
134              update(in[inOff]);
135              inOff++;
136              len--;
137          }
138  
139          //
140          // process whole words.
141          //
142          while (len > 16)
143          {
144              System.arraycopy(in,inOff,M,0,16);
145              processCheckSum(M);
146              processBlock(M);
147              len -= 16;
148              inOff += 16;
149          }
150  
151          //
152          // load in the remainder.
153          //
154          while (len > 0)
155          {
156              update(in[inOff]);
157              inOff++;
158              len--;
159          }
160      }
161      protected void processCheckSum(byte[] m)
162      {
163          int L = C[15];
164          for (int i=0;i<16;i++)
165          {
166              C[i] ^= S[(m[i] ^ L) & 0xff];
167              L = C[i];
168          }
169      }
170      protected void processBlock(byte[] m)
171      {
172          for (int i=0;i<16;i++)
173          {
174              X[i+16] = m[i];
175              X[i+32] = (byte)(m[i] ^ X[i]);
176          }
177          // encrypt block
178          int t = 0;
179  
180          for (int j=0;j<18;j++)
181          {
182              for (int k=0;k<48;k++)
183              {
184                  t = X[k] ^= S[t];
185                  t = t & 0xff;
186              }
187              t = (t + j)%256;
188          }
189       }
190       // 256-byte random permutation constructed from the digits of PI
191      private static final byte[] S = {
192        (byte)41,(byte)46,(byte)67,(byte)201,(byte)162,(byte)216,(byte)124,
193        (byte)1,(byte)61,(byte)54,(byte)84,(byte)161,(byte)236,(byte)240,
194        (byte)6,(byte)19,(byte)98,(byte)167,(byte)5,(byte)243,(byte)192,
195        (byte)199,(byte)115,(byte)140,(byte)152,(byte)147,(byte)43,(byte)217,
196        (byte)188,(byte)76,(byte)130,(byte)202,(byte)30,(byte)155,(byte)87,
197        (byte)60,(byte)253,(byte)212,(byte)224,(byte)22,(byte)103,(byte)66,
198        (byte)111,(byte)24,(byte)138,(byte)23,(byte)229,(byte)18,(byte)190,
199        (byte)78,(byte)196,(byte)214,(byte)218,(byte)158,(byte)222,(byte)73,
200        (byte)160,(byte)251,(byte)245,(byte)142,(byte)187,(byte)47,(byte)238,
201        (byte)122,(byte)169,(byte)104,(byte)121,(byte)145,(byte)21,(byte)178,
202        (byte)7,(byte)63,(byte)148,(byte)194,(byte)16,(byte)137,(byte)11,
203        (byte)34,(byte)95,(byte)33,(byte)128,(byte)127,(byte)93,(byte)154,
204        (byte)90,(byte)144,(byte)50,(byte)39,(byte)53,(byte)62,(byte)204,
205        (byte)231,(byte)191,(byte)247,(byte)151,(byte)3,(byte)255,(byte)25,
206        (byte)48,(byte)179,(byte)72,(byte)165,(byte)181,(byte)209,(byte)215,
207        (byte)94,(byte)146,(byte)42,(byte)172,(byte)86,(byte)170,(byte)198,
208        (byte)79,(byte)184,(byte)56,(byte)210,(byte)150,(byte)164,(byte)125,
209        (byte)182,(byte)118,(byte)252,(byte)107,(byte)226,(byte)156,(byte)116,
210        (byte)4,(byte)241,(byte)69,(byte)157,(byte)112,(byte)89,(byte)100,
211        (byte)113,(byte)135,(byte)32,(byte)134,(byte)91,(byte)207,(byte)101,
212        (byte)230,(byte)45,(byte)168,(byte)2,(byte)27,(byte)96,(byte)37,
213        (byte)173,(byte)174,(byte)176,(byte)185,(byte)246,(byte)28,(byte)70,
214        (byte)97,(byte)105,(byte)52,(byte)64,(byte)126,(byte)15,(byte)85,
215        (byte)71,(byte)163,(byte)35,(byte)221,(byte)81,(byte)175,(byte)58,
216        (byte)195,(byte)92,(byte)249,(byte)206,(byte)186,(byte)197,(byte)234,
217        (byte)38,(byte)44,(byte)83,(byte)13,(byte)110,(byte)133,(byte)40,
218        (byte)132, 9,(byte)211,(byte)223,(byte)205,(byte)244,(byte)65,
219        (byte)129,(byte)77,(byte)82,(byte)106,(byte)220,(byte)55,(byte)200,
220        (byte)108,(byte)193,(byte)171,(byte)250,(byte)36,(byte)225,(byte)123,
221        (byte)8,(byte)12,(byte)189,(byte)177,(byte)74,(byte)120,(byte)136,
222        (byte)149,(byte)139,(byte)227,(byte)99,(byte)232,(byte)109,(byte)233,
223        (byte)203,(byte)213,(byte)254,(byte)59,(byte)0,(byte)29,(byte)57,
224        (byte)242,(byte)239,(byte)183,(byte)14,(byte)102,(byte)88,(byte)208,
225        (byte)228,(byte)166,(byte)119,(byte)114,(byte)248,(byte)235,(byte)117,
226        (byte)75,(byte)10,(byte)49,(byte)68,(byte)80,(byte)180,(byte)143,
227        (byte)237,(byte)31,(byte)26,(byte)219,(byte)153,(byte)141,(byte)51,
228        (byte)159,(byte)17,(byte)131,(byte)20
229      };
230  }
231