encryptionhttprequest

How to protect against users submitting unencrypted data to a zero-access encryption system?


I am building a "drive" webapp with SvelteKit. To future-proof my project I also built an API for my app so I can later create a mobile version without having to rewrite all server-sided logic.

I wanted my app to be privacy-friendly so I have decided to implement a zero-access encryption system. That being said, it was clear to me I would have to implement client-side only encryption and only send encrypted data to the server to achieve true zero-access encryption.

I was successful in implementing that sort of a system using a symmetric key for encryption/decryption on the client. However, after implementing and writing all the code I realized my system has a serious flaw... There is no mechanism in place to check if the data sent to the server is indeed encrypted! In other words, although my client code truly encrypts the data before sending it to the server via an API call, there is nothing stopping some user from just creating their own request (API call) with unencrypted data. What I am trying to say is, the server has no way of knowing if the data it recieved is encrypted or not...

Putting some time into research made me contemplate if there even was a solution for this problem. I looked into asymmetric encryption, HMACs, encrypted data detectors (entropy calculators), ... Basically I think there is no way to actually achieve what I want, but regardless I am putting up this post as a last resort.

Conditions for the solution:

My concerns with the server recieving plaintext (unencrypted) data in a POST request are that after the server processes that data it will possibly, write files, create directories or rename files/folders with the given data, which is of course expected behaviour of an API endpoint. However, given the fact my goal is a zero-access encryption system, it is a serious privacy breach if the server is capable of storing and in general working with plaintext data.


Solution

  • I'm not aware of a general solution for this. Your research into entropy detection and measurement seems most relevant.

    A strong algorithm will not have any statistical measures that are distinguishable from randomness. Thus, you will be able to reject uploads with low entropy, but unencrypted uploads with high entropy, such as compressed data, cannot be rejected reliably.

    I think that such a measure, in combination with file structure and metadata, is sufficient to prevent accidental misuse of your API. If a user willfully circumvents those precautions to compromise the privacy of their own data, that's their problem.

    By file structure and metadata, I mean that you should not store raw ciphertext, but that it should be accompanied by metadata in something like CMS (or JWE) format that records the algorithm, parameters, and key identifiers. You can treat this sort of like a "magic number" to detect whether the client is uploading a valid encrypted envelope, and further check to see if the chosen algorithm and parameters provide sufficient security. Finally, if the ciphertext body of this package appears random, you've done all you can.