0

I hope this is the Right Place

I have implemented a full user encrypted data storage solution. This works well and I can sleep well in the knowledge that neither I nor anyone else except the user can access the data ( AES 265 encrypted should hold for a while). All thanks to you guys. Here is an honorable backlink to the used Algorithm: Store encrypted user data in database

Now to the problem. The customer no longer wants to manually pass the data into the storage and proposed that we integrate with two (my guess is the number will grow) external services that are trusted by the user and should, on behalf of the user, deliver additional data into our database.

How can this be realized without fully butcher the security existing in my current solution?

Currently, I have two ideas on how to resolve this situation:

IDEA 1: IDEA 1

  • Each User has an RSA key pair as well (The Private key is also encrypted like the Data Encryption Key).
  • The Service generates a new Data Encryption Key for each user and request pair and encrypts that with the Public RSA key
  • The encrypted password will be stored until the user logs in and then re-encrypted

This was the best solution I came up with so far. But not all users are regular and I am sure some will use the automation provided and use the service as a secure drop off place (which I do not mind) but I threaten the RSA security over time. Or maybe I am overengineering and the orange part is not necessary at all.

IDEA 2 IDEA 2

  • I switch my whole AES encryption to RSA with a very high bit rate 15'000+. And eat the performance loss

This seems like an easy but not very future proof solution. given the emergence of quantum computers

Any thoughts on my ideas and any help are greatly appreciated

EDIT I was asked to provide some more context. My customers store highly personalized data which makes user identification and tracking extremely easy and is valued by other companies for data mining. Since a data leak can result in personal damage as well as in some cases loss of face. I and my customers value a higher encryption standard to keep their data firmly in their control.

The Services are preidentified and then confirmed/trusted per user. They communicate over an https secured connection but with no further added security. They will push data to the secure storage and then drop the data or secure it internally. No user session /interaction is required. The data they provide is gaining value in conclusion with the rest of the data stored in my system or over a large period of time. But since I expect the number of integrated services will grow so will the worth of the data overall services -> that's why I am interested in fully restricting the access to the user.

Belliger
  • 1
  • 2
  • 1
    If quantum computers result in a compromise of RSA "soon", you (and the rest of the world) are going to have far larger problems than just field-level encryption - like the fact that the entire HTTPS session itself would be compromised. Otherwise, we don't know enough about your use case. For one thing, do these external services require an active session (ie, the user is already logged into your website, so the decrypted encryption key is already available)? Can you just wait to _retrieve_ data until they log in? Otherwise idea 1 seems reasonable. – Clockwork-Muse May 06 '20 at 16:39
  • Thanks for the feedback. I extended my initial post. You are correct about the RSA issue but since the data is stored for a long time and a theft of encrypted data can never completely be ruled out decrypting it after the fact is seen as a possible risk. The decryption encryption process is also done on the user end, therefore, I am not too concerned about the break of https and the encrypted data at the same time. – Belliger May 07 '20 at 06:48
  • Decrypting from a private key is not a likely threat, because (given current mathematics), a sufficient strength key would require more energy than in the solar system to "break". It would be **easier** to break the data protected by the password, because of user password issues. Decrypting on the user end relies on the security of the HTTPS session - if I break that, I can inject whatever code I want into a web session, including exfiltrating the data that the user just decrypted. – Clockwork-Muse May 07 '20 at 16:30

2 Answers2

1

I'm not even sure how your Idea #2 is supposed to work - you don't ever encrypt anything with private keys, and I'm not sure how your retrieval flow would decrypt the data if you did since you apparently would have used a different key depending on how the data was sourced - plus RSA makes an absolutely lousy bulk data cipher and there's literally no reason to ever attempt to use it as one.

