The idea is stupid, if you have the image, you can share it, downloading it, doing a screenshot, etc, and you don't have any way to get the complete URL of the image if the user don't share the image with you.
Ok, but I thought, what happens with the cache of the browser?, all the browsers catch all your images to increase the speed, and if someone have access to your computer after you, he can see your private images only looking into the cache directory of the browser. This is a real problem, for example, you can have commited pictures, and your parents / wife / etc can see these looking for images into the computer HD.
I did a video that shows it:
What can Facebook (and the rest of pages who works with pictures) do to avoid this?:
- They can set the cache control as no-store, no-cache, etc for all the pictures who came from the static servers. But they will increase a lot the bandwidth usage and the user experience will be awful.
I did a proof of concept of the second option, and I'll explain it.
The Proof of concept:
Ok, the steps to do this are the next:
- Take the picture from the user.
- Get the SHA1 of the picture, this will be used as key to encrypt/decrypt the image, but could be used to be sure that don't exist any error into the transmission. To this proof of concept I'm using it only to decrypt/encrypt.
- Save the picture encrypted into the HD (on a final version it will be stored into the static servers)
- Save the SHA1 into the database with a flag to give or revoke the access to the users to this picture.
- When a user wants to see the picture it will be served directly from the static servers, and the token will be send from the backend server after the security checks on another query that will not use the browser cache.
- The browser will save on the cache directory the encrypted image, then nobody can have access to it if the backend server don't send the key.
- If the user reloads the image, the browser wouldn't ask for the picture again, it will take the picture directly from the user cache, and will ask only for the key that will be send as JSON if the user have access.
Using this method we can:
- Revoke the access to an image when we want, the user can't get the image from the cache of the browser, then nobody will see this image again.
- Share the images to another users without authorization will be more complex (yes, you can, but not only sharing the link.
- If someone have access to the list of images contained into the static server, he can't do anything with the images.
- Will be more complex use the static servers to serve images to another site (stealing bandwidth).
You can see the proof of concept here:
Use the network tab of the Firebug to see the queries that the browser are doing to the server.
You can click on the "Revoke access" link, and only the administrators will have access to your images (the key is not served to the common users, but the image is still into the server HD, and the key into the database)
You can see a video about how this works here:
I used this libraries to encrypt / decrypt on AES: