Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 07.11.2010, 14:47
Аватар для poorking
prodigy
Отправить личное сообщение для poorking Посмотреть профиль Найти все сообщения от poorking
 
Регистрация: 01.11.2010
Сообщений: 503

Представление текста как массив байтов
Здравствуйте, уважаемые программисты.
Сейчас я взялся за реализацию алгоритма шифрования AES на javascript. Для тех кто не в курсе, супер-кратко опишу. AES - блочный симметричный шифр, единовременно шифрующий блоки информации по 128 бит ключом 128/192/256 бит. В самом шифре производятся различные операции с байтами, то бишь перестановка, нелинейная замена и т.п. Но это уже не суть.

На страничке есть 3 textarea, в одну я ввожу текст, 2 другие - readonly, когда нажимаю кнопку "Зашифровать", берется значение первого поля, шифруется, выводится вся эта абра-кадабра во второе поле. Когда нажимаем "Расшифровать", берется значение второго поля, расшифровывается и выводится в третье поле.

Но проблема моя заключается в следующем. Так как алгоритм оперирует с байтами, то входной текст надо представить как последовательность байтов, и это было бы не проблемой если бы все символы юникода весили одинаковое количество байт, но дело в том, что латиница, например имеет чаркоды до 1 байта, а кириллица уже по 2 байта, есть символы, которые весят и то более. Например имеем строку: "3ЖF". Если представлю этот текст в виде последовательности юникодных десятичных чаркодов то получится [51, 1046, 70]. В двоичном виде: [110011,10000010110,1000110] . Мы видим что символ "Ж" занимает 2 байта. "Ж"= 1046 = [4,26] .

Кстати, вот игрушка, сделал чтобы не мучить калькулятор. А в стандартной таблице символов в юникодных шрифтах можно найти 3-4 байтные символы.

<html>
<head><title></title></head>
<body>
<span>Enter the symbol (string): </span><input type='text' id="char" maxlength="1" size="1"/> <b id="info"></b>
<p id='chcode'></p>
<p id='dec'></p>
<p id='bin'></p>
<p id='tostr2'></p>
</body>

<script lang='javascript'>

document.getElementById("char").onkeyup=function(){

	var dbtz=[], bbtz=[];
		chCode = this.value.charCodeAt(0),
		q=Math.ceil(Math.log(chCode)/Math.log(255)),
		temp=chCode;

	for(var i=0; i<q;i++){
		
		var p = Math.floor(temp/Math.pow(255,q-i-1));
		
		temp = temp-p*Math.pow(255,q-i-1);
		
		dbtz[i] =p;
		bbtz[i] =p.toString(2);
	} 
	info.innerHTML = "= "+q+" bytes.";
	chcode.innerHTML ="Char code: " + chCode;
	dec.innerHTML = "In decimal: ["+dbtz+"].";
	bin.innerHTML = "In binary: ["+bbtz+"]."
	tostr2.innerHTML = "('"+this.value+"').charCodeAt(0).toString(2) = "+chCode.toString(2);
}


</script>
</html>

И как поступать в таком случае? Если я представлю эту строку в виде последовательности байтов [51,4,26,70], то раскодировать эту последовательность обратно в "3ЖF" будет, надеюсь я ошибаюсь, невозможно, из-за того что мы не знаем сколько брать байтов для раскодирования одного символа.

Как сначала делал я. Принял допущение, что больше 2х байт символов не будет. На самом деле, символы больше 2х байт очень редкие. Затем чаркод каждого символа переводил в двоичный вид с помощью .toString(2), и добивал вначале каждой строки недостающие нули до16 бит. Таким образом, в итоге у меня получалась строка, в которой я твердо знал, что каждый ее отрезок длиной в 16 - это двоичный чаркод одного символа. Но этот вариант меня не устроил, потому что мне кажется что это как-то не по-уму. Зачем хранить двоичный код в виде строки, тем более в данном контексте это не выгодно, так как сам алгоритм шифрования будет работать в разы медленнее, потому что "байтами" в 128-битном блоке будут строки по 8 символов "0" или "1", которые в свою очередь и так весят по 1-му байту. Вот собственно и суть проблемы. Как представить текст в виде массива байтов, чтобы потом его можно было раскодировать. Простите за много букв, просто накипело и не удержался, решил выплакаться. Пишу сюда, потому что вопрос не по Яваскрипту, а общего плана. Подскажите, пожалуйста, как это делать правильно.
__________________
readOnly
Ответить с цитированием
  #2 (permalink)  
Старый 07.11.2010, 15:01
Аватар для Gvozd
Матрос
Отправить личное сообщение для Gvozd Посмотреть профиль Найти все сообщения от Gvozd
 
Регистрация: 04.04.2008
Сообщений: 6,246

http://ru.wikipedia.org/wiki/Юни...BD.D0.B8.D1.8F
Ответить с цитированием
  #3 (permalink)  
Старый 07.11.2010, 15:04
Профессор
Отправить личное сообщение для SV0L0CH Посмотреть профиль Найти все сообщения от SV0L0CH
 
Регистрация: 07.11.2010
Сообщений: 301

Тут нормально будет использовать String.prototype.charCodeAt и рассматривать результат как 4 байта. Вся побитовая арифметика завязана именно на 4 байта. Непосредственная работа с utf-8 тут не оправдана как и использование для реализации 16-байтовой арифметики через операции над отдельными байтами(когда можно использовать сразу 4 байта).
Ответить с цитированием
  #4 (permalink)  
