/*
* Mentalis.org Security Library
*
* Copyright © 2002-2005, The KPD-Team
* All rights reserved.
* http://www.mentalis.org/
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Neither the name of the KPD-Team, nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Security.Cryptography;
using System.Runtime.InteropServices;
using Org.Mentalis.Security;
namespace Org.Mentalis.Security.Cryptography {
///
/// Computes the hash for the input data using the implementation provided by the cryptographic service provider (CSP).
///
/// Warning: The MD4 algorithm is a broken algorithm. It should only be used for compatibility with older systems.
public sealed class MD4CryptoServiceProvider : MD4 {
///
/// Initializes a new instance of the class. This class cannot be inherited.
///
public MD4CryptoServiceProvider() {
// acquire an MD4 context
m_Provider = CAPIProvider.Handle;
/* if (SspiProvider.CryptAcquireContext(ref m_Provider, IntPtr.Zero, null, SecurityConstants.PROV_RSA_FULL, 0) == 0) {
if (Marshal.GetLastWin32Error() == SecurityConstants.NTE_BAD_KEYSET)
SspiProvider.CryptAcquireContext(ref m_Provider, IntPtr.Zero, null, SecurityConstants.PROV_RSA_FULL, SecurityConstants.CRYPT_NEWKEYSET);
}*/
Initialize();
m_Disposed = false;
}
///
/// Initializes an instance of .
///
/// The MD4CryptoServiceProvider instance has been disposed.
public override void Initialize() {
if (m_Disposed)
throw new ObjectDisposedException(this.GetType().FullName);
if (m_Hash != 0) {
SspiProvider.CryptDestroyHash(m_Hash);
}
SspiProvider.CryptCreateHash(m_Provider, SecurityConstants.CALG_MD4, 0, 0, out m_Hash);
}
///
/// Routes data written to the object into the hash algorithm for computing the hash.
///
/// The array of data bytes.
/// The offset into the byte array from which to begin using data.
/// The number of bytes in the array to use as data.
/// The MD4CryptoServiceProvider instance has been disposed.
/// The data could not be hashed.
protected override void HashCore(byte[] array, int ibStart, int cbSize) {
if (m_Disposed)
throw new ObjectDisposedException(this.GetType().FullName);
byte[] copy = new byte[cbSize];
Array.Copy(array, ibStart, copy, 0, cbSize);
if (SspiProvider.CryptHashData(m_Hash, copy, copy.Length, 0) == 0)
throw new CryptographicException("The data could not be hashed.");
}
///
/// Returns the computed hash as an array of bytes after all data has been written to the object.
///
/// The computed hash value.
/// The MD4CryptoServiceProvider instance has been disposed.
/// The data could not be hashed.
protected override byte[] HashFinal() {
if (m_Disposed)
throw new ObjectDisposedException(this.GetType().FullName);
byte[] buffer = new byte[16];
int length = buffer.Length;
if (SspiProvider.CryptGetHashParam(m_Hash, SecurityConstants.HP_HASHVAL, buffer, ref length, 0) == 0)
throw new CryptographicException("The hash value could not be read.");
return buffer;
}
///
/// Releases the unmanaged resources used by the and optionally releases the managed resources.
///
/// true to release both managed and unmanaged resources; false to release only unmanaged resources.
protected override void Dispose(bool disposing) {
if (!m_Disposed) {
if (m_Hash != 0) {
SspiProvider.CryptDestroyHash(m_Hash);
m_Hash = 0;
}
/* if (m_Provider != 0) {
SspiProvider.CryptReleaseContext(m_Provider, 0);
m_Provider = 0;
}*/
try {
GC.SuppressFinalize(this);
} catch {}
m_Disposed = true;
}
}
///
/// Finalizes the MD4CryptoServiceProvider.
///
~MD4CryptoServiceProvider() {
Clear();
}
///
/// Holds the handle of the crypto service provider.
///
private int m_Provider;
///
/// Holds the hash handle.
///
private int m_Hash;
///
/// true if the object ahs been disposed, false otherwise.
///
private bool m_Disposed;
}
}