I have Created a C# Desktop Windows form Application and I have created a setup for that. In the C:\Programs files app folder I have a JSON file. I need to protect it from accessing by anyone (I need to protect the data). What should I do?
You can't. If the intruder have access to the computer with the Administrator rights (or even more - a physical access to the hardware), then any protection will be useless.
You can use some kind of encryption, code obfuscation and some anti-debugging techniques to make it harder to retrieve the data, but qualified intruder with the appropriate access level will be able to access the data in the moment when you will decrypt it.
The only working way is to completely remove the secret data from the client's computer and move it to the your secure server alongside with the processing of such a data. So, client sends the inputs to your server, the server performs the processing using the secret data and sends back ready-to-use results.
First of all: it's impossible to make it un-breakable - I won't argue on this. Then you can simply encrypt it with a simple Blowfish algorithm and keep the key hardcoded.
You can use a more secure algorithm if you want so.
Easiest solution is to use a binary serialization format instead of json. This will make it much harder to understand and decode. Or just hardcode the data instead. Most people lack the knowledge to do anything meaningfull with a binary chunk of data, or an assembly for that matter.
A more complicated solution would be to sign the data, as this would allow you to only hardcode the key. A related alternative is Encryption. Encryption is sufficient but not necessary for ensuring the integrity of the data, but is not really more difficult to apply, see encrypting data.
Whatever you do you cannot really prevent a sufficiently determined and knowledgeable attacker. It is possible to decompile the program and extract or replace any secrets therein. The only truly secure way would be to prevent access to the files in the first place, by moving it to the web for example.
I had a similar requirement and decided to encrypt the data.
I used the package "AuthenticatedEncryption" (available from NuGet ) and could hard-code the key in my code.
NuGet: https://www.nuget.org/packages/AuthenticatedEncryption/
Guthub: https://github.com/trustpilot/nuget-authenticated-encryption
I can do this, as my main purpose is more to make the data unreadable to users and I don't expect it to be unbreakable.
Even so, I change the key every few releases.
For my ~70Kb JSON file I only load it once at the start of the program, so performance is not a problem. Not that I anyway notice anything!
Related
I want to do the below. What is the best way to achieve this?
I have a desktop app in C# which will be installed on multiple client machines.
The application is capable of doing an operation X but it needs some auxillary info which it can read from a file. This auxiliary info essentially provides some specifics that identify that machine where the operation should be run and what operation to run etc.
I will work with the client to get some of this auxilary info about his machine (say hostname/ip address etc) which I want to put in this file along with other info and generate it on my machine and share it with him/her to provide it to my software. I want to encrypt this data so that the structure of the data is not obvious to somebody who opens it. (I will get some of the machine identification info from the client, either via phone or email).
I want to somehow encrypt and secure this file such that only I can generate the file but any of my installations can read it. But since the contained info is specific to a machine it will be executed only on one machine (other machines will read but reject it since the given hostname/ip etc won't match that machine)
How do I do this? I want to make sure the below:
Only I can generate this file.
I need to somehow authenticate that this is generated only by me and not by somebody else.
But my software on client machines should be able to decrypt this.
I don't want to take a password from the customer etc. all the decryption logic should be in the installed software itself. I want to code it in.
When I researched this online, many talk about public and private cryptography but there they talk about encrypting with the public key and decrypting with the private key. But I don't think this will work since decryption is being done by my software at the client machine and so I shouldn't put the private key in my code. Because, from what I read, private key can generate public key so somebody could potentially generate that instruction file if I do this.
What is the best way to do this? Can I encrypt with private key and decrypt with public key? Is it ok if somebody gets hold of my public key (say they disassemble the C# code)? Any other good ways to encrypt and authenticate such that I hold the private data with me but code only harmless public keys/data in the application?
TIA.
Who are you trying to protect this from?
You are giving the end user your application binary. Assume they can decompile it and work out how it works. Or step through your code in a debugger, with access to the contents of every variable. Assume that an attacker can learn everything they need to know about how it works.
At best I would recommend creating a hash of the machine details and a salt value. Then create a signature of that hash.
Keep the salt and the public key of the signature as a constant in the application binary. Maybe XOR values together so an attacker has to think a little about how it works.
But anything more is pointless. Any attacker with more skills will just patch your program to delete the test entirely. So I wouldn't bother building anything too complicated.
Giving someone a program, and preventing them from using it, is like trying to make water not wet.
You have two questions
How do you encrypt the information, and
How can your client make sure the information came from you.
Those are orthogonal
I'll address the second on first - it's easier.
First, hash the file, and add the hash to the payload. Then generate a public/private key pair, then encrypt some known (but non-trivial) information with the private key and add that to the payload. You can distribute the public key with your app. If your app hashes the file and the hashes match and it can decrypt the known information and make sense of it, then it came from you and no one has changed it.
This is known as a digital signature. If you look up a digital signature provider and follow the docs, it should just work.
The encryption problem is more of an issue. There's pretty much no way to do what you want. If your app can decrypt the information using information you distribute with the application, then a determined bad guy can extract that key material and decrypt it.
However, you can use the RSA key container on the client to do the encryption when you install the app. The process is similar to using encrypted sections in a web.config file. Since you won't be following the encrypted config section cookbook the process is complicated.
I've done this before, but it was several jobs ago, so I don't have anything I can show you.
But, it will be encrypted so that it can be read only where it was encrypted. No two installations will recognize each others files.
That said...
Encryption seems like a heavy hammer to prevent your customers from being able to guess "the structure of the data [so that it] is not obvious to somebody who opens it"
Unless you have something worth protecting, you can probably get away with obfuscating the data. For example, you could have the data as JSON, but then use GetBytes on a Utf8Encoding to get a byte[] and convert that to a hex string. A determined hacker could decompile you code, figure out what you've done and reverse it, but that doesn't seem like a threat you really need to worry about.
I have read extensively on SO and on the .NET but still do not think I have a workable solution or I have not considered something.
I am looking at an application that as part of its functionality has to write a document to disk on the web server.
Now assuming the worst and the web server is penetrated and the attacker gets to the file system or due to a misconfiguration of the web server the file is available via HTTP. It seems that encrypting the file would be sensible.
However would you suggest I use symmetric or asymmetric encryption?
At some level there will be a secret password that is accessed by the C# code. How do you obfusticate that? Or put another way how to you deal with using secret keys in code in a secure fashion?
All help and pointers greatly appreciated.
You mention that your app has to write the document, but does it have to read it? If not, then you can create a file service where you can only write to, but not read from, and problem solved. Also, if you use asymmetric encryption, the app can encode the document with the public key, but it won't be able to decode it without the private key. If the private key is not there, then again, problem solved. Otherwise, if the app has to be able to read it, the only thing you can hope for is security through obscurity, obfuscating the encryption stuff. But if your server is compromised, they can save both the document and the code that created it, and you can't stop them from eventually revealing the contents, no matter how hard you try. So it depends: how hard do you think the attackers will try? How hard do you want to try? What are the costs and benefits of investing into more security?
I was examining the ways of protecting my code from decompiling.
There are several good threads here describing obfuscation and code packing as the possible ways of protecting the code. However none of them is ideal, obfuscation doesn't work with reflection when the string method/property names are used. Many people do not recommend to use obfuscation at all.
So I currently decided not to go with any of the above. However, I have parts of the code where I need a sort of encryption, for example, a database connection string with an IP, login and password is stored inside the code as simple const string, same as email account data.
In ASP.NET there is an option to move the sensitive data to a .config file and encrypt it, but that requires the server key, i.e. linked to a single computer. I didn't read much about it, but I suppose something similar is available for desktop applications. But I need this to work on any computer where the application is installed.
And here is the question: are there ways to encode/protect such data so that it cannot be read along with decompiled code?
First advice is to never store anything sensitive in your code directly. You can always reverse engineer that, no matter how cleverly you try to obfuscate it.
I've read about things like breaking a password into several pieces, placing them at different places in the code and running them through a series of functions before finally using them... although this makes things harder, you can still always monitor the application using a debugger and ultimately you will be able to retrieve the secret information.
If I interpret your scenario correctly, what you have is code that is to be deployed at some client's premises and your code is connected to a database (which I suppose is also under the client's supervision), connecting to it requires a password. This password is known to that client, so trying to hide it from the client is rather useless. What you do want is to restrict access to that password from anybody who is not supposed to know it.
You typically achieve this by putting the sensitive information in a separate file in a folder that should have very restrictive permissions, only the application and a handful of selected people should have access. The application would then access the information when needed during runtime.
Additionally encrypting the separate file turns out to be a problem - if you do so then there is a key involved that again would have to be secured somehow - infinite recursion is on it's way :) Securing access to the file is often sufficient, but if you really require to be as secure as possible, then a solution is to use password-based encryption for the file. But the idea here is not to store the password in yet another location on the system, but rather as out-of-band information (e.g. in a physical vault) and entering the password when starting the application. This, too, has its problems: physical presence of a person is required for (re-)starting the application, and you could still retrieve the password from the RAM of the machine where the application is running on. But it is probably the best you can do without specialized hardware.
Another good alternative to password-based encryption would be to rely on OS-specific "password vaults" such as Windows' Isolated Storage, it's sort of a trade-off between not encrypting at all and keeping the password out-of-band.
This isn't an encryption answer, but one way to 'secure' this would be to make all your database calls through a web service. Your connection credentials would then be stored on your secure server and the clients pass all calls through there.
Nothing sensitive stored in your re-distributable at all...
I have grappled with this problem in the past and come up with three ways of dealing with the problem, but I'm not sure any of them are perfect:
Obfuscate or encrypt the value and hope for the best. Encryption, of course, is just an extra level of obfuscation since the key must be delivered with the rest.
Eliminate the need for the key itself by using one-way encryption instead. Use a private key to generate a public key. This can be used for licensing or password validation. You generate the licenses with the private key, but the public key can be used to validate them. Or you use the private key to generate a password that can be validated, but not reversed using the public key.
Create your own system-specific key-generation mechanism similar to that used by ASP.NET. You can limit the effect of someone reversing the encryption/obfuscation in step 1 by generating a unique key for each installation or site.
There are tons of methods, but the reality is that if you really want to protect your code, the only solution is to use "professional" products :-) don't try to reinvent the wheel. These products normally have options to encrypt strings. The real problem is another: without a professional product (and even WITH a professional product) an expert can simply put a breakpoint and look at the parameters passed to the library method (for example the one that opens the connections). Now... If you really really want to encrypt the strings of your code, it's quite easy. But would it be useful? No.
Now, just so that no one will mark this as "not an answer", I'll post some simple encryption/decryption code:
// Generate key. You do it once and save the key in the code
var encryptorForGenerateKey = Aes.Create();
encryptorForGenerateKey.BlockSize = 128;
encryptorForGenerateKey.KeySize = 128;
encryptorForGenerateKey.GenerateKey();
encryptorForGenerateKey.GenerateIV();
var key = encryptorForGenerateKey.Key;
var iv = encryptorForGenerateKey.IV;
// Encrypt: this code doesn't need to be in the program. You create a console
// program to do it
var encryptor = Aes.Create();
var encryptorTransformer = encryptorForGenerateKey.CreateEncryptor(key, iv);
string str = "Hello world";
var bytes = Encoding.UTF8.GetBytes(str);
var encrypted = encryptorTransformer.TransformFinalBlock(bytes, 0, bytes.Length);
var encryptedString = Convert.ToBase64String(encrypted);
Console.WriteLine(encryptedString);
// Decrypt: this code needs to be in the program
var decryptor = Aes.Create();
var decryptorTransformer = decryptor.CreateDecryptor(key, iv);
byte[] encrypted2 = Convert.FromBase64String(encryptedString)
var result = decryptorTransformer.TransformFinalBlock(encrypted2, 0, encrypted2.Length);
var str2 = Encoding.UTF8.GetString(result);
This code clearly isn't secure. Anyone can decompile the program, add a Console.WriteLine(str2) and recompile it.
You can of course encrypt your string before compiling it, but your code need that in plain text sometime if you are using a simple db or http url.
There is not a real protection in this case: Everyone can listen (breakpoint) to a specified method and when called see what's going on without really reading your code.
So no, there is not a real protection against this, also using obfuscation at some point you will call some .NET method with that plain text string, and everyone can read it.
You can for example put a COM or C++ dll for storing encrypted strings.
A unmanaged dll is not decompilable, however, expert people can of course understand the disassembly of a dll. And as said before, sometime you will need the plain data, and at that moment, there is no protection that can last.
The only thing you can do is to change your architecture.
For example, if your db is online and your application is a client application, you can connect using web services.
Then you can expose only the web services the user really need to use, there is no risk of user writing sql queries.
Then you can add the protection logic on the server instead that on the client.
If everything is offline there is not much you can do, you can make life harder using simple string encryption but it will never be a real protection.
As Lucas pointed out in its comment, if you have only one piece, then anybody decompiling your application can reverse-engineer it and decrypt your database passwords.
About storing credentials, my usual practice is to always store them in the application configuration file. If then I need to secure it, I use a SecureString and some encryption. And this could work for any kind of configuration information, not only credentials. There is a really good article about securing configuration files here: Encrypting Passwords in a .NET app.config File
Maybe you should read some more on encrypting the web.config http://learn.iis.net/page.aspx/141/using-encryption-to-protect-passwords/
Otherwise there isnt much you can do. Storing sensitive data in code isn't an option since anyone with a reflector tool can open it and see it. If you want code or variables to be invisible to everyone, you should create a webservice on a private server that accepts data, transforms it through it's magic and returns it to the client. In that way everything in between posting and retrieving the data is kept secret.
I am not sure if it is possible to protect your code at a client location, but a solution might be to store the password in Azure Key Vault and authenticate to it with Azure Active Directory. However, this might still be possible to reverse engineer. You can read more here: https://learn.microsoft.com/en-us/azure/key-vault/
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
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.
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.
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.
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.
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.
We have around 60 MB of device configuration implemented in at least 1000 xml files.
Now we are releasing the software to the customers. But our requirement is not to allow the user to view and edit the xml configuration files. XML configuration files contains a lot of secret of the device information which can be easily hacked if it is readable.
Now we need to encrypt the xml files. Are there any recommended method to encrypt the xml file and it can be decrypted at run time?
This is a problem known from DRM applications - you want to make the data available to the user agent of your choice but not to the user operating the user agent. But, since the user agent is usually on the user's side, as Jon and Oded point out, a determined hacker will find a way to break the encryption. It's a cat and mouse game. You are trying to find a solution to exactly the same problem that people implementing DRM want to solve. Software-only user agents are easier to hack than hardware-assisted user agents, but in either case time works for the hackers. The latest development is the latter - embedding all the cryptography in hardware - like the HDMI's HDCP method (High-bandwith Digital Content protection Path) where they have essentially made the decrypted digital signal inaccessible to the user by letting it pass along black-box hardware from its point of decryption until it is made so available, but at the intended destination - TV screen. The key for HDCP to succeed however was implementing it in hardware. Most hackers have learned to deal with software. But since I would say there is 1 good hardware hacker per 100 good software hackers these days, the mouse hopes no cat will be around to catch it. Sorry for too much theory, it is essential to your problem though, I believe. If you are still willing to play the game, encrypt your XML files and make sure the decryption key is not available to potential hackers on a silver plate - i.e. obfuscate it, can't do much else.
How determined are you expecting the "hackers" to be? If all the information required to decrypt the information has to be present on the system anyway, then a determined attacker is going to be able to get at it anyway.
You can use the classes in the Cryptography namespace.
Most of the encryption classes will allow you to encrypt and decrypt streams, so are good for your purpose.
However, you will still need to hold the encryption keys somewhere, even if it is in the assembly.
As Jon points out, a determined hacker will find a way to break any encryption.
As others explained, you won't get it absolutely secure without a trusted device which stores the key and does the decryption without granting access to the key under any circumstances. Computers aren't "trusted devices"...
My employer sells such technology and if your data is really money worth, you should possibly take such a solution into account.
If an additional USB-Dongle is not acceptable (or too expensive) at least use public-key (asymmetic) cryptography (see System.Security.Cryptography).
Asymmetric cryptography has the advantage that the key used to decrypt your data can't be used to encrypt the data.
Your application has to store the decryption key and the hacker can determine it with more or less effort. He then can decrypt all your data but he can't not encrpyt the changed data again. So he can't use your application with the changed data.
If you want to prevent him from doing this, you have to obfuscate your application and use anti-debugging techniques (static and runtime). If you go this way buying an existing solution is probably cheaper.
Watch out: Hackers can see all functions in .net generated executables and dll's!
If you make a decription algorithm in your .net project like DecryptXML(string Path), it is very easy for a hacker to call this instruction. So be sure to dotfuscate your project.