My situation is as follows:
I have to deploy a series of .NET desktop applications consisting of a file with encrypted data and an executable that will access that data and decrypt some parts of it in runtime.
What I need to achieve is that each data container should only be decryptable by that specific .exe it is provided with.
The first idea was to encrypt the data using, say, the hash value of the .exe file as a symmetric key and during decryption calculate the hash value of the .exe file in runtime and decrypt the parts of the data container with it.
However, the problem with that approach is that the user can easily look into the .NET assembly with ILSpy or any other decompiler and discover the whole encryption algorithm which will enable the user to decrypt all the data containers in my series of applications.
Another solution that comes to my mind is to make a small C native library (that is less easy to decomplile) that will perform some manipulations with the .exe assembly information and generate a key for decryption based on it (let's consider the user lazy enough so that he will not try to intercept the key from the memory).
But ideally I wouldn't like to resort to any languages other than C# because porting the application to other platforms with Mono will require additional effort (P/Invokes and so).
So my question is: is there a way I can encrypt the data so that only a certain application would be able to decrypt it?
Of course I understand that in case of a local application it is impossible to keep the data absolutely secure but I need to make the 'hacking' at least not worth the effort. Are there any reasonable solutions or I will have to stick to one of my ideas I described above?
Thank you in advance!
The simple answer is no.
To encrypt and decrypt data, you need an algorithm and, optionally, a secret or key. If a computer can execute the algorithm, someone else can learn what it is. Ignoring decompilation and disassembly, a user could just look at the instructions executed by the CPU and piece together the algorithm.
This leaves the secret. Unfortunately, if the computer or program can access or derive a secret, so can someone with root or administrator rights on that computer for the same reasons above.
However, maybe you are just thinking about the problem the wrong way. If you want the program to access data that no one else can, consider making that data available from a server that users must authenticate to access. Use SSL so data is protected in transit and encrypt the data locally using a key that only the local user and local administrators can access. It is not perfect but it is about the best you are going to get in the general case.
If you need more protection than that, you may want to consider hardware dongles but this gets expensive and complex quite quickly.
Related
I'd like to use Windows.Security.Credentials.PasswordVault in my desktop app (WPF-based) to securely store a user's password. I managed to access this Windows 10 API using this MSDN article.
I did some experiments and it appears that any data written to PasswordVault from one desktop app (not a native UWP app) can be read from any other desktop app. Even packaging my desktop app with Desktop Bridge technology and thus having a Package Identity does not fix this vulnerability.
Any ideas how to fix that and be able storing the app's data secure from other apps?
UPDATE: It appeared that PasswordVault adds no extra security over DPAPI. The case is closed with a negative result.
(this is from what I can understand of your post)
There is no real way of preventing data access between desktop apps when using these kind of API's http://www.hanselman.com/blog/SavingAndRetrievingBrowserAndOtherPasswords.aspx tells more about it. You'd probably just want to decrypt your information.
memory access restriction is difficult, code executed by the user is always retrievable by the user so it would be difficult to restrict this.
have you considered using the Windows Data Protection API :
https://msdn.microsoft.com/en-us/library/ms995355.aspx
grabbed straight from the source
DPAPI is an easy-to-use service that will benefit developers who must provide protection for sensitive application data, such as passwords and private keys
WDPAPI uses keys generated by the operating system and Triple DES to encrypt/decrypt your data. Which means your application doesn't have to generate these keys, which is always nice.
You could also use the Rfc2898DeriveBytes class, this uses a pseudo-random number generator to decrypt your password. It's safer than most decrypters since there is no practical way to go back from the result back to the password. This is only really useful for verifying the input password and not retrieving it back again. I have never actually used this myself so I would not be able to help you.
https://msdn.microsoft.com/en-us/library/system.security.cryptography.rfc2898derivebytes(v=vs.110).aspx
see also this post which gives a way better explanation than I can.
How to securely save username/password (local)?
If I misunderstood the question in some way, tell me, I will try to update the answer.
NOTE that modern/metro apps do not have this problem, although they still are accessible in other ways.
The hard truth is that storing a password in a desktop application, 100% securely is simply not possible. However, you can get close to 100%.
Regarding your original approach, PasswordVault uses the Credential Locker service which is built into windows to securely store data. Credential Locker is bound to the user's profile. Therefore, storing your data via PasswordVault is essentially equivalent to the master password approach to protecting data, which I talk about in detail further down. Only difference is that the master password in that case is the user's credentials. This allows applications running during the user's session to access the data.
Note: To be clear, I'm strictly talking about storing it in a way that allows you access to the plain text. That is to say, storing it in an encrypted database of any sort, or encrypting it yourself and storing the ciphertext somewhere. This kind of functionality is necessary in programs like password managers, but not in programs that just require some sort of authentication. If this is not a necessity then I strongly recommend hashing the password, ideally per the instructions laid out in this answer by zaph. (Some more information in this excellent post by Thomas Pornin).
If it is a necessity, things get a bit more complicated: If you want to prevent other programs (or users I suppose) from being able to view the plaintext password, then your only real option is to encrypt it. Storing the ciphertext within PasswordVault is optional since, if you use good encryption, your only weak point is someone discovering your key. Therefore the ciphertext itself can be stored anywhere. That brings us to the key itself.
Depending on how many passwords you're actually trying to store for each program instance, you might not have to worry about generating and securely storing a key at all. If you want to store multiple passwords, then you can simply ask the user to input one master password, perform some salting and hashing on that, and use the result as the encryption key for all other passwords. When it is time for decryption, then ask the user to input it again. If you are storing multiple passwords then I strongly urge you to go with this approach. It is the most secure approach possible. For the rest of my post however, I will roll with the assumption that this is not a viable option.
First off I urge you not to have the same key for every installation. Create a new one for every instance of your program, based on securely generated random data. Resist the temptation to "avoid having to store the key" by having it be generated on the fly every time it is needed, based on information about the system. That is just as secure as hardcoding string superSecretKey = "12345"; into your program. It won't take attackers long to figure out the process.
Now, storing it is the real tricky part. A general rule of infosec is the following:
Nothing is secure once you have physical access
So, ideally, nobody would. Storing the encryption keys on a properly secured remote server minimizes the chances of it being recovered by attackers. Entire books have been written regarding server-side security, so I will not discuss this here.
Another good option is to use an HSM (Hardware Security Module). These nifty little devices are built for the job. Accessing the keys stored in an HSM is pretty much impossible. However, this option is only viable if you know for sure that every user's computer has one of these, such as in an enterprise environment.
.Net provides a solution of sorts, via the configuration system. You can store your key in an encrypted section of your app.config. This is often used for protecting connection strings. There are plenty of resources out there on how to do this. I recommend this fantastic blog post, which will tell you most of what you need to know.
The reason I said earlier not to go with simply generating the key on the fly is because, like storing it as a variable in your code, you rely exclusively on obfuscation to keep it secure. The thing about this approach is that it usually doesn't. However, sometimes you have no other option. Enter White Box cryptography.
White box cryptography is essentially obfuscation taken to the extreme. It is meant to be effective even in a white-box scenario, where the attacker both has access to and can modify the bytecode. It is the epitome of security through obscurity. As opposed to mere constant hiding (infosec speak for the string superSecretKey approach) or generating the key when it is needed, white box cryptography essentially relies on generating the cipher itself on the fly.
Entire papers have been written on it, It is difficult to pull off writing a proper implementation, and your mileage may vary. You should only consider this if you really really really want to do this as securely as possible.
Obfuscation however is still obfuscation. All it can really do is slow the attackers down. The final solution I have to offer might seem backwards, but it works: Do not hide the encryption key digitally. Hide it physically. Have the user insert a usb drive when it is time for encryption, (securely) generate a random key, then write it to the usb drive. Then, whenever it is time for decryption, the user only has to put the drive back in, and your program reads the key off that.
This is a bit similar to the master password approach, in that it leaves it up to the user to keep the key safe. However, it has some notable advantages. For instance, this approach allows for a massive encryption key. A key that can fit in a mere 1 megabyte file can take literally billions of years to break via a brute force attack. Plus, if the key ever gets discovered, the user has only themselves to blame.
In summary, see if you can avoid having to store an encryption key. If you can't, avoid storing it locally at all costs. Otherwise, your only option is to make it as hard for hackers to figure it out as possible. No matter how you choose to do that, make sure that every key is different, so even if attackers do find one, the other users' keys are safe.
Only alternative is to encrypt password with your own private key stored somewhere in your code. (Someone can easily disassemble your code and get the key) and then store encrypted password inside PasswordVault, however the only security you have is any app will not have access to password.
This is dual security, in case of compromised machines, attacker can get access to PasswordVault but not your password as they will need one more private key to decrypt the password and that will be hidden somewhere in your code.
To make it more secure, if you leave your private key on your server and expose an API to encrypt and decrypt password before storing in Vault, will make it most secure. I think this is the reason people have moved on to OAuth (storing OAuth token in PasswordVault) etc rather then storing password in vault.
Ideally, I would recommend not storing password, instead get some token from server and save it and use that token for authentication. And store that token in PasswordVault.
It is always possible to push the security, with miscellaneous encryption and storage strategies. Making something harder is only making the data retrieval longer, never impossible. Hence you need to consider the most appropriate level of protection considering execution cost x time (human and machine) and development cost x time aspects.
If I consider strictly your request, I would simply add a layer (class, interface) to cipher your passwords. Best with asymmetrical encryption (and not RSA). Supposing the other softs are not accessing your program data (program, files OR process), this is sufficient. You can use SSH.NET (https://github.com/sshnet/SSH.NET) to achieve this quickly.
If you would like to push the security and give a certain level of protection against binary reverse-engineering (including the private key retrieval), I recommend a small (process limited) encrypted VM (like Docker, https://blogs.msdn.microsoft.com/mvpawardprogram/2015/12/15/getting-started-with-net-and-docker/) based solution such as Denuvo (https://www.denuvo.com/). The encryption is unique per customer and machine based. You'll have to encapsulated you c# program into a c/c++ program (which acts like a container) that will do all the in-memory ciphering-deciphering.
You can implement your own strategy, depending on the kind of investment and warranty you require.
In case your program is a backend program, you can pick the best strategy (the only I really recommend) of all which is to store the private key at the client side, public key at backend side and have local deciphering, all transmitted password would be hence encrypted. I would like to remark that password and keys are actually different strategies to achieve the same goal: checking if the program talks to the right person without knowing the person's identity; I mean this: instead of storing passwords, better store directly public keys.
Revisiting this rather helpful issue and adding a bit of additional information which might be helpful.
My task was to extend a Win32 application that uses passwords to authenticate with an online service with a "save password" functionality. The idea was to protect the password using Windows Hello (UserConsentVerifier). I was under the impression that Windows surely has something comparable to the macOS keychain.
If you use the Windows Credential Manager APIs (CredReadA, CredWriteA), another application can simply enumerate the credentials and if it knows what to look for (the target name), it will be able to read the credential.
I also explored using DPAPI where you are in charge of storing the encrypted blob yourself, typically in a file. Again, there seems to be no way (except obfuscation) to prevent another application from finding and reading that file. Supplying additional entropy to CryptProtectData and CryptUnprotectData again poses the question of where to store the entropy (typically I assume it would be hard-coded and perhaps obfuscated in the application: this is security by obscurity).
As it turns out, neither DPAPI (CryptProtectData, CryptUnprotectData) nor Windows Credential Manager APIs (CredRead, CredWrite) can prevent another application running under the same user from reading a secret.
What I was actually looking for was something like the macOS keychain, which allows applications to store secrets, define ACLs on those secrets, enforce biometric authentication on accessing the secret, and critically, prevents other applications from reading the secrets.
As it turns out, Windows has a PasswordVault which claims to isolate apps from each other, but its only available to UWP apps:
Represents a Credential Locker of credentials. The contents of the locker are specific to the app or service. Apps and services don't have access to credentials associated with other apps or services.
Is there a way for a Win32 Desktop application to access this functionality? I realize that if a user can be brought to install and run a random app, that app could probably mimic the original application and just prompt the user to enter the secret, but still, it's a little disappointing that there is no app-level separation by default.
I have a WinForms application which reads data from a sensitive file and performs calculations using that data. In order to keep the sensitive information from people's PCs, we decided to move the calculations to a web service, where the file will hide in a protected folder and only is accessible by the web service program itself.
Due to some complications it looks like it may not be possible to secure the server space in the required timeframe, so what we are now looking to do is use encryption to protect the file so that it can be safely distributed to people's PCs.
My question is this. Is is possible to encrypt a file (once, so a pre-encrypted file will be attached to the project) and then decrypt the file for use by the application without revealing
The sensitive information inside the file
The Encryption key used to decrypt the file
I know it is possible to generate source code from a .exe file so I would be looking for a solution that bears this in mind. I am new to this kind of app development so please excuse me if this is a stupid question and that what I am trying to do is not actually possible.
Cheers
No, it is not possible, you can only make it hard to do those two things. You can not make it impossible. All you can do is just make it hard enough it is not worth the effort to try, and that takes money to do (via specialized obfuscation software and paying experts in the field to look at your code and make it more secure)
Lets say my program is an Anti-Virus.
Lets also say I have a file, called "Signatures.dat". It contains a list of viruses to scan.
I would like to encrypt that file in a way that it can be opened my by anti-virus on any computer but the users wont able to see the content of that file.
How would I accomplish that task ?
I was looking at thigs like DPAPI, but I dont think that would work in my case because it's based on User's setting. I need my solution to be universal.
I've got a method to encrypt it, but then I am not sure how to store the keys.
I know that storing it in my code is really unsecure, so I am really not sure what to do at this point.
You want the computers of the users to be able to read the file, and you want the computers of the users to be unable to read the file. As you see, this is a contradiction, and it cannot be solved.
What you are implementing is basically a DRM scheme. Short of using TPM (no, that doesn't work in reality, don't even think about it), you simply cannot make it secure. You can just use obfuscation to make it as difficult as possible to reverse-engineer it and retrieve the key. You can store parts of the key on a server and retrieve it online (basically doing what EA did with their games) etc., but you probably will only make your product difficult to use for legitimate users, and anyone who really wants to will still be able to get the key, and thus the file.
In your example are you trying to verify the integrity of the file (to ensure it hasn't been modified), or hide the contents?
If you are trying to hide the contents then as has been stated ultimately you can't.
If you want to verify the file hasn't been modified than you can do this via hashes. You don't appear to have confused the two use-cases but sometimes people assume you use encryption to ensure a file hasn't been tampered with.
Your best bet might be to use both methods - encrypt the file to deter casual browsers, but know that this is not really going to deter anyone with enough time. Then verify the hash of the file with your server (use https, and ensure you validate the certificates thumbprints). This will ensure the file hasn't been modified even if someone has cracked your encryption.
I am about to sell a program I have written in C# and I want to control licenses for it, strictly. That means I want to let the client connect to my server every single time it starts. This also gives me the ability to disable keys (in case of chargebacks on paypal or distribution of the code). Of course this might be a hassle for other users, but it is necessary in this case.
Since I was unable to find any good .NET Licensing systems that are uncracked, I wanted to take the approach of writing a little one myself.
My plan was to do the following:
Generate a key.dat containing 1024 characters that gets shipped with the software (individual to each user)
In the application entrypoint add a httprequest to my server that sends the key.dat + current timestamp, encrypted.
My HTTP server (running PHP) decrypts the request and checks if the key is valid (in my database) and replies with the "access level" (license type). If the key is invalid or disabled it replies with an errorcode. Just like with the request, the reply is being salted with a timestamp, so someone can't validate his program by sending a valid packet to himself. The timestamp is being checked in the client. The reply is encrypted with RSA and a previously generated public key.
Client receives response, decrypts with private key and reacts.
Is RSA the correct approach for this, so I can assure that the packets are sent by me and are not crafted (by noone else having the public key)?
Is there a better approach for solving this problem?
Someone who wants your software bad enough will just decompile it and remove the part of the code that phones home on startup.
If you were to add a checksum to the app that checks whether the code has been altered, someone can just change the checksum the program checks against (or remove the check entirely).
People who want your application enough will find ways around any type of protection you can conceive. You're better off sticking to something simple, having a product that is worth paying for (and easily) and make sure it's worth the price you're asking.
EDIT
Given that protection is important, the fact that the users will have code running on their machines is a risk you can avoid. If the users don't have the code, they can't crack it. They can't copy it and share it.
Now, it might not apply to the application you intend to write, but you should consider writing a web, Flash or Silverlight application instead of a regular client application. That way you don't have to distribute the code to customers. All you have to do is manage credentials into the application, which should be a lot easier than your round-about RSA system.
It's also easier to push out new versions of the software in a centralized model, and you won't have to worry about theft at all. Of course, load will become an issue when it wasn't before. And not all applications can be centralized easily (or at all). I'm just proposing this to make sure you consider it because it is a valid solution to your problem.
A web-based application will have the same issues as your application (i.e. it will be down whenever the user is offline, whenever the network is down, whenever your server is down, etc). So there's no added risk in that regard.
Is RSA the correct approach for this?
I do not think RSA is your best choice.
One of the capabilities of PKE (Public Key Encryption) is that it lets parties talk to each other who previously have never exchanged information before (eg. strangers).
I do not see this applying to your case. Your software knows your server well. They are not "strangers".
Consider instead Shared Secret Key encryption, where each copy of the software you distribute is given a unique secret key, and your server knows each user's secret key as well. The keys are never sent, and must be protected, but can still be used to encrypt, sign, and validate communications.
Edit After considering the comments and other answers.
Anyone who wants your software badly enough will be able to bypass the authentication completely. RSA does nothing to prevent that.
The real question is: Does breaking a single license make all licenses vulnerable/worthless. In both cases, (RSA and Secret Key), the answer is No. Just because one copy of the software got hacked and got its key exposed, or the licenses system bypassed, other copies are no more exposed. PKE and SSE seem equal in that respect to me.
Because Shared Secret Key is easier to implement, and computationally faster to execute, I think it is preferred in this case over RSA/PKE. That is not to say RSA is "wrong". It will accomplish what you are after, to the same degree that SSE will (no more, no less). But I think SSE is the smarter choice.
Beforehand :
I have read indeed the other topics on SO, but I can't find an answer in them.
(The others are about config-files, or a list of techniques)
My question thus is very simple, though a bit subjective (I'll label it beforehand :-)) what is the easiest way..
File.Encrypt is pretty simple - one call (with one parameter).
Of course, it really depends on what you want the encryption for. File.Encrypt encrypts to the current account, which isn't much use if you're passing the file around. But, given your spec - i.e. easiest way to encrypt a file - it has to be a candidate!
Data Protection API in C#
Don't believe you have any security just because you encrypt a config file. If someone has access to the encrypted config file, and your executable, containing the password, it's likely to be possible to decrypt your configfile. It's just a little harder.
And say your config file contains passwords to database connections, it might be possible to get those passwords looking at the network packets.
Encryption is trivial with modern libraries: the hard part is securing the key(s).
So you need to look at what you're trying to secure, and what threats you are trying to secure against.
To encrypt a file so only the current user can see it on a client workstation, File.Encrypt is a good choice, or DPAPI with the CurrentUser scope.
For a configuration file on a single server, DPAPI using the LocalMachine scope is a good choice. You then need to make sure only authorized users are able to log in to the server. Here you're essentially delegating key management to Windows.
For a configuration file on a server farm, you need to share the key between the servers. RsaProtectedConfigurationProvide is a good choice, but you have more work ensuring that all servers have access to the same key, and that it is protected against unauthorized access (e.g. using a DACL).
I recommend the Cryptography Application block in Enterprise Library. Very easy, very flexible.