I'm working on a couple of projects that need to store user credentials for third-party applications, such as Paypal, Facebook developer creds etc. I've read a few books about different kinds of coding, including ASP.NET, WPF, jQuery, and all have nice examples on how to access the preceding services with own secrets, and also all of them use the exact phrase "in a real project you would store these in an encrypted file". None, however, give an example how to do so.
I have little (read: none) experience in encryption, but based on my understanding, I would need to encrypt a username and a password using some sort of key (salt?) and save them in a file. I would also want to be able to use these credentials on my apps so I would need to store the key (salt?) in my code.
Now my question is: How is it safer to store the decryption key, which is still plain text, in the program code, than the actual credentials?
Wouldn't the malicious user be able to decrypt my password-file as soon as he gets the key?
--EDIT--
I really mean my own credentials I need to store to log in to third party applications, not credentials of my users. For example I need to identify my self and/or my app to Google, so that users can log in to my app using their own Google account.
--EDIT 2--
To clarify, this is what I'm talking about. This screenshot is from asp.net PayPal tutorial:
Any quick pointers on good practises here?
You misunderstood the part about storing encrypted password* + salt: this is done when your system needs to validate someone else's credentials. In this situation storing password hash and the salt is more secure than storing the credentials, encrypted or not, because an attacker would have no way of getting the password back, even if he manages to get his hands on both the hash and the salt.
Storing decryption key in plain text is never a good option, because an attacker would get your users' passwords as soon as he gets access to the key.
There is no good solution to persisting your own credentials, encrypted or not. Your component that talks to 3-rd party services should use developer APIs from these providers. For example, PayPal provides two sets of APIs which you can use to access your account without having to store your password.
If you need to store a small amount of secret information in an encrypted form, use registry APIs to store the data in a key known to your application, and accessible from the user running your server-side component. This secret would be safe, as long as hackers do not hack the password for the account under which your service is running.
* Technically, password is not encrypted, it's hashed, i.e. there is no reliable way to turn the result of conversion back to the original value.
Your suspicions are correct. If the user has access to the key they can just go and decrypt the username and passwords themselves.
The two options you have are
Make it difficult enough to get the password that the reword of getting the password is not worth the effort to find it. This approach is done via things like Code Obfuscateors, I would not recommend this to someone starting out. Its not easy to get it right and it only takes one person who things it is "worth the effort" for it to break.
Don't give the user the information ever. Instead of storing the usernames and passwords in the program have your program call out to a server you own, then that server is what makes the request using the credentials. This approach is the more reliable one and is "unbreakable" (as long as your server is secure) but costs more because you now need to keep a server up and running that can handle the load of your entire userbase.
Related
If I have a stored key file used to decrypt the encrypted input coming into my application, and I store that key file as an embedded resource so that it is embedded in the assembly when deploying, how difficult would it be for someone to reverse engineer the application and retrieve the key file?
Also, the application is deployed through ClickOnce "Online only" mode which I imagine would also make it more difficult to reverse engineer? (I'm not exactly sure of the workings of ClickOnce but I wasn't able to find the dll's/assemblies on my local machine after running the application in online only mode...).
Update:
As Ralf essentially answered the main question below in his comment (answer: it's not really safe at all), here's some more information so that you knowledgeable people can possibly suggest a better security model.
The encryption will be used to encrypt the login password for my application, to be used in a SSO setup (the user will first sign on to a different system and then by clicking a link will be able to directly open my application without having to enter in their login details).
The encrypted data will be sent as a base-64 string URL parameter in the link that will launch the my click-once application.
I will also be developing the application that will create the encrypted data for the URL parameter (clarification: not the first application the user will sign in to for the SSO, I will only be creating a small tool to convert the plain text password into an encrypted base64 string).
It's only an internal application so bullet proof security isn't essential and ease of deployment is more important, but it'd be nice to know what the best practices and different options that are available.
Whether in clear text or encrypted, you don't want to store the password. When you get a password, all you should do is pass it to your server app where you compare it against the salted hash of the password you have in the DB. Even if you don't think security is that important, you need to take care with the password because people frequently reuse passwords across different systems. I know they shouldn't but they do.
If you want to implement a single sign on (SSO), create a sign on token on the server side and pass it back to the client, either encrypted or signed (HMAC is a good choice for signing). This is an unforgeable token because you need to know the encryption key or shared secret for the HMAC and that data is only known on your servers. So you have your SSO and all data involving the SSO is managed on servers so there's no data leakage or chance of spoofing.
As long as the aplication can be launched, the files have to be somewhere on the computer. You just have to know where to look. The reverse-engineering may be ugly but it is always possible. The computer has to be able to understand what he is supposed to do so you only have to extraxt the information one is looking for. Therefore the security of your application should never depend on the difficulty of reverse-engineering! I believe that a secure application should be open-source anyways.
You propably need a diffent security model. The important thing here is that you know against what you want to protect the data. If you simply want that you know the data is sent by the server and not somebody else (man in the middle attack) you could use digital signatures instead.
If you do not want anybody to read any data sent between server and client you should use some sort of ssl implementation to create an encrypted channel. Then you only need to watch out that the public key of the server is not altered on the client. This may be done by an certificate of an official CA but unfortunately those are usualy not for free.
We are currently developing a web application in .Net which will also have Android, iPhone and Windows Mobile 8 apps to occupancy it. All of these applications need to have a unified login system. Our site and web services will be using SSL but obviously we want to do all we can to make sure user passwords stay safe. As such we are looking for a common password hashing function that can be used throughout the platforms outlined above.
Currently the only common one we have found is SAH256 however I would like to use something a little stronger. C# has the Rfc2898DeriveBytes class which I would like to use (and can be used in the website and Win8 Mobile) but are there any implementations of this for Android/Java and iOS/Objective C? If this can’t be used what would be our next best option?
The password hashing function should be used on your back-end when storing the user's password and comparing during a login attempt.
Login scenerio:
User sends password over SSL via one of the versions of your app.
The back-end server hashes the password that was sent from the user, retreives the stored hash from the data store, compares the hash of the password sent with the stored hash.
Hashes match, user is allowed access, otherwise access is denied.
The SSL encryption prevents exposure of the password during transmission from the client, storing passwords as hashes prevents exposure of user passwords if your database is breached.
Using this scenerio, since the hashing is all done at the back-end server, only one implementation of the hash algorithm is required.
PBKDF2 is not something that fits well in your situation. It is mainly intended to prevent attacks when the attacker already has your data (ie. an encrypted file). It does this by eating up CPU to force a delay during brute-forcing. Because you're performing auth server-side, you can easily save some CPU and just wait a second or two to send an response to the client if they get the password wrong. Just use a salted hash (like HMAC), and you'll be fine.
If you're using SSL, then your passwords are secure. The only way you can do any better is to implement full public-key crypto, which can prevent MITM attacks. SSL even has this built in.
Sending password hashes over a network is not really more secure than sending passwords. Yes, the password text is hidden from attackers, but they've still got the hash and if they have that, they don't need the password. In the case of SSL, your plain text is also protected.
While I've never used it personally, bcrypt appears to have all the implementations you are looking for.
http://en.wikipedia.org/wiki/Bcrypt#See_also
Hope that helps.
I am looking forward to have the less information as possible on my application resulting in pulling most of the data from a website or server and I would like to hear by advices and recommendations from everyone with experience in the field to help me improve my application.
Currently my authentication consists of:
To start the application the user have to input their username and password (without a valid user and pass the app does not work) and click login.
The credentials will be sent to my login page using HTTPS, the script only accept SSL connection and a personalized User-Agent name.
The login page will verify the credentials and send back a session and some initial data.
The session is reused to gather more data over time or as needed.
Side note: the SSL is 256 bits, the session auto expire after a few minutes
For the above basic authetication and data pulling would you recommend me anything else to implement ?
Should I change anything ?
2nd Layer of protection
Now I would like to implement more security by encrypting all the data sent from/to my application, my question:
What should I use to encrypt and decrypt the data, a pair of private and public keys held on both sides or RIJNDAEL's method ?
What is the proper way or what parts of information should I leave on the client and server or how should I form the knowledge of the common passwords or keys ?
For example if I was using a pair of RSA keys, I would need to leave 1 private key at the client and 1 public key since you cannot decrypt any data with the public key on c# while you can do it on the server and for Rijndael would need to have the IV and the key on both side.
What is the proper way to handle these ?
I will be very glad with practical reading material, comments, examples, suggestions, advices :)
UPDATE:
No one else wants to say anything ? I was hoping to get more input on this question and also tough that this was a fairly used method around ...
Sounds like you've considered the security of the app side of the equation at length. I'd suggest you turn your thinking to the website part of the equation.
When I look at security, I always look at two things:
Transport security--is your data protected while in transit? Sounds like it is, assuming you are using sufficient key length for the SSL cert on the server. Also, you can force the website do client cert validation as part of the SSL handshake. That ensures that no one can spoof the client app and convince your website to share information.
Payload security--should you encrypt the data payload? Is there a chance someone may be able to break into your web server, or better yet, via the DNS poisoning or some other method, convince your app to connect to a malicious server with a valid (for that cn), but different HTTPs certificate? Should you choose to encrypt the payload, you can piggy back the whole thing onto the same certificates you already use. Just make sure that the certs have data encryption bits turned on, and you can use private/public keys from the certs to encrypt the payload. So, if the malicious user replaced the cert, not only do they need to spoof the cn and the chain of trust, but also have the right public key from the app to decrypt the data you are encrypting with your private key and signing with server's public key.
Some other questions to ponder:
You are saying that the session is reused? Does it not expire? If not, you'd want to make it expire.
Can you leverage network security? Can you use a VPN tunnel or IP ACL to limit who can even gain access to the web server?
What about keyloggers? Passwords can be intercepted. The second authentication factor can be something a user has, like a key card or a fingerprint, or an RSA SecurId. If you don't want to go that far, you can present a user with a "site seal"-- an image that they have to recognize as associated with their account. Maybe even present several images and let them choose one that they've chosen during the signup process. You can also make them solve a small puzzle--something that will distinguish a human from a machine (CAPTCHA-type).
All these points minimize info stored on the client side--just a cert or two and a key to go with that cert.
The topic of security is vast, and we can start a whole discussion here on different implementation details. The above is just some points to think about.
Remember, that everything has cost. Security costs usability and CPU cycles. Proper balance is key, but that of course is up to you.
Before you build Fort Knox, make sure someone is going to want to live there :)
Suppose someone gets access all of my hard disk, I guess the weak spot would be my windows password. Without knowing/being able to retrieve that, the data should be pretty much safe, shouldn't it?
I'm asking specifically because of the EFS entry in wikipedia which states that
In Windows 2000, the local administrator is the default Data Recovery Agent, capable of decrypting all files encrypted with EFS by any local user.
and EFS happens to use DPAPI. So does the same apply to my own data protected using this:
ProtectedData.Protect(plain, null, DataProtectionScope.CurrentUser);
And if that is indeed the case, how could I prevent it?
[Edit] N.B. I'm trying to store credentials for a winforms app so that the user does not have to enter their password every time they login. In other words, if someone is able to login as that user (i.e. know the user password), then they might as well be able read the encrypted data.
Which - not coming from a windows background - now makes me wonder - can't the local admin login as any local user anyway? In that case I shouldn't be concerned about the admin being able to retrieve passwords anyway...
[Edit2] As google reveals, it looks like an Administrator cannot just login as any user without resetting/changing their password first. So my question still seems relevant...
EFS uses DPAPI, not the other way around. And Administrator can't read your key just like that.
Before forgetting about DPAPI, I would consider the alternatives. If you encrypt the file yourself,
You must select a strong algorithm and implement it well.
You will need a key. Where will it be ?
You will store the key in a file somewhere on your drive.
That key is sensitive, obviously, you will want to encrypt it
Goto 1
DPAPI does 1 to 3 well. 4 and 5 are moot. If a Windows password is not enough to protect data, ask yourself why it is enough to CRUD that data in the first place.
For better security, you can consider not saving the data but a (salted) hash of it, if possible. It makes your data write only, though. For example, if you want to verify a customer license number :
Save a salted hash value of it
Run the same hash on the salted license number you want to verify,
Compare the two. It they match, the license is valid.
If you must read back encrypted data and a locally encrypted key is not enough, consider encrypting your application key (step 2 above) with a private key stored on a smart card.
Either way, remember that things happens. You always need a backup key somewhere.
See this article on DPAPI Security. Basically, it is as secure as your Windows password -- if your password is reset by an administrator, the decryption key will be lost. The major attack vectors you'll need to look at are:
Password disclosure: "shoulder surfing", sticky notes, etc.
Capture of the computer's accounts database and the use of a password cracker
Online attack by "drive-by download", removable media AutoPlay, etc.
Capture of a password reset disk, if you've made one
Physical installation of a key-logging device or other "bug"
DPAPI can be used both with and without optional entropy. There are only two ways DPAPI blobs without optional entropy can be compromised:
A domain admin can directly retrieve anyone's history of DPAPI master keys at any time. Nothing else is required. These can be used to decrypt all blobs. Local administrators cannot do this.
The user's Windows credentials are compromised.
If you use optional entropy then the data cannot be decrypted by anyone who doesnt know the value. The entropy may be derived from a password required to launch the application etc. Without the value, the data is lost forever.
EFS works differently. The user's key is protected using DPAPI for his profile, but the decryption key for the file itself is additionally directly encrypted with the administrator's public key as well. Therefore a domain admin can access the files.
I need to store my users' name/password somewhere (preferably the Registry) so my .Net application can use them to log in to some remote service on behalf of the user. I know it's possible to store values in the registry as "secrets", which means their encrypted using the Windows domain user token or something. In other words, I don't want to have to deal with the encryption myself.
To clarify: I can't store hashes of the password or salt them or anything. These credentials are for a 3rd party system and the only way for me to be able to login to this system on behalf of my users is to somehow keep their credentials and be able to restore them.
So anyway, I remember vaguely there's such a place in the registry, but the details are murky. And I need to do it in C# (though if it's simple registry access it shouldn't matter).
Edit: One more thing, it should persist between Windows user sessions (IOW it doesn't help me if the password in unreadable after the user logs off and on).
You're probably thinking of the Data Protection API. Search MSDN or read some blogs and see if that'll work for you.
You can try using System.Security.Cryptography.ProtectedData, which can encrypt them using a per user key. http://msdn.microsoft.com/en-us/library/system.security.cryptography.protecteddata.aspx.
It's not completely secure, since code running as the user could decrypt the data.
Keep in mind that you're not really securely storing anything if you can automatically (without user input) retrieve the password. Using RSA, symmetric, or other encryption doesn't make a difference so long as you store the decoding key within your application. Once anyone gets the key, the secret's out.
However, the Data Protection API mentioned above should protect passwords from other users on the same machine. (It sounds like DPAPI uses your login credentials for encryption.)
For a few more options, check out the msdn page for Threat Mitigation.
You should never store credentials as plaintext. Use a symmetric key cipher. Take the password out at runtime. See the MSDN reference on Cryptography functions.