2

I'm looking for a secure way to encrypt and decrypt a string in a Visual Studio Project (in C#). I found that there is native DES classes, but it's not secure enough. Do you have any suggestions?

UPDATE : OK then, the question is : What's the most secure way to encrypt/decrypt a string without too much hassle (aka having to install external tools, etc. An external library is fine though). And where to put the secret "key" (is compiling the value inside the code secure enough?).

Update #2 If I'm using something like this code to save encrypted string in a config file :

using System.Security.Cryptography;
using System.Security;
byte[] encrypted = ProtectedData.Protect(StrToByteArray("my secret text"), null, DataProtectionScope.LocalMachine);
byte[] derypted = ProtectedData.Unprotect(encrypted , null, DataProtectionScope.LocalMachine);

Is this secure enough? I guess that with the "LocalMachine" parameter instead of "User" parameter, somebody could just write an application in .net, put it on the machine and execute it to decrypt the encrypted string. So if I want it more secure, I'll have to have a config file different for each user? Am I understanding that correctly?

tink01
  • 94
  • 1
  • 2
  • 5
  • 1
    At this point, DES isn't secure enough to keep out my kid sister. – Steven Sudit Sep 14 '10 at 15:57
  • What dtb said. Also, when you found the DES classes, you didn't notice the AES, RSA, Rijndael classes in here http://msdn.microsoft.com/en-us/library/system.security.cryptography.aspx? – R. Martinho Fernandes Sep 14 '10 at 15:58
  • 1
    The "security" of symmetric encryption algorithms like DES, TripleDES, AES, Rijndael, etc. mostly differ by how long it takes to break them. AES is better than DES in this term. But the weak spot is usually somewhere else, such as protecting the symmetric key, choosing the right padding or preventing [social engineering](http://xkcd.com/538/). Attackers tend to attack the weakest spot, not the one you put your most attention to. – dtb Sep 14 '10 at 15:59
  • @dtb: Secure enough for paranoid adminsys. @Martinho Fernandes : I guess not ;) @dtb: see update of my question – tink01 Sep 14 '10 at 16:05
  • Does the transport provided by mule team differ from that offered by airliner differ mostly by how long it takes to reach your destination? When dealing with exponential growth, a quantitative difference becomes a qualitative difference at some point. Such is the difference between DES and AES. – erickson Sep 14 '10 at 16:08
  • @dtb: DES is so broken that it's weaker than the key. It is no longer a viable option. Also, AES *is* Rijndael, so please don't list this twice under two names. – Steven Sudit Sep 14 '10 at 16:08
  • @erickson: I could break DES, and not with difficulty. I could not easily break AES. That's the bottom line difference. – Steven Sudit Sep 14 '10 at 16:09
  • 2
    @erickson: My point is: If you ship your symmetric key along your decryption method, I can "break" both DES and AES immediately. It takes actually more time to fire up Reflector and locate the key than to decrypt the secret data. – dtb Sep 14 '10 at 16:12
  • @Steven Sudit - Right, and that's a difference in quality, not simply a difference in how long it takes to break them. "Never" is not a longer version of "soon". – erickson Sep 14 '10 at 16:37
  • 1
    @dtb - Right. But my point is that if you implement your protocol correctly but choose DES, you're screwed, while if you choose something like AES, you're safe. – erickson Sep 14 '10 at 16:38
  • @erickson: It's never never. At worst, I can use brute force. With a small key, such as DES's 56 bits, that's actually feasible with the right hardware. With a larger key -- 128 to 256 for AES -- it's really not. – Steven Sudit Sep 14 '10 at 18:13
  • To keep things in perspective, just counting to 2^128, without doing any other computation, on an ideal computer would cost hundreds of millions of dollars in energy. Counting to 2^56 on the same computer would be free. – erickson Sep 14 '10 at 19:10

6 Answers6

7

To answer your second question, no, storing the encryption key in the executable, even obfuscated, is not secure at all. It'll keep casual prying eyes out, but not those with an hour to devote to walking through your decompiled source.

