1 files changed, 118 insertions, 0 deletions
diff --git a/Crypto/src/crypto/digests/GeneralDigest.cs b/Crypto/src/crypto/digests/GeneralDigest.cs
new file mode 100644
index 000000000..77c17ed58
--- /dev/null
+++ b/Crypto/src/crypto/digests/GeneralDigest.cs
@@ -0,0 +1,118 @@
+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;
+ Array.Clear(xBuf, 0, xBuf.Length);
+ }
+
+ 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);
+ }
+}
|