1

I got to thinking this morning over my coffee, that it would be nice if I could encrypt data for a Tenant with one key, and decrypt it with another key. In such a way that only a logged in User can access data in his organization (Tenant). I, as the system administrator, cannot access it. That's public key encryption so far. The public key can be used by the system to encrypt data and the private key is the decrypt key, similar to TLS. The decrypt key could itself be encrypted and stored in the users table using the plaintext passwords of each Tenant User, which is not stored. Thus the decrypt key can only be obtained when a Tenant User logs in to the system with the plaintext password. This way not even the system administrator can access the data when no Tenant User is logged in.

Encrypting the same plaintext with multiple keys doesn't make them materially more vulnerable, so it's ok to have multiple encrypted copies of the private key like this.

A tricky part is encrypting the decrypt key with the users password when they create an account. Another user would need to login and create an invite link first, which would contain the decrypt key encrypted with a system key. That seems ok, since that's a common flow for adding a user to an organization anyway.

Another tricky part is resetting the user's password. They'd need access to their email plus an invite link created by another logged in user (or the original invite link.)

This seems to me like it could work. If you lose all passwords, the data is unrecoverable, but that's how it should be.

It seems like it would reduce a lot of surface area to attacks because decrypt keys only exist in plaintext when a user is logged in. In fact, if you send the password with every user request, instead of having a separate login and session, the decrypt key is only in plaintext for the duration of a request, which is the minimum possible. An attacker would need to compromise the system and wait for a request to snag the key and be able to decrypt the data. System administrators wouldn't have access to user's data unless they also compromised the system in some way. On the other hand, if you can't trust your system admins, you're screwed. But this would protect against casual access to user's data - which is still valuable and it means attackers would need to gain access to both the persisted data and the transient in-memory decrypt key.

Would this work like I'm describing? Does it improve security? Is there a flaw here I'm not seeing?

1
  • 1
    What you are describing seems very similar to what ProtonMail does, where a single password is used to authenticate the user with the system, and to decrypt the user's private key. The user's private key is used to decrypt messages that were encrypted using the user's public key, and the server never sees the user's plaintext messages or unencrypted private key. See proton.me/blog/encrypted-email-authentication for more info.
    – mti2935
    Oct 26, 2022 at 21:43

3 Answers 3

2

Not sure the issue with this will be the crypto. All of that seems fine.

  • Transporting the password for a user in plaintext over the internet feels weird. But there's no reason a hashed password couldn't be used as the key instead.

  • Depending on the type of asymmetric key used, storing an encrypted copy for each user might get a bit heavy (RSA-4096 for example). Not massively heavy, Walmart with 2.2Mil employees would be 8.8gig of duplicated encrypted key data but still.

  • Key rotation (of encryption/decryption key if it is ever exposed) would require every user to log in and update their encrypted store of the key. By the sound of it, this would require an invitation from a user which was part of the key rotation. That email would probably be pretty confusing to the uninitiated.

  • Not sure how much this really gains. The key instead could be stored in a KMS/HSM where it can never be seen again (compared to in-memory) and requests for decryption only asked for after the user has been verified as part of the tenant.

4
  • Those are some fair points. I think this is more secure than storing the private key in a KMS because a hacker cannot simply make a request to the KMS for the decryption key (remember if he has access to your user's data, he probably has your KMS credentials), if the user isn't logged in, the key is unavailable. That raises the bar quite a bit. It also means your own employees can't access the data. With a KMS, they can just use the credentials to get the key.
    – Eloff
    Oct 26, 2022 at 21:16
  • Also my experience is passwords are usually transmitted as plaintext, but over a TLS connection. Doing that without TLS is really a terrible idea.
    – Eloff
    Oct 26, 2022 at 21:17
  • 1
    I'm not a webdev, so that's surprising. With the prevalence of corporate/school wifi that mandates broken TLS, there's room for abuse at the admin level of the network without protecting the password in transit. The hash does effectively become the password for that site but it doesn't expose a password which may (unfortunately) be common between sites for that user.
    – foreverska
    Oct 26, 2022 at 21:31
  • I agree with you, I think in this day and age of broken without JavaScript, plus builtin high-performance cryto in the browser, there's no excuse for sending plaintext passwords. That's vulnerable to weakened TLS, it's vulnerable to logging, debuggers, etc on the server. Heck if the memory page the password is in gets swapped out, you just wrote a plaintext password to disk with a helpful label like password=xxxx, where it may live for a very long time (SSDs don't like to overwrite things.) Plus you can do more rounds of hashing if you do it on the client instead of the server.
    – Eloff
    Oct 27, 2022 at 12:20