Старый 07.11.2010, 15:23
Аватар для poorking
prodigy
Отправить личное сообщение для poorking Посмотреть профиль Найти все сообщения от poorking
 
Регистрация: 01.11.2010
Сообщений: 503

Gvozd,
Цитата:
...поскольку в Юникоде нет символов с кодом больше 10FFFF, и вводить их в будущем не планируется)....
Скажите мне придется каждый символ представлять как последовательность 3х байт тогда? даже если символ на 1 байт, в начале добавлять вначале "пустые" байты равные 0? Например символ "1" будет равен [0,0,49].

SV0L0CH,
На вики написано что в Юникоде нет символов с кодом больше 1114111=3байта, все равно брать по 4 байта лучше?
__________________
readOnly
Ответить с цитированием
  #5 (permalink)  
Старый 07.11.2010, 15:45
Профессор
Отправить личное сообщение для tenshi Посмотреть профиль Найти все сообщения от tenshi
 
Регистрация: 20.03.2008
Сообщений: 1,183

encodeURIComponent('текст').split('%').map(fu nction( val ){return Number( '0x'+val ) })
__________________
.ня
Ответить с цитированием
  #6 (permalink)  
Старый 07.11.2010, 15:47
Профессор
Отправить личное сообщение для tenshi Посмотреть профиль Найти все сообщения от tenshi
 
Регистрация: 20.03.2008
Сообщений: 1,183

пиздец, илья, ты опустился в моих глазах совсем ниже плинтуса =_=
__________________
.ня
Ответить с цитированием
  #7 (permalink)  
Старый 07.11.2010, 16:22
Аватар для poorking
prodigy
Отправить личное сообщение для poorking Посмотреть профиль Найти все сообщения от poorking
 
Регистрация: 01.11.2010
Сообщений: 503

tenshi,
encodeURIComponent() ведь кодирует все символы кроме латиницы. А у меня текст может быть абсолютно из любого набора символов.

Буду делать как предложил SV0L0CH, наверно. Не нравится мне что 128/192/256 ключи тогда будут 4/6/8 символов всего.. как то это не так..
__________________
readOnly
Ответить с цитированием
  #8 (permalink)  
Старый 07.11.2010, 16:58
Аватар для poorking
prodigy
Отправить личное сообщение для poorking Посмотреть профиль Найти все сообщения от poorking
 
Регистрация: 01.11.2010
Сообщений: 503

function str2bytes(str){
	var arr=[], bytesPerSymbol=4;
		
	for (var i=0;i<str.length;i++){			
			var chCode = str.charCodeAt(i);			
			var temp=chCode;
	
		for(var j=0; j<bytesPerSymbol;j++){			
				var oneByte = Math.floor(temp/Math.pow(255,bytesPerSymbol-j-1));
				
				arr.push(oneByte);
				
				temp = temp-oneByte*Math.pow(255,bytesPerSymbol-j-1);			
		} 
	
	}
	return arr;
}

function bytes2str(arr){
	var bytesPerSymbol=4, str="";
	
	for (var i=0; i<arr.length; i+=bytesPerSymbol){
		var chCode=0;
		for (var j=0;j<bytesPerSymbol;j++){	
			chCode+=arr.slice(i,i+bytesPerSymbol)[j]*Math.pow(255,bytesPerSymbol-j-1);
		
		}
		str+=String.fromCharCode(chCode);
	}
	return str;
}

document.write(str2bytes("Привет!"));

document.write("<br />"+ bytes2str(str2bytes("Привет!")));


Что-то типа того. Такой массив я раскодировать смогу, потому что знаю, что каждые bytesPerSymbol его элементов = 1 символ
__________________
readOnly

Последний раз редактировалось poorking, 07.11.2010 в 17:42.
Ответить с цитированием
  #9 (permalink)  
Старый 07.11.2010, 18:13
Профессор
Отправить личное сообщение для SV0L0CH Посмотреть профиль Найти все сообщения от SV0L0CH
 
Регистрация: 07.11.2010
Сообщений: 301

Сообщение от poorking
Юникоде нет символов с кодом больше 1114111=3байта, все равно брать по 4 байта лучше?
Это на много лучше, один байт можно перед шифрованием заменять рандомным значением, а после расшифровки подставлять обратно 0, но это уже дело вкуса. Место можно экономить, а можно и не экономить.
Ответить с цитированием
  #10 (permalink)  
Старый 07.11.2010, 19:07
Аватар для poorking
prodigy
Отправить личное сообщение для poorking Посмотреть профиль Найти все сообщения от poorking
 
Регистрация: 01.11.2010
Сообщений: 503

SV0L0CH,
Ну я согласен что шифрование будет сильнее но я ничего заменять не буду, в самом AES и так достаточно замен и перестановок. Спасибо
__________________
readOnly
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как создать многомерный массив FRIE Общие вопросы Javascript 29 02.06.2010 19:14
Подскажите, как вернуть js-скрипт массив Polkan AJAX и COMET 18 30.04.2010 23:30
Как передать массив данных на сервер DVVID Общие вопросы Javascript 7 08.04.2010 12:11
Как сделать чтобы text() брал только текст родителя без текста вложенных контейнеров? Andrey32 jQuery 3 23.05.2009 01:33
Как лучше сделать глобальный массив skyfish AJAX и COMET 4 17.02.2009 18:05