In my game app, running from iPhone/iPad to a central server that I control via TCP, I need to send login information.
What I currently do is send a LOGIN opcode with ascii bytes for login and password in the clear. I don't want to send user's passwords in the clear - they could be on a wifi connection for example.
How can I handle encryption of this? Here are my requirements:
I don't want to use a 3rd party lib, I will if absolutely necessary. If necessary it has to be BSD license or similar
What's the impact of me answering "yes" on "does your App have cryptography in it" to the App store
I want this app to be available in every country
Is it acceptable to, locally on the device, hash the password, and send that cached value only? The user's account could be compromised by the hash being stolen, but the password wouldn't be lost (and I wouldn't be storing their passwords)..
I can't have some kind of OAuth out-of-the-app setup system done as I've experienced before, it's too invasive
I'm sort of at a loss here. I appreciate any good help here as this is one of the last 3 things I need to address before ending almost a year of development.. (so this isn't theoretical or premature optimizing! it has grown in to an actual issue..)
First, the obligatory: "Don't invent your own password scheme. If you aren't an expert, you will do it wrong. If you are an expert, you will do it wrong in a creative way that is horribly broken but which brokenness will be invisible until your scheme is in use by thousands"
Next, be clear about what you want to protect, and why. You mention plaintext user passwords being bad for some reason. Are you concerned that a password the user uses in a bunch of places will be leaked by your application, compromising the user's other accounts, or are you more concerned that the attacker will be able to gain access to your user's account?
My concern with what I read in the subtext of your hashing idea is that the hash that the client sends will never change (unless the password changes). This makes it a plaintext-equivalent for authentication (the attacker need only steal the hash; they can then authenticate without knowing the password). It also makes the password a little more vulnerable to brute-force attacks by someone who can see the hash.
I get the impression that you want to avoid encryption for concerns that it will limit the availability of your application. I can understand that reason.
Let's assume that a cryptographically secure hash isn't cryptography (and I don't know if it is or not, but it isn't in terms of U.S. export restrictions as far as I have read). My suggestion would be a very simple challenge-response protocol to use to verify that the user has the password (I recommend you look up "challenge-response protocol" online).
One caveat here is that I don't address getting the password to the server in the first place; just the server verifying that the user has the correct password for the account. Think of this as a general idea of how you might prevent things like replay attacks, and make life more difficult for attackers that can see the data stream:
Client: "I wish to authenticate as John Smith"
Server: "Okay 'John Smith'-claiming-person, take the current date and time (2011-09-09#12:04:33AM) and a random number I just thought up: 4bazillion, and hash them with your password. Let me know what you got."
Client:
prompts user for password
hashes
Says: "I got: gaAGRtcq4qt22332."
Server:
takes date and time and random number and hashes with password
compares data from client with calculated data
If there is a match:
Says: "Okay, you're in."
Otherwise:
Says: "Go pound sand."
TLS/SSL. Just use it. It is built into iOS.
As for encryption, yes, you will need to claim you use encryption, which will require you to get an (easy) online registration certificate from the government.
Authenticate with your service over HTTPs. You will not need to use any third party libraries. You can implement this as either a post or a get.
Related
I have most of my MVC 4 web application ready. I have even developed the password auto-generation algorithm. Now I am stuck as to how to show this password to the user.
The controller handling the Sign Up process is the one that will generate the password by calling a method from the PasswordGenerator class. I want to show this to the user in a message box using some jQuery.
I've tried passing it through TempData and ViewBag but the password can be seen in the HTML code sent over the internet. Is there anyway to do this securely without showing the password over the internet?
FYI, sending an email with the password is not an option. This is a class project, not intended for something of that magnitude.
Any help would be appreciated.
For starters, there's nothing special about jQuery, TempData, or ViewBag that's useful to you here. Anything you send over the internet gets, you know, sent over the internet. If an attacker has control of your user's network, then they can intercept a javascript->WebApi call or an email more-or-less as easily as they can intercept an HTML page.
More generally, you should be aware of the trade-offs between security, usability, and development cost. By-and-large there is no such thing as "secure". There are threats you can mitigate and specific attacks you can and should defend against, but there's also a level of risk you can accept depending on the nature of your service.
So, what can we do in this situation:-
The most obvious action to take (and the only one I would truly recommend in your case) is to enable SSL. This secures your transport layer against most snooping with no practical drawbacks. Any time you send sensitive data over the internet, you should use SSL. Some would argue you should use SSL always.
You can mitigate over-the-shoulder-type snooping by hiding the password using javascript, and having the user perform some action to "uncover" it (such as hovering the mouse pointer over a target, or pressing a button). Beware that some of your users may be inexperienced, disabled, or using a mobile device. If I were assessing you, I would care far more that you were "being careful" about accessibility than about hand-rolling your own security hacks!
You can mitigate computer-left-unlocked attacks somewhat by timing out the user's session. You'll see this used frequently with internet banking. Be aware that this also has a usability cost - in particular I would be concerned about timing a user out while they're looking for a pen and a post-it to write down the password you generated for them!
A tangential note:- Storing passwords properly is hard, and storing passwords improperly can be disastrous. Make sure you're doing it correctly! At your level of experience, I would strongly advise against rolling your own password storage system unless your assessor has specifically asked you to. Furthermore, having the server generate passwords for end users to remember is quite controversial. If you haven't been specifically asked for it, you should consider whether it is the right approach and make sure you justify it. For something of this scale, you may want to look into some kind of federated authentication (e.g. "sign in with your google account") instead of handling passwords at all.
I am creating an app and a website for a project I've got going, but I'm not sure what I should do about login. This is not a "I'm a noob and I want an app with login"-question. I am somewhat experienced with both web-, database- and app-development, but I've never actually touched the subject of security before other than by application templates.
What I'm imagining is a 'simple' login-system like Skype, Facebook, NetFlix, really any app that you are able to log in to, which also has a website to log in to.
A part of my question is towards the security of the process. My initial thought is that a password in clean text should never be sent over internet, which makes me believe that the passwords should be hashed/encrypted on the phone, as well on the website, when logging in. I've done some small-time hashing/encrypting before, but just by using sha1 and md5 to "convert" the text. What's the proper way to do this? With my current knowledge, I assume that if I'm using md5 to encrypt a password, anyone could decrypt it with md5 too, but that I could use a SALT(?) or some form for altering key. Is that how the "big boys" are doing it, or is there a secret passage I don't know of?
Now onto the real question.. How should I store a login securely?
What I've tried: When making a "test-project" in Xcode for this, I simply created a class User with a field for username. When "logging in" by entering a username and password, I simply sent a POST-method HTTP-request to my .php-page, which simply performed a SELECT * FROM User WHERE Username = '$_POST['username']' AND Password = '$_POST['password']'; If the database returned one row, then the password was correct, and the page could print out the user in JSON or whatever. When the device got the successful login, I converted the user-object in the app, now containing the username (and potentially UserID, E-mail, Address etc.) to NSData*, and using NSKeyedArchiver and NSKeyedUnarchiver to save and load the user, never to authenticate again. If the user clicks "Log out", I wipe this 'archive'. This works, but I sense that it's not a particularly secure way of doing it. If so, why exactly is that?
(Our back-end is currently Google's App Engine(java), which has support for OAuth. Some are recommending this, but we can't find any proper documentation that makes sense for our plan with custom users)
Password Transmission
The easy way to secure this is to just send passwords over SSL. If you set up an SSL certificate and do all your authentication over https, all the back-and-forth communication is encrypted by the transport layer. Note - md5 is not an encryption algorithm, it's a weak hashing algorithm - don't use it for security.
Storing Logins
Your passwords should be stored in the database as a salted hash (random salt, with a collision-resistant hash function such as SHA256). Don't store the plaintext version of the password anywhere. If you're using PHP on the server side, you can use the new password_hash() function or crypt() to generate and compare your salted hashes.
If you're communicating securely over SSL, you should be able to just use the session capabilities of your web server to keep track of logins (e.g., $_SESSION['user_id'] = ...).
If you want to securely store your username/email/address, or anything else for that matter, the built-in keychain is the only Apple-happy way to go.
Have a look at SSKeychain (or PDKeychain or UICKeychain) and extend it to include each property you'd like to store. Generally it's used to store username and password combinations, but can be extended to store arbitrary data safely.
As for passing secure data to your server, do it over HTTPS.
I can provide examples if you'd like.
Another option is to add some sort of OAuth or XAuth login process.
That way, you are not storing any passwords, but only so called "Tokens". The tokens expire, and can be revoked.
Not storing the username and password at all is the best way to secure them.
Alex
I have an iPhone App communicating with a web server. When starting the App the user must authenticate with a user name and password.
The communication between the App and the web server is secured (HTTPS) but I don't want to send to the web server the clear password, I would like to send just the "signature" of the password (the signature will be stored in the database on the web server).
What is the best solution to create this "signature" on IOS? Should I use MD5 or something else?
Do I need to get an external library to build this signature or can it be done using SecKeyEncrypt from IOS SDK?
In the long term I will have an App running on Android and I must be able to generate the same signature for IOS and Android.
Thanks for your help,
Sébastien.
Transmitting the password in clear text is bad, so doing anything is a good first step. If you're going to make the effort, it is worth knowing how to do it right.
While MD5 is not a strong hashing algorithm anymore, choosing between MD5 and SHA256 (or even SHA512) is less important than how you use it. Let's ignore the specifics of the hashing algorithm and look at how it can be used first.
The idea of using a hash is that the hash of a string is always the same and is a one-way operation. By capturing the string, it is not supposed to be possible (or practical) to determine the password. That has become untrue in recent years with the mass use of rainbow tables. A rainbow table contains every possible password (up to a given length) and their hash, so that the attacker can use a reverse lookup to discover the password. Rainbow tables are readily available for all hash algorithms for passwords under 16 characters.
There are a few common solutions to this problem. One is to perform the hash many (around 1,000) times. The exact number of times must be known and predetermined by both the client and server so they can do it the same. This has the advantage and disadvantage of making hash generation expensive. It becomes computationally more difficult for an attacker to brute force, but rainbow tables are still useful if they are expanded to be large enough.
A better, but less common, solution is to add a known random string (commonly referred to as a Salt) to the password to make it long (maybe 64 characters). This salt must be known by both client and server in advance. This solution is cheap and easy, and it doesn't even matter if the salt is leaked out.
There is another common problem with password hashing. If a malicious user knows the hash of a user's password, that is as good as knowing the password itself for a poorly designed system. Let's assume we have an RPC function that requires a username and password hash. A malicious user that knows the password hash can submit it, even without knowing the password, and get access into the system. This known password hash will continue to work until the user changes their password, which could be months or years. What is needed is a way to limit the duration that the password hash is useful. That is achieved by using a dynamic salt.
The authentication then becomes a multi-step process.
The client connects to the server and presents some sort of client (or device) identifier, such as a UUID.
The server then generates a dynamic salt for that client identifier. The dynamic salt is only good for a short period of time (generally minutes to hours).
The server stores the dynamic salt, its expiration, and the associated client identifier in a database table for future use.
The server returns the dynamic salt back to the client, along with its expiration.
The client hashes the password, using either of the two mechanisms above, concatenates the dynamic salt, hashes again, and then attempts to authenticate by using username, client identifier, and dynamically-salted hash.
The server validates the submitted credentials by checking the users known password hash against the submitted value trying to concatenate and hash each known dynamic salt for that client identifier. If a match is found, authentication is accepted.
This is (roughly) the mechanism that is used by MySQL. It is secure enough that it can be used without SSL safely, but I would always recommend using SSL so that the rest of the payload is protected.
If you use secure mechanisms like this, it doesn't matter much if you use MD5 or a SHA variant. That said, it wouldn't make sense for any new development to not use SHA256, unless there was a very good reason MD5 was necessary.
md5 is not the best idea - there are lots of really fast rainbow tables nowdays to decrypt them.
I would suggest using AES256 - on iOS you have NSData+CommonCrypto which allows you to easily do that.
NSString* encryptionPass = #"myEncryptionPass";
NSData* passData = [userPassword dataUsingEncoding:NSStringEncodingConversionAllowLossy];
NSError* error = nil;
NSData* encryptedPassData = [passData AES256EncryptedDataUsingKey:encryptionPass error:&error];
if(!error)
{
NSString* encryptedString = [[NSString alloc] initWithData:encryptedPassData encoding:NSUTF8StringEncoding]
}
Got a bit of an issue where I am required to maintain a secure connection with one server that proxies out requests to another, over basic authentication. However I can't be allowed to gain access to the password for the users who want to access the other server. Can anyone suggest a way to store the password (having been given it once) securely in say the session variable, encrypted by a key that only the client holds until the point when it's needed?
After a time it can expire, ie, you could give the username and password and half an hour would be an acceptable time to keep the credentials in case the user wanted to access the site again.
I've rewritten this a few times after producing pure waffle, sincerely sorry if the editing didn't make much difference.
If your server is going to be handling the password in plaintext (to talk to the other server with Basic auth), you're going to gain access to the password. Perhaps you want to avoid storing the password in plaintext?
Send the password in plain text to the server, which then encrypts it, stores the encrypted version and adds a cookie to the client with the key. Then any future requests provide the key to the server.
If you're looking for an encryption library, Recommended two-way encryption gems for Ruby?
I want to create a multi-user application, but I don't know how to save and read encrypted passwords.
procedure SavePass(Password: WideString);
var
Pass: TIniFile;
begin
Pass := TIniFile.Create(ChangeFileExt(Application.ExeName, '.PASS'));
Pass.WriteString('Users', 'USERNAME', Password);
Pass.Free;
The passwords must be stored on the computer.
This works but it's stupid to save passwords using this.
Hashing passwords would be also good.
If the connecting software accepts hashed passwords, it's not going to stop people who steal the hashed passwords from connecting. All it will do is hide what the real password is.
Furthermore, if the software that you're connecting to does not accept hashed passwords (database, website, ...), you're going to have to store your password in such a way that you can get it back to its original state. A hashed version is not going to help you there.
If you want to scramble your storage so that humans cannot read the file, you could use Windows.EncryptFile() and Windows.DecryptFile(). In newer Delphi's that's neatly wrapped into IoUtils.TFile.Encrypt() and IoUtils.TFile.Decrypt.
If you really want to stop others from reading the cleartext version of your password, you're going to have to use some encryption with a key. Where do you store that key then?That would defeat the whole purpose of storing a password in the first place. It's better to prevent access by other users by using user privileges to the file system for example, because anything you or your software can do, a "hacker" can do if he has the same privileges.
My suggestion is to not use passwords in your application at all, unless you really need to. The user experience of having yet another password to enter & remember is usually not needed.
What I do for my applications is default to using the domain and user name of the current user as the identification. The user has already logged on with a password, or more secure system if they want it. Only by logging on can they be that current user. My server then accepts that as their identification.
Variations on this include optionally passing the machine name too, so that the same user is treated differently on different computers (when they need to use more than once computer at once). And of course you can still allow a normal password if you want to.
You should store hashed passwords. For example you could use one of the SHA algorithms from the Delphi Cryptography Package. When you check passwords hash the password that the user supplies and compare against that saved in the file.
Have you considered using Windows security rather than attempting to roll your own?
As an aside, you are liable to encounter problems writing to your program directory if your program resides under the program files directory and UAC is in use.
There are hash and encryption routines in Lockbox. You should hash the password concatenated with a random 'salt' and store the salt and hash together. To make it harder for people to brute-force the hash - trying all likely passwords until the right one is found - you should iterate the hash. When the user subsequently enters their password to login take the salt from your store and hash it with their entered password, and iterate, and test the result against the hash you have stored. If they are the same they have given the correct password.
As long as you can, don't store password, but hash them properly (use a salt, repeat hash n times, etc.) because rainbow table attacks are feasible and work well against poor chosen passwords and too simple hashing.
If possible, take advantage of "integrated security". Use Windows authentication to avoid storing passwords.
If you really need to store a master password or the like, use Windows APIs like CryptProtectData to protect them locally.
I think its best to keep user-specific settings in the Registry under HKEY_CURRENT_USER. That will keep their settings all together and separate from other users' settings.
You'll automatically read the correct user's settings when you read from this area of the Registry, and you should store your password there as well. Yes, do encrypt it as David recommends. The Registry is easy for anyone to read using RegEdit.
Here's an article on how you can write to and read from the registry.