How to create a cryptographically secure authentication without requiring keyboard input? - security

I'm working on a system that will require a user to log in on a device using an account that they created on a website. Authentication will be over HTTPS, so that is not an issue. The application running on the device will allow in-app purchase using a credit card linked to their account, so it's important that the login credentials are secure enough that it would be difficult to attack using brute-force. The only problem is that the device that the user will be using will have limited user input capabilities (essentially, arrow keys and a selection button).
In this case, a typical username/password may be too cumbersome to enter, also requiring the development of a on-screen keyboard that is navigable via the arrow keys. Users would likely end up creating simple passwords that are easily cracked. However, once logged in, the user will be using an access token behind the scenes so they may not need to enter their password very many times.
The first step is that the user will need to enter their username or ID number. Using a number may be easier to enter, but also easier to guess. I'm open to suggestions in this area as well.
Next is the process of entering a "password". So here are a few ideas that I have, but I'm not a cryptography expert so I don't know how to gauge the level of security.
User must first register the device. This might be a step that I require anyway, for extra security. The device would generate a key that is sent to the server and stored with the account. The key would be required when performing future authentication requests. The user would need to log into the website to approve the device. The device isn't going to have any sort of identifier, so unless you log in soon you wouldn't know if it was your device or someone else trying to spoof you. It would be nice to be able to create some sort of additional identifier, maybe a short code, phrase, or an image is displayed so you can know it's the same device that you just tried to register.
Since entering a text password may be too difficult, as long as the device is registered, maybe a 4 digit passcode can be used when confirming in-app purchases. This may be nice anyway to prevent other users of the device from using your account without your permission. However, if they are watching you enter your passcode, then it's not really good for that purpose anymore.
If registering the device is not necessary, instead of logging in with a text password, maybe the user is presented with images or phrases as options and they must choose the right combination of images/phrases that matches their account.
That's all I've got so far. What are your thoughts? How can I create an easy, but secure, login when in-app purchases are involved?

I have been dealing with limited user input capability scenario. Would you describe the platform your app running on?It helps to fit the solution according to the platform security model.
Update: I hope you are not considering multi-user per device scenario. So, I am assuming that there is one user per device. The second assumption is the device may have a unique serial number that can be accessible through some APIs and the serial number is registered on the server in advance.
At the initial stage, the user generates a random key through the device select button and the app confirms the success of key generation probably it display the serial number (the user may need to register the serial number for latter configuration). Behind the scenes, the app sends the new key with its serial number to the server. The server updates its serial number with the random key in the database entry. The device can block further key generation or may allow until it is finally configured with a dedicated user. The device also persist the serial number with the random key in the local database/file. The user is then login to their account through a web interface to configure the device. For logged in user, the server presents a list of available devices and the user can choose a specific one that belongs to her/him and set four digit pin code. The server performs the following:
Link the user account, the serial number, the random key (the one the device sent at the beginning).
generate a token
generate a key using pin code and the random key as a salt through Password based key derivative algorithm (PBKDF2)
encrypt the token using the key derived at step 3
Update database user row with the cipher token.
The user can sync the cipher token through the device select button. To unlock the app, user must enter the pin code through a simple numeric screen. The app uses the pin code and a random key (persisted at the beginning) and generates a PBKDF2 key and decrypt the token. PBKDF2 helps us to slow down the brute force a bit but it is possible to enforce time based or attempt based lockout as well. For instance after some trail, the app can drop the user credentials and force the user to configure from the scratch.

Related

How to store passwords safely on a device?

