Home | Work | Play | Photos | Contact | About
8/15/2013
Home > Work > Interact \ Security
When I started work on Interact I thought I'd just need to encrypt a couple of fields in a database. Thinking it through a little more that started to seem naïve. Actually building it and getting the security protocols right turned out to be harder than expected.
My objective is to mitigate primarily two threats - information disclosure, and denial of service. Consequently, these are the security design goals I set out:
SSL/TLS is showing it's age[1], so I want Interact to use application-level transport encryption that mitigates the risk of information disclosure through known or unknown vulnerabilities in SSL. Here's a trivialised example of how not relying on SSL might work:
A → S: KA(PUB) S → A: KS(PUB) A → S: {KAS}KS(PUB), {M}KAS S → A: {KSA}KA(PUB), {R}KSA
All of that works independently of how user data is encrypted, but more on that below.
[Edit, April 2014] When I first wrote this section I felt a bit stupid, thinking I was overdoing it. Heartbleed (ref. below) has just been discovered.Now that we have secure comms, we can look at user registration and login. Registration (shown below) is as you'd expect. The user provides the minimum amount of information required - a user name and a password. As per standard practice, the password is entered twice to confirm correctness. The user can choose any name, as long as it's unique. The maximum number of characters allowed for both user names and passwords is 500.
Windows Desktop | Windows Phone | |
User registration requires a working network connection to at least one server, because of the unique user name constraint. If Interact is unable to connect to a server, it will not proceed.
Login is similarly straight forward. Interact remembers the last user name that was used to register or login with, and prompts the user for a password. If a working network connection exists, the user account will be verified remotely, and authenticated locally. If there are no comms account verification is skipped, and authentication proceeds on the client, as before.
Windows Desktop | Windows Phone | |
Interact was designed to withstand the loss of a sync server. Availability is important, and eventual consistency is good enough. Consequenctly, if one server goes offline another should pick up the load. For this to work, servers are distributed, sync content to each other, and clients know about all currently-avaialable sync servers. Additional server endpoints can be added on the client. Because accessing a server in one location might be quicker than another, the user might select a preferred (or default) server if he or she so choses. The Windows Phone UI looks like this:
The user taps the server icon on the registration/login pop-up's application bar, and the UI changes by including a drop-down list of avaialble servers. The default item in the list is either the first server, or the server designated as the default server by the user.
If the user wants to change the default server, manually add a new server, or modify an existing one, he or she taps the icon next to the drop-down list, from where these changes can be made:
The corresponding Windows desktop client screenshots look like this:
Select a server
Modify an existing server
Interact is designed to mitigate the risk of information disclosure. This is achieved by generating a strong symmetric password on the client, which is not known to the server, and is used to encrypt all data stored in Interact on the client and the server. Encrypted data that is uploaded to sync servers cannot be decrypted by the server because servers don't have access to keys.
Client-side, data-level encryption allows sync-servers to operate as zero-knowledge service providers, offering a higher degree of privacy. Client-side encryption also mitigates some of the vulnerabilities in web-based password managers like LastPass and PasswordBox [2].
In conclusion then, data at rest is protected using client-side encryption. Data in transit benefits both from the application-level encryption scheme described above, as well as SSL/TLS.
Getting the application-level protocol right, and making it work with authentication and data-level encryption took a long time (there's more that I didn't cover in this post, like timestamps and signing). Another thing I learnt was that just sending bytes to the server (encoded as TLV) made things a lot easier than using JSON[3] - I got to a point where encoding and decoding messages just needed to get out of the way. The solution I have will do for now, but I've spotted areas where I can make improvements. Making this work was fun.
JSON is easy to use, whether you're using your own, or a third-party library that does the work for you. A substantial part of Interact is about security, so I don't use third-party libaries I haven't had a close look at. I don't have my own JSON library, and I haven't the time (interest) to look at existing ones, because: TLV is a lot easier to implement than JSON, and TLV doesn't duplicate metadata for each and every data entity. TLV has other benefits too, which I describe here.
< Back to Work | ^ Back to top
All content copyright © Michael Wittenburg 1995 to 2024. All rights reserved.
Merch (t-shirts designed by my twin)