Disclaimer I: These post includes examples on BAD practices such as a bit of “roll your own crypto” and “security by obscurity”. I DO NOT recommend to do this unless you understand all the downsides of this approach.
Disclaimer II: The approach followed here was chosen both as a temporary solution to the problem which needed to be developed in a short time window (these took me about 6 hours to get it working).
I’m developing a webpage for a client, which uses Firebase as backend. The owners upload videos to the server, which clients pay to watch. I was asked by the client to make these videos “as hard to download as possible”. Of course when I was asked to do this, the first thing I thought about was DRM. But it turns that DRM solutions are quite complex to implement, require custom code running on backend. They’re also quite expensive in terms of server CPU time. As this project started using Firebase (a choice I did not make), implementing custom and expensive backend logic wasn’t the most desirable approach.
After discussing this with the client and telling them a proper solution would take long to land in production, they told me something in the lines of “as long as I can’t do[wnload the videos] myself, it’s ok to me” (translation by me, the original was, in spanish, “que no lo pueda hacer yo”).
With this they meant someone without technical skills should not be able to download the video with some google-able process, like right-click -> download, or installing an addon. This made sense to me, as, in the end, anyone can just hit play and use a screen recording program to get the video ripped and then share it for free. So I start thinking about what could I do to prevent this.
Some requirements I set to myself were:
Avoid using non-standard technologies
Avoid using deprecated technologies (yes, I’m looking at you, Flash)
Make it painless for the user
Make it cross-platform (avoid silverlight & co.)
Quick development time
About the “don’t let the users download the video (easily)”, I mostly devised two things:
It should not appear as a media element in the page (aka, no
src=""), so browsers and addons can’t locate it.
The file downloaded must not be the video file “as-is”, so in the case someone opens the dev tools panel, look at the network requests, and figure out the video url, can’t just download it and play.
And so I decided to take the following approach: Upload the video file encrypted (preferrably symmetrically), and use some JS magick to decrypt it on the fly and feed it to the browser.
This, however, doesn’t look like a trivial task, so let’s dig into it.