/*
* 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 {
///
/// Represents an ARCFour managed ICryptoTransform.
///
internal class RC4UnmanagedTransform : ICryptoTransform {
///
/// Initializes a new instance of the class.
///
/// The key used to initialize the RC4 state.
public RC4UnmanagedTransform(byte[] key) {
m_Key = new SymmetricKey(CryptoProvider.RsaFull, CryptoAlgorithm.RC4, key);
}
///
/// Gets a value indicating whether the current transform can be reused.
///
/// This property returns true.
public bool CanReuseTransform {
get {
return true;
}
}
///
/// Gets a value indicating whether multiple blocks can be transformed.
///
/// This property returns true.
public bool CanTransformMultipleBlocks {
get {
return true;
}
}
///
/// Gets the input block size.
///
/// This property returns 1.
public int InputBlockSize {
get {
return 1;
}
}
///
/// Gets the output block size.
///
/// This property returns 1.
public int OutputBlockSize {
get {
return 1;
}
}
///
/// Transforms the specified region of the input byte array and copies the resulting transform to the specified region of the output byte array.
///
/// The input for which to compute the transform.
/// The offset into the input byte array from which to begin using data.
/// The number of bytes in the input byte array to use as data.
/// The output to which to write the transform.
/// The offset into the output byte array from which to begin writing data.
/// The number of bytes written.
/// The object has been disposed.
/// or is a null reference (Nothing in Visual Basic).
/// , or is invalid.
public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) {
if (m_Key == null)
throw new ObjectDisposedException(this.GetType().FullName);
if (inputBuffer == null || outputBuffer == null)
throw new ArgumentNullException();
if (inputCount < 0 || inputOffset < 0 || outputOffset < 0 ||inputOffset + inputCount > inputBuffer.Length || outputBuffer.Length - outputOffset < inputCount)
throw new ArgumentOutOfRangeException();
byte[] buffer = new byte[inputCount];
int length = buffer.Length;
Array.Copy(inputBuffer, inputOffset, buffer, 0, length);
if (SspiProvider.CryptEncrypt(m_Key.Handle, 0, 0, 0, buffer, ref length, length) == 0)
throw new CryptographicException("Could not transform data.");
Array.Copy(buffer, 0, outputBuffer, outputOffset, length);
Array.Clear(buffer, 0, buffer.Length);
return length;
}
///
/// Transforms the specified region of the specified byte array.
///
/// The input for which to compute the transform.
/// The offset into the byte array from which to begin using data.
/// The number of bytes in the byte array to use as data.
/// The computed transform.
/// The object has been disposed.
/// is a null reference (Nothing in Visual Basic).
/// or is invalid.
public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount ) {
if (m_Key == null)
throw new ObjectDisposedException(this.GetType().FullName);
if (inputBuffer == null)
throw new ArgumentNullException();
if (inputCount < 0 || inputOffset < 0 ||inputOffset + inputCount > inputBuffer.Length)
throw new ArgumentOutOfRangeException();
byte[] buffer = new byte[inputCount];
int length = buffer.Length;
Array.Copy(inputBuffer, inputOffset, buffer, 0, length);
if (SspiProvider.CryptEncrypt(m_Key.Handle, 0, 1, 0, buffer, ref length, length) == 0)
throw new CryptographicException("Could not transform data.");
return buffer;
}
///
/// Disposes of the cryptographic parameters.
///
public void Dispose() {
if (m_Key != null) {
m_Key.Dispose();
m_Key = null;
}
try {
GC.SuppressFinalize(this);
} catch {}
}
///
/// Finalizes the object.
///
~RC4UnmanagedTransform() {
Dispose();
}
///
/// Holds the used for the cryptographic transformations.
///
private SymmetricKey m_Key;
}
}