Encrypt 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
  {
    public static byte[] Encrypt(byte[] clearData, byte[] Key, byte[] IV) 
    { 
      // Create a MemoryStream to accept the encrypted 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 before it is encrypted, and then each
      // encrypted block is XORed with the 
      // following block of plaintext.
      // 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.CreateEncryptor(), CryptoStreamMode.Write); 

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

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

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

      return encryptedData; 
    } 


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

    public static string Encrypt(string clearText, string Password) 
    { 
      // First we need to turn the input string into a byte array. 
      byte[] clearBytes = 
        System.Text.Encoding.Unicode.GetBytes(clearText); 

      // 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 encryption 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[] encryptedData = Encrypt(clearBytes, 
        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 Convert.ToBase64String(encryptedData); 

    }

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

    public static byte[] Encrypt(byte[] clearData, 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 encryption 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 Encrypt(clearData, pdb.GetBytes(32), pdb.GetBytes(16)); 

    }

    // Encrypt a file into another file using a password 
    public static void Encrypt(string fileIn, 
      string fileOut, string Password) 
    { 

      // 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 encrypted bytes. 
      CryptoStream cs = new CryptoStream(fsOut, 
        alg.CreateEncryptor(), 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); 

        // encrypt it 
        cs.Write(buffer, 0, bytesRead); 
      } while(bytesRead != 0); 

      // close everything 

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

   
     


This entry was posted in Security. Bookmark the permalink.