2

I love c# for programming applications (I consider myself intermediate with c#, and a bit less with C/C++, but am only learning, nothing real yet in the arena), and I used to like it until i discovered "anyone" who understand MSIL (not an easy task to learn neither) could decompile my code. I don’t really care about someone decompiling my code, but my utter concern is the security for my eventual program users. I know obfuscators exist, and I even know of one or two that are really good, I hear (even if they only delay a decompiling).

For example, if I want to decrypt something using c#, some where in the code the key should be, making it a danger for anyone who use my program (someone who know someone who encrypted the file using my program could decrypt it by researching on my MSIL code, finding my key). Then, the developing of massive applications that encrypt/decrypt stuff (or OpenSSL) is insane with c#, I think, for this reason.

I mean, most users won’t know what language was used to make that exe, but a bunch of people are able to program n c#, and an elite of this people can read MSIL, and a minority of this elite would like to hack what ever is possible to hack. Of those people who like to hack, some of them can do it with perverse intentions (in a value-less world where we live that shouldn’t surprise anyone).

So, if I want to make a program that download a file from the internet, someone could interfere the transmission and do some evil, even if I use OpenSSL with c#, because somewhere in the c# file is the key. I know avoiding hacking is probably impossible, but it looks like c# is a very unsecure way.

Does it happen with Java? (Java has the same “interpreting” and “decompile” structure as C#); I mean, the fact that the key is visible in Java (with some educated eye) some where in the building file? Or does Java use some C/C++ based API that makes it harder (way harder) to decompile the file where the key is and so making it hard to get the key?

Is my only option to write my program with c/c++? Because if so, my only option is C++Builder, since its a hell to even try to watch (and less to learn) MFC/OWL code; I mean: I cant hardly think of someone who could like MFC/OWL programming. In fact, I suppose Assembly could be of more interest in the today programming world.

So, here I am, wanting to find someone who could explain me better a way to store securely crypto keys for encrypting/decrypting or to use OpenSSL with c#. Or even with Java. I would like to confirm that C/C++ is the only way of really using these features with some security for decompiling reasons (as other compiled programming languages, i.e. Delphi).

If anyone knows a site where I can find precise information about the subtle reasoning I suppose I have done (specially one that shows am wrong in my analysis), please tell me. If any one can confirm my analysis, please confirm. If anyone find any hole in my analysis, again, please tell me, and where to find more information that rule me to get a better understanding of all this.

Am sorry for making this philosophical computer programming question that long.

Thank you,

McNaddy

McNaddy
  • 21
  • 1
  • 5
  • 1
    `in a value-less world where we live` Awww cheer up, we are here to help you out :D – AaronLS Aug 16 '11 at 04:25
  • Assuming the files you are downloading from the internet are ones you have produced yourself, see [this question](http://stackoverflow.com/questions/4595537) on safely downloading your own update files. [My answer](http://stackoverflow.com/questions/4595537/verify-authenticode-signature-as-being-from-our-company-for-automatic-updater/4596025#4596025) explains why it may be OK to use self-signing rather than buying a certificate from a signing authority. It's tagged c, but there's no code so that doesn't matter. – Brian Aug 16 '11 at 15:22

5 Answers5

17

Could I hide the encryption key of a c# exe securely (in a way that can't be decompiled in any known way), as in C/C++?

No. You can't do that in any language.

The .NET security system is designed to protect benign users from hostile code. You are trying to protect benign code from hostile users. You simply cannot do that, so don't even try. If you have a secret, do not share it with anyone.

The purpose of crypto is to leverage the secrecy of some private key into the secrecy of a text. If that is not the security problem you face, crypto is the wrong tool. Explain the security problem you actually have and someone here can help you solve it.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • Eric: Yes, that is the security problem I am attacking. Am just trying to understand all this about cryptography. It is easy to use the Crypto classes, but it's harder to make smart choices on protecting the user from evil hackers. Is there any book you recommend me to read that tell me the ABC's of smart cryptography and security decissions for desktop applications that require data from servers (like OpenSSL)? (specially on C#) Thank you very much for your answers, it had helped me... – McNaddy Aug 16 '11 at 03:30
  • @McNaddy: I gather that you wish to communicate securely between a client that is not trusted by the server, and a server that is trusted by the client. I presume you wish to ensure that (1) the client is really talking to the server, and (2) that the communications cannot be read by attackers, and (3) attempts to change the message by attackers will be detected. You seem to have some idea that you need to store a key in a program to do so. Why do you have this false belief? SSL does not work by storing keys. It generates session keys at runtime. – Eric Lippert Aug 16 '11 at 03:50
  • 1
    @McNaddy: SSL works because the server's public key is known (because its certificate chains to a trusted root cert). The client generates a *random session key* which is only used once; the session key is encrypted with the server's public key and sent to the server. The server is the only one that can decrypt it, with the private key. Now the client and the server have a session key known to both, and they then use that session key to encrypt and decrypt the communications for that session. The program using SSL does not store any key anywhere. – Eric Lippert Aug 16 '11 at 03:55
  • Eric: Ok, thank you!! right now am analyzing all the informations i have got... am researching, and coming back soon... with smarter questions... ha ha ha :) thank you, Eric – McNaddy Aug 16 '11 at 03:56
  • 1
    @McNaddy: You're welcome. To answer your question about books: "Writing Secure Code" by Michael Howard is a great book about how to analyze security issues and write solid code that solves the real problem; it does not go into heavy crypto detail. I would start with that. Crypto is a very small part of computer security; it is important, but it gets more attention than it deserves. Better to have a solid understanding of how to analyze all security problems. – Eric Lippert Aug 16 '11 at 12:39
4

So, if I want to make a program that download a file from the internet, someone could interfere the transmission and do some evil, even if I use OpenSSL with c#, because somewhere in the c# file is the key.

You don't need to store a secret key in the program just to download a file safely.

If you want to ensure that the file you downloaded is authentic and hasn't been modified in transit, you use a digital signature. The private key used to make the signature doesn't have to be (and shouldn't be) distributed with the program; all the program needs is the corresponding public key, which you don't have to hide.

If you want to prevent eavesdroppers from reading the file as it's downloaded, then you need to encrypt it, but that can be done with a temporary session key generated randomly for each download; it doesn't have to be stored anywhere. If you use HTTPS for your download, it'll do this for you.

Wyzard
  • 33,849
  • 3
  • 67
  • 87
  • Wow, thank you!! it was VERY informative to me!! :) Am going to be analyzing your info for some hours/days, and I will be back, if God allows me to, with further comments if needed... THANK YOU... your recommendations of key security books for me, are allowed... ;) – McNaddy Aug 16 '11 at 03:51
  • +1 Also note that it is usually important to combine these two techniques mentioned above: verification of source(verify digital signature with known public key) with encrypting the data to prevent man(or woman)-in-the-middle attacks. This is why SSL is best used with digital certificates that have a signing authority, so that the data can be encrypted for transmission and also verified through the signing chain that the certificate belongs to whom you believe it does. – AaronLS Aug 16 '11 at 04:10
  • Thank you, AaronLS!! Am copying!! ;) – McNaddy Aug 16 '11 at 05:12
