tags:

views:

203

answers:

5

Really not having a good week with encryption. Let me explain what I need.

  1. I want to encrypt string values to a file....
  2. I want to decrypt the file contents back to a string using C#
  3. I want to do this without having to worry about machine store or user store or any other store, neither a registry , etc.
  4. Any security key can be shipped in my application.

security doesn't have to be remarkably strong, and my code is obfuscated.

I just want a solution that is portable. I've tried RSA and it got me nowhere fast after finding out that in production a certain key file is missing, something I know nothing about and can't locate it on the dev machine.

Please help.

A: 

Have you looked into the Bouncy Castle API?

Chris Conway
A: 

From Eric's response it sounds like you may be making things more complicated than you have to; by perhaps attempting asymmetric encryption when it is not necessary?

For the type of encryption you're describing you should really just need to pass a few arguments to an encrypt and decrypt method to get your task accomplished.

Take a look at this example from CodeProject. It uses the Rijndael algorithm in a straightforward manner and even includes code for reading/writing files.

Paul Sasik
Do you know if the method in the example is completely portable without auto generated and intangible machine keys?
JL
i've used this example as a base for web, desktop and windows mobile apps. So it's been fairly portable. Though i do recall a little bit of tweaking necessary for the mobile side due to a missing API. In any case, looks like this question is closed.
Paul Sasik
+2  A: 

Here is some code that I use quite a bit (adapted it from source on the web) which relies solely on a passphrase stored in web.config/app.config under setttings. It uses triple des.

 /// <summary>
        /// Encrypts the string.
        /// </summary>
        /// <param name="text">The text.</param>
        /// <returns>Encrypted string</returns>
        public string EncryptString(string text)
        {
            // Locals
            var passphrase = ConfigurationManager.AppSettings["Your Encrypt Passphrase"];
            byte[] results;
            var utf8 = new UTF8Encoding();

            // Step 1. We hash the passphrase using MD5
            // We use the MD5 hash generator as the result is a 128 bit byte array
            // which is a valid length for the TripleDES encoder we use below
            var hashProvider = new MD5CryptoServiceProvider();
            var tdesKey = hashProvider.ComputeHash(utf8.GetBytes(passphrase));

            // Step 2. Create a new TripleDESCryptoServiceProvider object
            // Step 3. Setup the encoder
            var tdesAlgorithm = new TripleDESCryptoServiceProvider
                                    {
                                        Key = tdesKey,
                                        Mode = CipherMode.ECB,
                                        Padding = PaddingMode.PKCS7
                                    };

            // Step 4. Convert the input string to a byte[]
            var dataToEncrypt = utf8.GetBytes(text);

            // Step 5. Attempt to encrypt the string
            try
            {
                var encryptor = tdesAlgorithm.CreateEncryptor();
                results = encryptor.TransformFinalBlock(dataToEncrypt, 0, dataToEncrypt.Length);
            }
            finally
            {
                // Clear the TripleDes and Hashprovider services of any sensitive information
                tdesAlgorithm.Clear();
                hashProvider.Clear();
            }

            // Step 6. Return the encrypted string as a base64 encoded string
            return Convert.ToBase64String(results);
        }

        /// <summary>
        /// Decrypts the string.
        /// </summary>
        /// <param name="text">The text.</param>
        /// <returns>Decrypted string</returns>
        public string DecryptString(string text)
        {
            // Locals
            var passphrase = ConfigurationManager.AppSettings["Your Encrypt Passphrase"];
            byte[] results;
            var utf8 = new UTF8Encoding();

            // Step 1. We hash the passphrase using MD5
            // We use the MD5 hash generator as the result is a 128 bit byte array
            // which is a valid length for the TripleDES encoder we use below
            var hashProvider = new MD5CryptoServiceProvider();
            var tdesKey = hashProvider.ComputeHash(utf8.GetBytes(passphrase));

            // Step 2. Create a new TripleDESCryptoServiceProvider object
            // Step 3. Setup the decoder
            var tdesAlgorithm = new TripleDESCryptoServiceProvider
                                    {
                                        Key = tdesKey,
                                        Mode = CipherMode.ECB,
                                        Padding = PaddingMode.PKCS7
                                    };

            // Step 4. Convert the input string to a byte[]
            var dataToDecrypt = Convert.FromBase64String(text);

            // Step 5. Attempt to decrypt the string
            try
            {
                var decryptor = tdesAlgorithm.CreateDecryptor();
                results = decryptor.TransformFinalBlock(dataToDecrypt, 0, dataToDecrypt.Length);
            }
            finally
            {
                // Clear the TripleDes and Hashprovider services of any sensitive information
                tdesAlgorithm.Clear();
                hashProvider.Clear();
            }

            // Step 6. Return the decrypted string in UTF8 format
            return utf8.GetString(results);
        }

