Screenshot-proof images via temporal dithering #
Snapchat's (and now Facebook Poke's) main claim to fame is that it lets you send "self-destructing" image messages. Setting aside the debate about the uses of this beyond sexting, the key vulnerability in both apps is the built-in ability to take screenshots. Both take a reactive approach, where you're notified if the recipient took a screenshot, but can't really do anything about it.
I was thinking about ways of mitigating this issue, and figured that perhaps turning the image into an animation where individual frames are not (or at least less) recognizable would be the right path. This is a variant of temporal dithering, except we're intentionally pretending like each frame has a limited amount of precision, and only when averaged together is the original image re-created.
I've created a proof of concept (source) of this. It loads the image into a <canvas>
and generates a "positive" and "negative" frame out of it. The positive frame has a random offset added to each pixel's RGB components, while the negative one has it subtracted. When displayed in quick sequence (requestAnimationFrame is used to do this every time the screen refreshes) the two offsets should cancel out, and the resulting image should re-appear.
Source | Temporal dithering1 |
Positive frame | Negative frame |
The resulting flicker is unfortunate, but perhaps that only enhances the furtiveness of an image that will disappear in a few seconds. It also seemed fitting to include Lenna as a source image, given its origin.
Obviously this technique is meant to deter only casual attempts at screen capture. Beyond the analog hole, screen recording software (albeit not an issue on non-jailbroken iOS devices) can easily reconstruct the original image.
Potential areas of exploration are doing the offsets in a different color space (RGB is not linear) and using more than two frames. One option for generating more frames is to keep making random positive and negative pairs. That way repeated screen captures are less likely to yield a pair that can be combined to reconstruct the original image. Another option for generating more frames is to create three or more images that need to be averaged together to yield the original. However, that will result in more image degradation, since the frames are less likely to be perceived as one image; persistence of vision lasts for 1/25th of a second, which is between 2 and 3 frames at 60Hz.
Update: See also the discussion on Hacker News.
- The embedded example in this blog post is rendered as an animated GIF. Due to clamping of GIF frame rates, lack of precision (the delay is specified as an integer counting hundredths of a second) and guessing at the screen's refresh rate (it assumes 60Hz), it will exhibit even more flicker than the programmatic version.
20 Comments
Peekaboo works by displaying only a small circular area around mouse cursor or finger. To get the whole image, hacker has to record many images and stitch them together. Consider its voyeuristic nature to be a feature. ;-)
In saying all that, it's quite interesting, and algorithms which can reverse such an effect could have some wider image-processing applications.
I took 3 screenshots and ended up with the positive and negative versions. Shouldn't be too difficult for a screen scraping program to be created that merges the two images.
It's done in JavaScript, and my browser is in control of all JavaScript provided to it.... so I can also just parse the code for the source image and then grab it.
What about people with medical disorders such as epilepsy? Seems like this approach could trigger seizures with all that flashing.
Unfortunately now my eyes hurt after just 20 seconds of looking at that.
Sure WE can work around this issue, but if I am sexting with someone who is a computeretarded they might not think of a work around. Even if they could, so what? Whining here about there being work arounds is like claiming that bike locks are useless because there are workarounds, they serve a certain purpose in making it more difficult to steal the bike. Same goes for this.
Think hackerproof or SSL secured seals that could easily be copied and pasted on another site. With this, it adds a painful step to overcome if you want to steal a seal image and post it on your own site.
Folks, remember, nothing is 100% fool-proof, but you need to think of making your content, product, or feature a little bit harder to steal than the rest of the competition to protect yourself.
Another approach would be for the mobile OS makers to grant apps the right to disable screenshots, though I suppose that would open a pandora's box of copyright abuses (e.g. apps which suddenly don't allow users to make fair use of content).
I got curious if the animation jitteriness is easily fixed by making a requestAnimationFrame loop that flips the images and runs in full 60Hz, instead of whatever drives the animation now. Or is this already the case?
A possible workaround: Create a double-buffer. Two divs, each contains a canvas, one pixelated variation image per canvas, setTimeout alternatively toggling div visibility. This should allow animation without canvas functions in the inner loop.
Side note: Smooth animation might depend on knowning the user's monitor refresh rate. 60Hz = 16.666ms timer, 75Hz = 13.333ms, 100Hz = 10ms. Can we get the refresh rate via user agent or javascript?
As far as the complaint that we're all picking the solutions apart, that's what hacking IS, and if you don't have an answer for a workaround that took three smart guys two days to come up with, then you don't have a robust enough concept to bring to market yet. To catch a thief, you must think like a thief, etc.
Post a Comment