diff --git a/Source/Editor/Misc/StringEncryptionHelper.cs b/Source/Editor/Misc/StringEncryptionHelper.cs index 75fa95a..d5b3858 100644 --- a/Source/Editor/Misc/StringEncryptionHelper.cs +++ b/Source/Editor/Misc/StringEncryptionHelper.cs @@ -20,55 +20,54 @@ public static class StringEncryptionHelper public static byte[] Encrypt(byte[] clearData, byte[] key, byte[] iv) { // Create a MemoryStream to accept the encrypted bytes - MemoryStream ms = new MemoryStream(); - + using (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; + using (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. + using (CryptoStream cs = new CryptoStream(ms, + alg.CreateEncryptor(), CryptoStreamMode.Write)) + { + // Write the data and make it do the encryption + cs.Write(clearData, 0, clearData.Length); + + // FlushFinalBlock tells the crypto stream 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.FlushFinalBlock(); + + // 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; + } + } } /// @@ -87,33 +86,33 @@ public static string Encrypt(string clearText, string password) // 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, + using (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); - + 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); + } } /// @@ -129,24 +128,24 @@ public static byte[] Encrypt(byte[] clearData, string password) // 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, + using (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)); - + 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)); + } } /// @@ -158,49 +157,44 @@ public static byte[] Encrypt(byte[] clearData, string 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); - + using (FileStream fsIn = new FileStream(fileIn, + FileMode.Open, FileAccess.Read)) + using (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, + using (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 + 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76})) + using (Rijndael alg = Rijndael.Create()) { - // 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(); + 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. + using (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); + } + } } /// @@ -214,54 +208,53 @@ public static byte[] Decrypt(byte[] cipherData, byte[] key, byte[] iv) { // Create a MemoryStream that is going to accept the // decrypted bytes - MemoryStream ms = new MemoryStream(); - + using (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; + using (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. + using (CryptoStream cs = new CryptoStream(ms, + alg.CreateDecryptor(), CryptoStreamMode.Write)) + { + // Write the data and make it do the decryption + cs.Write(cipherData, 0, cipherData.Length); + + // FlushFinalBlock tells the crypto stream 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.FlushFinalBlock(); + + // 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; + } + } } /// @@ -281,32 +274,33 @@ public static string Decrypt(string cipherText, string password) // 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, + using (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); + 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); + } } /// @@ -322,24 +316,25 @@ public static byte[] Decrypt(byte[] cipherData, string password) // 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, + using (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)); + 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)); + } } /// @@ -351,48 +346,45 @@ public static byte[] Decrypt(byte[] cipherData, string password) public static void Decrypt(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); - + using (FileStream fsIn = new FileStream(fileIn, + FileMode.Open, FileAccess.Read)) + using (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, + using (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 + 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76})) + using (Rijndael alg = Rijndael.Create()) { - // 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(); + 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. + using (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); + } + } } } } \ No newline at end of file diff --git a/Source/SqlCeDatabase/TableExtensions.cs b/Source/SqlCeDatabase/TableExtensions.cs index 6a24932..8f16418 100644 --- a/Source/SqlCeDatabase/TableExtensions.cs +++ b/Source/SqlCeDatabase/TableExtensions.cs @@ -60,7 +60,7 @@ public static string GenerateDataScript(this Table table, ISqlCeDatabase databas foreach (var column in table.Columns.Where(column => column.Value.ManagedType != typeof(byte[]))) { var value = row[column.Value.Ordinal - 1]; - if (value == null) + if (value == null || value == DBNull.Value) { builder.Append("NULL,"); continue; diff --git a/Source/SqlCeDatabase35/SqlCeDatabase.cs b/Source/SqlCeDatabase35/SqlCeDatabase.cs index 61cde14..c5f6983 100644 --- a/Source/SqlCeDatabase35/SqlCeDatabase.cs +++ b/Source/SqlCeDatabase35/SqlCeDatabase.cs @@ -137,7 +137,7 @@ public object ExecuteQuery(string query, StringBuilder errors, StringBuilder mes { try { - if (sql.StartsWith("select", StringComparison.InvariantCultureIgnoreCase)) + if (sql.Trim().StartsWith("select", StringComparison.InvariantCultureIgnoreCase)) { using (var adapter = new SqlCeDataAdapter(sql, conn)) {