The original source was here: http://www.dijksterhuis.org/encrypting-decrypting-string/

Nissan Fan
+1 and accepted answer, - please tell me - that there is no need to import export machine keys with this solution?
JL
None at all. Since you are shipping your app out don't use app.config and web.config for your passphrase. Hardcode it and rely on obsfucation to hide the literal.
Nissan Fan
Oh, you're shipping the app? Then this encryption is about as effective as ROT13 or XOR encoding. The weakest link will be the literal in your code. Reflector+Deblector will own your obfuscation in no time.
Yannick M.
Yannick, crypto of literals is pretty much used across the board in obsfucators. If he puts the passphrase into the code itself there's no chance in hell that someone would be able to decrypt it.
Nissan Fan
You might indeed have a hard time finding and decrypting the literal with Reflector. However since you can debug the application with Deblector the only thing you need to break on is the ComputeHash call.
Yannick M.
But good luck in finding it when your methods, variables, dummy method calls and params etc. handled by the obsfucator are all encrypted. Notice his requirements above as well. He didn't ask for quantum encryption via entagled calcium-generated photons. This is still a very viable encryption method. Keys are not the holy grail.
Nissan Fan
I agree that the amount of work is certainly a factor. Maybe it is worth exploring how hard it is to intercept the method call -- found something to do this evening -- :)
Yannick M.
@Nissan: embeded passwords are as good as ROT13. Nothing more. They only need to be found *once* and you don't search for them, uou put a breackpoint in the actual encrypt function and wait under debugger for the break point to hit, then read the password from the stack. This is not only not *viable*, is pure BS.
Remus Rusanu
Remus, he is using an obsfucator which will encrypt literals and rename all methods, variables, etc. His requirement is not for NSA level encryption. I know you feel that you are correct in your statements, but please read his requirements and the dicussion at hand. I could argue against 1024 bit RSA even because people have already found an attack angle. http://arstechnica.com/old/content/2007/05/researchers-307-digit-key-crack-endangers-1024-bit-rsa.ars
Nissan Fan
Nissan, the problem is that the only thing an attacker needs to do is find the call to ComputeHash and break on it when debugging. As far as I can tell (from the ones I have worked with), obfuscators can obfuscate object/member names in the assembly itself, but not beyond. Thus your 'ComputeHash' method call will stand out between all of the non-sensical code.
Yannick M.
Yannick, take a look here. http://www.ssware.com/cryptoobfuscator/features.htm Most obsfucators do have these types of features. Which are you using?
Nissan Fan
Well, I tried a few yesterday evening. The last one I tried had a trial with more or less all the features the one you're suggesting has(http://www.9rays.net/Products/Spices.Obfuscator/). It did everything except `Assembly Embedding`. However I doubt it would let you / you would want to embed the entire mscorlib to obfuscate the ComputeHash call.
Yannick M.
That being said, as I hinted yesterday, I was going to back up my claim of it being a flawed security measure. I tried it out, obfuscated and encrypted the hell out of a small app that is running your encryption code. But using Reflector+Deblector+Reflexil I was able to intercept the ComputeHash call in minutes. (Mind you, I am a novice at best when it comes to Reflector)
Yannick M.
I would write a blogpost about it, but thankfully I don't have a blog... yet ;-)
Yannick M.
A: 

You can't store secrets in an application. Period. If the prize is worth anything, somebody will find your secret key. In this day and age, once is enough. Google will give the answer for anybody who is interested to find that key. And once the key is compromized, it will compromize the data for everybody, everywhere.

Your secret (key) must come from outside (eg. user provided password, provisioned certificates and keys, key exchange protocols).

If you insist on storing the key in the applicaiton, thus providing a minimum level of obfuscation of the data (is not trully protected), then use a CryptoStream and symmetric key algorithm, like the Rijndael based example at http://msdn.microsoft.com/en-us/library/system.security.cryptography.cryptostream.aspx with a hardcodded key. But you must undesrand that this is notthing but obfuscation.

Remus Rusanu
A: 

If you're having trouble with creating keys try CrypTool, an enormously useful tool when learning about cryptology.

Yannick M.