Having problems storing encrypted column to string and then decrypting to valid data
-
20. dubna 2012 16:44
Hi there,
Iam trying to implement an application which will move data from a local unencrypted database, encrypt it and paste it in the cloud, the app will also take the encrypted data in the cloud, decrypt it and paste it in the local database.
I have already implemented this using a Symmetric encryption algorithm but now want to make use of the Trust Services framework for added security
The issue I am experiencing is in the way the data is stored (I believe), currently the application encypts a line of text and returns the encrypted string, which is stored in a database NVarchar column. That column will (after modification) be downloaded and decrypted. At seemingly random intervals I experience a System.IndexOutOfRangeException when attempting to decrypt.
To make my problem easier to understand, below is a snippet of code in which I can replicate the problem:
byte[] encData; byte[] decData; String encText; ITransformation transform = mPDP.GetTransformation(SqlColumnUri.Create("example", "dbo", "Accounts", "EMail"), PolicyContext.ToUntrusted); System.Text.UnicodeEncoding encoding = new System.Text.UnicodeEncoding(); System.Text.UnicodeEncoding dec = new UnicodeEncoding(); encData = transform.Transform(encoding.GetBytes("Hello World")); encText = encoding.GetString(encData); // encData = null; decData = null; transform.Dispose(); transform = null; encoding = new UnicodeEncoding(); encData = encoding.GetBytes(encText); transform = mPDP.GetTransformation(SqlColumnUri.Create("example", "dbo", "Accounts", "EMail"), PolicyContext.ToTrusted); try { decData = transform.Transform(encData); Console.WriteLine(dec.GetString(decData)); } catch (Exception ex) { Console.WriteLine("Failed!\r\n" + ex.ToString()); }The above code is attached to a button handler, the code takes a series of characters as input (In this case "Hello World"), encrypts the data and then attempts to decrypt the data. Below is the output of pressing the button several times in a row:
Hello World
Hello World
????o Wo(ld
Failed!
System.IndexOutOfRangeException: Index was outside the bounds of the array.
at Security.Cryptography.PkcsPadding.DepadBlock(Byte[] block, Int32 offset, Int32 count)
at Security.Cryptography.BCryptSymmetricCryptoTransform.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
at System.Security.Cryptography.CryptoStream.FlushFinalBlock()
at System.Security.Cryptography.CryptoStream.Dispose(Boolean disposing)
at System.IO.Stream.Close()
at System.IO.Stream.Dispose()
at Microsoft.SqlAzure.Trust.TfsClientServerCommon.Crypt.EkmAesCryptAlgorithm.AesCrypt(Byte[] originalBytes, ICryptoTransform transform)
at Microsoft.SqlAzure.Trust.TfsClientServerCommon.Crypt.EkmAesCryptAlgorithm.Decrypt(Byte[] cypherTextBytes)
at Microsoft.SqlAzure.Trust.EdgeComplianceModule.Internal.ToTrustedTransformation.Transform(Byte[] sourceBytes)
at MSTSTest.Form1.myButton1_Click(Object sender, EventArgs e) in C:\Software Projects\MSTSTest\MSTSTest\Form1.cs:line 192This "System.IndexOutOfRangeException" is the same problem I am getting on my main application. However, if I do not convert the encrypted byte array to a string, and instead decrypt straight from the encrypted byte array, the problem goes away.
I never experienced this problem using the Symmetric encryption algorithm, it was able to encrypt a string into another, store it as an NVarchar, and decrypt without issue.
I have tried encoding the bytes using UTF8Encoding, UTF32Encoding, UnicodeEncoding but each return an error after several runs of the code.
I would prefer to be able to store the encrypted data in an NVarchar column in the database, is there a way that this is possible that I am not seeing, or will every column we require to be encrypted have to be a VARBinary column.
Apologies for the long post,
Many thanks in advance for whatever help you can offer.
- Upravený Chris_M68 20. dubna 2012 16:44
Všechny reakce
-
20. dubna 2012 17:22
This link advices that a string is always linked to an encoding and all byte sequences are not valid strings.
http://stackoverflow.com/questions/542766/c-sharp-convert-string-into-its-byte-equivalent
So, the correct way to do this is to store the encrypted value in binary format. If you must store it as a string, the binary can be converted to string using Base64, at the expense of 33% more storage size.
-
21. dubna 2012 2:29You really should never store the encrypted byte array as a string. It will very nearly-always end up corrupted somehow because of Unicode conversions. If you need to store the data as a string, convert the encrypted byte array to base64 using Convert.ToBase64String(byte[]). Yes it will use more space, but it's more manageable. Otherwise store the byte array in a varbinary column.
Developer Security MVP | www.syfuhs.net
-
25. dubna 2012 7:40
Many thanks to you both for your replies, it felt like I was banging my head against a brick wall for a solution that seems simple...
I'll let you know how the tests go :)
-
25. dubna 2012 8:07
Many thanks again to you both, I have converted to/from Base64 character arrays and the initial testing has proved sucessful.
Even though you both provided (effectively) the same answers I will mark Lucifure as the answer, because of the hyperlink and it was posted a day earlier.