2017-03-28 17:03:42 +00:00
|
|
|
|
/*
|
2017-04-02 03:50:28 +00:00
|
|
|
|
Snow10 - Whitespace steganography. electronic invisible ink.
|
|
|
|
|
Copyright (C) 2017 Kevin Froman https://ChaosWebs.net/
|
|
|
|
|
|
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2017-03-28 17:03:42 +00:00
|
|
|
|
*/
|
2016-05-28 04:34:52 +00:00
|
|
|
|
var clipboard = new Clipboard('.btn');
|
|
|
|
|
|
2017-03-28 04:36:51 +00:00
|
|
|
|
var zero = '';
|
|
|
|
|
var one = '';
|
|
|
|
|
|
|
|
|
|
var z_zero = '';
|
|
|
|
|
var z_one = '';
|
|
|
|
|
|
|
|
|
|
var w_zero = ' ';
|
|
|
|
|
var w_one = '\t';
|
|
|
|
|
|
2017-03-31 01:17:52 +00:00
|
|
|
|
|
|
|
|
|
function showError(msg){
|
|
|
|
|
$.bootstrapGrowl(msg, {type: 'danger'})
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-28 04:36:51 +00:00
|
|
|
|
function escapeRegExp(str) {
|
|
|
|
|
return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function replaceAll(str, find, replace) {
|
|
|
|
|
return str.replace(new RegExp(escapeRegExp(find), 'g'), replace);
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-28 04:34:52 +00:00
|
|
|
|
clipboard.on('success', function(e) {
|
|
|
|
|
$('#copyFeedback').css('display', 'inherit');
|
|
|
|
|
$('#copyFeedback').css('color', 'green');
|
|
|
|
|
$('#copyFeedback').html('Copied!');
|
|
|
|
|
e.clearSelection();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
clipboard.on('error', function(e) {
|
|
|
|
|
$('#copyFeedback').css('display', 'inherit');
|
|
|
|
|
$('#copyFeedback').css('color', 'red');
|
2016-08-05 11:08:47 +00:00
|
|
|
|
$('#copyFeedback').html('Your browser doesn\'t seem to support automatic copying. Get a better one.');
|
2016-05-28 04:34:52 +00:00
|
|
|
|
e.clearSelection();
|
|
|
|
|
});
|
|
|
|
|
|
2016-08-05 11:08:47 +00:00
|
|
|
|
if ($('#useEncrypt').is(':checked') == false)
|
|
|
|
|
{
|
|
|
|
|
$('#encryptArea').css('display', 'none');
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-28 04:34:52 +00:00
|
|
|
|
$('#modalClose').click(function(){
|
|
|
|
|
$('#copyFeedback').css('display', 'none');
|
|
|
|
|
});
|
|
|
|
|
|
2016-08-05 11:08:47 +00:00
|
|
|
|
|
|
|
|
|
$("#output").on("click", function () {
|
|
|
|
|
$(this).select();
|
|
|
|
|
});
|
2016-05-28 04:34:52 +00:00
|
|
|
|
|
2017-03-28 04:36:51 +00:00
|
|
|
|
$('#useZeroWidthCharacters').click(function(){
|
|
|
|
|
|
|
|
|
|
if (zero == w_zero)
|
|
|
|
|
{
|
|
|
|
|
zero = z_zero;
|
|
|
|
|
one = z_one;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
zero = w_zero;
|
|
|
|
|
one = z_one;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
2016-08-05 11:08:47 +00:00
|
|
|
|
/* based on stackoverflow.com/questions/14430633/how-to-convert-text-to-binary-code-in-javascript */
|
|
|
|
|
function binToText(str) {
|
2017-03-28 04:36:51 +00:00
|
|
|
|
var str = replaceAll(replaceAll(str, one, "1"), zero, "0");
|
2016-08-05 11:08:47 +00:00
|
|
|
|
if(str.match(/[10]{8}/g)){
|
|
|
|
|
var wordFromBinary = str.match(/([10]{8}|\s+)/g).map(function(fromBinary){
|
|
|
|
|
return String.fromCharCode(parseInt(fromBinary, 2) );
|
|
|
|
|
}).join('');
|
|
|
|
|
return wordFromBinary;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* based on stackoverflow.com/questions/21354235/converting-binary-to-text-using-javascript */
|
|
|
|
|
function textToBin(text) {
|
|
|
|
|
var output = '';
|
|
|
|
|
var length = text.length,
|
|
|
|
|
output = [];
|
|
|
|
|
for (var i = 0;i < length; i++) {
|
|
|
|
|
var bin = text[i].charCodeAt().toString(2);
|
|
|
|
|
output.push(Array(8-bin.length+1).join("0") + bin);
|
2017-03-30 14:53:52 +00:00
|
|
|
|
}
|
2016-08-05 11:08:47 +00:00
|
|
|
|
return output.join('');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$('#useEncrypt').click(function(){
|
|
|
|
|
if (! this.checked)
|
2016-05-28 04:34:52 +00:00
|
|
|
|
{
|
2016-08-05 11:08:47 +00:00
|
|
|
|
$('#encryptArea').css('display', 'none');
|
2016-05-28 04:34:52 +00:00
|
|
|
|
}
|
2016-08-05 11:08:47 +00:00
|
|
|
|
else
|
2016-05-28 04:34:52 +00:00
|
|
|
|
{
|
2016-08-05 11:08:47 +00:00
|
|
|
|
$('#encryptArea').css('display', 'inherit');
|
|
|
|
|
}
|
|
|
|
|
})
|
2016-05-28 04:34:52 +00:00
|
|
|
|
|
2016-08-05 11:08:47 +00:00
|
|
|
|
function verifyPass(mode)
|
|
|
|
|
{
|
|
|
|
|
if ($('#password').val() == '')
|
|
|
|
|
{
|
2017-03-31 01:17:52 +00:00
|
|
|
|
showError('You must provide a password.');
|
2016-08-05 11:08:47 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
2016-05-28 04:34:52 +00:00
|
|
|
|
|
2016-08-05 11:08:47 +00:00
|
|
|
|
if (mode == 'encrypt')
|
|
|
|
|
{
|
|
|
|
|
if ($('#password').val() != $('#confirmPass').val())
|
2016-05-28 04:34:52 +00:00
|
|
|
|
{
|
2017-03-31 01:17:52 +00:00
|
|
|
|
showError('Passwords must match.');
|
2016-08-05 11:08:47 +00:00
|
|
|
|
return false;
|
2016-05-28 04:34:52 +00:00
|
|
|
|
}
|
2016-08-05 11:08:47 +00:00
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-30 14:53:52 +00:00
|
|
|
|
$('#encode').click(function(){
|
2017-04-04 15:19:47 +00:00
|
|
|
|
$('#encodeDecodeArea').css('display', 'none');
|
2017-03-30 14:53:52 +00:00
|
|
|
|
go('encode');
|
2017-04-04 15:19:47 +00:00
|
|
|
|
$('#encodeDecodeArea').css('display', 'inline-block');
|
2017-03-30 14:53:52 +00:00
|
|
|
|
});
|
|
|
|
|
$('#decode').click(function(){
|
2017-04-04 15:19:47 +00:00
|
|
|
|
$('#encodeDecodeArea').css('display', 'none');
|
2017-03-30 14:53:52 +00:00
|
|
|
|
go('decode');
|
2017-04-04 15:19:47 +00:00
|
|
|
|
$('#encodeDecodeArea').css('display', 'inline-block');
|
2017-03-30 14:53:52 +00:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
function go(mode) {
|
2016-08-05 11:08:47 +00:00
|
|
|
|
var output = '';
|
|
|
|
|
|
|
|
|
|
var input = $('#text').val();
|
|
|
|
|
|
|
|
|
|
if (input == '') { return false; }
|
2016-05-28 04:34:52 +00:00
|
|
|
|
|
|
|
|
|
|
2017-03-30 14:53:52 +00:00
|
|
|
|
// If we're encoding:
|
|
|
|
|
if (mode == 'encode')
|
2016-08-05 11:08:47 +00:00
|
|
|
|
{
|
|
|
|
|
// If we should use encryption, encrypt first:
|
|
|
|
|
if ($('#useEncrypt').is(':checked'))
|
|
|
|
|
{
|
|
|
|
|
// verify password first
|
|
|
|
|
if (verifyPass('encrypt'))
|
|
|
|
|
{
|
|
|
|
|
input = CryptoJS.AES.encrypt(input, $('#password').val()).toString();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2016-05-28 04:34:52 +00:00
|
|
|
|
}
|
2016-08-05 11:08:47 +00:00
|
|
|
|
// convert result to binary
|
2017-03-28 05:14:08 +00:00
|
|
|
|
output = textToBin(encodeURIComponent(input));
|
2017-03-31 03:42:02 +00:00
|
|
|
|
$('#output').text(replaceAll(replaceAll(output.toString(), "1", one), "0", zero));
|
2016-05-28 04:34:52 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2017-03-30 01:52:02 +00:00
|
|
|
|
var sanitized = "";
|
|
|
|
|
var split = input.split("");
|
|
|
|
|
for (var i = 0; i < split.length; i++)
|
|
|
|
|
if(split[i] == one || split[i] == zero)
|
|
|
|
|
sanitized = sanitized + split[i]
|
|
|
|
|
var output = decodeURIComponent(binToText(sanitized));
|
2017-04-04 15:19:47 +00:00
|
|
|
|
if (output === 'undefined'){
|
|
|
|
|
showError('Could not decode message. Maybe there wasn\'t one?');
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2016-08-05 11:08:47 +00:00
|
|
|
|
if ($('#useEncrypt').is(':checked'))
|
|
|
|
|
{
|
|
|
|
|
if (verifyPass('decrypt'))
|
2016-05-28 04:34:52 +00:00
|
|
|
|
{
|
2016-08-05 11:08:47 +00:00
|
|
|
|
output = CryptoJS.AES.decrypt(output, $('#password').val()).toString(CryptoJS.enc.Utf8);
|
2016-05-28 04:34:52 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2016-08-05 11:08:47 +00:00
|
|
|
|
return false;
|
2016-05-28 04:34:52 +00:00
|
|
|
|
}
|
2016-08-05 11:08:47 +00:00
|
|
|
|
}
|
2017-03-31 03:42:02 +00:00
|
|
|
|
$('#output').text(output.toString());
|
2016-05-28 04:34:52 +00:00
|
|
|
|
}
|
2016-08-05 11:08:47 +00:00
|
|
|
|
$('#outputModal').modal();
|
2017-03-30 14:53:52 +00:00
|
|
|
|
}
|
2017-03-28 16:40:00 +00:00
|
|
|
|
|
|
|
|
|
$('#clearInputButton').click(function(){
|
|
|
|
|
$('#text').val('');
|
|
|
|
|
});
|