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    }