Generic Hash

image_pdfimage_print

//******************************
// Written by Peter Golde
// Copyright (c) 2004-2007, Wintellect
//
// Use and restribution of this code is subject to the license agreement
// contained in the file “License.txt” accompanying this file.
//******************************

using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Runtime.Serialization;

namespace Wintellect.PowerCollections
{
///

/// The base implementation for various collections classes that use hash tables
/// as part of their implementation. This class should not (and can not) be
/// used directly by end users; it's only for internal use by the collections package. The Hash
/// does not handle duplicate values.
///

///
/// The Hash manages items of type T, and uses a IComparer<ItemTYpe> that
/// hashes compares items to hash items into the table.
///

internal class Hash : IEnumerable//, ISerializable, IDeserializationCallback
{
// NOTE: If you add new member variables, you very well may need to change the serialization
// code to serialize that member.
private IEqualityComparer equalityComparer; // interface for comparing elements

private int count; // The count of elements in the table.
private int usedSlots; // Includes real elements and deleted elements with the collision bit on. Used to determine
// when we need to resize.
private int totalSlots; // Size of the table. Always a power of two.
private float loadFactor; // maximal load factor for the table.
private int thresholdGrow; // floor(totalSlots * loadFactor);
private int thresholdShrink; // thresholdGrow / 3.
private int hashMask; // Mask to convert hash values to the size of the table.
private int secondaryShift; // Shift to get the secondary skip value.

private Slot[] table; // The hash table.

private int changeStamp; // An integer that is changed every time the table structurally changes.
// Used so that enumerations throw an exception if the tree is changed
// during enumeration.

private const int MINSIZE = 16; // minimum number of slots.

//private SerializationInfo serializationInfo; // Info used during deserialization.

///

/// The structure that has each slot in the hash table. Each slot has three parts:
/// 1. The collision bit. Indicates whether some item visited this slot but had to
/// keep looking because the slot was full.
/// 2. 31-bit full hash value of the item. If zero, the slot is empty.
/// 3. The item itself.
///

struct Slot
{
private uint hash_collision; // Lower 31 bits: the hash value. Top bit: the collision bit.
public T item; // The item.

///

/// The full hash value associated with the value in this slot, or zero
/// if the slot is empty.
///

public int HashValue
{
get
{
return (int)(hash_collision & 0x7FFFFFFF);
}
set
{
Debug.Assert((value & 0x80000000) == 0); // make sure sign bit isn't set.
hash_collision = (uint)value | (hash_collision & 0x80000000);
}
}

///

/// Is this slot empty?
///

public bool Empty
{
get
{
return HashValue == 0;
}
}

///

/// Clear this slot, leaving the collision bit alone.
///

public void Clear()
{
HashValue = 0;
item = default(T); // Done to avoid keeping things alive that shouldn't be.
}

///

/// The “Collision” bit indicates that some value hit this slot and
/// collided, so had to try another slot.
///

public bool Collision
{
get
{
return (hash_collision & 0x80000000) != 0;
}
set
{
if (value)
hash_collision |= 0x80000000;
else
hash_collision &= 0x7FFFFFFF;
}
}
}

///

/// Constructor. Create a new hash table.
///

/// The comparer to use to compare items. public Hash(IEqualityComparer equalityComparer)
{
this.equalityComparer = equalityComparer;
this.loadFactor = 0.70F; // default load factor.
}

///

/// Gets the current enumeration stamp. Call CheckEnumerationStamp later
/// with this value to throw an exception if the hash table is changed.
///

/// The current enumeration stamp.
internal int GetEnumerationStamp()
{
return changeStamp;
}

///

/// Must be called whenever there is a structural change in the tree. Causes
/// changeStamp to be changed, which causes any in-progress enumerations
/// to throw exceptions.
///

internal void StopEnumerations()
{
++changeStamp;
}

///

/// Checks the given stamp against the current change stamp. If different, the
/// collection has changed during enumeration and an InvalidOperationException
/// must be thrown
///

/// changeStamp at the start of the enumeration. internal void CheckEnumerationStamp(int startStamp)
{
if (startStamp != changeStamp)
{
throw new InvalidOperationException(“Change During Enumeration”);
}
}
///

/// Gets the hash code for an object using a comparer. Correctly handles
/// null.
///

/// Item to get hash code for. Can be null. /// The comparer to use. /// The hash code for the item.
public static int GetHashCode(T item, IEqualityComparer equalityComparer)
{
if (item == null)
return 0x1786E23C;
else
return equalityComparer.GetHashCode(item);
}
///

/// Gets the full hash code for an item.
///

/// Item to get hash code for. /// The full hash code. It is never zero.
private int GetFullHash(T item)
{
uint hash;

hash = (uint)GetHashCode(item, equalityComparer);

// The .NET framework tends to produce pretty bad hash codes.
// Scramble them up to be much more random!
hash += ~(hash << 15); hash ^= (hash >> 10);
hash += (hash << 3); hash ^= (hash >> 6);
hash += ~(hash << 11); hash ^= (hash >> 16);
hash &= 0x7FFFFFFF;
if (hash == 0)
hash = 0x7FFFFFFF; // Make sure it isn't zero.
return (int)hash;
}

///

/// Get the initial bucket number and skip amount from the full hash value.
///

/// The full hash value. /// Returns the initial bucket. Always in the range 0..(totalSlots – 1). /// Returns the skip values. Always odd in the range 0..(totalSlots – 1). private void GetHashValuesFromFullHash(int hash, out int initialBucket, out int skip)
{
initialBucket = hash & hashMask;

// The skip value must be relatively prime to the table size. Since the table size is a
// power of two, any odd number is relatively prime, so oring in 1 will do it.
skip = ((hash >> secondaryShift) & hashMask) | 1;
}

///

/// Gets the full hash value, initial bucket number, and skip amount for an item.
///

/// Item to get hash value of. /// Returns the initial bucket. Always in the range 0..(totalSlots – 1). /// Returns the skip values. Always odd in the range 0..(totalSlots – 1). /// The full hash value. This is never zero.
private int GetHashValues(T item, out int initialBucket, out int skip)
{
int hash = GetFullHash(item);
GetHashValuesFromFullHash(hash, out initialBucket, out skip);
return hash;
}

///

/// Make sure there are enough slots in the hash table that /// items can be inserted into the table.
///

/// Number of additional items we are inserting. private void EnsureEnoughSlots(int additionalItems)
{
StopEnumerations();

if (usedSlots + additionalItems > thresholdGrow)
{
// We need to expand the table. Figure out to what size.
int newSize;

newSize = Math.Max(totalSlots, MINSIZE);
while ((int)(newSize * loadFactor) < usedSlots + additionalItems) { newSize *= 2; if (newSize <= 0) { // Must have overflowed the size of an int. Hard to believe we didn't run out of memory first. throw new InvalidOperationException("CollectionTooLarge"); } } ResizeTable(newSize); } } ///

/// Check if the number of items in the table is small enough that
/// we should shrink the table again.
///

private void ShrinkIfNeeded()
{
if (count < thresholdShrink) { int newSize; if (count > 0)
{
newSize = MINSIZE;
while ((int)(newSize * loadFactor) < count) newSize *= 2; } else { // We've removed all the elements. Shrink to zero. newSize = 0; } ResizeTable(newSize); } } ///

/// Given the size of a hash table, compute the “secondary shift” value — the shift
/// that is used to determine the skip amount for collision resolution.
///

/// The new size of the table. /// The secondary skip amount.
private static int GetSecondaryShift(int newSize)
{
int x = newSize – 2; // x is of the form 0000111110 — a single string of 1's followed by a single zero.
int secondaryShift = 0;

// Keep shifting x until it is the set of bits we want to extract: it be the highest bits possible,
// but can't overflow into the sign bit.
while ((x & 0x40000000) == 0)
{
x <<= 1; ++secondaryShift; } return secondaryShift; } ///

/// Resize the hash table to the given new size, moving all items into the
/// new hash table.
///

/// The new size of the hash table. Must be a power
/// of two. private void ResizeTable(int newSize)
{
Slot[] oldTable = table; // Move all the items from this table to the new table.

Debug.Assert((newSize & (newSize – 1)) == 0); // Check newSize is a power of two.
totalSlots = newSize;
thresholdGrow = (int)(totalSlots * loadFactor);
thresholdShrink = thresholdGrow / 3;
if (thresholdShrink <= MINSIZE) thresholdShrink = 1; hashMask = newSize - 1; secondaryShift = GetSecondaryShift(newSize); if (totalSlots > 0)
table = new Slot[totalSlots];
else
table = null;

if (oldTable != null && table != null)
{
foreach (Slot oldSlot in oldTable)
{
int hash, bucket, skip;

hash = oldSlot.HashValue;
GetHashValuesFromFullHash(hash, out bucket, out skip);

// Find an empty bucket.
while (!table[bucket].Empty)
{
// The slot is used, but isn't our item. Set the collision bit and keep looking.
table[bucket].Collision = true;
bucket = (bucket + skip) & hashMask;
}

// We found an empty bucket.
table[bucket].HashValue = hash;
table[bucket].item = oldSlot.item;
}
}

usedSlots = count; // no deleted elements have the collision bit on now.
}

///

/// Get the number of items in the hash table.
///

/// The number of items stored in the hash table.
public int ElementCount
{
get
{
return count;
}
}

///

/// Get the number of slots in the hash table. Exposed internally
/// for testing purposes.
///

/// The number of slots in the hash table.
internal int SlotCount
{
get
{
return totalSlots;
}
}

///

/// Get or change the load factor. Changing the load factor may cause
/// the size of the table to grow or shrink accordingly.
///

///
public float LoadFactor
{
get
{
return loadFactor;
}
set
{
// Don't allow hopelessly inefficient load factors.
if (value < 0.25 || value > 0.95)
throw new ArgumentOutOfRangeException(“value”, value.ToString());
//throw new ArgumentOutOfRangeException(“value”, value, Strings.InvalidLoadFactor);

StopEnumerations();

bool maybeExpand = value < loadFactor; // May need to expand or shrink the table -- which? // Update loadFactor and thresholds. loadFactor = value; thresholdGrow = (int)(totalSlots * loadFactor); thresholdShrink = thresholdGrow / 3; if (thresholdShrink <= MINSIZE) thresholdShrink = 1; // Possibly expand or shrink the table. if (maybeExpand) EnsureEnoughSlots(0); else ShrinkIfNeeded(); } } ///

/// Insert a new item into the hash table. If a duplicate item exists, can replace or
/// do nothing.
///

/// The item to insert. /// If true, duplicate items are replaced. If false, nothing
/// is done if a duplicate already exists. /// If a duplicate was found, returns it (whether replaced or not). /// True if no duplicate existed, false if a duplicate was found.
public bool Insert(T item, bool replaceOnDuplicate, out T previous)
{
int hash, bucket, skip;
int emptyBucket = -1; // If >= 0, an empty bucket we can use for a true insert
bool duplicateMightExist = true; // If true, still the possibility that a duplicate exists.

EnsureEnoughSlots(1); // Ensure enough room to insert. Also stops enumerations.

hash = GetHashValues(item, out bucket, out skip);

for (; ; )
{
if (table[bucket].Empty)
{
// Record the location of the first empty bucket seen. This is where the item will
// go if no duplicate exists.
if (emptyBucket == -1)
emptyBucket = bucket;

if (!duplicateMightExist || !table[bucket].Collision)
{
// There can't be a duplicate further on, because a bucket with the collision bit
// clear was found (here or earlier). We have the place to insert.
break;
}
}
else if (table[bucket].HashValue == hash && equalityComparer.Equals(table[bucket].item, item))
{
// We found a duplicate item. Replace it if requested to.
previous = table[bucket].item;
if (replaceOnDuplicate)
table[bucket].item = item;
return false;
}
else
{
// The slot is used, but isn't our item.
if (!table[bucket].Collision)
{
// Since the collision bit is off, we can't have a duplicate.
if (emptyBucket >= 0)
{
// We already have an empty bucket to use.
break;
}
else
{
// Keep searching for an empty bucket to place the item.
table[bucket].Collision = true;
duplicateMightExist = false;
}
}
}

bucket = (bucket + skip) & hashMask;
}

// We found an empty bucket. Insert the new item.
table[emptyBucket].HashValue = hash;
table[emptyBucket].item = item;

++count;
if (!table[emptyBucket].Collision)
++usedSlots;
previous = default(T);
return true;
}

///

/// Deletes an item from the hash table.
///

/// Item to search for and delete. /// If true returned, the actual item stored in the hash table (must be
/// equal to , but may not be identical. /// True if item was found and deleted, false if item wasn't found.
public bool Delete(T item, out T itemDeleted)
{
int hash, bucket, skip;

StopEnumerations();

if (count == 0)
{
itemDeleted = default(T);
return false;
}

hash = GetHashValues(item, out bucket, out skip);

for (; ; )
{
if (table[bucket].HashValue == hash && equalityComparer.Equals(table[bucket].item, item))
{
// Found the item. Remove it.
itemDeleted = table[bucket].item;
table[bucket].Clear();
–count;
if (!table[bucket].Collision)
–usedSlots;
ShrinkIfNeeded();
return true;
}
else if (!table[bucket].Collision)
{
// No collision bit, so we can stop searching. No such element.
itemDeleted = default(T);
return false;
}

bucket = (bucket + skip) & hashMask;
}
}

///

/// Find an item in the hash table. If found, optionally replace it with the
/// finding item.
///

/// Item to find. /// If true, replaces the equal item in the hash table
/// with . /// Returns the equal item found in the table, if true was returned. /// True if the item was found, false otherwise.
public bool Find(T find, bool replace, out T item)
{
int hash, bucket, skip;

if (count == 0)
{
item = default(T);
return false;
}

hash = GetHashValues(find, out bucket, out skip);

for (; ; )
{
if (table[bucket].HashValue == hash && equalityComparer.Equals(table[bucket].item, find))
{
// Found the item.
item = table[bucket].item;
if (replace)
table[bucket].item = find;
return true;
}
else if (!table[bucket].Collision)
{
// No collision bit, so we can stop searching. No such element.
item = default(T);
return false;
}

bucket = (bucket + skip) & hashMask;
}
}

///

/// Enumerate all of the items in the hash table. The items
/// are enumerated in a haphazard, unpredictable order.
///

/// An IEnumerator&lt;T&gt; that enumerates the items
/// in the hash table.

public IEnumerator GetEnumerator()
{
if (count > 0)
{
int startStamp = changeStamp;

foreach (Slot slot in table)
{
if (!slot.Empty)
{
yield return slot.item;
CheckEnumerationStamp(startStamp);
}
}
}
}

///

/// Enumerate all of the items in the hash table. The items
/// are enumerated in a haphazard, unpredictable order.
///

/// An IEnumerator that enumerates the items
/// in the hash table.

System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}

///

/// Creates a clone of this hash table.
///

/// If non-null, this function is applied to each item when cloning. It must be the
/// case that this function does not modify the hash code or equality function. /// A shallow clone that contains the same items.
public Hash Clone(Converter cloneItem)
{
Hash clone = new Hash(equalityComparer);
clone.count = this.count;
clone.usedSlots = this.usedSlots;
clone.totalSlots = this.totalSlots;
clone.loadFactor = this.loadFactor;
clone.thresholdGrow = this.thresholdGrow;
clone.thresholdShrink = this.thresholdShrink;
clone.hashMask = this.hashMask;
clone.secondaryShift = this.secondaryShift;
if (table != null)
{
clone.table = (Slot[])table.Clone();

if (cloneItem != null)
{
for (int i = 0; i < table.Length; ++i) { if (!table[i].Empty) table[i].item = cloneItem(table[i].item); } } } return clone; } #region Serialization /* ///

/// Serialize the hash table. Called from the serialization infrastructure.
///

void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
if (info == null)
throw new ArgumentNullException(“info”);

info.AddValue(“equalityComparer”, equalityComparer, typeof(IEqualityComparer));
info.AddValue(“loadFactor”, loadFactor, typeof(float));
T[] items = new T[count];
int i = 0;
foreach (Slot slot in table)
if (! slot.Empty)
items[i++] = slot.item;
info.AddValue(“items”, items, typeof(T[]));
}

///

/// Called on deserialization. We cannot deserialize now, because hash codes
/// might not be correct now. We do real deserialization in the OnDeserialization call.
///

protected Hash(SerializationInfo serInfo, StreamingContext context)
{
// Save away the serialization info for use later. We can't be sure of hash codes
// being stable until the entire object graph is deserialized, so we wait until then
// to deserialize.
serializationInfo = serInfo;
}

///

/// Deserialize the hash table. Called from the serialization infrastructure when
/// the object graph has finished deserializing.
///

void IDeserializationCallback.OnDeserialization(object sender)
{
if (serializationInfo == null)
return;

loadFactor = serializationInfo.GetSingle(“loadFactor”);
equalityComparer = (IEqualityComparer) serializationInfo.GetValue(“equalityComparer”, typeof(IEqualityComparer));

T[] items = (T[])serializationInfo.GetValue(“items”, typeof(T[]));
T dummy;

EnsureEnoughSlots(items.Length);
foreach (T item in items)
Insert(item, true, out dummy);

serializationInfo = null;
}
*/
#endregion Serialization

#if DEBUG
///

/// Print out basic stats about the hash table.
///

internal void PrintStats()
{
Console.WriteLine(“count={0} usedSlots={1} totalSlots={2}”, count, usedSlots, totalSlots);
Console.WriteLine(“loadFactor={0} thresholdGrow={1} thresholdShrink={2}”, loadFactor, thresholdGrow, thresholdShrink);
Console.WriteLine(“hashMask={0:X} secondaryShift={1}”, hashMask, secondaryShift);
Console.WriteLine();
}

///

/// Print out the state of the hash table and each of the slots. Each slot looks like:
/// Slot 4: C 4513e41e hello
/// where the “C” indicates the collision bit is on
/// the next hex number is the hash value
/// followed by ToString() on the item.
///

internal void Print()
{
PrintStats();
for (int i = 0; i < totalSlots; ++i) Console.WriteLine("Slot {0,4:X}: {1} {2,8:X} {3}", i, table[i].Collision ? "C" : " ", table[i].HashValue, table[i].Empty ? "” : table[i].item.ToString());
Console.WriteLine();
}

///

/// Check that everything appears to be OK in the hash table.
///

internal void Validate()
{
Debug.Assert(count <= usedSlots); Debug.Assert(count <= totalSlots); Debug.Assert(usedSlots <= totalSlots); Debug.Assert(usedSlots <= thresholdGrow); Debug.Assert((int)(totalSlots * loadFactor) == thresholdGrow); if (thresholdShrink > 1)
Debug.Assert(thresholdGrow / 3 == thresholdShrink);
else
Debug.Assert(thresholdGrow / 3 <= MINSIZE); if (totalSlots > 0)
{
Debug.Assert((totalSlots & (totalSlots – 1)) == 0); // totalSlots is a power of two.
Debug.Assert(totalSlots – 1 == hashMask);
Debug.Assert(GetSecondaryShift(totalSlots) == secondaryShift);
Debug.Assert(totalSlots == table.Length);
}

// Traverse the table. Make sure that count and usedSlots are right, and that
// each slot looks reasonable.
int expectedCount = 0, expectedUsed = 0, initialBucket, skip;
if (table != null)
{
for (int i = 0; i < totalSlots; ++i) { Slot slot = table[i]; if (slot.Empty) { // Empty slot if (slot.Collision) ++expectedUsed; Debug.Assert(object.Equals(default(T), slot.item)); } else { // not empty. ++expectedCount; ++expectedUsed; Debug.Assert(slot.HashValue != 0); Debug.Assert(GetHashValues(slot.item, out initialBucket, out skip) == slot.HashValue); if (initialBucket != i) Debug.Assert(table[initialBucket].Collision); } } } Debug.Assert(expectedCount == count); Debug.Assert(expectedUsed == usedSlots); } #endif //DEBUG } } [/csharp]

Verify Hex Hash, Base64 Hash, Byte Hash

image_pdfimage_print

using System;
using System.Text;

class MainClass {
public static bool VerifyHexHash(byte[] hash, string oldHashString) {
StringBuilder newHashString = new StringBuilder(hash.Length);

foreach (byte b in hash) {
newHashString.AppendFormat(“{0:X2}”, b);
}

return (oldHashString == newHashString.ToString());
}

private static bool VerifyB64Hash(byte[] hash, string oldHashString) {
string newHashString = Convert.ToBase64String(hash);
return (oldHashString == newHashString);
}
private static bool VerifyByteHash(byte[] hash, byte[] oldHash) {
if (hash == null || oldHash == null || hash.Length != oldHash.Length)
return false;

for (int count = 0; count < hash.Length; count++) { if (hash[count] != oldHash[count]) return false; } return true; } } [/csharp]

FileIOPermissionAccess.Append

image_pdfimage_print
   
 

using System;
using System.Collections.Generic;
using System.Text;
using System.Security;
using System.Security.Permissions;
using System.IO;

class Program {
    static void Main(string[] args) {
        CodeAccessPermission permission = new FileIOPermission(FileIOPermissionAccess.Append,@"C:audit.txt");
        permission.Deny();
        AuditClass.Save("some data to audit");
        CodeAccessPermission.RevertDeny();
    }
}

class AuditClass {
    public static void Save(string value) {
        try {
            FileIOPermission permission = new FileIOPermission(FileIOPermissionAccess.Append,@"C:audit.txt");
            permission.Assert();
            FileStream stream = new FileStream(@"C:audit.txt",FileMode.Append, FileAccess.Write);
            CodeAccessPermission.RevertAssert();
            Console.WriteLine("Data written to audit file");
        } catch {
            Console.WriteLine("Failed to write data to audit file");
        }
    }
}

    


FileIOPermissionAccess.AllAccess

image_pdfimage_print
   
 
using System;
using System.Collections.Generic;
using System.Text;
using System.Security;
using System.Security.Permissions;

class Program {
    static void Main(string[] args) {
        CodeAccessPermission permissionA = new FileIOPermission(FileIOPermissionAccess.AllAccess, @"C:");
        CodeAccessPermission permissionB = new FileIOPermission(FileIOPermissionAccess.Read, @"C:	emp");
        if (permissionB.IsSubsetOf(permissionA)) {
            Console.WriteLine("PermissionB is a subset of PermissionA");
        } else {
            Console.WriteLine("PermissionB is NOT a subset of PermissionA");
        }
    }
}

    


Encrypts the value by password and salt.

image_pdfimage_print
   
 

/* 
  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 
  ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 
  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 
  PARTICULAR PURPOSE. 
  
    This is sample code and is freely distributable. 
*/

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Web;

namespace Wmb.Web {
    /// <summary>
    /// The StringUtility class holds the extensions and/or helpermethods for the String class.
    /// </summary>
    public static class EcryptionUtility {
        /// <summary>
        /// Encrypts the value by password and salt.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="password">The password.</param>
        /// <param name="salt">The salt.</param>
        /// <returns>The encrypted bytes</returns>
        public static byte[] PasswordEncrypt(this byte[] value, string password, string salt) {
            if (value == null) {
                throw new ArgumentNullException("value");
            }

            if (string.IsNullOrEmpty(password)) {
                throw new ArgumentNullException("password");
            }

            if (string.IsNullOrEmpty(salt)) {
                throw new ArgumentNullException("salt");
            }

            byte[] retVal = null;
            Rijndael rijndaelAlg = CreateRijndael(password, salt);

            using (MemoryStream memoryStream = new MemoryStream())
            using (CryptoStream cryptoStream = new CryptoStream(memoryStream,
                                                               rijndaelAlg.CreateEncryptor(),
                                                               CryptoStreamMode.Write)) {
                cryptoStream.Write(value, 0, value.Length);
                cryptoStream.Close();
                retVal = memoryStream.ToArray();
            }

            return retVal;
        }


        /// <summary>
        /// Decrypts the value by password and salt.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="password">The password.</param>
        /// <param name="salt">The salt.</param>
        /// <returns>The decrypted bytes</returns>
        public static byte[] PasswordDecrypt(this byte[] value, string password, string salt) {
            if (value == null) {
                throw new ArgumentNullException("value");
            }

            if (string.IsNullOrEmpty(password)) {
                throw new ArgumentNullException("password");
            }

            if (string.IsNullOrEmpty(salt)) {
                throw new ArgumentNullException("salt");
            }

            byte[] retVal = null;
            Rijndael rijndaelAlg = CreateRijndael(password, salt);

            using (MemoryStream memoryStream = new MemoryStream())
            using (CryptoStream cryptoStream = new CryptoStream(memoryStream,
                                                               rijndaelAlg.CreateDecryptor(),
                                                               CryptoStreamMode.Write)) {
                cryptoStream.Write(value, 0, value.Length);
                cryptoStream.Close();
                retVal = memoryStream.ToArray();
            }

            return retVal;
        }

        /// <summary>
        /// Ecrypts the value to a url encoded string.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="password">The password.</param>
        /// <param name="salt">The salt.</param>
        /// <returns>The encrypted and url encoded string</returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1055:UriReturnValuesShouldNotBeStrings", Justification="This method does not return a Uri.")]
        public static string UrlEncodedPasswordEncrypt(this string value, string password, string salt) {
            if (value == null) {
                throw new ArgumentNullException("value");
            }

            if (string.IsNullOrEmpty(password)) {
                throw new ArgumentNullException("password");
            }

            if (string.IsNullOrEmpty(salt)) {
                throw new ArgumentNullException("salt");
            }

            string retVal = null;

            byte[] bytesToEncrypt = Encoding.Unicode.GetBytes(value);
            byte[] encryptedValue = bytesToEncrypt.PasswordEncrypt(password, salt);
            retVal = HttpServerUtility.UrlTokenEncode(encryptedValue);

            return retVal;
        }

        /// <summary>
        /// Decrypts the url encoded value.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="password">The password.</param>
        /// <param name="salt">The salt.</param>
        /// <returns>The decrypted and url decoded string</returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1055:UriReturnValuesShouldNotBeStrings", Justification="This method does not return a Uri.")]
        public static string UrlEncodedPasswordDecrypt(this string value, string password, string salt) {
            if (value == null) {
                throw new ArgumentNullException("value");
            }

            if (string.IsNullOrEmpty(password)) {
                throw new ArgumentNullException("password");
            }

            if (string.IsNullOrEmpty(salt)) {
                throw new ArgumentNullException("salt");
            }

            string retVal = null;

            byte[] bytesToDecrypt = HttpServerUtility.UrlTokenDecode(value);
            byte[] decryptedValue = bytesToDecrypt.PasswordDecrypt(password, salt);
            retVal = Encoding.Unicode.GetString(decryptedValue);

            return retVal;
        }

        private static Rijndael CreateRijndael(string password, string salt) {
            byte[] saltBytes = Encoding.Unicode.GetBytes(salt);

            PasswordDeriveBytes passwordDeriveBytes = new PasswordDeriveBytes(password,
                                                                              saltBytes);

            Rijndael rijndael = Rijndael.Create();
            rijndael.Key = passwordDeriveBytes.GetBytes(32);
            rijndael.IV = passwordDeriveBytes.GetBytes(16);

            return rijndael;
        }
    }
}

   
     


Provides the Unix crypt() encryption algorithm.

image_pdfimage_print
   
 
// <copyright file="UnixCrypt.cs" company="C&eacute;dric Belin">
//    This sourcecode is a port from Java to C#.
//    The original (Java) version was made by John Dumas and can be found at: http://www.dynamic.net.au/christos/crypt/UnixCrypt.txt
// </copyright>
// <summary>
//   Impl&eacute;mentation de la classe <c>DigiWar.Security.Cryptography.UnixCrypt</c>.
// </summary>
// <author>$Author: cedx $</author>
// <date>$Date: 2009-09-10 19:44:34 +0200 (jeu. 10 sept. 2009) $</date>
// <version>$Revision: 1827 $</version>


  using System;
  using System.Linq;
  using System.Text;

  //// 
  
  /// <summary>
  /// Provides the Unix crypt() encryption algorithm.
  /// </summary>
  /// <remarks>
  /// This class is a port from Java source. I do not understand the underlying algorithms, I just converted it to C# and it works.
  /// Because I do not understand the underlying algorithms I cannot give most of the variables useful names. I have no clue what their
  /// significance is. I tried to give the variable names as much meaning as possible, but the original source just called them a, b, c , etc...
  /// 
  /// A very important thing to note is that all ints in this code are UNSIGNED ints! Do not change this, ever!!! It will seriously fuckup the working
  /// of this class. It uses major bitshifting and while Java gives you the >>> operator to signify a right bitshift WITHOUT setting the MSB for
  /// a signed int, C# does not have this operator and will just set the new MSB for you if it happened to be set the moment you bitshifted it.
  /// This is undesirable for most bitshifts and in the cases it did matter, I casted the variable back to an int. This was only required where
  /// a variable was on the right-side of a bitshift operator.
  /// </remarks>
   internal static class UnixCrypt
   {
      /// <value>
      /// The list with characters allowed in a Unix encrypted password.
      /// It is used to randomly chose two characters for use in the encryption.
      /// </value>
      private const string m_encryptionSaltCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";
      /// <value>
      /// A lookup-table, presumably filled with some sort of encryption key. 
      /// It is used to calculate the index to the m_SPTranslationTable lookup-table.
      /// </value>
      private static readonly uint[] m_saltTranslation =
                           {
                              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
                              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
                              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
                              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
                              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
                              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 
                              0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 
                              0x0A, 0x0B, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 
                              0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 
                              0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 
                              0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 
                              0x23, 0x24, 0x25, 0x20, 0x21, 0x22, 0x23, 0x24, 
                              0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 
                              0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 
                              0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 
                              0x3D, 0x3E, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 
      };
      /// <value>
      /// A lookup-table.
      /// It is used to calculate the index to the m_skb lookup-table.
      /// </value>
      private static readonly bool[] m_shifts =
                           {
                              false, false, true, true, true, true, true, true,
                              false, true,  true, true, true, true, true, false
                           };
      /// <value>
      /// A lookup-table.
      /// It is used the dynamically create the schedule lookup-table.
      /// </value>
      private static readonly uint[,] m_skb =
                           {
                              {
                                 /* for C bits (numbered as per FIPS 46) 1 2 3 4 5 6 */
                                 0x00000000, 0x00000010, 0x20000000, 0x20000010, 
                                 0x00010000, 0x00010010, 0x20010000, 0x20010010, 
                                 0x00000800, 0x00000810, 0x20000800, 0x20000810, 
                                 0x00010800, 0x00010810, 0x20010800, 0x20010810, 
                                 0x00000020, 0x00000030, 0x20000020, 0x20000030, 
                                 0x00010020, 0x00010030, 0x20010020, 0x20010030, 
                                 0x00000820, 0x00000830, 0x20000820, 0x20000830, 
                                 0x00010820, 0x00010830, 0x20010820, 0x20010830, 
                                 0x00080000, 0x00080010, 0x20080000, 0x20080010, 
                                 0x00090000, 0x00090010, 0x20090000, 0x20090010, 
                                 0x00080800, 0x00080810, 0x20080800, 0x20080810, 
                                 0x00090800, 0x00090810, 0x20090800, 0x20090810, 
                                 0x00080020, 0x00080030, 0x20080020, 0x20080030, 
                                 0x00090020, 0x00090030, 0x20090020, 0x20090030, 
                                 0x00080820, 0x00080830, 0x20080820, 0x20080830, 
                                 0x00090820, 0x00090830, 0x20090820, 0x20090830, 
                           },
                              {
                                 /* for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 */
                                 0x00000000, 0x02000000, 0x00002000, 0x02002000, 
                                 0x00200000, 0x02200000, 0x00202000, 0x02202000, 
                                 0x00000004, 0x02000004, 0x00002004, 0x02002004, 
                                 0x00200004, 0x02200004, 0x00202004, 0x02202004, 
                                 0x00000400, 0x02000400, 0x00002400, 0x02002400, 
                                 0x00200400, 0x02200400, 0x00202400, 0x02202400, 
                                 0x00000404, 0x02000404, 0x00002404, 0x02002404, 
                                 0x00200404, 0x02200404, 0x00202404, 0x02202404, 
                                 0x10000000, 0x12000000, 0x10002000, 0x12002000, 
                                 0x10200000, 0x12200000, 0x10202000, 0x12202000, 
                                 0x10000004, 0x12000004, 0x10002004, 0x12002004, 
                                 0x10200004, 0x12200004, 0x10202004, 0x12202004, 
                                 0x10000400, 0x12000400, 0x10002400, 0x12002400, 
                                 0x10200400, 0x12200400, 0x10202400, 0x12202400, 
                                 0x10000404, 0x12000404, 0x10002404, 0x12002404, 
                                 0x10200404, 0x12200404, 0x10202404, 0x12202404, 
                           },
                              {
                                 /* for C bits (numbered as per FIPS 46) 14 15 16 17 19 20 */
                                 0x00000000, 0x00000001, 0x00040000, 0x00040001, 
                                 0x01000000, 0x01000001, 0x01040000, 0x01040001, 
                                 0x00000002, 0x00000003, 0x00040002, 0x00040003, 
                                 0x01000002, 0x01000003, 0x01040002, 0x01040003, 
                                 0x00000200, 0x00000201, 0x00040200, 0x00040201, 
                                 0x01000200, 0x01000201, 0x01040200, 0x01040201, 
                                 0x00000202, 0x00000203, 0x00040202, 0x00040203, 
                                 0x01000202, 0x01000203, 0x01040202, 0x01040203, 
                                 0x08000000, 0x08000001, 0x08040000, 0x08040001, 
                                 0x09000000, 0x09000001, 0x09040000, 0x09040001, 
                                 0x08000002, 0x08000003, 0x08040002, 0x08040003, 
                                 0x09000002, 0x09000003, 0x09040002, 0x09040003, 
                                 0x08000200, 0x08000201, 0x08040200, 0x08040201, 
                                 0x09000200, 0x09000201, 0x09040200, 0x09040201, 
                                 0x08000202, 0x08000203, 0x08040202, 0x08040203, 
                                 0x09000202, 0x09000203, 0x09040202, 0x09040203, 
                           },
                              {
                                 /* for C bits (numbered as per FIPS 46) 21 23 24 26 27 28 */
                                 0x00000000, 0x00100000, 0x00000100, 0x00100100, 
                                 0x00000008, 0x00100008, 0x00000108, 0x00100108, 
                                 0x00001000, 0x00101000, 0x00001100, 0x00101100, 
                                 0x00001008, 0x00101008, 0x00001108, 0x00101108, 
                                 0x04000000, 0x04100000, 0x04000100, 0x04100100, 
                                 0x04000008, 0x04100008, 0x04000108, 0x04100108, 
                                 0x04001000, 0x04101000, 0x04001100, 0x04101100, 
                                 0x04001008, 0x04101008, 0x04001108, 0x04101108, 
                                 0x00020000, 0x00120000, 0x00020100, 0x00120100, 
                                 0x00020008, 0x00120008, 0x00020108, 0x00120108, 
                                 0x00021000, 0x00121000, 0x00021100, 0x00121100, 
                                 0x00021008, 0x00121008, 0x00021108, 0x00121108, 
                                 0x04020000, 0x04120000, 0x04020100, 0x04120100, 
                                 0x04020008, 0x04120008, 0x04020108, 0x04120108, 
                                 0x04021000, 0x04121000, 0x04021100, 0x04121100, 
                                 0x04021008, 0x04121008, 0x04021108, 0x04121108, 
                           },
                              {
                                 /* for D bits (numbered as per FIPS 46) 1 2 3 4 5 6 */
                                 0x00000000, 0x10000000, 0x00010000, 0x10010000, 
                                 0x00000004, 0x10000004, 0x00010004, 0x10010004, 
                                 0x20000000, 0x30000000, 0x20010000, 0x30010000, 
                                 0x20000004, 0x30000004, 0x20010004, 0x30010004, 
                                 0x00100000, 0x10100000, 0x00110000, 0x10110000, 
                                 0x00100004, 0x10100004, 0x00110004, 0x10110004, 
                                 0x20100000, 0x30100000, 0x20110000, 0x30110000, 
                                 0x20100004, 0x30100004, 0x20110004, 0x30110004, 
                                 0x00001000, 0x10001000, 0x00011000, 0x10011000, 
                                 0x00001004, 0x10001004, 0x00011004, 0x10011004, 
                                 0x20001000, 0x30001000, 0x20011000, 0x30011000, 
                                 0x20001004, 0x30001004, 0x20011004, 0x30011004, 
                                 0x00101000, 0x10101000, 0x00111000, 0x10111000, 
                                 0x00101004, 0x10101004, 0x00111004, 0x10111004, 
                                 0x20101000, 0x30101000, 0x20111000, 0x30111000, 
                                 0x20101004, 0x30101004, 0x20111004, 0x30111004, 
                           },
                              {
                                 /* for D bits (numbered as per FIPS 46) 8 9 11 12 13 14 */
                                 0x00000000, 0x08000000, 0x00000008, 0x08000008, 
                                 0x00000400, 0x08000400, 0x00000408, 0x08000408, 
                                 0x00020000, 0x08020000, 0x00020008, 0x08020008, 
                                 0x00020400, 0x08020400, 0x00020408, 0x08020408, 
                                 0x00000001, 0x08000001, 0x00000009, 0x08000009, 
                                 0x00000401, 0x08000401, 0x00000409, 0x08000409, 
                                 0x00020001, 0x08020001, 0x00020009, 0x08020009, 
                                 0x00020401, 0x08020401, 0x00020409, 0x08020409, 
                                 0x02000000, 0x0A000000, 0x02000008, 0x0A000008, 
                                 0x02000400, 0x0A000400, 0x02000408, 0x0A000408, 
                                 0x02020000, 0x0A020000, 0x02020008, 0x0A020008, 
                                 0x02020400, 0x0A020400, 0x02020408, 0x0A020408, 
                                 0x02000001, 0x0A000001, 0x02000009, 0x0A000009, 
                                 0x02000401, 0x0A000401, 0x02000409, 0x0A000409, 
                                 0x02020001, 0x0A020001, 0x02020009, 0x0A020009, 
                                 0x02020401, 0x0A020401, 0x02020409, 0x0A020409, 
                           },
                              {
                                 /* for D bits (numbered as per FIPS 46) 16 17 18 19 20 21 */
                                 0x00000000, 0x00000100, 0x00080000, 0x00080100, 
                                 0x01000000, 0x01000100, 0x01080000, 0x01080100, 
                                 0x00000010, 0x00000110, 0x00080010, 0x00080110, 
                                 0x01000010, 0x01000110, 0x01080010, 0x01080110, 
                                 0x00200000, 0x00200100, 0x00280000, 0x00280100, 
                                 0x01200000, 0x01200100, 0x01280000, 0x01280100, 
                                 0x00200010, 0x00200110, 0x00280010, 0x00280110, 
                                 0x01200010, 0x01200110, 0x01280010, 0x01280110, 
                                 0x00000200, 0x00000300, 0x00080200, 0x00080300, 
                                 0x01000200, 0x01000300, 0x01080200, 0x01080300, 
                                 0x00000210, 0x00000310, 0x00080210, 0x00080310, 
                                 0x01000210, 0x01000310, 0x01080210, 0x01080310, 
                                 0x00200200, 0x00200300, 0x00280200, 0x00280300, 
                                 0x01200200, 0x01200300, 0x01280200, 0x01280300, 
                                 0x00200210, 0x00200310, 0x00280210, 0x00280310, 
                                 0x01200210, 0x01200310, 0x01280210, 0x01280310, 
                           },
                              {
                                 /* for D bits (numbered as per FIPS 46) 22 23 24 25 27 28 */
                                 0x00000000, 0x04000000, 0x00040000, 0x04040000, 
                                 0x00000002, 0x04000002, 0x00040002, 0x04040002, 
                                 0x00002000, 0x04002000, 0x00042000, 0x04042000, 
                                 0x00002002, 0x04002002, 0x00042002, 0x04042002, 
                                 0x00000020, 0x04000020, 0x00040020, 0x04040020, 
                                 0x00000022, 0x04000022, 0x00040022, 0x04040022, 
                                 0x00002020, 0x04002020, 0x00042020, 0x04042020, 
                                 0x00002022, 0x04002022, 0x00042022, 0x04042022, 
                                 0x00000800, 0x04000800, 0x00040800, 0x04040800, 
                                 0x00000802, 0x04000802, 0x00040802, 0x04040802, 
                                 0x00002800, 0x04002800, 0x00042800, 0x04042800, 
                                 0x00002802, 0x04002802, 0x00042802, 0x04042802, 
                                 0x00000820, 0x04000820, 0x00040820, 0x04040820, 
                                 0x00000822, 0x04000822, 0x00040822, 0x04040822, 
                                 0x00002820, 0x04002820, 0x00042820, 0x04042820, 
                                 0x00002822, 0x04002822, 0x00042822, 0x04042822, 
                           }
      };
      /// <value>
      /// A lookup-table.
      /// It is used to calculate two ints that are used to encrypt the password.
      /// </value>
      private static readonly uint[,] m_SPTranslationTable =
                           {
                              {
                                 /* nibble 0 */
                                 0x00820200, 0x00020000, 0x80800000, 0x80820200,
                                 0x00800000, 0x80020200, 0x80020000, 0x80800000,
                                 0x80020200, 0x00820200, 0x00820000, 0x80000200,
                                 0x80800200, 0x00800000, 0x00000000, 0x80020000,
                                 0x00020000, 0x80000000, 0x00800200, 0x00020200,
                                 0x80820200, 0x00820000, 0x80000200, 0x00800200,
                                 0x80000000, 0x00000200, 0x00020200, 0x80820000,
                                 0x00000200, 0x80800200, 0x80820000, 0x00000000,
                                 0x00000000, 0x80820200, 0x00800200, 0x80020000,
                                 0x00820200, 0x00020000, 0x80000200, 0x00800200,
                                 0x80820000, 0x00000200, 0x00020200, 0x80800000,
                                 0x80020200, 0x80000000, 0x80800000, 0x00820000,
                                 0x80820200, 0x00020200, 0x00820000, 0x80800200,
                                 0x00800000, 0x80000200, 0x80020000, 0x00000000,
                                 0x00020000, 0x00800000, 0x80800200, 0x00820200,
                                 0x80000000, 0x80820000, 0x00000200, 0x80020200,
                              },
                              {
                                 /* nibble 1 */
                                 0x10042004, 0x00000000, 0x00042000, 0x10040000,
                                 0x10000004, 0x00002004, 0x10002000, 0x00042000,
                                 0x00002000, 0x10040004, 0x00000004, 0x10002000,
                                 0x00040004, 0x10042000, 0x10040000, 0x00000004,
                                 0x00040000, 0x10002004, 0x10040004, 0x00002000,
                                 0x00042004, 0x10000000, 0x00000000, 0x00040004,
                                 0x10002004, 0x00042004, 0x10042000, 0x10000004,
                                 0x10000000, 0x00040000, 0x00002004, 0x10042004,
                                 0x00040004, 0x10042000, 0x10002000, 0x00042004,
                                 0x10042004, 0x00040004, 0x10000004, 0x00000000,
                                 0x10000000, 0x00002004, 0x00040000, 0x10040004,
                                 0x00002000, 0x10000000, 0x00042004, 0x10002004,
                                 0x10042000, 0x00002000, 0x00000000, 0x10000004,
                                 0x00000004, 0x10042004, 0x00042000, 0x10040000,
                                 0x10040004, 0x00040000, 0x00002004, 0x10002000,
                                 0x10002004, 0x00000004, 0x10040000, 0x00042000,
                              },
                              {
                                 /* nibble 2 */
                                 0x41000000, 0x01010040, 0x00000040, 0x41000040,
                                 0x40010000, 0x01000000, 0x41000040, 0x00010040,
                                 0x01000040, 0x00010000, 0x01010000, 0x40000000,
                                 0x41010040, 0x40000040, 0x40000000, 0x41010000,
                                 0x00000000, 0x40010000, 0x01010040, 0x00000040,
                                 0x40000040, 0x41010040, 0x00010000, 0x41000000,
                                 0x41010000, 0x01000040, 0x40010040, 0x01010000,
                                 0x00010040, 0x00000000, 0x01000000, 0x40010040,
                                 0x01010040, 0x00000040, 0x40000000, 0x00010000,
                                 0x40000040, 0x40010000, 0x01010000, 0x41000040,
                                 0x00000000, 0x01010040, 0x00010040, 0x41010000,
                                 0x40010000, 0x01000000, 0x41010040, 0x40000000,
                                 0x40010040, 0x41000000, 0x01000000, 0x41010040,
                                 0x00010000, 0x01000040, 0x41000040, 0x00010040,
                                 0x01000040, 0x00000000, 0x41010000, 0x40000040,
                                 0x41000000, 0x40010040, 0x00000040, 0x01010000,
                              },
                              {
                                 /* nibble 3 */
                                 0x00100402, 0x04000400, 0x00000002, 0x04100402,
                                 0x00000000, 0x04100000, 0x04000402, 0x00100002,
                                 0x04100400, 0x04000002, 0x04000000, 0x00000402,
                                 0x04000002, 0x00100402, 0x00100000, 0x04000000,
                                 0x04100002, 0x00100400, 0x00000400, 0x00000002,
                                 0x00100400, 0x04000402, 0x04100000, 0x00000400,
                                 0x00000402, 0x00000000, 0x00100002, 0x04100400,
                                 0x04000400, 0x04100002, 0x04100402, 0x00100000,
                                 0x04100002, 0x00000402, 0x00100000, 0x04000002,
                                 0x00100400, 0x04000400, 0x00000002, 0x04100000,
                                 0x04000402, 0x00000000, 0x00000400, 0x00100002,
                                 0x00000000, 0x04100002, 0x04100400, 0x00000400,
                                 0x04000000, 0x04100402, 0x00100402, 0x00100000,
                                 0x04100402, 0x00000002, 0x04000400, 0x00100402,
                                 0x00100002, 0x00100400, 0x04100000, 0x04000402,
                                 0x00000402, 0x04000000, 0x04000002, 0x04100400,
                              },
                              {
                                 /* nibble 4 */
                                 0x02000000, 0x00004000, 0x00000100, 0x02004108,
                                 0x02004008, 0x02000100, 0x00004108, 0x02004000,
                                 0x00004000, 0x00000008, 0x02000008, 0x00004100,
                                 0x02000108, 0x02004008, 0x02004100, 0x00000000,
                                 0x00004100, 0x02000000, 0x00004008, 0x00000108,
                                 0x02000100, 0x00004108, 0x00000000, 0x02000008,
                                 0x00000008, 0x02000108, 0x02004108, 0x00004008,
                                 0x02004000, 0x00000100, 0x00000108, 0x02004100,
                                 0x02004100, 0x02000108, 0x00004008, 0x02004000,
                                 0x00004000, 0x00000008, 0x02000008, 0x02000100,
                                 0x02000000, 0x00004100, 0x02004108, 0x00000000,
                                 0x00004108, 0x02000000, 0x00000100, 0x00004008,
                                 0x02000108, 0x00000100, 0x00000000, 0x02004108,
                                 0x02004008, 0x02004100, 0x00000108, 0x00004000,
                                 0x00004100, 0x02004008, 0x02000100, 0x00000108,
                                 0x00000008, 0x00004108, 0x02004000, 0x02000008,
                              },
                              {
                                 /* nibble 5 */
                                 0x20000010, 0x00080010, 0x00000000, 0x20080800,
                                 0x00080010, 0x00000800, 0x20000810, 0x00080000,
                                 0x00000810, 0x20080810, 0x00080800, 0x20000000,
                                 0x20000800, 0x20000010, 0x20080000, 0x00080810,
                                 0x00080000, 0x20000810, 0x20080010, 0x00000000,
                                 0x00000800, 0x00000010, 0x20080800, 0x20080010,
                                 0x20080810, 0x20080000, 0x20000000, 0x00000810,
                                 0x00000010, 0x00080800, 0x00080810, 0x20000800,
                                 0x00000810, 0x20000000, 0x20000800, 0x00080810,
                                 0x20080800, 0x00080010, 0x00000000, 0x20000800,
                                 0x20000000, 0x00000800, 0x20080010, 0x00080000,
                                 0x00080010, 0x20080810, 0x00080800, 0x00000010,
                                 0x20080810, 0x00080800, 0x00080000, 0x20000810,
                                 0x20000010, 0x20080000, 0x00080810, 0x00000000,
                                 0x00000800, 0x20000010, 0x20000810, 0x20080800,
                                 0x20080000, 0x00000810, 0x00000010, 0x20080010,
                              },
                              {
                                 /* nibble 6 */
                                 0x00001000, 0x00000080, 0x00400080, 0x00400001,
                                 0x00401081, 0x00001001, 0x00001080, 0x00000000,
                                 0x00400000, 0x00400081, 0x00000081, 0x00401000,
                                 0x00000001, 0x00401080, 0x00401000, 0x00000081,
                                 0x00400081, 0x00001000, 0x00001001, 0x00401081,
                                 0x00000000, 0x00400080, 0x00400001, 0x00001080,
                                 0x00401001, 0x00001081, 0x00401080, 0x00000001,
                                 0x00001081, 0x00401001, 0x00000080, 0x00400000,
                                 0x00001081, 0x00401000, 0x00401001, 0x00000081,
                                 0x00001000, 0x00000080, 0x00400000, 0x00401001,
                                 0x00400081, 0x00001081, 0x00001080, 0x00000000,
                                 0x00000080, 0x00400001, 0x00000001, 0x00400080,
                                 0x00000000, 0x00400081, 0x00400080, 0x00001080,
                                 0x00000081, 0x00001000, 0x00401081, 0x00400000,
                                 0x00401080, 0x00000001, 0x00001001, 0x00401081,
                                 0x00400001, 0x00401080, 0x00401000, 0x00001001,
                              },
                              {
                                 /* nibble 7 */
                                 0x08200020, 0x08208000, 0x00008020, 0x00000000,
                                 0x08008000, 0x00200020, 0x08200000, 0x08208020,
                                 0x00000020, 0x08000000, 0x00208000, 0x00008020,
                                 0x00208020, 0x08008020, 0x08000020, 0x08200000,
                                 0x00008000, 0x00208020, 0x00200020, 0x08008000,
                                 0x08208020, 0x08000020, 0x00000000, 0x00208000,
                                 0x08000000, 0x00200000, 0x08008020, 0x08200020,
                                 0x00200000, 0x00008000, 0x08208000, 0x00000020,
                                 0x00200000, 0x00008000, 0x08000020, 0x08208020,
                                 0x00008020, 0x08000000, 0x00000000, 0x00208000,
                                 0x08200020, 0x08008020, 0x08008000, 0x00200020,
                                 0x08208000, 0x00000020, 0x00200020, 0x08008000,
                                 0x08208020, 0x00200000, 0x08200000, 0x08000020,
                                 0x00208000, 0x00008020, 0x08008020, 0x08200000,
                                 0x00000020, 0x08208000, 0x00208020, 0x00000000,
                                 0x08000000, 0x08200020, 0x00008000, 0x00208020
                              }
                           };
      /// <value>
      /// A lookup-table filled with printable characters.
      /// It is used to make sure the encrypted password contains only printable characters. It is filled with
      /// ASCII characters 46 - 122 (from the dot (.) untill (including) the lowercase &#039;z&#039;).
      /// </value>
      private static readonly uint[] m_characterConversionTable =
                           {
                              0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 
                              0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 
                              0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 
                              0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 
                              0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x61, 0x62, 
                              0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 
                              0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 
                              0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A
                           };
      /// <value>
      /// Marks the size of the dynamically created schedule lookup-table.
      /// </value>
      private const int m_desIterations = 16;

      /// <summary>
      /// Converts four seperate bytes into one uint.
      /// </summary>
      /// <param name="inputBytes">The bytes to use for the conversion.</param>
      /// <param name="offset">The offset at which to start in the inputBytes buffer.</param>
      /// <returns></returns>
      private static uint FourBytesToInt(byte[] inputBytes, uint offset)
      {
         // I used an int here because the compiler would complain the stuff below would require a cast from int to uint.
         // To keep the code cleaner I opted to use an int and cast it when I returned it.
         int resultValue = 0;

         resultValue = (inputBytes[offset++] &amp; 0xFF);
         resultValue |= (inputBytes[offset++] &amp; 0xFF) << 8;
         resultValue |= (inputBytes&#91;offset++&#93; &amp; 0xFF) << 16;
         resultValue |= (inputBytes&#91;offset++&#93;&amp; 0xFF) << 24;

         return (uint)resultValue;
      }



      /// <summary>
      /// Converts an uint into 4 seperate bytes.
      /// </summary>
      /// <param name="inputInt">The uint to convert.</param>
      /// <param name="outputBytes">The byte buffer into which to store the result.</param>
      /// <param name="offset">The offset to start storing at in the outputBytes buffer.</param>
      private static void IntToFourBytes(uint inputInt, byte[] outputBytes, uint offset)
      {
         outputBytes[offset++] = (byte)(inputInt &amp; 0xFF);
         outputBytes[offset++] = (byte)((inputInt >> 8) &amp; 0xFF);
         outputBytes[offset++] = (byte)((inputInt >> 16) &amp; 0xFF);
         outputBytes[offset++] = (byte)((inputInt >> 24) &amp; 0xFF);
      }



      /// <summary>
      /// Performs some operation on 4 uints. It&#039;s labeled PERM_OP in the original source.
      /// </summary>
      /// <param name="firstInt">The first uint to use.</param>
      /// <param name="secondInt">The second uint to use.</param>
      /// <param name="thirdInt">The third uint to use.</param>
      /// <param name="fourthInt">The fourth uint to use.</param>
      /// <param name="operationResults">An array of 2 uints that are the result of this operation.</param>
      private static void PermOperation(uint firstInt, uint secondInt, uint thirdInt, uint fourthInt, uint[] operationResults)
      {
         // Because here an uint variable is at the right side of a bitshift, I needed to cast it to int. See the remarks of the class itself
         // for more details.
         uint tempInt = ((firstInt >> (int)thirdInt) ^ secondInt) &amp; fourthInt;
         firstInt ^= tempInt << (int)thirdInt;
         secondInt ^= tempInt;

         operationResults&#91;0&#93; = firstInt;
         operationResults&#91;1&#93; = secondInt;
      }



      /// <summary>
      /// Performs some operation on 3 uints. It&#039;s labeled HPERM_OP in the original source.
      /// </summary>
      /// <param name="firstInt">The first uint to use.</param>
      /// <param name="secondInt">The second int to use.</param>
      /// <param name="thirdInt">The third uint to use.</param>
      /// <returns>An int that is the result of this operation.</returns>
      private static uint HPermOperation(uint firstInt, int secondInt, uint thirdInt)
      {
         // The variable secondInt is always used to calculate the number at the right side of a
         // bitshift. It is not used anywhere else, so I made the method parameter an int, to avoid
         // unnecessary casting.
         uint tempInt = ((firstInt << (16 - secondInt)) ^ firstInt) &amp; thirdInt;
         uint returnInt = firstInt ^ tempInt ^ (tempInt >> (16 - secondInt));

         return returnInt;
      }



      /// <summary>
      /// This method does some very complex bit manipulations.
      /// </summary>
      /// <param name="encryptionKey">The input data to use for the bit manipulations.</param>
      /// <returns>m_desIterations * 2 number of uints that are the result of the manipulations.</returns>
      private static uint[] SetDESKey(byte[] encryptionKey)
      {
         uint[] schedule = new uint[m_desIterations * 2];

         uint firstInt = FourBytesToInt(encryptionKey, 0);
         uint secondInt = FourBytesToInt(encryptionKey, 4);

         uint[] operationResults = new uint[2];
         PermOperation(secondInt, firstInt, 4, 0x0F0F0F0F, operationResults);
         secondInt = operationResults[0];
         firstInt = operationResults[1];

         firstInt = HPermOperation(firstInt, -2, 0xCCCC0000);
         secondInt = HPermOperation(secondInt, -2, 0xCCCC0000);

         PermOperation(secondInt, firstInt, 1, 0x55555555, operationResults);
         secondInt = operationResults[0];
         firstInt = operationResults[1];

         PermOperation(firstInt, secondInt, 8, 0x00FF00FF, operationResults);
         firstInt = operationResults[0];
         secondInt = operationResults[1];

         PermOperation(secondInt, firstInt, 1, 0x55555555, operationResults);
         secondInt = operationResults[0];
         firstInt = operationResults[1];

         secondInt = (((secondInt &amp; 0xFF) << 16) | (secondInt &amp; 0xFF00) |
            ((secondInt &amp; 0xFF0000) >> 16) | ((firstInt &amp; 0xF0000000) >> 4));

         firstInt &amp;= 0x0FFFFFFF;

         bool needToShift;
         uint firstSkbValue, secondSkbValue;
         uint scheduleIndex = 0;

         for(int index = 0; index < m_desIterations; index++)
         {
            needToShift = m_shifts&#91;index&#93;;
            if(needToShift)
            {
               firstInt = (firstInt >> 2) | (firstInt << 26);
               secondInt = (secondInt >> 2) | (secondInt << 26);
            }
            else
            {
               firstInt = (firstInt >> 1) | (firstInt << 27);
               secondInt = (secondInt >> 1) | (secondInt << 27);
            }

            firstInt &amp;= 0x0FFFFFFF;
            secondInt &amp;= 0xFFFFFFF;

            firstSkbValue = m_skb&#91;0, firstInt &amp; 0x3F&#93; |
               m_skb&#91;1, ((firstInt >> 6) &amp; 0x03) | ((firstInt >> 7) &amp; 0x3C)] |
               m_skb[2, ((firstInt >> 13) &amp; 0x0F) | ((firstInt >> 14) &amp; 0x30)] |
               m_skb[3, ((firstInt >> 20) &amp; 0x01) | ((firstInt >> 21) &amp; 0x06) | ((firstInt >> 22) &amp; 0x38)];

            secondSkbValue = m_skb[4, secondInt &amp; 0x3F] |
               m_skb[5, ((secondInt >> 7) &amp; 0x03) | ((secondInt >> 8) &amp; 0x3C)] |
               m_skb[6, (secondInt >> 15) &amp; 0x3F] |
               m_skb[7, ((secondInt >> 21) &amp; 0x0F) | ((secondInt >> 22) &amp; 0x30)];

            schedule[scheduleIndex++] = ((secondSkbValue << 16) | (firstSkbValue &amp; 0xFFFF)) &amp; 0xFFFFFFFF;
            firstSkbValue = ((firstSkbValue >> 16) | (secondSkbValue &amp; 0xFFFF0000));

            firstSkbValue = (firstSkbValue << 4) | (firstSkbValue >> 28);
            schedule[scheduleIndex++] = firstSkbValue &amp; 0xFFFFFFFF;
         }

         return schedule;
      }



      /// <summary>
      /// This method does some bit manipulations.
      /// </summary>
      /// <param name="left">An input that is manipulated and then used for output.</param>
      /// <param name="right">This is used for the bit manipulation.</param>
      /// <param name="scheduleIndex">The index of an uint to use from the schedule array.</param>
      /// <param name="firstSaltTranslator">The translated salt for the first salt character.</param>
      /// <param name="secondSaltTranslator">The translated salt for the second salt character.</param>
      /// <param name="schedule">The schedule arrray calculated before.</param>
      /// <returns>The result of these manipulations.</returns>
      private static uint DEncrypt(uint left, uint right, uint scheduleIndex, uint firstSaltTranslator, uint secondSaltTranslator, uint[] schedule)
      {
         uint firstInt, secondInt, thirdInt;

         thirdInt = right ^ (right >> 16);
         secondInt = thirdInt &amp; firstSaltTranslator;
         thirdInt = thirdInt &amp; secondSaltTranslator;

         secondInt = (secondInt ^ (secondInt << 16)) ^ right ^ schedule&#91;scheduleIndex&#93;;
         firstInt = (thirdInt ^ (thirdInt << 16)) ^ right ^ schedule&#91;scheduleIndex+1&#93;;
         firstInt = (firstInt >> 4) | (firstInt << 28);

         left ^= (m_SPTranslationTable&#91;1, firstInt &amp; 0x3F&#93; |
                     m_SPTranslationTable&#91;3, (firstInt >> 8) &amp; 0x3F] |
                     m_SPTranslationTable[5, (firstInt >> 16) &amp; 0x3F] |
                     m_SPTranslationTable[7, (firstInt >> 24) &amp; 0x3F] |
                     m_SPTranslationTable[0, secondInt &amp; 0x3F] |
                     m_SPTranslationTable[2, (secondInt >> 8) &amp; 0x3F] |
                     m_SPTranslationTable[4, (secondInt >> 16) &amp; 0x3F] |
                     m_SPTranslationTable[6, (secondInt >> 24) &amp; 0x3F]);

         return left;
      }



      /// <summary>
      /// Calculates two uints that are used to encrypt the password.
      /// </summary>
      /// <param name="schedule">The schedule table calculated earlier.</param>
      /// <param name="firstSaltTranslator">The first translated salt character.</param>
      /// <param name="secondSaltTranslator">The second translated salt character.</param>
      /// <returns>2 uints in an array.</returns>
      private static uint[] Body(uint[] schedule, uint firstSaltTranslator, uint secondSaltTranslator)
      {
         uint left = 0;
         uint right = 0;
         uint tempInt;

         for(int index = 0; index < 25; index++)
         {
            for(uint secondIndex = 0; secondIndex < m_desIterations * 2; secondIndex += 4)
            {
               left = DEncrypt(left, right, secondIndex, firstSaltTranslator, secondSaltTranslator, schedule);
               right = DEncrypt(right, left, secondIndex + 2, firstSaltTranslator, secondSaltTranslator, schedule);
            }
            
            tempInt = left;
            left = right;
            right = tempInt;
         }

         tempInt = right;
         right = (left >> 1) | (left << 31);
         left = (tempInt >> 1) | (tempInt << 31);

         left &amp;= 0xFFFFFFFF;
         right &amp;= 0xFFFFFFFF;

         uint&#91;&#93; operationResults = new uint&#91;2&#93;;

         PermOperation(right, left, 1, 0x55555555, operationResults);
         right = operationResults&#91;0&#93;;
         left = operationResults&#91;1&#93;;

         PermOperation(left, right, 8, 0x00FF00FF, operationResults);
         left = operationResults&#91;0&#93;;
         right = operationResults&#91;1&#93;;

         PermOperation(right, left, 2, 0x33333333, operationResults);
         right = operationResults&#91;0&#93;;
         left = operationResults&#91;1&#93;;

         PermOperation(left, right, 16, 0xFFFF, operationResults);
         left = operationResults&#91;0&#93;;
         right = operationResults&#91;1&#93;;

         PermOperation(right, left, 4, 0x0F0F0F0F, operationResults);
         right = operationResults&#91;0&#93;;
         left = operationResults&#91;1&#93;;

         uint&#91;&#93; singleOutputKey = new uint&#91;2&#93;;
         singleOutputKey&#91;0&#93; = left;
         singleOutputKey&#91;1&#93; = right;

         return singleOutputKey;
      }


      /// <summary>
      /// Automatically generate the encryption salt (2 random printable characters for use in the encryption) and call the Crypt() method.
      /// </summary>
      /// <param name="textToEncrypt">The text that must be encrypted.</param>
      /// <returns>The encrypted text.</returns>
      public static string Crypt(string textToEncrypt)
      {
         Random randomGenerator = new Random();

         int maxGeneratedNumber = m_encryptionSaltCharacters.Length;
         int randomIndex;
         StringBuilder encryptionSaltBuilder = new StringBuilder();
         for(int index = 0; index < 2; index++)
         {
            randomIndex = randomGenerator.Next(maxGeneratedNumber);
            encryptionSaltBuilder.Append(m_encryptionSaltCharacters&#91;randomIndex&#93;);
         }

         string encryptionSalt = encryptionSaltBuilder.ToString();
         string encryptedString = Crypt(encryptionSalt, textToEncrypt);

         return encryptedString;
      }



      /// <summary>
      /// Encrypts the specified string using the Unix crypt algorithm.
      /// </summary>
      /// <param name="encryptionSalt">2 random printable characters that are used to randomize the encryption.</param>
      /// <param name="textToEncrypt">The text that must be encrypted.</param>
      /// <returns>The encrypted text.</returns>
      public static string Crypt(string encryptionSalt, string textToEncrypt)
      {
         if(encryptionSalt==null) throw new ArgumentNullException("encryptionSalt");
      if(textToEncrypt==null) throw new ArgumentNullException("textToEncrypt");
          
      bool isSaltTooSmall = (encryptionSalt.Length < 2);
         if(isSaltTooSmall)
         {
            throw new ArgumentException("The encryptionSalt must be 2 characters big.");
         }

         char firstSaltCharacter = encryptionSalt&#91;0&#93;;
         char secondSaltCharacter = encryptionSalt&#91;1&#93;;

         // Make sure the string builder is big enough AND filled with 13 characters (the length of the encrypted password).
         // We will use the index operator to set them, but when the characters are not present, even though the string builder
         // has enough capacity, it will throw an exception.
         StringBuilder encryptionBuffer = new StringBuilder("*************");
         encryptionBuffer&#91;0&#93; = firstSaltCharacter;
         encryptionBuffer&#91;1&#93; = secondSaltCharacter;

         // Use the ASCII value of the salt characters to lookup a number in the salt translation table.
         uint firstSaltTranslator = m_saltTranslation&#91;Convert.ToUInt32(firstSaltCharacter)&#93;;
         uint secondSaltTranslator = m_saltTranslation&#91;Convert.ToUInt32(secondSaltCharacter)&#93; << 4;

         // Build the first encryption key table by taking the ASCII value of every character in the text to encrypt and
         // multiplying it by two. Note how the cast will not lose any information. The highest possible ASCII character
         // in a password is the tilde (~), which has ASCII value 126, so the highest possible value after the
         // multiplication would be 252.
         byte&#91;&#93; encryptionKey = new byte&#91;8&#93;;
         for(int index = 0; index < encryptionKey.Length &amp;&amp; index < textToEncrypt.Length; index++)
         {
            int shiftedCharacter = Convert.ToInt32(textToEncrypt&#91;index&#93;);
            encryptionKey&#91;index&#93; = (byte)(shiftedCharacter << 1);
         }

         uint&#91;&#93; schedule = SetDESKey(encryptionKey);
         uint&#91;&#93; singleOutputKey = Body(schedule, firstSaltTranslator, secondSaltTranslator);

         byte&#91;&#93; binaryBuffer = new byte&#91;9&#93;;
         IntToFourBytes(singleOutputKey&#91;0&#93;, binaryBuffer, 0);
         IntToFourBytes(singleOutputKey&#91;1&#93;, binaryBuffer, 4);
         binaryBuffer&#91;8&#93; = 0;

         uint binaryBufferIndex = 0;
         uint passwordCharacter;
         uint bitChecker = 0x80;
         bool isAnyBitSet, bitCheckerOverflow;
         for(int index = 2; index < 13; index++)
         {
            passwordCharacter = 0;
            for(int secondIndex = 0; secondIndex < 6; secondIndex++)
            {
               passwordCharacter <<= 1;
               isAnyBitSet = ((binaryBuffer&#91;binaryBufferIndex&#93; &amp; bitChecker) != 0);
               if(isAnyBitSet)
               {
                  passwordCharacter |= 1;
               }

               bitChecker >>= 1;
               bitCheckerOverflow = (bitChecker == 0);
               if(bitCheckerOverflow)
               {
                  binaryBufferIndex++;
                  bitChecker = 0x80;
               }

               // The original source had the line below, I moved it outside the compound signs, because it will overwrite the value
               // a few times before incrementing the index. Where it is now it will be written only once.
               // Just to be on the safe side, I keep the original line here, so I know where it originally was.
               //encryptionBuffer[index] = Convert.ToChar(m_characterConversionTable[passwordCharacter]);
            }

            encryptionBuffer[index] = Convert.ToChar(m_characterConversionTable[passwordCharacter]);
         }
         
         return encryptionBuffer.ToString();
      }
   }

   
     


Decrypt Utils

image_pdfimage_print
   
 

///////////////////////////////////////////////////////////////////////////////////////////////
//
//    This File is Part of the CallButler Open Source PBX (http://www.codeplex.com/callbutler
//
//    Copyright (c) 2005-2008, Jim Heising
//    All rights reserved.
//
//    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.
//
//    * Redistributions in binary form must reproduce the above copyright notice,
//      this list of conditions and the following disclaimer in the documentation and/or
//      other materials provided with the distribution.
//
//    * Neither the name of Jim Heising 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.Text;
using System.Globalization;
using System.IO;

namespace WOSI.Utilities
{
  /// <summary>
  /// Summary description for CryptoUtils.
  /// </summary>
  public class CryptoUtils
  {
    private CryptoUtils()
    {
      //
      // TODO: Add constructor logic here
      //
    }

    // Decrypt a byte array into a byte array using a key and an IV 
    public static byte[] Decrypt(byte[] cipherData, 
      byte[] Key, byte[] IV) 
    {
            try
            {
                // Create a MemoryStream that is going to accept the
                // decrypted bytes 
                MemoryStream ms = new MemoryStream();

                // Create a symmetric algorithm. 
                // We are going to use Rijndael because it is strong and
                // available on all platforms. 
                // You can use other algorithms, to do so substitute the next
                // line with something like 
                //     TripleDES alg = TripleDES.Create(); 
                Rijndael alg = Rijndael.Create();

                // Now set the key and the IV. 
                // We need the IV (Initialization Vector) because the algorithm
                // is operating in its default 
                // mode called CBC (Cipher Block Chaining). The IV is XORed with
                // the first block (8 byte) 
                // of the data after it is decrypted, and then each decrypted
                // block is XORed with the previous 
                // cipher block. This is done to make encryption more secure. 
                // There is also a mode called ECB which does not need an IV,
                // but it is much less secure. 
                alg.Key = Key;
                alg.IV = IV;

                // Create a CryptoStream through which we are going to be
                // pumping our data. 
                // CryptoStreamMode.Write means that we are going to be
                // writing data to the stream 
                // and the output will be written in the MemoryStream
                // we have provided. 
                CryptoStream cs = new CryptoStream(ms,
                    alg.CreateDecryptor(), CryptoStreamMode.Write);

                // Write the data and make it do the decryption 
                cs.Write(cipherData, 0, cipherData.Length);

                // Close the crypto stream (or do FlushFinalBlock). 
                // This will tell it that we have done our decryption
                // and there is no more data coming in, 
                // and it is now a good time to remove the padding
                // and finalize the decryption process. 
                cs.Close();

                // Now get the decrypted data from the MemoryStream. 
                // Some people make a mistake of using GetBuffer() here,
                // which is not the right way. 
                byte[] decryptedData = ms.ToArray();

                return decryptedData;
            }
            catch
            {
                return null;
            }
    }

    // Decrypt a string into a string using a password 
    //    Uses Decrypt(byte[], byte[], byte[]) 

    public static string Decrypt(string cipherText, string Password) 
    {
            try
            {
                // First we need to turn the input string into a byte array. 
                // We presume that Base64 encoding was used 
                byte[] cipherBytes = Convert.FromBase64String(cipherText);

                // Then, we need to turn the password into Key and IV 
                // We are using salt to make it harder to guess our key
                // using a dictionary attack - 
                // trying to guess a password by enumerating all possible words. 
                PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password,
                    new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 
                 0x64, 0x76, 0x65, 0x64, 0x65, 0x76});

                // Now get the key/IV and do the decryption using
                // the function that accepts byte arrays. 
                // Using PasswordDeriveBytes object we are first
                // getting 32 bytes for the Key 
                // (the default Rijndael key length is 256bit = 32bytes)
                // and then 16 bytes for the IV. 
                // IV should always be the block size, which is by
                // default 16 bytes (128 bit) for Rijndael. 
                // If you are using DES/TripleDES/RC2 the block size is
                // 8 bytes and so should be the IV size. 
                // You can also read KeySize/BlockSize properties off
                // the algorithm to find out the sizes. 
                byte[] decryptedData = Decrypt(cipherBytes,
                    pdb.GetBytes(32), pdb.GetBytes(16));

                // Now we need to turn the resulting byte array into a string. 
                // A common mistake would be to use an Encoding class for that.
                // It does not work 
                // because not all byte values can be represented by characters. 
                // We are going to be using Base64 encoding that is 
                // designed exactly for what we are trying to do. 
                return System.Text.Encoding.Unicode.GetString(decryptedData);
            }
            catch
            {
                return null;
            }
    }

    // Decrypt bytes into bytes using a password 
    //    Uses Decrypt(byte[], byte[], byte[]) 

    public static byte[] Decrypt(byte[] cipherData, string Password) 
    { 
      // We need to turn the password into Key and IV. 
      // We are using salt to make it harder to guess our key
      // using a dictionary attack - 
      // trying to guess a password by enumerating all possible words. 
      PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, 
        new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 
                 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76}); 

      // Now get the key/IV and do the Decryption using the 
      //function that accepts byte arrays. 
      // Using PasswordDeriveBytes object we are first getting
      // 32 bytes for the Key 
      // (the default Rijndael key length is 256bit = 32bytes)
      // and then 16 bytes for the IV. 
      // IV should always be the block size, which is by default
      // 16 bytes (128 bit) for Rijndael. 
      // If you are using DES/TripleDES/RC2 the block size is
      // 8 bytes and so should be the IV size. 

      // You can also read KeySize/BlockSize properties off the
      // algorithm to find out the sizes. 
      return Decrypt(cipherData, pdb.GetBytes(32), pdb.GetBytes(16)); 
    }

    // Decrypt a file into another file using a password 
    public static void Decrypt(string fileIn, 
      string fileOut, string Password) 
    {
            try
            {
                // First we are going to open the file streams 
                FileStream fsIn = new FileStream(fileIn,
                    FileMode.Open, FileAccess.Read);
                FileStream fsOut = new FileStream(fileOut,
                    FileMode.OpenOrCreate, FileAccess.Write);

                // Then we are going to derive a Key and an IV from
                // the Password and create an algorithm 
                PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password,
                    new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 
                 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76});
                Rijndael alg = Rijndael.Create();

                alg.Key = pdb.GetBytes(32);
                alg.IV = pdb.GetBytes(16);

                // Now create a crypto stream through which we are going
                // to be pumping data. 
                // Our fileOut is going to be receiving the Decrypted bytes. 
                CryptoStream cs = new CryptoStream(fsOut,
                    alg.CreateDecryptor(), CryptoStreamMode.Write);

                // Now will will initialize a buffer and will be 
                // processing the input file in chunks. 
                // This is done to avoid reading the whole file (which can be
                // huge) into memory. 
                int bufferLen = 4096;
                byte[] buffer = new byte[bufferLen];
                int bytesRead;

                do
                {
                    // read a chunk of data from the input file 
                    bytesRead = fsIn.Read(buffer, 0, bufferLen);

                    // Decrypt it 
                    cs.Write(buffer, 0, bytesRead);

                } while (bytesRead != 0);

                // close everything 
                cs.Close(); // this will also close the unrelying fsOut stream 
                fsIn.Close();
            }
            catch
            {
            }
    }
  }
}