Think hard about where to store your encryption key - it looks like that'll be your weak point. And yes, this is a hard problem to solve. The most secure way to store encryption keys is not to - require the user to type a password, or require external hardware, like a key fob.

If you're encrypting contents intended to be read only on a single machine or by a single domain user, consider the Data Protection API (DPAPI). It takes the encryption key out of your hands - it uses the user's Windows credentials as the key.

I've got a little more detail in another answer here: Persistent storage of encrypted data using .Net

Regarding your second edit (is DataProtectionScope.LocalMachine good enough?); this MSDN blog entry summarizes it well:

Setting a scope of DataProtectionScope.CurrentUser encrypts the data so that only the currently logged on user can decrypt it. Switching to DataProtectionScope.LocalMachine allows any process running on the current machine to decrypt the data. This could be useful in a server scenario, where there are no untrusted logins to the machine, but for a general purpose workstation using LocalMachine encryption is almost equivalent to using no encryption at all (since anybody logged in can get at the data).

Community
  • 1
  • 1
Michael Petrotta
  • 59,888
  • 27
  • 145
  • 179
  • I see. So basically, if I want to store a secure string in a config file, I'll have to make a different file for each user logged in or use a key from a remote service? – tink01 Sep 14 '10 at 18:13
  • 7
    Indeed, the second paragraph is key. Remember: **the purpose of a cryptosystem is to leverage the security of a short secret key into the security of a long secret message.** The whole *point* of strong crypto is that your long secret message is *exactly* as secure as the effort you are willing to invest in keeping the key secret. **How you choose to keep the key secret is not a part of the cryptosystem: that's the bit you have to solve for yourself.** All crypto does is *decrease* the amount of data you have to keep hidden. It does not remove the requirement to hide *something*! – Eric Lippert Sep 14 '10 at 18:22
1

It also has AES.

Steven Sudit
  • 19,391
  • 1
  • 51
  • 53
1

If I read your update correctly, you basically want to conceal some string constant from a sysadmin snooping around your assembly.

There is no way to make it impossible that someone with too much time extracts your string constant eventually. But you can annoy them, hoping that they give up trying before they unmask your secret.

One way to achieve that are Obfuscation Tools. These obfuscate your compiled assembly as much as possible, making it much harder to follow program flow when decompiling it with Reflector. Try it. If your string constant is still not hidden enough, you can additionally invent your own scheme to make it harder to find.

If you need more security, the almost only option is to not give the relevant parts of the code to the user. Create a web service that contains the secret parts of your application and secure the connection with SSL/TLS.