1

The choice you've mentioned (embed key into executable) is bad irrespective of language you choose - it is not too hard to extract data from C/C++ and slightly easier for C#/Java.

As Jordão said - you need to figure out your story of distributing key outside the binaries. You also need to figure out what you actually trying to protect and understand possible exploits. Just using encryption of some sort in an application does not make it more secure.

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
  • Alexei: Thank you!! One more question: is it equally easier to extract data from a small C/C++ assembly than from a larger one generated from, say, Borland with all its adds? is there any relation with the size? A curious question i have done for a long time... Thank you again, and as I asked Mr. Lippert, would you mind to recommend me a good book on taking good security decissions? (and like how far can a good decission help me, because if some decission only upgrades security but is not THE solution, i would like to be aware of that)... – McNaddy Aug 16 '11 at 03:37
0

You should not store cryptographic keys inside assemblies; they should normally be provided from outside, e.g. from a key-store, or derived from a secret known to a user.

Jordão
  • 55,340
  • 13
  • 112
  • 144
  • the key store could be seen by others??... also, is it secure to store cryptokeys on C/C++ assemblies? Your suggestion is interesting – McNaddy Aug 16 '11 at 03:03
  • Key stores are normally protected by the operating system, and so are specific for a user. C/C++ binaries can also be "hacked" to expose their secrets. – Jordão Aug 16 '11 at 03:13
  • Thank you Jordão for your answer, again.. you say "normally", and i would like to know how secure are keys protected by OS's, and how to make sure mines are always protected on that level... the same for you, as i did with Mr. Lippert and Mr. Levenkov: please recommend me an special book you like that could help me, according your intuition with my case: one that explains wich are the do's and don't's with security decisions... specially with c#. I wouldnt mind neither with C/C++... thank you for your patience... – McNaddy Aug 16 '11 at 03:42
  • Take a look at "Writing Secure Code". It an all-around reference on the topic of security-programming, and it also touches on cryptography. – Jordão Aug 16 '11 at 03:52
  • @Jordão: That should be "you should not store unprotected private or secret keys" inside assemblies, I think. And even then you could make a point of having secret or private keys in applications server side (if you're really really careful - to be avoided at most times). – Maarten Bodewes Aug 16 '11 at 18:51
  • @owlstead: I really meant what I wrote. You shouldn't embed this kind of information in an assembly. – Jordão Aug 16 '11 at 20:18
0

You can also generate a key from a password(this means the key is no more stronger than the password though). So each time the user runs the program, they are prompted for a password, and that password is then used to generate a key. Depending on your requirements you could employ this in a variety of ways.

When the user needs to access the encrypted data, the password can be provided again and this generates the key for use during that session. Once the program is closed the key is discarded(there are techniques/APIs in C# to help ensure that sensitive data is only present in memory as short a time as possible).

For example, this is essentially what many password storing programs like Keepass or Roboform do. The user can upload and download the encrypted data to and from servers. No keys are ever stores, and instead generated on demand as the user supplies their password for that session.

With a service like Dropbox, when you register with their site, they generate the private key on their server and keep a copy there. So the user's machine and client software never store the key, but the server has a copy stored. Dropbox does this so that they can decrypt user data for many purposes, such as compression, de-duplication, compliance with law enforcement, etc.

AaronLS
  • 37,329
  • 20
  • 143
  • 202
  • AaronLS: Thank you for your ideas, and as i wrote above, am copying... interesting your informations... – McNaddy Aug 16 '11 at 05:14