I have a raspberry pi that needs to access a service using a username and password. What is the standard procedure to store the user credentials on the device.
I know that a user on a phone would enter the username and password in order to get a token which is valid for a certain period of time. This allows to !not! store the credentials locally.
However, my device (DVR) needs to run 24/7 and the user cannot regularly enter the password. So I somehow need to store the password on the device to login every once in a while or after a reboot.
I am concerned because the device is publicly accessible and someone could potentially take it, plug it into a computer and read the password from storage.
You have to think about what exact attacks you want to protect against. The TL;DR is you won't be able to protect it against everything that comes to mind.
One question is whether it's ok to enter some kind of a secret (a password) when the device boots up. You're saying it's running 24/7, so a reboot should probably not be very frequent. If your concern is somebody taking the Raspberry and reading the password from the disk (or card, in case of a Pi), you could try and keep it in memory only. Startup would need the password to be entered, but whoever takes the device (or the card) physically would not be able to learn the password. Of course this is not entirely secure, somebody could either read the password from memory without taking the Pi (you said they have physical access), or they could maintain power while taking it so that the password is kept in memory. But it would be much more secure than writing the password to the storage.
Another thing you can do is assign the device some kind of a token. If you think the token is compromised (somebody learnt it in any way), you can just change the token to a new one. But you still need a way to discover when credentials are stolen. But you would need this anyway.
You can monitor the device for physical tampering or theft. If it is tampered with or stolen, you can assume the credentials are compromised, and you can then issue new credentials to your service.
Also you're saying it runs 24/7, so I assume it has a fixed IP address. You can implement IP address restriction on the service that it connects to with the credentials, so even if credentials are compromised, an attacker is very limited in where he can connect from (but you mentioned a DVR, which typically uses UDP traffic, and it's much easier to forge source IP addresses over UDP than over TCP).
Probably needless to say, but obviously you should use unique credentials on this device that you use nowhere else and for no other puspose.
Note that you can pick several of these if you like to protect against different threats, or to build defense in depth. But you have to keep in mind that whatever you give to users (potential attackers) is lost and you can safely assume they have full control. However, the level of effort is different, and if you can make it hard or risky enough for an attacker, that's probably reasonably good in many situations.

TOTP : Changing secret upon every session

I have such requirement about changing the users secret for every session for generating OTP. We decided to use TOTP as our algorithm to do so. We are sending OTP in SMS to the user for authorization verification (no need to generate OTP at client side).
TOTP = HOTP(WhereSessionCalculate(SecretKey), TC)
So, Is it good practice to change the secret of an user session wise. If not then what are the consequence that can possibly arise. Please explain and let me know if more information needed.
The basic premise of two-factor (or multi-factor, to be more accurate) authentication is to supplement the normal username/password combination - these are things you know - with one or more additional factors of a different type. Most commonly used are what you have (e.g. your cellphone, with a Google Authenticator app or an RSA, Gemalto etc. token) or something about what you are (biometric data such as iris, fingerprint etc.)
Someone can learn a username and password from shoulder-surfing (easy if the password is short), even sniff it from an insecure network connection (hope you're using SSL with AES256 or somesuch to encrypt the sessions to your app!) but the addition of 2FA stops that.
So let me some back to your question and whether your approach is accretive to the security of authenticating your users . Once the user's OTP key is set and stored in the user's record in the database, and that key is used to seed the TOTP generator, what would having the user re-seed with a new key accomplish? Yes, generating a OTP code and sending by SMS verifies that the person logging on has their phone with them at that very moment, but then so would using Google Authenticator; moreover, and I betray my Apple fanboi bias here (!) incoming SMSes are displayed on the lock screen of my iPhone, which would also therefore display your OTP, whereas to access the Google Authenticator app I have to unlock my phone with my PIN.
Also bear in mind that most systems are compromised at a network or system level and whole databases of usernames and passwords stolen to be cracked - compromising a single user's access isn't generally worth the trouble, unless you have a very high value asset attracting the attention of state actors!
Having explored the issues here for my own app I've gone with a username and password initial login (minimum length 20 characters to perplex rainbow tables, but with no stipulation on complexity or frequent changing), maximum number of attempts before locking the account for an increasing amount of time for failed logins, and a secondary login using Google Authenticator (as it's free, runs on iOS, Android and BB10, and is pretty easy to use). To improve on this I would consider biometrics but my application is commercial not military etc. so what I have is quite enough for my assessment of the risk.
I hope that helps you work out the best approach for your application.

Two - Step authentication, how does it work?

So as part of a project, I want to implement a two step authentication system (in rails)
I understand the principles of it,
=> Client: Username and password
<= Server: Generate PIN code and send it to client via SMS/email
=> Client: enter PIN
<= Server: authenticate client as normal
Now what I want to know is in a web based application such as rails, the PIN needs to be kept secret at every point, so when redirecting from the username/password part to the PIN part, I need to keep the PIN code secret while passing it over to the next part of the system (the PIN part)
Is the only decent way to do this, by temporarily storing the PIN in the database alongside a user ID?
No, not quite that.
There are two (most used) types of one-time passwords (OTPs, PINs in your terminology):
Time-based
Counter-based
Time-based ones (TOTP) generate some number based on current time (for example: number of 30-second intervals from 1970.1.1 00:00) and some shared secret. When receiving such one-time password, server generates one on its side and checks whether it's correct.
In counter-based OTPs, you have a counter and a secret key stored in database near user ID, and it is used to generate the OTP. It can be incremented based on login attempt.
Time-based tokens are usually better, as they don't require counter synchronization (time synchronization is usually easier). Best example of this is the Google Authenticator, which implements standard TOTP from RFC6238.
There's one Ruby OTP library which claims compatibility with Google Authenicator, you may want to try it out: link
Can't vouch for its security and/or quality, but it looks promising.

