Open onlykey opened 4 years ago
Interesting idea! I have not thought about this before, but this indeed feels like a natural extension to the Webcrypt, to have the whole communication encrypted including web pages and their data. While not the current aim of the project, it might be worth to think about this in the subsequent releases. I wonder whether on desktop this could not be realized already with PKCS#11 modules available via the browser, but otherwise your proposition would be more 'plug-and-play' (no need to install anything on the system), and available to mobile devices as well. I do not see any flaws in your solution at the moment. Regarding caveats and the domain, I am the opinion that data migration to a new domain name should be responsibility of the service.
So currently the outlined webcrypt approach is to have a way for users to do things like decrypt and sign with a security key in web apps. They basically provide user physical presence to authorize decrypting/signing something. I wanted to share something I have been working on to get some feedback and also it may be worth considering integrating here.
Overview:
So in contrast to the traditional approach above, I am going to describe something different and new, lets call it private web. The use case is lets say you want to create a website where every page is encrypted and rather than just have authentication to the website, have physical security keys (FIDO2 used) that are required to decrypt the website. The website/webapp has all important data encrypted so you could host it where its publicly readable, like github pages. Users accessing it would have to have a security key to decrypt and view the web page, web page could have multiple users such as a social media site.
How it would work:
With OnlyKey we do a single FIDO2 message first to set up transport encryption, a similar thing is being discussed here - https://github.com/Nitrokey/nitrokey-webcrypt/issues/13 This message does not require physical user presence so its transparent to the user and some basic information is exchanged including public keys to establish a shared secret between the web app and the security key. With this initial message we could also add a new feature where in addition to exchanging info for transport security we also have the security key send a derived private key that could be used to decrypt data on a web app.
So decrypting an encrypted web page/app would work like this:
From web app to security key -
<transport public key> <input public key> <RPID (unique per origin)> <Optional key derivation data>
On receiving, security key does this:
Security key uses <transport public key> to create a shared secret and encrypts all future data in transport.
Security key uses <RPID (unique per origin)> , <Optional key derivation data>, and a stored private key to generate a derived key that is unique per domain. Meaning that if a user is phished, the derived key for phishing domain would be different. Call this derived key <derived private>, you could use this to generate <derived public>
.Security key uses <input public key> and <derived private> to create a <shared secret>
.From security key to web app -
All encrypted in transit - <shared secret> <derived public>
On the web app you could basically have a lookup table with known public keys that have access to the web app, and you would check if derived public is in the list. If it is there would be an encrypted blob corresponding with derived public. This blob would be decrypted with shared secret which would contain the decryption key for the web page which would then render the decrypted HTML/Javascript so the user can now view the encrypted page.
Benefits:
This approach would enable a transparent encrypted web, user experience would be if my security key is plugged in I can view these encrypted websites, if it's not I can't. I think this is the key differentiator, having no physical presence for these derived keys makes it possible. If you had to constantly press a security key to load every single page you view that would probably not work as its a bad user experience. Of course this provides a security tradeoff, that if a user's system gets malware that malware could launch a web browser to view the encrypted web pages. But at that point theres lots of other threat models anyway where if malware is on a users computer they could just trick a user into pressing their security key anyway, so the tradeoff here I think makes a sensible compromise. The threat model of phishing is pretty well handled by including the RPID in the key derivation. If my encrypted web app is example.com and a phishing link sends me to examplee.com the private key would not match even if the website was cloned.
EXAMPLE USE CASE 1
Alice goes to a privatesocialmedia.com and friend requests Bob. By doing this the web app sends a message to Alice’s security key and Alice’s derived public key for privatesocialmedia.com is returned to the web app. This public key is then sent over to Bob in the friend request.
“Alice on domain privatesocialmedia.com wants to be your friend, do you accept?”
If Bob accepts then the web app sends a message to his security key using Alice’s public key as . A shared secret is generated that will only be known to Alice and Bob. This shared secret is used as a key encryption key (KEK) in the web app to encrypt the master key (keyblob-alice) that encrypts Bob’s profile and Alice’s public key is added to a list of authorized users (alice-privatesocialmedia.com). The two variables alice-privatesocialmedia.com and keyblob-alice make up a record that is stored in the web app.
Alice now goes to view Bob’s profile which was not previously visible. The web app sends a message to Alice’s security key using Bob’s public key which is stored in his profile. Alice’s public key and shared secret is returned to the web app, the public key is used to lookup that alice is an authorized user (alice-privatesocialmedia.com) and that the shared secret may be used to decrypt (keyblob-alice). Now Alice can view the decrypted profile of Bob.
Caveats In this example Alice must access the site at privatesocialmedia.com domain, if the domain changes so does the key. In this example once Alice is able to decrypt the site, there is no way of stopping Alice from sharing this decrypted data with others if Alice is malicious, i.e. Screenshots, data dump, etc. However, there is really no way of stopping valid users from sharing decrypted data anyway.
EXAMPLE USE CASE 2
While EXAMPLE USE CASE 1 gives all friends of Bob complete access to his profile it may in some applications make sense to have certain friends/users with access to some things but not other things. This can be accomplished in the web app as each user has a unique keyblob. To do this the web application would have instead of a master key, a list of site area keys. Different pages or objects in a web app could be encrypted with different keys and each keyblob could contain multiple site area keys based on what a user has been granted access to.
Obviously the complexity of web encrypted web apps could scale and become quite complex. The idea here would be to create the a developer API where developers could build web apps to whatever complexity they want, the API would simply be used to return derived public keys and shared secrets from devices. Thoughts? @szszszsz @jans23