dtb
  • 213,145
  • 36
  • 401
  • 431
  • I'm downvoting this because obfuscation is a much worse answer than the DPAPI. – Steven Sudit Sep 14 '10 at 18:18
  • @Steven Sudit: But how do you get the data into the DPAPI store? If you're not physically present to type in the secret, again, you have to hide the it somewhere in your code. Maybe this is not an issue for the OP, but still don't really get what his scenario is. – dtb Sep 14 '10 at 18:31
  • You do it as part of installation. The whole point is that the secret is never in your code. – Steven Sudit Sep 14 '10 at 18:38
  • @Steven Sudit: So you embed the secret in the installer executable? – dtb Sep 14 '10 at 18:40
  • *NO!* Whoever does the installation is responsible. – Steven Sudit Sep 14 '10 at 18:43
  • @Steven Sudit: So you have to be physically present and type the secret in. That works. If you can be physically present. If not, I stay with my answer that obfuscation might be good enough in some cases. (Note the lots of If's.) – dtb Sep 14 '10 at 18:51
  • The problem is that the secret is just some arbitrary bit of information shared between this app and whoever it calls, and this should be very changeable, so you don't want to ever hardcode it. – Steven Sudit Sep 14 '10 at 18:59
  • @Steven Sudit: It really depends on what the OP is trying to achieve. Or you know more about his use case than I do. :-) – dtb Sep 14 '10 at 19:02
  • My crystal ball is no more effective at reading the OP's mind than yours is. :-) Still, there are practices that cannot be secure, so they should be avoided. Hardcoding a password and counting on obfuscation to hide it is a guarantee of failure. – Steven Sudit Sep 14 '10 at 19:04
  • 1
    @Steven Sudit: It really depends. Choosing a security strategy is always the result of analysing how precious the asset is and how much protection is required. So, if obfuscation is good enough for his use case, then obfuscation is good enough. You cannot deny the truth of a tautology. :-) – dtb Sep 14 '10 at 19:08
  • Correct, I can only deny its relevance. In this case, the predicate is rarely, if ever, true. – Steven Sudit Sep 14 '10 at 19:09
  • @Steven Sudit: Aren't all software serial number mechanisms that don't use online verification based on this? – dtb Sep 14 '10 at 19:12
  • Yes, and they're all easy to crack. Google "serial number generator" and the name of any such program. – Steven Sudit Sep 14 '10 at 19:14
  • @Steven Sudit: Let's assume the OP's application is a puzzle for humans to solve. When the user solves the puzzle, the application displays the string "You won! Please send your cover letter and resume to jobs@google.com". Now, it's not really fun to solve the puzzle if you can cheat by opening the .exe file in notepad and see what will be displayed when you win. Then you could obfuscate the string so it takes just a bit longer to de-obfuscate the string than to solve the actual puzzle. Problem solved. Solution is good enough. – dtb Sep 14 '10 at 19:21
  • Well, in this case, the right answer would be to store a verifier, such as a hash. The hash would be enough to confirm whether the answer is correct, but not enough to yield the answer. In fact, this is the right way to go if all you want to do is have people register the program to enable full functionality. The registration key is just the name of the user and an HMAC code. This more than does its job; any additional obfuscation will yield no net benefit. – Steven Sudit Sep 14 '10 at 19:24
0

Try using AesManaged.

Randolpho
  • 55,384
  • 17
  • 145
  • 179
  • This really isn't much worse than using http://msdn.microsoft.com/en-us/library/system.security.cryptography.aescryptoserviceprovider.aspx so I don't understand the downvote. – Steven Sudit Sep 14 '10 at 18:18
  • 1
    I think MSDN or SO links are ok. This answer looks good for me. – Evgeny Lazin Nov 19 '12 at 06:54
0

That depends on your definition of secure enough. You may use triple DES. .Net also has native Rijandel class. Is it secure enough? http://www.obviex.com/samples/Encryption.aspx

Alex Reitbort
  • 13,504
  • 1
  • 40
  • 61
0

Using a well tested and accepted library is a good idea too...

http://www.bouncycastle.org/csharp/

JeremyWeir
  • 24,118
  • 10
  • 92
  • 107
  • Was that a sarcastic downvote? "Yeah, like I'm going to be dumb enough use the best encryption library, I'll roll my own" – JeremyWeir Sep 14 '10 at 17:22
  • I disagree with the downvote, but perhaps the thought was that the built encryption classes that come with .NET are enough. – Steven Sudit Sep 14 '10 at 18:39
  • IMO a well tested and accepted library is a precondition, but not a guarantee that a resulting application is secure. Using crypto algorithms correctly is really hard to get right. – dtb Sep 14 '10 at 18:57
  • @dtb: You're not wrong. It's best to avoid trying to come up with novel solutions. If possible, avoid crpyto primitives entirely and stick to higher-level constructs. – Steven Sudit Sep 14 '10 at 19:25
  • @Steven Sudit: Those higher-level constructs are unfortunately lacking in the .NET Framework and, I believe, also in Bouncy Castle. Just look at all the horrible homegrown solutions to storing salted hashes in databases. – dtb Sep 14 '10 at 19:45
  • @dtb: Well, there are *some*. For example, instead of using SHA-1 directly and concatenating a key, you can use HMACSHA1. And, one level above this, there's PBKDF2, which uses HMACSHA1. – Steven Sudit Sep 14 '10 at 20:46
  • (I should probably mention that PBKDF2 would be a fine way to generate salted hashes that are expensive to create rainbow tables for.) – Steven Sudit Sep 14 '10 at 20:51