Securing a login system without passwords

I'm developing a mobile application for a company. Everyone at the company has an #company.com email address. The app itself is confidential, so it will only be installed on employees' devices. This app communicates with an external server to store and retrieve data.
Ideally what I would like to accomplish is to let people log in to the app by just providing their email address, without a password. Here is my current thinking:
A new user opens the app for the first time on a certain device and puts in their email address. The email address is sent to the server, along with a static token embedded in the application (which is the same for all instances of the application).
The server verifies the token and the fact that the email address is #company.com. It responds with a new token/key for use only with that user and device, which the client stores in plain text locally. That key is effectively the user's password. It is hashed, stored in the server database, and marked as disabled.
There are two possibilities at this point:
The server sends an email to that address confirming that they want to log in on a new device. The email contains a link which, when clicked, marks the key as enabled. There would need to be rate-limiting on new device requests so people can't get spammed if someone discovers the token embedded in the app.
An administrator specifically approves new device requests.
Every subsequent client request to the server must include the key.
Assuming all communication is over SSL, does this sound like a secure strategy? Is there a more secure or simpler approach?
Additionally, what is the best way to generate the token that will be stored client-side? Since I want users to only put in their email address the first time they use the app, I believe that this token will never change. Here is my current algorithm (PHP) loosely based on Drupal's drupal_get_token():
// Usage: get_token($email) or get_token($client_token)
function get_token($value = '') {
$salt = hash('sha256', 'Some static, predefined phrase');
$hmac = base64_encode(hash_hmac('sha256', $email, $salt, TRUE));
return $hmac;
}
As you can see it doesn't protect against parallel attacks (e.g. if someone figured out the predefined phrase and algorithm and they had access to the database, they could generate hashes and compare them against the ones stored in the database) but because the original key value is already long I don't think this would be nearly as effective as it would be against normal passwords. Additionally I am not sure of a way to create a dynamic salt that an attacker would not already have access to if they could access the database (or honestly if it would even matter at that point, since getting access to the database would expose the data we're trying to keep confidential anyway).
After some research and more thought, I believe that the answer to this question comes down to the vulnerability of the local storage. Since it's safe to assume in this case that only company employees will be using the app, there is insignificant risk of malicious code running in it even if there was a problem in the code that would make that possible. As a result the main risk is from some other app taking advantage of a security hole in the OS's local storage implementation to read the local private key off the disk. Since the existence of the app should not be known to anyone outside the company, it is very unlikely that this information would be directly targeted. So I think this is an acceptable process for this company.
In the general case though, anyone considering implementing a similar model should be aware of the risks of basically storing a password in plain text locally. (This is as opposed to storing a password in the user's head, or equally likely in plain text in a password file elsewhere on their machine; it's your call which is more secure.)

How can you encrypt users' data server-side without ruining the experience?

Many users – myself included – would like the security of having everything they do on a web service encrypted. That is, they don't won't any one at the web service to be able to look at their: posts, info, tasks, etc...
This is also major complaint in this discussion of an otherwise cool service: http://news.ycombinator.com/item?id=1549115
Since this data needs to be recoverable, some sort of two-way encryption is required. But unless you're prompting the user for the encryption key on every request, this key will need to be stored on the server, and the point of encrypting the data is basically lost.
What is a way to securely encrypt user data without degrading the user experience (asking for some key on every request)?
-- UPDATE --
From #Borealid's answer, I've focused on two possibilities: challenge-response protocols, where no data (password included) is sent in the "clear", and non-challenge-response protocols, where data (password included) is sent in the "clear" (although over HTTPS).
Challenge-response protocols (specifically SRP: http://srp.stanford.edu/)
It seems that its implementation would need to rely on either a fully AJAX site or using web storage. This is so the browser can persist the challenge-response data during encryption and also the encryption key between different "pages". (I'm assuming after authentication is completed I would send them back the encrypted encryption key, which they would decrypt client-side to obtain the real encryption key.)
The problem is that I'm either:
fully AJAX, which I don't like because I love urls and don't won't a user to live exclusively on a single url, or
I have to store data encryption keys in web storage, which based on http://dev.w3.org/html5/webstorage/ will persist even after the browser is closed and could be a security vulnerability
In addition, as SRP takes more than one request ( http://srp.stanford.edu/design.html ), there needs to be some persistence on the server-side. This is just another difficulty.
Traditionally
If I'm ok transmitting passwords and data in the clear (although over HTTPS), then the client-side issues above are not present.
On registration, I'll generate a random unique encryption key for the user, and encrypt it using their password and a random salt.
In the database, I'll store the user's password hash and salt (through bcrypt), encrypted encryption key, encryption key salt, and encryption iv.
After an authentication, I'll also need to use their password to decrypt the encryption key so that they may view and enter new data. I store this encryption key only temporarily and delete it when they explicitly "log out".
The problems with this approach is that (like #Borealid points out) evil sysadmins can still look at your data when you are logged in.
I'm also not sure how to store the encryption keys when users are logged in. If they are in the same data store, a stolen database would reveal all data of those who were logged in at the time of theft.
Is there a better in-memory data store for storing these encryption keys (and challenge data during an SRP authentication)? Is this something Redis would be good for?
If the data need to be recoverable in the event of user error, you can't use something like a cookie (which could get deleted). And as you point out, server-side keys don't actually secure the user against malicious sysadmins; they only help with things like databases stolen offline.
However, if you're running a normal web service, you've already gotten pretty lucky - the user, in order to be unique and non-ephemeral, must be logged in. This means they go through some authentication step which proves their identity. In order to prove their identity, most web sites use a passed credential (a password).
So long as you don't use a challenge-response authentication protocol, which most web sites don't, you can use an encryption key derived from a combination of a server-side secret and the user's password. Store the encryption key only while the user is authenticated.
If you do this, the users are still vulnerable to sysadmins peeking while they're using the service (or stealing their passwords). You might want to go a step further. To go one up, don't send the password to the server at all. Instead, use a challenge-response protocol for authentication to your website, and encrypt the data with a derivative of the user's password via JavaScript before uploading anything.
This is foolproof security: if you try to steal the user's password, the user can see what you're doing because the code for the theft is right there in the page you sent them. Your web service never touches their data unencrypted. This is also no hindrance to the normal user experience. The user just enters their password to log in, as per normal.
This method is what is used by Lacie's storage cloud service. It's very well done.
Note: when I say "use foo to encrypt", I really mean "use foo to encrypt a secure symmetric key which is then used with a random salt to encrypt". Know your cryptography. I'm only talking about the secret, not the methodology.
None of those other solutions are going to maintain the feature set requested -- which specifically wants to preserve the user experience. If you look at the site referenced in the link, they email you a nightly past journal entry. You're not going to get that with JavaScript trickery per above because you don't have the browser to depend on. So basically this is all leading you down a path to a degraded user experience.
What you would want, or more precisely the best solution you're going to find in this space, is not so much what wuala does per above, but rather something like hush.com. The handling of user data needs to be done on the client side at all times -- this is generally accomplished via full client-side Java (like the Facebook photo uploader, etc), but HTML/JavaScript might get you there these days. JavaScript encryption is pretty poor, so you may be better off ignoring it.
OK, so now you've got client-side Java running a Journal entry encryption service. The next feature was to email past journal entries to users every night. Well, you're not going to get that in an unencrypted email obviously. This is where you're going to need to change the user experience one way or the other. The simplest solution is not to email the entry and instead to provide for instance a journal entry browser in the Java app that reminds them of some old entry once they get to the website based on a link in the daily email. A much more complex solution would be to use JavaScript encryption to decrypt the entry as an attachment inline in the email. This isn't rocket science but there is a fairly huge amount of trickery involved. This is the general path used by several web email encryption services such as IronPort. You can get a demo email by going to http://www.ironport.com/securedemo/.
As much as I'd love to see a properly encrypted version of all this, my final comment would be that journal entries are not state secrets. Given a solid privacy policy and good site security semantics, I'm sure 99% of your users will feel just fine about things. Doing all this right with true security will take an enormous amount of effort per above and at least some design/UE changes.
You should look into the MIT project CryptDB which supports querying an encrypted database using a subset of SQL. (see the forbes article, mefi thread, or Homomorphic encryption on wikipedia)
There is the Tahoe-LAFS project for cloud storage too, which conceivably could be leveraged into a fully anonymous social networking application, one day in the distant future.
If you want to perform computations on a server without even the server being able to see the data, you may be interested in knowing about fully homomorphic encryption. A fully homomorphic encryption scheme lets you perform arbitrary computations on encrypted data, even if you can't decrypt it. However, this is still a topic of research.
For now, I guess your best bet would be to encrypt all posts and assign meaningless (e.g. sequential) IDs to each one. For a more in-depth discussion of how to encrypt server-side data with today's technology, look up.

Resources