I'm looking for a way to securely store an API key in a WP7 application. The key is a string and is currently hard coded into the code (see below). I know that someone with a reflector program could easily view this. Is there a better way to package this key as part of my app? Would a resource be more secure?
string key = "DSVvjankjnersnkaecjnDFSD44VDS23423423rcsedzcadERVSDRFWESDVTsdt";
Thank you in advance.
Have a look at Safeguard Database Connection Strings and Other Sensitive Settings in Your Code, it is a good read. Your question is under the "Hiding Keys in the Application Source Code" section.
Excerpt:
If you define the key in the application, in addition to obfuscating the assembly, try not to store the actual key bytes in the source code. Instead, implement key-generation logic using persistent characteristics, such as the encryption algorithm, key size, pass phrase, initialization vector, and salt (see an example at Encrypt and Decrypt Data Using a Symmetric (Rijndael) Key). This will introduce an extra layer of indirection, so the key will not be accessible by simply dumping the symbols from the application binary. As long as you do not change key-generation logic and key characteristics, the resulting key is guaranteed to be the same. It may also be a good idea not to use static strings as key-generation characteristics, but rather build them on the fly. Another suggestion would be to treat the assembly the same way as the data store should be treated, that is, by applying the appropriate ACLs. And only use this option as a last resort, when none of the other data protection techniques work and your only alternative is leaving sensitive data unencrypted.
I've read through all these answers, and I don't think there is any way you can securely embed this - regardless of where you put it, or how you obfuscate it. As long as its in your XAP and decoded within the application then it will always be available to hacking.
If you need to ship the key inside the xap with a reasonable degree of protection, then I think #maka's answer yields your best bet - obfuscate it as best you can - but don't think this will make you secure - i.e. don't do this for your mobile banking apps!
Alternatively, if you really need security then don't operate solely within the app - use a web server as well. For example, if you were doing a Facebook app and needed to somehow protect your facebook secret key, then you would need to redirect the user from your app to a web page on your server for authentication. That web page would then need to guide the user through the process of getting an access token - and then just that access token (along with the public appid) would need to go back to your app. And for those webservices which require knowledge of the secret key to accompany every call, then I'm afraid every single call will probably need to go via your server.
You can encrypt Api key with ProtectedData and then decrypt it in runtime. This is good tutorial how to encrypt data in Windows Phone: Encryption in Mango
May be you can encrypt it before hand and save it in app.config. And while reading it decrypt it using the same algorithm.
You could use DotFuscator to disable the ability to use reflector.
But, this will not allow you to change the key without recompiling.
In the past I've used the following method in other (web/winform-based) software:
http://weblogs.asp.net/jgalloway/archive/2008/04/13/encrypting-passwords-in-a-net-app-config-file.aspx
It's not an answer maybe, but sure it's a suggestion:
Store encrpyted key in a db. And store encrypted "db password" in app.config.
Use two proper string encrypt/decrypt algorithm, let's say algorithm x and y.
Put encrypted db password in app.config before to publish it.
Decypt app.config password(algo y) to connect the db for taking new encrpyted string(real one).
Close the connection and decyrpt new string with algorithm x if reflector/etc. not running.
Use it.
Dispose the object that holds the string.
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 am planing to write a C# class library which will include my encryption algorithms like RC4, DES. These are single key encryption algorithms.
Now i want the best secure decision to protect my key. Should i put my key hardcoded inside the DLL or should i set my key from my external application which uses the DLL? Which one do you think is more secure when you consider the decompling tools?
Loudly thinking:
if the key is hardcoded in my security library and someone find the DLL and import it to his C# application, can he easly decode my chipper data?
if the key is not hardcoded in my security library but is set from my external application, someone needs to decompile also my external application to find my key?
Setting the key values from my external application which will use the security DLL seems more secure to me. What do you think?
Thanks.
Hard Coded Key
If you include the shared/private key in the DLL, then anyone who has a copy of the DLL will have a copy of the key. If your model is to share your application with multiple users, all users will have the same encryption key, and can decrypt anything encrypted by another user. If your application is easily available, then you have to assume the attacker has the application (and therefore the key) as well.
It also means that all developers will have access to the production encryption key, since they have the source code. QE will also have access, as they probably have access to the binary. Either of these two insider groups will be able to decrypt anythign that your application protects for your customers.
Is this what you want? It's generally a bad practice, but it's worse in some environments than others. For example, if you're writing code to learn how to write crypto and nothing more, it probably doesn't matter - just make sure nobody else can use it :) If you're writing a service, it's a bad practice and introduces risk, but it's not the worst thing you could do. If you're writing something that will be shared to multiple customers, then you defeat the purpose of encrypting by including the key in the binary.
And it's not really that hard to generate random data (using a cryptographically strong random number generator), store it in a file, and use that file as your encryption key. My recommendation is go with the separate key.
Separate Key
If you ship the key in a separate file, you eliminate all the risks introduced by shipping the key in the binary but you introduce others. Or, stated differently, now that your crypto can do some good, you need to make sure you do it right or it'll still be useless.
The key needs to be generated using a cryptographically strong random number generator, so that it's not predictable. The key needs to be stored securely - the whole path to the key file needs to be protected, and you should consider using a password protected store (like a keystore) to ensure that only users with the right password can access the key. Of course, that last one depends upon your deployment model, and if you need unattended restart. And the key needs to be used securely - constant order operations, don't act an encryption or decryption oracle, verify integrity of data before semantically parsing it, etc.
My application makes use of the RijndaelManaged class to encrypt data. As a part of this encryption, I use a SecureString object loaded with a password which get's get converted to a byte array and loaded into the RajindaelManaged object's Key at runtime.
The question I have is the storage of this SecureString. A user entered password can be entered at run-time, and that can be "securely" loaded into a SecureString object, but if no user entered password is given, then I need to default to something.
So ultimately the quesiton comes down to:
If I have to have some known string or byte array to load into a SecureString object each time my application runs, how do I do that? The "encrypted" data ultimately gets decrypted by another application, so even if no user entered password is specified, I still need the data to be encrypted while it goes from one app to another. This means I can't have the default password be random, because the other app wouldn't be able to properly decrypt it.
One possible solution I'm thinking is to create a dll which only spits out a single passphrase, then I use that passphrase and run it through a couple of different hashing/reorganizing functions at runtime before I ultimately feed it into the secureString object. Would this be secure enough?
Edit For clarity*: The encrypted data is being passed via files between machines. Think of it as a Zip file which always has a password, a default one is assumed if nothing is directly entered by the user.
There is no point in symmetrically encrypting with a string that's hard-coded into your executable. It will only give a false sense of security. No amount of hashing fixes this scheme.
See this Pidgin FAQ for the same point in a different context.
I am unclear why you think you need the inter-app communication to be encrypted. If this communication is local to the machine, then I don't see the need for encryption, particularly encryption that isn't user-specific. Is this a DRM scheme?
EDIT: If it's being passed to a different machine, perhaps you can hard-code a public key, and then have the other machine decrypt with the matching private key.
Let me tackle your final question first.
"Would this be secure enough?"
The only one that can answer that is you. Nobody here knows what "secure enough" means in the context of your application.
Are you building an application to keep the diary of teenage girls? Sure, it would be "secure enough".
Are you building an application to encrypt information or authentication for military grade secure systems? Nope, not even close.
You can only rely on one type of security if you intend to store the password in your source code and thus executable, and that is security by obscurity.
If your problem is that you can't, or won't, store the password in the source code, then moving it into a separate dll solves nothing, you've just moved the problem to a different project.
However, I'm wondering about something. You say "I have to default to something". Is that it? You're trying to store a default value for the secure password string in the source code? How about "THISISNOTAPASSWORD"?
Eric Lippert's You Want Salt With That? (original blog post)
Also read his post to Use the right tool for the job where he ends with the following tips:
If you possibly can, simply don’t go there. Encryption is extremely difficult to get right and is frequently the wrong solution in the first place. Use other techniques to solve your security problems.
If the problem is an untrustworthy client then don’t build a security solution which requires trusting the client.
If you can use off-the-shelf parts then do so.
If you cannot use off-the-shelf-parts and do have to use a cryptosystem then don’t use a cryptosystem that you don’t fully understand.
If you have to use a cryptosystem that you don’t fully understand, then at least don’t use it to solve problems it was not designed to solve.
If you have to use a cryptosystem to ski through the trees, then at least don’t allow the presumably hostile client to choose the message which is encrypted. Choose the token yourself. If the token must include information from the client then sanitize it in some way; require it to be only straight ASCII text, insert random whitespace, and so on.
If you have to allow the client to choose the token, then don’t encrypt the token itself. Sign a cryptographically-secure hash of the token. Its much harder for the attacker to choose a token which produces a desired hash.
Don’t use the same key pair for encrypting outgoing messages as you do for protecting incoming messages. Get a key pair for each logically different operation you're going to perform.
Encrypt the communications both ways.
Consider having a revocation mechanism, so that once you know that Eve is attacking you, you can at least revoke her license. (Or you can revoke a known-to-be compromised license, and so on.)
This article on securing SQL connection strings should be just as applicable for storing encrypted passwords, where you let the OS handle the encryption of the salting seed for your decryption.
It sounds to me like perhaps you should be using a PKI solution instead of encryption/decryption. If you have another application that needs to consume the encrypted data, then you could have a key pair for that application, and give the public key to the app that is doing the encryption. That way you are still keeping your data secure, but not introducing a bunch of additional code that ultimately doesn't give all that much protection.
A quick google search gave me this Code Project article that talks about using the Windows Certificate Store in .Net
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.
I'm adding some encryption methods to a class library (C# 2.0) and would like to know the best place to put the pass phrase, salt value and initialisation vector required. Is it a really bad idea just to hard-code these into the DLL, or should I be be encoding them and storing them somewhere else?
Thanks.
Edit: Further info - encryption required for personal info in database (addresses, phone numbers etc..), no bank/medical type info so solution doesn't need to be too hard-core. Class library will be used on a server for a web-app, encryption methods to be used in the data layer.
If you hard-code you initialisation vector and key into the DLL, then you really may as well forgo encryption altogether. If you could tell us a bit more about the reason you're using encryption here and how the data needs to be accessed precisely, perhaps I can suggest how you can make it secure.
EDIT: You'll probably want to use public key encryption for this purpose (the RSA algorithm specifically, as it's known to be secure, and is implemented fully in the .NET framework). It's asymmetric, which means that it requires a different key to encrypt (public) and decrypt (private) data. Although I'm still not totally sure how your system works, I suspect you'll just need to restrict access to the private key to just those people who are able to view the database information - you certainly don't want to store it at the same location as the database. Public key can essentially be given to anyone, as it just allows you to encrypt data to be put in the database (assuming write-access to the database is properly restricted). Anyway here are some links to get you started:
Implementing RSA in C#
http://www.dotnetspider.com/resources/692-RSA-Encryption-C.aspx
http://msdn.microsoft.com/en-us/library/system.security.cryptography.rsacryptoserviceprovider.aspx
Hope that helps.
If you're using public key encryption, then you'll want to freely distribute the public key (most likely) and keep access to the private key highly restricted (only on storage media that you know are secure). Either way, it is typical to store keys as base64-encoded strings in XML files. The RSACryptoServiceProvider class has built-in capability to do this, I believe.
Unless your concern is that your data layer is exposed over a web service and you're concerned about possible interception of the data, it sounds like all you need to do is implement encryption on the database itself and not worry about the application.
I had it in mind to use the encryption in basic utility methods mainly for use with a database, but also for configuration data in xml files etc.. and anything else that comes up.
Whatever encryption you use needs keys or pass phrases of one kind or another, I'd like to know where and how you store these strings.
Thanks.