Здравствуйте, уважаемые программисты.
Сейчас я взялся за реализацию алгоритма шифрования 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-му байту. Вот собственно и суть проблемы. Как представить текст в виде массива байтов, чтобы потом его можно было раскодировать. Простите за много букв, просто накипело и не удержался, решил выплакаться. Пишу сюда, потому что вопрос не по Яваскрипту, а общего плана. Подскажите, пожалуйста, как это делать правильно.