001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 package org.apache.geronimo.util.crypto.digests;
019
020 import org.apache.geronimo.util.crypto.ExtendedDigest;
021
022 /**
023 * base implementation of MD4 family style digest as outlined in
024 * "Handbook of Applied Cryptography", pages 344 - 347.
025 */
026 public abstract class GeneralDigest
027 implements ExtendedDigest
028 {
029 private static final int BYTE_LENGTH = 64;
030 private byte[] xBuf;
031 private int xBufOff;
032
033 private long byteCount;
034
035 /**
036 * Standard constructor
037 */
038 protected GeneralDigest()
039 {
040 xBuf = new byte[4];
041 xBufOff = 0;
042 }
043
044 /**
045 * Copy constructor. We are using copy constructors in place
046 * of the Object.clone() interface as this interface is not
047 * supported by J2ME.
048 */
049 protected GeneralDigest(GeneralDigest t)
050 {
051 xBuf = new byte[t.xBuf.length];
052 System.arraycopy(t.xBuf, 0, xBuf, 0, t.xBuf.length);
053
054 xBufOff = t.xBufOff;
055 byteCount = t.byteCount;
056 }
057
058 public void update(
059 byte in)
060 {
061 xBuf[xBufOff++] = in;
062
063 if (xBufOff == xBuf.length)
064 {
065 processWord(xBuf, 0);
066 xBufOff = 0;
067 }
068
069 byteCount++;
070 }
071
072 public void update(
073 byte[] in,
074 int inOff,
075 int len)
076 {
077 //
078 // fill the current word
079 //
080 while ((xBufOff != 0) && (len > 0))
081 {
082 update(in[inOff]);
083
084 inOff++;
085 len--;
086 }
087
088 //
089 // process whole words.
090 //
091 while (len > xBuf.length)
092 {
093 processWord(in, inOff);
094
095 inOff += xBuf.length;
096 len -= xBuf.length;
097 byteCount += xBuf.length;
098 }
099
100 //
101 // load in the remainder.
102 //
103 while (len > 0)
104 {
105 update(in[inOff]);
106
107 inOff++;
108 len--;
109 }
110 }
111
112 public void finish()
113 {
114 long bitLength = (byteCount << 3);
115
116 //
117 // add the pad bytes.
118 //
119 update((byte)128);
120
121 while (xBufOff != 0)
122 {
123 update((byte)0);
124 }
125
126 processLength(bitLength);
127
128 processBlock();
129 }
130
131 public void reset()
132 {
133 byteCount = 0;
134
135 xBufOff = 0;
136 for (int i = 0; i < xBuf.length; i++)
137 {
138 xBuf[i] = 0;
139 }
140 }
141
142 public int getByteLength()
143 {
144 return BYTE_LENGTH;
145 }
146
147 protected abstract void processWord(byte[] in, int inOff);
148
149 protected abstract void processLength(long bitLength);
150
151 protected abstract void processBlock();
152 }