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