Idea #1 is valid, though. It does have some "gotchas" but the basics of it are solid. Provide a public key (after authentication), data is encrypted (and gets a MAC / signature) using a random DEK and then the DEK is encrypted using the public key and stored along with the encrypted data. Retrieval requires using a password-derived key (PDK) to unwrap the private key, which then unwraps the DEK for that item and the DEK is used to decrypt the data. Elegant in theory, although there's some stuff you want to look out for (like, what if a user changes their password? Then the PDK changes, so you need to unwrap the private key with the old PDK and re-wrap it with the new one).


One thing that's not entirely clear from your description of the service is where the encryption and decryption is happening. For this sort of end-to-end, zero-trust encryption to work, you need the client to be the only one who can unwrap the DEKs, which means the server can never even receive the data necessary to derive the PDK. It also means the client must do 100% of the encrypting and decrypting, because the server neither ever sees the keys nor the data in plaintext.

In a system like that, you need a certain amount of complexity in your client; it's unavoidable. You can do this with a modern browser no problem - the modern JS crypto library is quite capable of all this, and there exist polyfills (of varying quality) for older browsers if you don't mind the performance cost of implementing crypto primitives in JS - but you can't do it in some external service that wants to push data to your system and the only parameters it accepts are "what credentials do I use and what URL do I send the POST request to?".

You'd need some sort of middleware that can take the data from the external service, authenticate to your service, and perform the crypto before pushing the encrypted data to your server. This is entirely possible but definitely increases complexity. It gets even worse if you need to be able to retrieve the data through such middleware; inputting data can be done without needing a PDK (since the PDK is only needed for the private key) so it doesn't need the real password and can instead use an API key or similar (sufficient to retrieve the user's public key, but no ability to unwrap the private key needed for the DEK). However, any client that wants to retrieve data needs to be able to unwrap the DEKs, which means it needs to unwrap the private key, which means it either needs to know the user's actual password (although it still never sends it to the server, otherwise the server can also unwrap the private key) or the private key needs to be wrapped (encrypted) using multiple client-specific keys (one is the usual PDK, another is based on some secret stored in the middleware or whatever) or else the client/middleware needs to store the private key long-term.

CBHacking
  • 42,359
  • 3
  • 76
  • 107
  • ... except doing this in JS means that the client still has to trust the service, because the code is being delivered from the service each time. From a user perspective, you have to trust the service the same amount as if the decryption was being performed server-side. Additionally, you have to trust that the service properly encrypted it in the first place. Further, exfiltrating the DEK this way increases the likelyhood of compromise, since now it's being handed to a (usually) less-protected environment. – Clockwork-Muse May 07 '20 at 16:28
  • @Clockwork-Muse Yeah, that's a weakness of host-based security. The user *can* audit the script in their browser, and even change it if they want to, but realistically that won't happen. However, JS isn't *just* served with web pages. Browser extensions use JS but are much harder to sneak malicious code onto one specific user's session, and of course you could use Node or similar (for your middleware) and then JS is mostly just another programming language. – CBHacking May 08 '20 at 09:26
  • ... none of that matters? What I was getting at is that doing this work client-side doesn't actually provide any greater guarantees to the user about the trustworthiness of the service. For the _vast_ majority of users, they're not going to be able to tell it's happening locally in the first place, and of those that are, most aren't going to be able vet the local process either (especially as an ongoing concern). The trust the user places in the remote service is essentially no different in either case. – Clockwork-Muse May 08 '20 at 16:03
  • A user being personally unable to verify the trustworthiness of the system doesn't make it less trustworthy. Holding the key material on the server, and ever exposing the plain text to the server, does. There's a *reason* all the major password managers (at least, the ones that provide sync servers) work this way... – CBHacking May 09 '20 at 05:19
0

@CBHacking had similar impressions I had (about both ideas) when I went over the question; the main concern should be at which point (where) of the process encryption is taking place? And determining whether middleware will be required (I might say yes, as I did not consider that clients are trusted parties to protect KEKs and DEKs by themselves). I consider that the time data not encrypted (when is encrypted for storage the first time or when the user access it) should represent another vector to consider in the scheme (how long?).

UndercoverDog
  • 616
  • 3
  • 17