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