using System; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Digests; namespace JXCMS.Core.Encrypt { public abstract class SM3Digest: IDigest { private const int BYTE_LENGTH = 64; private byte[] xBuf; private int xBufOff; private long byteCount; internal SM3Digest() { xBuf = new byte[4]; } internal SM3Digest(SM3Digest 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); } }