HashAlgorithm.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. //
  2. // System.Security.Cryptography HashAlgorithm Class implementation
  3. //
  4. // Authors:
  5. // Matthew S. Ford ([email protected])
  6. // Sebastien Pouliot ([email protected])
  7. //
  8. // Copyright 2001 by Matthew S. Ford.
  9. // Portions (C) 2002 Motus Technologies Inc. (http://www.motus.com)
  10. //
  11. using System.IO;
  12. namespace System.Security.Cryptography {
  13. public abstract class HashAlgorithm : ICryptoTransform {
  14. protected byte[] HashValue; // Caches the hash after it is calculated. Accessed through the Hash property.
  15. protected int HashSizeValue; // The size of the hash in bits.
  16. protected int State; // nonzero when in use; zero when not in use
  17. private bool disposed;
  18. /// <summary>
  19. /// Called from constructor of derived class.
  20. /// </summary>
  21. protected HashAlgorithm ()
  22. {
  23. disposed = false;
  24. }
  25. /// <summary>
  26. /// Get whether or not the hash can transform multiple blocks at a time.
  27. /// Note: MUST be overriden if descendant can transform multiple block
  28. /// on a single call!
  29. /// </summary>
  30. public virtual bool CanTransformMultipleBlocks {
  31. get { return true; }
  32. }
  33. public virtual bool CanReuseTransform {
  34. get { return true; }
  35. }
  36. public void Clear()
  37. {
  38. // same as System.IDisposable.Dispose() which is documented
  39. Dispose (true);
  40. }
  41. /// <summary>
  42. /// Computes the entire hash of all the bytes in the byte array.
  43. /// </summary>
  44. public byte[] ComputeHash (byte[] input)
  45. {
  46. return ComputeHash (input, 0, input.Length);
  47. }
  48. public byte[] ComputeHash (byte[] buffer, int offset, int count)
  49. {
  50. if (disposed)
  51. throw new ObjectDisposedException ("HashAlgorithm");
  52. HashCore (buffer, offset, count);
  53. HashValue = HashFinal ();
  54. Initialize ();
  55. return HashValue;
  56. }
  57. public byte[] ComputeHash (Stream inputStream)
  58. {
  59. // don't read stream unless object is ready to use
  60. if (disposed)
  61. throw new ObjectDisposedException ("HashAlgorithm");
  62. int l = (int) (inputStream.Length - inputStream.Position);
  63. byte[] buffer = new byte [l];
  64. inputStream.Read (buffer, 0, l);
  65. return ComputeHash (buffer, 0, l);
  66. }
  67. /// <summary>
  68. /// Creates the default implementation of the default hash algorithm (SHA1).
  69. /// </summary>
  70. public static HashAlgorithm Create ()
  71. {
  72. return Create ("System.Security.Cryptography.HashAlgorithm");
  73. }
  74. /// <summary>
  75. /// Creates a specific implementation of the general hash idea.
  76. /// </summary>
  77. /// <param name="hashName">Specifies which derived class to create.</param>
  78. public static HashAlgorithm Create (string hashName)
  79. {
  80. return (HashAlgorithm) CryptoConfig.CreateFromName (hashName);
  81. }
  82. /// <summary>
  83. /// Gets the previously computed hash.
  84. /// </summary>
  85. public virtual byte[] Hash {
  86. get {
  87. if (HashValue == null)
  88. throw new CryptographicUnexpectedOperationException ();
  89. return HashValue;
  90. }
  91. }
  92. /// <summary>
  93. /// When overridden in a derived class, drives the hashing function.
  94. /// </summary>
  95. /// <param name="rgb"></param>
  96. /// <param name="start"></param>
  97. /// <param name="size"></param>
  98. protected abstract void HashCore (byte[] rgb, int start, int size);
  99. /// <summary>
  100. /// When overridden in a derived class, this pads and hashes whatever data might be left in the buffers and then returns the hash created.
  101. /// </summary>
  102. protected abstract byte[] HashFinal ();
  103. /// <summary>
  104. /// Returns the size in bits of the hash.
  105. /// </summary>
  106. public virtual int HashSize {
  107. get { return HashSizeValue; }
  108. }
  109. /// <summary>
  110. /// When overridden in a derived class, initializes the object to prepare for hashing.
  111. /// </summary>
  112. public abstract void Initialize ();
  113. protected virtual void Dispose (bool disposing)
  114. {
  115. disposed = true;
  116. }
  117. /// <summary>
  118. /// Must be overriden if not 1
  119. /// </summary>
  120. public virtual int InputBlockSize {
  121. get { return 1; }
  122. }
  123. /// <summary>
  124. /// Must be overriden if not 1
  125. /// </summary>
  126. public virtual int OutputBlockSize {
  127. get { return 1; }
  128. }
  129. void IDisposable.Dispose ()
  130. {
  131. Dispose (true);
  132. GC.SuppressFinalize (this); // Finalization is now unnecessary
  133. }
  134. /// <summary>
  135. /// Used for stream chaining. Computes hash as data passes through it.
  136. /// </summary>
  137. /// <param name="inputBuffer">The buffer from which to grab the data to be copied.</param>
  138. /// <param name="inputOffset">The offset into the input buffer to start reading at.</param>
  139. /// <param name="inputCount">The number of bytes to be copied.</param>
  140. /// <param name="outputBuffer">The buffer to write the copied data to.</param>
  141. /// <param name="outputOffset">At what point in the outputBuffer to write the data at.</param>
  142. public int TransformBlock (byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
  143. {
  144. Buffer.BlockCopy (inputBuffer, inputOffset, outputBuffer, outputOffset, inputCount);
  145. HashCore (inputBuffer, inputOffset, inputCount);
  146. return inputCount;
  147. }
  148. /// <summary>
  149. /// Used for stream chaining. Computes hash as data passes through it. Finishes off the hash.
  150. /// </summary>
  151. /// <param name="inputBuffer">The buffer from which to grab the data to be copied.</param>
  152. /// <param name="inputOffset">The offset into the input buffer to start reading at.</param>
  153. /// <param name="inputCount">The number of bytes to be copied.</param>
  154. public byte[] TransformFinalBlock (byte[] inputBuffer, int inputOffset, int inputCount)
  155. {
  156. byte[] outputBuffer = new byte[inputCount];
  157. Buffer.BlockCopy (inputBuffer, inputOffset, outputBuffer, 0, inputCount);
  158. HashCore (inputBuffer, inputOffset, inputCount);
  159. HashValue = HashFinal ();
  160. Initialize ();
  161. return outputBuffer;
  162. }
  163. }
  164. }