Created
March 29, 2016 19:38
-
-
Save plugnburn/783965e6a10eb6575d1d2907aa7e0683 to your computer and use it in GitHub Desktop.
PNG steganography in less than a kilo minified
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//PNG steganography utils | |
//ratio: about 2 pixels per 1 byte of text message | |
//Auto EOD byte as 255 | |
//Use only non-transparent images as the algo has to modify alpha-channel of affected pixels | |
//to protect RGB values from in-browser rounding | |
+function(w) { | |
var bitMapping = [0, 1, 2, 4, 5, 6, 8, 9], img = new Image(), cnv = document.createElement('canvas'), ctx=cnv.getContext('2d') | |
w.Stego = { | |
hide: function(imglink, msg, cb) { //image data URI (not only PNG) and message as input, resulting PNG image data URI as output (to callback) | |
var data = btoa(unescape(encodeURIComponent(msg)))+'\xff', dlen = data.length | |
img.onload = function() { | |
cnv.width = this.width | |
cnv.height = this.height | |
ctx.drawImage(this, 0, 0) | |
var idata=ctx.getImageData(0, 0, this.width, this.height) | |
for(var p = -1, i = 0;i < (dlen<<4);i += 16) { | |
for(var c = data.charCodeAt(++p), bmi = 0; bmi < 8; bmi++) | |
idata.data[i+bitMapping[bmi]] = (idata.data[i+bitMapping[bmi]]&~1)|((c>>bmi)&1) | |
idata.data[i+3] = idata.data[i+7] = idata.data[i+11] = 255 | |
} | |
ctx.putImageData(idata, 0, 0) | |
cb(cnv.toDataURL('image/png')) | |
} | |
img.src=imglink | |
}, | |
reveal: function(imglink, cb) { //PNG image data URI as input, message as output (to callback) | |
img.onload = function() { | |
cnv.width = this.width | |
cnv.height = this.height | |
ctx.drawImage(this, 0, 0) | |
var idata = ctx.getImageData(0, 0, this.width, this.height).data, data = [], i, c | |
for(i = 0;i < idata.length;i += 16) { | |
for(var c = 0, bmi = 0; bmi < 8; bmi++) | |
c |= (idata[i+bitMapping[bmi]]&1)<<bmi | |
if(c===255) break | |
else if(c) data.push(String.fromCharCode(c)) | |
} | |
cb(decodeURIComponent(escape(atob(data.join(''))))) | |
} | |
img.src=imglink | |
} | |
} | |
}(window) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment