using System; namespace Org.BouncyCastle.Crypto.Digests { /** * base implementation of MD4 family style digest as outlined in * "Handbook of Applied Cryptography", pages 344 - 347. */ public abstract class GeneralDigest : IDigest { private const int BYTE_LENGTH = 64; private byte[] xBuf; private int xBufOff; private long byteCount; internal GeneralDigest() { xBuf = new byte[4]; } internal GeneralDigest(GeneralDigest t) { xBuf = new byte[t.xBuf.Length]; Array.Copy(t.xBuf, 0, xBuf, 0, t.xBuf.Length); xBufOff = t.xBufOff; byteCount = t.byteCount; } public void Update(byte input) { xBuf[xBufOff++] = input; if (xBufOff == xBuf.Length) { ProcessWord(xBuf, 0); xBufOff = 0; } byteCount++; } public void BlockUpdate( byte[] input, int inOff, int length) { // // fill the current word // while ((xBufOff != 0) && (length > 0)) { Update(input[inOff]); inOff++; length--; } // // process whole words. // while (length > xBuf.Length) { ProcessWord(input, inOff); inOff += xBuf.Length; length -= xBuf.Length; byteCount += xBuf.Length; } // // load in the remainder. // while (length > 0) { Update(input[inOff]); inOff++; length--; } } public void Finish() { long bitLength = (byteCount << 3); // // add the pad bytes. // Update((byte)128); while (xBufOff != 0) Update((byte)0); ProcessLength(bitLength); ProcessBlock(); } public virtual void Reset() { byteCount = 0; xBufOff = 0; for ( int i = 0; i < xBuf.Length; i++ ) xBuf[i] = 0; } public int GetByteLength() { return BYTE_LENGTH; } internal abstract void ProcessWord(byte[] input, int inOff); internal abstract void ProcessLength(long bitLength); internal abstract void ProcessBlock(); public abstract string AlgorithmName { get; } public abstract int GetDigestSize(); public abstract int DoFinal(byte[] output, int outOff); } }