/* * 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 the base class from which all implementations of the RC4 symmetric stream cipher must inherit. /// /// /// RC4 is a trademark of RSA Data Security Inc. /// public abstract class RC4 : SymmetricAlgorithm { /// /// Initializes a new instance of the RC4 class. /// /// /// The default keysize is 128 bits. /// public RC4() { this.KeySizeValue = 128; } /// /// Gets or sets the block size of the cryptographic operation in bits. /// /// The block size of RC4 is always 8 bits. /// The block size is invalid. public override int BlockSize { get { return 8; } set { if (value != 8 && value != 0) throw new CryptographicException("RC4 is a stream cipher, not a block cipher."); } } /// /// Gets or sets the feedback size of the cryptographic operation in bits. /// /// This property always throws a . /// This exception is always thrown. /// RC4 doesn't use the FeedbackSize property. public override int FeedbackSize { get { throw new CryptographicException("RC4 doesn't use the feedback size property."); } set { throw new CryptographicException("RC4 doesn't use the feedback size property."); } } /// /// Gets or sets the initialization vector (IV) for the symmetric algorithm. /// /// This property always returns a byte array of length one. The value of the byte in the array is always set to zero. /// An attempt is made to set the IV to an invalid instance. /// RC4 doesn't use the IV property, however the property accepts IV's of up to one byte (RC4's ) in order to interoperate with software that has been written with the use of block ciphers in mind. public override byte[] IV { get { return new byte[1]; } set { if (value != null && value.Length > 1) throw new CryptographicException("RC4 doesn't use an Initialization Vector."); } } /// /// Gets the block sizes that are supported by the symmetric algorithm. /// /// An array containing the block sizes supported by the algorithm. /// Only a block size of one byte is supported by the RC4 algorithm. public override KeySizes[] LegalBlockSizes { get { return new KeySizes[] { new KeySizes(8, 8, 0) }; } } /// /// Gets the key sizes that are supported by the symmetric algorithm. /// /// An array containing the key sizes supported by the algorithm. /// Only key sizes that match an entry in this array are supported by the symmetric algorithm. public override KeySizes[] LegalKeySizes { get { return new KeySizes[] { new KeySizes(8, 2048, 8) }; } } /// /// Gets or sets the mode for operation of the symmetric algorithm. /// /// The mode for operation of the symmetric algorithm. /// RC4 only supports the OFB cipher mode. See for a description of this mode. /// The cipher mode is not OFB. public override CipherMode Mode { get { return CipherMode.OFB; } set { if (value != CipherMode.OFB) throw new CryptographicException("RC4 only supports OFB."); } } /// /// Gets or sets the padding mode used in the symmetric algorithm. /// /// The padding mode used in the symmetric algorithm. This property always returns PaddingMode.None. /// The padding mode is set to a padding mode other than PaddingMode.None. public override PaddingMode Padding { get { return PaddingMode.None; } set { if (value != PaddingMode.None) throw new CryptographicException("RC4 is a stream cipher, not a block cipher."); } } /// /// This is a stub method. /// /// Since the RC4 cipher doesn't use an Initialization Vector, this method will not do anything. public override void GenerateIV() { // do nothing } /// /// Generates a random Key to be used for the algorithm. /// /// Use this method to generate a random key when none is specified. public override void GenerateKey() { byte[] key = new byte[this.KeySize / 8]; GetRNGCSP().GetBytes(key); this.Key = key; } /// /// Creates an instance of the default cryptographic object used to perform the RC4 transformation. /// /// The instance of a cryptographic object used to perform the RC4 transformation. public static new RC4 Create() { return Create("ARCFOUR"); } /// /// Creates an instance of the specified cryptographic object used to perform the RC4 transformation. /// /// The name of the specific implementation of to create. /// A cryptographic object. public static new RC4 Create(string AlgName) { try { if (AlgName.ToUpper() == "RC4" || AlgName.ToLower() == "org.mentalis.security.cryptography.rc4cryptoserviceprovider") return new RC4CryptoServiceProvider(); else if (AlgName.ToUpper() == "ARCFOUR" || AlgName.ToLower() == "org.mentalis.security.cryptography.arcfourmanaged") return new ARCFourManaged(); } catch {} return null; } /// /// Returns an instance. /// /// An RNGCryptoServiceProvider instance. protected RNGCryptoServiceProvider GetRNGCSP() { if (m_RNG == null) m_RNG = new RNGCryptoServiceProvider(); return m_RNG; } /// /// Holds the RNGCryptoServiceProvider object. /// private RNGCryptoServiceProvider m_RNG; } }