5

I need to create a PHP Web application which stores some user entered data. These data should only be readable to some selective users of the system (including the user who created it).The data should not be decrypted by the server administrators or other backend managers. Only the end users should be able to decrypt data.

I do know that HTTPS/TLS will securely encrypt data between client and server but here my requirement is that only some selected end users should be able to read data. I am also aware that here browser is the end points in communication. So on research I came upon the concept of End to End encryption using private/public key pairs.So my question is whether it is possible to implement this in a Web application using PHP.

Anders
  • 65,052
  • 24
  • 180
  • 218
Kiran Muralee
  • 151
  • 1
  • 4

3 Answers3

7

You can certainly implement a system that uses end-to-end encryption and has the server portion written in PHP [1]. You'll just have to implement the crypto part as something that runs on the "ends" - that is, the browsers, so realistically you'll need to implement it in JavaScript - and your PHP code would serve this JS to the endpoints. The PHP code would also need to serve up the public keys [2] for everybody who is supposed to have access to the data being encrypted. Depending on how you're going to store the private keys, the PHP would probably store (and serve) a "wrapped" (that is, encrypted) version of those, too.

The server-side (PHP) portion of this whole project ends up being slightly more complicated than a typical web app. It needs to be able to authenticate users, which is normal, but without enabling the admins impersonate users (this is not normal) [3]. It probably needs to be able to store (and control access to) private-per-user data (the wrapped secret keys), per-user public data (the public keys), and restricted-access shared data (the actual encrypted user data). Depending on what sort of data is being stored, how much of it, whether you need to be able to adjust who has access to it after-the-fact, and whether it needs any kind of searchability, you may run into any of a host of additional complexities. Secure end-to-end systems are hard. [4]

The client-side (JS) portion of this thing is going to be where the heavy lifting occurs, crypto-wise, though. That's kind of awkward, because JS isn't great at crypto. There exist pure JS implementations of the standard crypto functions, but they tend to have problems (like being relatively slow, and potentially exposing side-channel vulnerabilities such as timing attacks). Some browsers support performing native crypto operations using data from JS, which is faster and more secure (assuming you trust the browser developer, which you kind of need to here), but it's not yet universal.


[1] You probably shouldn't. PHP is a poor choice for any highly-security-sensitive code, as it is relatively easy to make security mistakes in. Secure code in (modern, fully-patched) PHP is certainly possible, but I would recommend using a language that makes it harder to shoot your own foot off, like Java, C#, VB.NET, or perhaps Go or Python.

[2] This presents a security weakness you need to figure out a way around, because the endpoint system - the user and their web browser - have no way to tell if the public keys sent to the client (to which the data is being encrypted) are the right public keys. A malicious server admin could add their own public key to the list of keys, and then any data encrypted with that list of keys would be readable by the malicious admin. You need some way of verifying key authenticity.

[3] One tricky bit here is that, while the server should never store the user's password, the server does typically see the password, briefly, when creating the account and whenever the password is used (logging in, changing the password, etc.). A malicious server admin could modify the server to steal this password. If that password is all that is needed to log in as that user - for example, if knowing the user's password allows you to unwrap the user's private key - then the malicious admin could then decrypt the data that they aren't supposed to have access to by impersonating a legitimate user.

[4] Honestly, this sounds like a project for somebody both more experienced in information security and as a developer. It's not an easy problem, and crypto is hard to do right.

Nisarg Shah
  • 109
  • 5
CBHacking
  • 42,359
  • 3
  • 76
  • 107
  • With regard to 'The client-side (JS) portion of this thing is going to be where the heavy lifting occurs...', the Web Crypto API might come in handy here. See https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API. – mti2935 Dec 25 '19 at 20:50
  • @mti2935 Sure, and full support for WebCrypto is now pretty widespread (everything except IE, I think? Which you can probably work around if you must support IE for some reason), but this answer is almost two years old and it was newer then. – CBHacking Dec 26 '19 at 10:26
3

If system administrators must be unable to read the data, you cannot implement it in PHP, because that runs on the server.

In that case, the private key can't be on the server, because administrators will always have a way to access it if it is.

I think the best way to achieve your goal is to encrypt/decrypt the data in the browser (using Javascript) with a key entered by the user.

Mark Koek
  • 1,321
  • 1
  • 8
  • 16
2

End to end encryption in a browser is impossible because the client application (the JavaScript) is served by a server and the server admin (or any third party script) can easily taint the script served and steal all the secrets that are generated client side. There is no way around that. End to end means you don't have to trust any central authority including the server that transmits the encrypted payloads, but in this case your server is just that - a central authority that distributes the client program on each page load to your users, and your users have to trust it that it doesn't taint the client program.

So you will need a separate client program built from source from a community reviewed code, that is independent of any trusted party. So your E2E app can't be a web app. But the server side part that just delivers the encrypted payloads can be implemented in PHP.

Calmarius
  • 1,905
  • 2
  • 12
  • 6
  • Well said by Calmarius. If you can't trust the server with your secrets, then how can you trust the server to serve you secure code. This is known as the 'chicken-and-egg' problem when it comes to browser crypto. See https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/august/javascript-cryptography-considered-harmful/ for more info. – mti2935 Dec 25 '19 at 20:55
  • Also see https://security.stackexchange.com/questions/238441/solution-to-the-browser-crypto-chicken-and-egg-problem – mti2935 Jul 08 '21 at 11:11