Cryptography
JavaScript
Algorithms
8 July 2015

Мой алгоритм шифрования

Не так давно передо мною встала задача закодировать переписку пользователей. Целью задачи было пересылать уже закодированную строку от пользователя А пользователю Б. Строка кодируется и декодируется с помощью ключа, который известен обоим. Подразумевается, что сообщение от пользователя А отсылается на сервер пользователю Б, где пользователь Б его и забирает. Чтобы избежать получение данных в случае получения сообщения третьим лицом путем перехвата сообщения, либо доступа к серверу, где оно хранится, функцию было решено организовать на 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>';
	}); 
}


Результат можно увидеть на сайтах avtodot.ru, baby-all-pro.ru и building-repairs.ru

Юридические аспекты шифрования данных

-51
16.4k 48
Comments 29