2004-06-16 Sebastien Pouliot <sebastien@ximian.com>
[mono.git] / mcs / class / corlib / System.Security.Cryptography / HashAlgorithm.cs
1 //
2 // System.Security.Cryptography HashAlgorithm Class implementation
3 //
4 // Authors:
5 //      Matthew S. Ford (Matthew.S.Ford@Rose-Hulman.Edu)
6 //      Sebastien Pouliot (sebastien@ximian.com)
7 //
8 // Copyright 2001 by Matthew S. Ford.
9 // Portions (C) 2002 Motus Technologies Inc. (http://www.motus.com)
10 // (C) 2004 Novell (http://www.novell.com)
11 //
12
13 //
14 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
15 //
16 // Permission is hereby granted, free of charge, to any person obtaining
17 // a copy of this software and associated documentation files (the
18 // "Software"), to deal in the Software without restriction, including
19 // without limitation the rights to use, copy, modify, merge, publish,
20 // distribute, sublicense, and/or sell copies of the Software, and to
21 // permit persons to whom the Software is furnished to do so, subject to
22 // the following conditions:
23 // 
24 // The above copyright notice and this permission notice shall be
25 // included in all copies or substantial portions of the Software.
26 // 
27 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
31 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
32 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
33 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 //
35
36 using System.Globalization;
37 using System.IO;
38
39 namespace System.Security.Cryptography {
40
41         public abstract class HashAlgorithm : ICryptoTransform {
42
43                 protected byte[] HashValue;
44                 protected int HashSizeValue;
45                 protected int State;
46                 private bool disposed;
47
48                 protected HashAlgorithm () 
49                 {
50                         disposed = false;
51                 }
52
53                 public virtual bool CanTransformMultipleBlocks {
54                         get { return true; }
55                 }
56
57                 public virtual bool CanReuseTransform {
58                         get { return true; }
59                 }
60
61                 public void Clear () 
62                 {
63                         // same as System.IDisposable.Dispose() which is documented
64                         Dispose (true);
65                 }
66
67                 public byte[] ComputeHash (byte[] input) 
68                 {
69                         if (input == null)
70                                 throw new ArgumentNullException ("input");
71
72                         return ComputeHash (input, 0, input.Length);
73                 }
74
75                 public byte[] ComputeHash (byte[] buffer, int offset, int count) 
76                 {
77                         if (disposed)
78                                 throw new ObjectDisposedException ("HashAlgorithm");
79                         if (buffer == null)
80                                 throw new ArgumentNullException ("buffer");
81                         if (offset < 0)
82                                 throw new ArgumentOutOfRangeException ("offset", "< 0");
83                         if (count < 0)
84                                 throw new ArgumentException ("count", "< 0");
85                         // ordered to avoid possible integer overflow
86                         if (offset > buffer.Length - count) {
87                                 throw new ArgumentException ("offset + count", 
88                                         Locale.GetText ("Overflow"));
89                         }
90
91                         HashCore (buffer, offset, count);
92                         HashValue = HashFinal ();
93                         Initialize ();
94                         
95                         return HashValue;
96                 }
97
98                 public byte[] ComputeHash (Stream inputStream) 
99                 {
100                         // don't read stream unless object is ready to use
101                         if (disposed)
102                                 throw new ObjectDisposedException ("HashAlgorithm");
103
104                         byte[] buffer = new byte [4096];
105                         int len = inputStream.Read (buffer, 0, 4096);
106                         while (len > 0) {
107                                 HashCore (buffer, 0, len);
108                                 len = inputStream.Read (buffer, 0, 4096);
109                         }
110                         HashValue = HashFinal ();
111                         Initialize ();
112                         return HashValue;
113                 }
114         
115                 public static HashAlgorithm Create () 
116                 {
117                         return Create ("System.Security.Cryptography.HashAlgorithm");
118                 }
119         
120                 public static HashAlgorithm Create (string hashName)
121                 {
122                         return (HashAlgorithm) CryptoConfig.CreateFromName (hashName);
123                 }
124         
125                 public virtual byte[] Hash {
126                         get { 
127                                 if (HashValue == null) {
128                                         throw new CryptographicUnexpectedOperationException (
129                                                 Locale.GetText ("No hash value computed."));
130                                 }
131                                 return HashValue; 
132                         }
133                 }
134         
135                 protected abstract void HashCore (byte[] rgb, int start, int size);
136
137                 protected abstract byte[] HashFinal ();
138
139                 public virtual int HashSize {
140                         get { return HashSizeValue; }
141                 }
142         
143                 public abstract void Initialize ();
144
145                 protected virtual void Dispose (bool disposing)
146                 {
147                         disposed = true;
148                 }
149         
150                 public virtual int InputBlockSize {
151                         get { return 1; }
152                 }
153         
154                 public virtual int OutputBlockSize {
155                         get { return 1; }
156                 }
157
158                 void IDisposable.Dispose () 
159                 {
160                         Dispose (true);
161                         GC.SuppressFinalize (this);  // Finalization is now unnecessary
162                 }
163                 
164                 public int TransformBlock (byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) 
165                 {
166                         if (inputBuffer == null)
167                                 throw new ArgumentNullException ("inputBuffer");
168                         if (outputBuffer == null)
169                                 throw new ArgumentNullException ("outputBuffer");
170
171                         if (inputOffset < 0)
172                                 throw new ArgumentOutOfRangeException ("inputOffset", "< 0");
173                         if (inputCount < 0)
174                                 throw new ArgumentException ("inputCount");
175
176                         // ordered to avoid possible integer overflow
177                         if ((inputOffset < 0) || (inputOffset > inputBuffer.Length - inputCount))
178                                 throw new ArgumentException ("inputBuffer");
179                         // ordered to avoid possible integer overflow
180                         if ((outputOffset < 0) || (outputOffset > outputBuffer.Length - inputCount))
181                                 throw new IndexOutOfRangeException ("outputBuffer");
182
183                         // note: other exceptions are handled by Buffer.BlockCopy
184                         Buffer.BlockCopy (inputBuffer, inputOffset, outputBuffer, outputOffset, inputCount);
185                         HashCore (inputBuffer, inputOffset, inputCount);
186
187                         return inputCount;
188                 }
189         
190                 public byte[] TransformFinalBlock (byte[] inputBuffer, int inputOffset, int inputCount) 
191                 {
192                         if (inputBuffer == null)
193                                 throw new ArgumentNullException ("inputBuffer");
194                         if (inputCount < 0)
195                                 throw new ArgumentException ("inputCount");
196                         // ordered to avoid possible integer overflow
197                         if (inputOffset > inputBuffer.Length - inputCount) {
198                                 throw new ArgumentException ("inputOffset + inputCount", 
199                                         Locale.GetText ("Overflow"));
200                         }
201
202                         byte[] outputBuffer = new byte [inputCount];
203                         
204                         // note: other exceptions are handled by Buffer.BlockCopy
205                         Buffer.BlockCopy (inputBuffer, inputOffset, outputBuffer, 0, inputCount);
206                         
207                         HashCore (inputBuffer, inputOffset, inputCount);
208                         HashValue = HashFinal ();
209                         Initialize ();
210                         
211                         return outputBuffer;
212                 }
213         }
214 }