In my application I need to read an encrypted file that is distributed with the app. I also need to connect to a download service using a password. My conundrum is where to store the passwords for these resources? In other languages, such as C++, I would just have stored them in the code. However, as there are tools that can disassemble C#, such as JetBrains DotPeek, that is not secure.
Below are the solutions I have thought of so far, but I don't think any of them are secure:
Store the passwords in the code: No good because C# can be disassembled.
Store the passwords in an encrypted external resource: No good, because then you need to store the password for that!
Ask the user for the password on first use (which they have been told by other means): No good, I think, because don't you still need to store it for subsequent use?
Store them in a C++ dll: No good, because what is to stop anyone else calling the function in that dll?
Hide and encrypt the passwords in the code: For example, don't call it password and use multiple levels of encrypting it. This would make it difficult for someone who was just text searching the code, but wouldn't stop someone prepared to debug the program to find out how the resources were accessed. No good.
Obfuscate the code base to prevent disassembly: Possibly this might work. Is it secure? Does anyone do it?
What is the normal solution to this quite typical problem?
Note: if you want the authentication to be done 100% offline, there is no truly secure way since someone that has access to the computer has access to all of it content.
First off, cpp CAN be decompiled as per this SO answer. It's just ugly as hell.
Why not just use a database which would store hashed passwords ? When the user wants to read the file or download from the service, you ask him for a password then hash it and match it with the hashed version stored in your database. The matching would of course be done over a secure protocol.
Here is a tutorial about ASP.NET auth. You may read it just to understand the way they store the password and match it.
Keep in mind that obfuscation/multiple levels of encryption won't stop someone really determined.
You haven't mentioned my answer at all in your post. Do you dislike this approach or did you not think of it ?
edit: regarding the file, since the user must not be allowed to decrypt it you could have an other "key" stored in the database. When the user authenticates with their password you retrieve the key from the database and decrypt the file. this way the user never sees the key for the file.
As per Vytautas Plečkaitis's suggesstion: you could use the has of your application as an authentication token to retrieve the password for the file from the database. The idea is good from a user-friendly point of view since it allow the user to not have to give any password but it means that the "key" to the database is the same for every instance of your application (crack it once, you cracked them all). Also, this means that to obtain the key to your application all you have to do is get the hash of your executing exe ... i'm nto a security expert (not even close to that) so i dont know how secure that is but i'm not sure that it's the best idea.
To me the password/hash/database pattern is the best, especially since it has been used over and over again for years. This is the built-in method for .NET Core authentication
Did a quick search and found this gem Encrypting app.config File which could be an option for you, just store those credentials inside the app.config. What you'd be doing here is encrypting sections of your configuration file.
You cannot encrypt the entire - it's a
configuration section group, which contains configuration sections.
The aspnet_regiis will only encrypt configuration sections - so you
need to selectively encrypt those parts you need, like this:
cd C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727
aspnet_regiis.exe -pef "system.serviceModel/bindings" .
aspnet_regiis.exe -pef "system.serviceModel/services" .
etc.
With this, you can encrypt what you need easily - what isn't too
important, can be left in clear text.
Word of warning: since it's aspnet_regiis, it expects to be dealing
with a web.config file - copy your app.config to a location and call
it web.config, encrypt your sections, and copy those encrypted
sections back into your own app.config.
Or write your own config section encrypter/decrypter - it's really
just a few lines of code! Or use mine - I wrote a small
ConfigSectionCrypt utility, come grab it off my OneDrive - with full
source (C# - .NET 3.5 - Visual Studio 2008). It allows you to encrypt
and decrypt sections from any config file - just specify the file name
on the command line.
Here is the link to the said OneDrive https://1drv.ms/u/s!AtQ29cmdYW3QgnnBpcHRRCc4_mop and it is currently active.
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 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!
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'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?
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).
It also has AES.
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.
Try using AesManaged.
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
Using a well tested and accepted library is a good idea too...
http://www.bouncycastle.org/csharp/
I'd like to bind a configuration file to my executable. I'd like to do this by storing an MD5 hash of the file inside the executable. This should keep anyone but the executable from modifying the file.
Essentially if someone modifies this file outside of the program the program should fail to load it again.
EDIT: The program processes credit card information so being able to change the configuration in any way could be a potential security risk. This software will be distributed to a large number of clients. Ideally client should have a configuration that is tied directly to the executable. This will hopefully keep a hacker from being able to get a fake configuration into place.
The configuration still needs to be editable though so compiling an individual copy for each customer is not an option.
It's important that this be dynamic. So that I can tie the hash to the configuration file as the configuration changes.
A better solution is to store the MD5 in the configuration file. But instead of the MD5 being just of the configuration file, also include some secret "key" value, like a fixed guid, in the MD5.
write(MD5(SecretKey + ConfigFileText));
Then you simply remove that MD5 and rehash the file (including your secret key). If the MD5's are the same, then no-one modified it. This prevents someone from modifying it and re-applying the MD5 since they don't know your secret key.
Keep in mind this is a fairly weak solution (as is the one you are suggesting) as they could easily track into your program to find the key or where the MD5 is stored.
A better solution would be to use a public key system and sign the configuration file. Again that is weak since that would require the private key to be stored on their local machine. Pretty much anything that is contained on their local PC can be bypassed with enough effort.
If you REALLY want to store the information in your executable (which I would discourage) then you can just try appending it at the end of the EXE. That is usually safe. Modifying executable programs is virus like behavior and most operating system security will try to stop you too. If your program is in the Program Files directory, and your configuration file is in the Application Data directory, and the user is logged in as a non-administrator (in XP or Vista), then you will be unable to update the EXE.
Update: I don't care if you are using Asymmetric encryption, RSA or Quantum cryptography, if you are storing your keys on the user's computer (which you must do unless you route it all through a web service) then the user can find your keys, even if it means inspecting the registers on the CPU at run time! You are only buying yourself a moderate level of security, so stick with something that is simple. To prevent modification the solution I suggested is the best. To prevent reading then encrypt it, and if you are storing your key locally then use AES Rijndael.
Update: The FixedGUID / SecretKey could alternatively be generated at install time and stored somewhere "secret" in the registry. Or you could generate it every time you use it from hardware configuration. Then you are getting more complicated. How you want to do this to allow for moderate levels of hardware changes would be to take 6 different signatures, and hash your configuration file 6 times - once with each. Combine each one with a 2nd secret value, like the GUID mentioned above (either global or generated at install). Then when you check you verify each hash separately. As long as they have 3 out of 6 (or whatever your tolerance is) then you accept it. Next time you write it you hash it with the new hardware configuration. This allows them to slowly swap out hardware over time and get a whole new system. . . Maybe that is a weakness. It all comes down to your tolerance. There are variations based on tighter tolerances.
UPDATE: For a Credit Card system you might want to consider some real security. You should retain the services of a security and cryptography consultant. More information needs to be exchanged. They need to analyze your specific needs and risks.
Also, if you want security with .NET you need to first start with a really good .NET obfuscator (just Google it). A .NET assembly is way to easy to disassemble and get at the source code and read all your secrets. Not to sound a like a broken record, but anything that depends on the security of your user's system is fundamentally flawed from the beginning.
Out of pure curiosity, what's your reasoning for never wanting to load the file if it's been changed?
Why not just keep all of the configuration information compiled in the executable? Why bother with an external file at all?
Edit
I just read your edit about this being a credit card info program. That poses a very interesting challenge.
I would think, for that level of security, some sort of pretty major encryption would be necessary but I don't know anything about handling that sort of thing in such a way that the cryptographic secrets can't just be extracted from the executable.
Is authenticating against some sort of online source a possibility?
I'd suggest you use a Assymmetric Key Encryption to encrypt your configuration file, wherever they are stored, inside the executable or not.
If I remember correctly, RSA is one the variants.
For the explanation of it, see Public-key cryptography on Wikipedia
Store the "reading" key in your executable and keep to yourself the "writing" key. So no one but you can modify the configuration.
This has the advantages of:
No-one can modify the configuration unless they have the "writing" key because any modification will corrupt it entirely, even if they know the "reading" key it would takes ages to compute the other key.
Modification guarantee.
It's not hard - there are plenty of libraries available these days. There're also a lot of key-generation programs that can generate really, really long keys.
Do take some research on how to properly implement them though.
just make a const string that holds the md5 hash and compile it into your app ... your app can then just refer to this const string when validating the configuration file