HashAlgorithm.cs 5.9 KB

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