Не так давно передо мною встала задача закодировать переписку пользователей. Целью задачи было пересылать уже закодированную строку от пользователя А пользователю Б. Строка кодируется и декодируется с помощью ключа, который известен обоим. Подразумевается, что сообщение от пользователя А отсылается на сервер пользователю Б, где пользователь Б его и забирает. Чтобы избежать получение данных в случае получения сообщения третьим лицом путем перехвата сообщения, либо доступа к серверу, где оно хранится, функцию было решено организовать на JavaScript, что дает возможность пользователям отсылать закодированную строку прямо из окна браузера.
Бегло пробежавшись по некоторым способом шифрования, я решил написать собственный алгоритм. Суть алгоритма было решено свести к тому, чтобы перемешивать каждый отдельный символ в неким уникальным значением смешанным с ключом, причем так, чтобы значение, которое будет смешивать данные символы было уникальным и формировалось из заданного пароля или ключа. Творческой идеей для написания именно такого алгоритма послужил шифр Эль-Гамаля, метод преобразования Punycode и Base64. На нобелевскую премию я не претендую, но тем не менее решил поделиться собственным творением и…
passCode — пароль, ключ. Так как пользователь задает данный параметр самостоятельно, а он может быть достаточно простым, то я кодирую ее дополнительно в MD5.
Incode — кодируемая строка
function txtencode(Incode, passCode) { //Так как сам результат может содержать нежелательные символы, эта переменная содержит символы с помощью которых мы будем выдавать закодированный результат, который вдальнейшем сможем отправить без особых хлопот var b52 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; //Эти переменные будут меняться в процессе кодировки и создавать мешанину каждого кодируемого символа в отдельности var maxPC = ifPC = 0; //Уникализируем переменную maxPC. Ее значение будет происходить от суммы каждого юникодного значения символов пароля for(var i=0; i<passCode.length; i++) maxPC += passCode.charCodeAt(i); //Значение maxPCmod будет меняться на убывание, опять же в зависимости от юникодного значения символа пароля //А вот значение maxPC сохраним, оно понадобиться вдальнейшем, чтобы присвоить переменной maxPCmod новое значение, когда то будет меньше 0. maxPCmod = maxPC; //Результат кодируемой строки. Изначально равно пустоте. var rexcode = ""; //Переменная содержит первый символ пароля: passCode.charCodeAt(numPC) //С ее помощью будем перебирать пароль и перемешивать его с символом строки var numPC = 0; //Перебираем каждый символ строки for(var i=0; i<Incode.length; i++) { //Если все символы пароля перемешаны, начинаем перебор пароля с первого символа if(numPC == passCode.length) numPC = 0; //Присвоиваем переменной maxPCmod новое значение, если оно меньше нуля. if(maxPCmod < 1) maxPCmod = maxPC+ifPC; //Эта переменная нужна для создания уникального значения maxPCmod, и как следствие уникального символа, с которым будет перемешиваться символ исходной строки. // Получаем ее путем деления по модулю значений maxPCmod и текущего используемого юникодного значения символа пароля //В целом постоянная мешанина переменных maxPCmod, maxPC и ifPC позволяет кодировать каждый отдельный символ исходной строки с уникальным значением, что подразумевает невозможность отследить какую-либо синхронизацию алгоритма ifPC += maxPCmod % passCode.charCodeAt(numPC); //Создаем непосредственно символ, с которым и будем перемешивать текущий символ строки var iscode = maxPCmod % passCode.charCodeAt(numPC); //Создаем мешанину, путем сложения предыдущей переменной с переменной текущего символа var nCode = (Incode.charCodeAt(i)+iscode); //Уменьшаем значение maxPCmod для ее дальнейшей уникализации maxPCmod -= passCode.charCodeAt(numPC); //Переходим к следующему символу пароля numPC++; //Это будет уникальный номер текущего символа. //При делении закодированного символа на 52 число означает неполное частно, а буква остаток. //Например 22С означает 22*52+2, так как С второй по счету символ начиная с нуля. rexcode += parseInt(nCode / 52) + b52.charAt(parseInt(nCode % 52)); } //Возвращаем закодированную строку return rexcode; }
Функция декодировки практически аналогично предыдущей за небольшими исключениями
function txtdecode(Incode, passCode) { var b52 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; var maxPC = 0; for(var i=0; i<passCode.length; i++) maxPC += passCode.charCodeAt(i); maxPCmod = maxPC; ifPC = 0; //Разбиваем строку на массив, который будет состоять из каждого закодированного символа var Incode = Incode.match(/\d+\w/g); var rexcode = ""; var numPC = 0; for(var i=0; i<Incode.length; i++) { if(numPC == passCode.length) numPC = 0; if(maxPCmod < 1) maxPCmod = maxPC+ifPC; ifPC += maxPCmod % passCode.charCodeAt(numPC); var iscode = maxPCmod % passCode.charCodeAt(numPC); //В отличии от фунции кодирования, тут дейтсвие происходит в обратную сторону var nCode = (parseInt(Incode[i])*52)+parseInt(b52.indexOf(Incode[i].substr(-1))); maxPCmod -= passCode.charCodeAt(numPC); numPC++; //И в результате соответственно уже не сложение, а вычитание rexcode += String.fromCharCode(nCode-iscode); } //Уже можно вернуть return rexcode. //Но для корректного отображения в браузере, я преобразую некоторые символы во мнемоники, а урлы преобразую в ссылки. return rexcode.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/ /g, " ").replace(/\r\n|\r|\n/g,"<br />").replace(/(https?\:\/\/|www\.)([а-яА-Я\d\w#!:.?+=&%@!\-\/]+)/gi, function(url) { return '<a target="_blank" href="'+ (( url.match('^https?:\/\/') )?url:'http://' + url) +'">'+ url +'</a>'; }); }
ссылка на оригинал статьи http://habrahabr.ru/post/262081/
Добавить комментарий