1

First of all asymetric encryption is rather expensive. For that reason, the common usage for large data encryption is to use symetric encryption with a random key, and only encrypt that key using asymetric encryption. This pattern allows to easily encrypt a bunch of data once for a number of symetric key pairs: only the symetric key has to be encrypted with all the public keys. You can even have a physicaly unique private key (for example a key on a smartcard) stored in a physical safe and used as a last resort decryption tool if data availability is a concern. As we are back in the physical world, it is easier to have a system requiring 2 physical keys, owned by different persons to make sure that no single human being will ever be able to have an unnoticed access to the smartcard.

The rest of your proposal still stands, with the exact same problem of trust that you showed at the end of your post, neither more nor less.

1
  • That's a great point, also it seems like it wouldn't detract from the security to use symmetric encryption with an encrypted key.
    – Eloff
    Oct 27, 2022 at 12:25
1

There are a few technical issues with the cryptographic approach you've mentioned, but the biggest issue with this solution is the threat model and the assumptions you have made about trust.

If your sysadmins are untrusted, then the server is inherently untrusted. If the server is untrusted, you cannot assume that your server-side code will remain intact and unmodified. Your system requires sending the user's plaintext password (or some derivative that is used to encrypt the information) to the server. As such, a malicious sysadmin can manipulate the server to dump the passwords and/or the plaintext data being stored when any user logs in.

If the server is untrusted, you must encrypt (and authenticate) the data client-side, using a passphrase (or key, or some other secret provider) that the server does not know. This is, however, not typically feasible if the application is a web page doing the cryptographic operations in JS. In such a context, the JS must be trusted to not transmit the plaintext data or key to the server, but the JS is provided by the server and therefore cannot be trusted.

You might choose to publish an application (desktop, mobile app, etc.) for doing the client-side encryption. But, if you don't trust your sysadmins, how can you trust your source control and build infrastructure, or the application installer files that you publish? Do you arbitrarily choose to trust the developers despite not trusting the sysadmins? If a developer moves to the sysadmin department, are they suddenly untrusted? What rationale could possibly justify this? It's impossible to reconcile.

An organisational security culture where the people with the keys to the kingdom are deemed untrustworthy is untenable. It is reasonable to implement checks and balances to provide oversight and reduce the risk of mistakes and insider threats, but you must lend a high degree of trust to your staff by default.

There are situations in which you might want to deploy client-side encryption to protect user data, but these are typically based on data theft scenarios where a threat actor breaks in and steals all of the server-side data.

4
  • The point is not to make something secure from system admins, it's to raise the bar for both employees and hackers alike. It's not that easy to grab the key out of memory on the server during a request. It goes from needing just access to the disk + key, to needing disk + memory + at the right time. That time requirement really raises the odds of detection and limits the scope of a potential breach.
    – Eloff
    Oct 28, 2022 at 17:41
  • 1
    I focused on the sysadmin insider threat because it was a risk that you mentioned repeatedly in your question. You're correct that E2EE modifies the temporal requirements of an attack. However, your assumption about needing additional access (e.g. to memory) is not the case; an attacker who is in a position to read the encrypted data files (in most cases this means interactive access to the server) can also trivially modify the server-side web application code/binaries to save every login credential to a file or send it to a third party server via a HTTP request. No memory dumping needed.
    – Polynomial
    Oct 28, 2022 at 17:53
  • 1
    If users interact with the system via a web page, the attacker doesn't necessarily need to modify the server-side code, either. They could modify a static resource such as a JavaScript library or HTML template file to inject malicious JS that sends login credentials, decrypted sensitive information, and/or session token information to a third party server over XHR. This kind of post-exploitation technique isn't uncommon, either. A common tactic for compromised web stores is for attackers to redirect the checkout flow to a cloned site for payment harvesting and PAN/PII collection.
    – Polynomial
    Oct 28, 2022 at 18:00
  • 1
    This is also why SRI exists for enforcing the integrity of static JS/CSS resources, particularly those hosted on third party CDNs. CSP can also frustrate client-side exfiltration if you've got a restrictive connect-src directive, as long as the attacker doesn't reconfigure the CSP headers being sent by the server. You can also specify content hashes in the CSP source value for script-src, style-src, etc. directives, to further enforce SRI. Having CSP headers (re)applied at a frontend load balancer (e.g. Cloudflare Workers / AWS Lambda) is a useful form of defence in depth here.
    – Polynomial
    Oct 28, 2022 at 18:13

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .