//
// System.Security.Cryptography HashAlgorithm Class implementation
//
// Authors:
// Matthew S. Ford (Matthew.S.Ford@Rose-Hulman.Edu)
// Sebastien Pouliot (spouliot@motus.com)
//
// Copyright 2001 by Matthew S. Ford.
// Portions (C) 2002 Motus Technologies Inc. (http://www.motus.com)
//
// Comment: Adapted to the Project from Mono CVS as Sebastien Pouliot suggested to enable
// support of Npgsql MD5 authentication in platforms which don't have support for MD5 algorithm.
//
using System;
using System.IO;
namespace Npgsql
{
// Comment: Removed the ICryptoTransform implementation as this interface may be not supported by
// all platforms.
internal abstract class HashAlgorithm : IDisposable
{
protected byte[] HashValue; // Caches the hash after it is calculated. Accessed through the Hash property.
protected int HashSizeValue; // The size of the hash in bits.
protected int State; // nonzero when in use; zero when not in use
private bool disposed;
///
/// Called from constructor of derived class.
///
protected HashAlgorithm()
{
disposed = false;
}
///
/// Finalizer for HashAlgorithm
///
~HashAlgorithm()
{
Dispose(false);
}
///
/// Get whether or not the hash can transform multiple blocks at a time.
/// Note: MUST be overriden if descendant can transform multiple block
/// on a single call!
///
public virtual bool CanTransformMultipleBlocks
{
get { return true; }
}
public virtual bool CanReuseTransform
{
get { return true; }
}
public void Clear()
{
// same as System.IDisposable.Dispose() which is documented
Dispose(true);
}
///
/// Computes the entire hash of all the bytes in the byte array.
///
public byte[] ComputeHash(byte[] input)
{
return ComputeHash(input, 0, input.Length);
}
public byte[] ComputeHash(byte[] buffer, int offset, int count)
{
if (disposed)
{
throw new ObjectDisposedException("HashAlgorithm");
}
HashCore(buffer, offset, count);
HashValue = HashFinal();
Initialize();
return HashValue;
}
public byte[] ComputeHash(Stream inputStream)
{
// don't read stream unless object is ready to use
if (disposed)
{
throw new ObjectDisposedException("HashAlgorithm");
}
int l = (int) (inputStream.Length - inputStream.Position);
byte[] buffer = new byte[l];
inputStream.Read(buffer, 0, l);
return ComputeHash(buffer, 0, l);
}
// Commented out because it uses the CryptoConfig which can't be available in all platforms
/*
///
/// Creates the default implementation of the default hash algorithm (SHA1).
///
public static HashAlgorithm Create ()
{
return Create ("System.Security.Cryptography.HashAlgorithm");
}*/
/*
///
/// Creates a specific implementation of the general hash idea.
///
/// Specifies which derived class to create.
public static HashAlgorithm Create (string hashName)
{
return (HashAlgorithm) CryptoConfig.CreateFromName (hashName);
}*/
// Changed Exception type because it uses the CryptographicUnexpectedOperationException
// which can't be available in all platforms.
///
/// Gets the previously computed hash.
///
public virtual byte[] Hash
{
get
{
if (HashValue == null)
{
throw new NullReferenceException("HashValue is null");
}
return HashValue;
}
}
///
/// When overridden in a derived class, drives the hashing function.
///
///
///
///
protected abstract void HashCore(byte[] rgb, int start, int size);
///
/// When overridden in a derived class, this pads and hashes whatever data might be left in the buffers and then returns the hash created.
///
protected abstract byte[] HashFinal();
///
/// Returns the size in bits of the hash.
///
public virtual int HashSize
{
get { return HashSizeValue; }
}
///
/// When overridden in a derived class, initializes the object to prepare for hashing.
///
public abstract void Initialize();
protected virtual void Dispose(bool disposing)
{
disposed = true;
}
///
/// Must be overriden if not 1
///
public virtual int InputBlockSize
{
get { return 1; }
}
///
/// Must be overriden if not 1
///
public virtual int OutputBlockSize
{
get { return 1; }
}
void IDisposable.Dispose()
{
Dispose(true);
GC.SuppressFinalize(this); // Finalization is now unnecessary
}
///
/// Used for stream chaining. Computes hash as data passes through it.
///
/// The buffer from which to grab the data to be copied.
/// The offset into the input buffer to start reading at.
/// The number of bytes to be copied.
/// The buffer to write the copied data to.
/// At what point in the outputBuffer to write the data at.
public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
{
Buffer.BlockCopy(inputBuffer, inputOffset, outputBuffer, outputOffset, inputCount);
HashCore(inputBuffer, inputOffset, inputCount);
return inputCount;
}
///
/// Used for stream chaining. Computes hash as data passes through it. Finishes off the hash.
///
/// The buffer from which to grab the data to be copied.
/// The offset into the input buffer to start reading at.
/// The number of bytes to be copied.
public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount)
{
byte[] outputBuffer = new byte[inputCount];
Buffer.BlockCopy(inputBuffer, inputOffset, outputBuffer, 0, inputCount);
HashCore(inputBuffer, inputOffset, inputCount);
HashValue = HashFinal();
Initialize();
return outputBuffer;
}
}
}