Advertisement
parabola949

FileEncryption Class

Apr 10th, 2012
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 9.45 KB | None | 0 0
  1. using System;
  2. using System.IO;
  3. using System.Security.Cryptography;
  4.  
  5. namespace THRServiceTool.Common
  6. {
  7.     public class CryptoHelpException : ApplicationException
  8.        {
  9.            public CryptoHelpException(string msg):base(msg){}
  10.        }
  11.  
  12.     public class FileEncryption
  13.     {
  14.         private const ulong FC_TAG = 0xFC010203040506CF;
  15.         private const int BUFFER_SIZE = 128 * 1024;
  16.         /// <summary>
  17.         /// This takes an input file and encrypts it into the output file>
  18.         /// </summary>
  19.         /// <param name="inFile">the file to encrypt</param>
  20.         /// <param name="outFile">the file to write the encrypted data to</param>
  21.         /// <param name="password">the password for use as the key</param>
  22.         /// <param name="callback">the method to call to notify of progress</param>
  23.         public static void EncryptFile(string inFile, string outFile,
  24.                             string password)
  25.         {
  26.             using (FileStream fin = File.OpenRead(inFile),
  27.                   fout = File.OpenWrite(outFile))
  28.             {
  29.                 long lSize = fin.Length; // the size of the input file for storing
  30.                 int size = (int)lSize;  // the size of the input file for progress
  31.                 byte[] bytes = new byte[BUFFER_SIZE]; // the buffer
  32.                 int read = -1; // the amount of bytes read from the input file
  33.                 int value = 0; // the amount overall read from the input file for progress
  34.  
  35.                 // generate IV and Salt
  36.                 byte[] IV = GenerateRandomBytes(16);
  37.                 byte[] salt = GenerateRandomBytes(16);
  38.  
  39.                 // create the crypting object
  40.                 SymmetricAlgorithm sma = CreateRijndael(password, salt);
  41.                 sma.IV = IV;
  42.  
  43.                 // write the IV and salt to the beginning of the file
  44.                 fout.Write(IV, 0, IV.Length);
  45.                 fout.Write(salt, 0, salt.Length);
  46.  
  47.                 // create the hashing and crypto streams
  48.                 HashAlgorithm hasher = SHA256.Create();
  49.                 using (CryptoStream cout = new CryptoStream(fout, sma.CreateEncryptor(),
  50.                     CryptoStreamMode.Write),
  51.                       chash = new CryptoStream(Stream.Null, hasher,
  52.                         CryptoStreamMode.Write))
  53.                 {
  54.                     // write the size of the file to the output file
  55.                     BinaryWriter bw = new BinaryWriter(cout);
  56.                     bw.Write(lSize);
  57.  
  58.                     // write the file cryptor tag to the file
  59.                     bw.Write(FC_TAG);
  60.  
  61.                     // read and the write the bytes to the crypto stream
  62.                     // in BUFFER_SIZEd chunks
  63.                     while ((read = fin.Read(bytes, 0, bytes.Length)) != 0)
  64.                     {
  65.                         cout.Write(bytes, 0, read);
  66.                         chash.Write(bytes, 0, read);
  67.                         value += read;
  68.                         //callback(0, size, value);
  69.                     }
  70.                     // flush and close the hashing object
  71.                     chash.Flush();
  72.                     chash.Close();
  73.  
  74.                     // read the hash
  75.                     byte[] hash = hasher.Hash;
  76.  
  77.                     // write the hash to the end of the file
  78.                     cout.Write(hash, 0, hash.Length);
  79.  
  80.                     // flush and close the cryptostream
  81.                     cout.Flush();
  82.                     cout.Close();
  83.                 }
  84.             }
  85.         }
  86.  
  87.         /// <summary>
  88.            /// Checks to see if two byte array are equal
  89.            /// </summary>
  90.            /// <param name="b1">the first byte array</param>
  91.            /// <param name="b2">the second byte array</param>
  92.            /// <returns>true if b1.Length == b2.Length and each byte in b1 is
  93.            /// equal to the corresponding byte in b2</returns>
  94.         private static bool CheckByteArrays(byte[] b1, byte[] b2)
  95.         {
  96.             if (b1.Length == b2.Length)
  97.             {
  98.                 for (int i = 0; i < b1.Length; ++i)
  99.                 {
  100.                     if (b1[i] != b2[i])
  101.                         return false;
  102.                 }
  103.                 return true;
  104.             }
  105.             return false;
  106.         }
  107.  
  108.         private static SymmetricAlgorithm CreateRijndael(string password, byte[] salt)
  109.         {
  110.             PasswordDeriveBytes pdb = new PasswordDeriveBytes(password, salt, "SHA256", 1000);
  111.  
  112.             SymmetricAlgorithm sma = Rijndael.Create();
  113.             sma.KeySize = 256;
  114.             sma.Key = pdb.GetBytes(32);
  115.             sma.Padding = PaddingMode.PKCS7;
  116.             return sma;
  117.         }
  118.  
  119.         private static RandomNumberGenerator rand = new RNGCryptoServiceProvider();
  120.  
  121.         private static byte[] GenerateRandomBytes(int count)
  122.         {
  123.             byte[] bytes = new byte[count];
  124.             rand.GetBytes(bytes);
  125.             return bytes;
  126.         }
  127.  
  128.         /// <summary>
  129.         /// takes an input file and decrypts it to the output file
  130.         /// </summary>
  131.         /// <param name="inFile">the file to decrypt</param>
  132.         /// <param name="outFile">the to write the decrypted data to</param>
  133.         /// <param name="password">the password used as the key</param>
  134.         /// <param name="callback">the method to call to notify of progress</param>
  135.         public static void DecryptFile(string inFile, string outFile,
  136.                     string password)
  137.         {
  138.             // NOTE:  The encrypting algo was so much easier...
  139.  
  140.             // create and open the file streams
  141.             using (FileStream fin = File.OpenRead(inFile),
  142.                       fout = File.OpenWrite(outFile))
  143.             {
  144.                 // the size of the file for progress notification
  145.                 int size = (int)fin.Length;
  146.                 // byte buffer
  147.                 byte[] bytes = new byte[BUFFER_SIZE];
  148.                 int read = -1; // the amount of bytes read from the stream
  149.                 int value = 0;
  150.                 int outValue = 0; // the amount of bytes written out
  151.  
  152.                 // read off the IV and Salt
  153.                 byte[] IV = new byte[16];
  154.                 fin.Read(IV, 0, 16);
  155.                 byte[] salt = new byte[16];
  156.                 fin.Read(salt, 0, 16);
  157.  
  158.                 // create the crypting stream
  159.                 SymmetricAlgorithm sma = CreateRijndael(password, salt);
  160.                 sma.IV = IV;
  161.  
  162.                 value = 32; // the value for the progress
  163.                 long lSize = -1; // the size stored in the input stream
  164.  
  165.                 // create the hashing object, so that we can verify the file
  166.                 HashAlgorithm hasher = SHA256.Create();
  167.  
  168.                 // create the cryptostreams that will process the file
  169.                 using (CryptoStream cin = new CryptoStream(fin, sma.CreateDecryptor(),
  170.                         CryptoStreamMode.Read),
  171.                           chash = new CryptoStream(Stream.Null, hasher,
  172.                             CryptoStreamMode.Write))
  173.                 {
  174.                     // read size from file
  175.                     BinaryReader br = new BinaryReader(cin);
  176.                     lSize = br.ReadInt64();
  177.                     ulong tag = br.ReadUInt64();
  178.  
  179.                     if (FC_TAG != tag)
  180.                         throw new CryptoHelpException("File Corrupted!");
  181.  
  182.                     //determine number of reads to process on the file
  183.                     long numReads = lSize / BUFFER_SIZE;
  184.  
  185.                     // determine what is left of the file, after numReads
  186.                     long slack = (long)lSize % BUFFER_SIZE;
  187.  
  188.                     // read the buffer_sized chunks
  189.                     for (int i = 0; i < numReads; ++i)
  190.                     {
  191.                         read = cin.Read(bytes, 0, bytes.Length);
  192.                         fout.Write(bytes, 0, read);
  193.                         chash.Write(bytes, 0, read);
  194.                         value += read;
  195.                         outValue += read;
  196.                         //callback(0, size, value);
  197.                     }
  198.  
  199.                     // now read the slack
  200.                     if (slack > 0)
  201.                     {
  202.                         read = cin.Read(bytes, 0, (int)slack);
  203.                         fout.Write(bytes, 0, read);
  204.                         chash.Write(bytes, 0, read);
  205.                         value += read;
  206.                         outValue += read;
  207.                         //callback(0, size, value);
  208.                     }
  209.                     // flush and close the hashing stream
  210.                     chash.Flush();
  211.                     chash.Close();
  212.  
  213.                     // flush and close the output file
  214.                     fout.Flush();
  215.                     fout.Close();
  216.  
  217.                     // read the current hash value
  218.                     byte[] curHash = hasher.Hash;
  219.  
  220.                     // get and compare the current and old hash values
  221.                     byte[] oldHash = new byte[hasher.HashSize / 8];
  222.                     read = cin.Read(oldHash, 0, oldHash.Length);
  223.                     if ((oldHash.Length != read) || (!CheckByteArrays(oldHash, curHash)))
  224.                         throw new CryptoHelpException("File Corrupted!");
  225.                 }
  226.  
  227.                 // make sure the written and stored size are equal
  228.                 if (outValue != lSize)
  229.                     throw new CryptoHelpException("File Sizes don't match!");
  230.             }
  231.         }
  232.     }
  233. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement