Данная статья публикуется в связи с заменой способа обработки второго пароля, в БК так как информацию по шифрованию во flash-ке уже можно считать не секретной, а новые данные шифрования содержатся в открытом доступе на странице ввода 2-го пароля. Статья даётся исключительно в ознакомительных целях, и ни в коем случае не является каким-либо пособием по взлому и т.д. и т.п.
Немного ликбеза. Для чего и зачем нужен второй пароль. Основная задача второго пароля заключается в том, чтобы предотвратить перехват передаваемых данных где-нибудь на промежуточном участке сети. Если первый пароль передаётся в открытом виде, то второй не передаётся вовсе, вместо него передаётся 32 разрядный 16-ричный код, сгенерированный браузером клиента по определённому алгоритму и с определённым ключем, переданным клиенту при открытии странички ввода 2-го пароля. Перехват этого зашифрованного кода ничего не даст, так как преобразование это одностороннее, и обратное преобразование (из ЗАШИФРОВАННОГО КОДА в пароль) не возможно.
В предыдущем варианте программа шифрования на actionscript была внутри flash-ки. Вместе с flash-кой передавался и ключ шифрования в виде переменной "r=xxxxxxxxxx.xxxxx".
sBox = new Array(99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118, 202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192, 183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21, 4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117, 9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132, 83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207, 208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168, 81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210, 205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115, 96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219, 224, 200, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121, 231, 50, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8, 186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138, 112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158, 225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223, 140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22);
rCon = new Array(1, 2, 4, 8, 16, 32, 64, 128, 27, 54, 108);
w = new Array(176);
tar = new Array(16);
b = new Array(4);
var i = 0;
var j = 0;
var k = 0;
var l = 0;
for (i = 0; i < 4; i++)
{
for (j = 0; j < 4; j++)
{
w[i * 4 + j] = ikey[i * 4 + j];
} // end of for
} // end of for
for (i = 1; i < 11; i++)
{
for (j = 0; j < 4; j++)
{
for (k = 0; k < 4; k++)
{
b[k] = w[(i - (j == 0) ? (1) : (0)) * 16 + k * 4 + (j == 0 ? (3) : (j - 1))];
} // end of for
if (j == 0)
{
for (k = 0; k < 4; k++)
{
if (k < 3)
{
b[k] = sBox[b[k + 1]];
continue;
} // end if
b[k] = sBox[0] ^ rCon[i];
} // end of for
} // end if
for (k = 0; k < 4; k++)
{
w[i * 16 + k * 4 + j] = w[(i - 1) * 16 + k * 4 + j] ^ b[k];
} // end of for
} // end of for
} // end of for
for (i = 0; i < 4; i++)
{
for (j = 0; j < 4; j++)
{
tar[i * 4 + j] = src[i * 4 + j] ^ w[i * 4 + j];
} // end of for
} // end of for
for (i = 1; i < 4; i++)
{
for (l = 0; l < i; l++)
{
tmp = tar[i * 4];
for (j = 0; j < 3; j++)
{
tar[i * 4 + j] = tar[i * 4 + (j + 1) % 4];
} // end of for
tar[i * 4 + 3] = tmp;
} // end of for
} // end of for
if (k != 9)
{
for (j = 0; j < 4; j++)
{
for (i = 0; i < 4; i++)
{
tmp = tar[i * 4 + j] ^ tar[(i + 1) % 4 * 4 + j];
b[i] = tar[(i + 1) % 4 * 4 + j] ^ tar[(i + 2) % 4 * 4 + j] ^ tar[(i + 3) % 4 * 4 + j] ^ (tmp > 127 ? (tmp << 1 ^ 283) : (tmp << 1));
} // end of for
for (i = 0; i < 4; i++)
{
tar[i * 4 + j] = b[i];
} // end of for
} // end of for
} // end if
for (i = 0; i < 4; i++)
{
for (j = 0; j < 4; j++)
{
tar[i * 4 + j] = tar[i * 4 + j] ^ w[(k + 1) * 16 + i * 4 + j];
} // end of for
} // end of for
return (tar);
} // End of the function
function md5(src)
{
tar = new Array(16);
res = new Array(16);
for (i = 0; i < src.length || i < 16; i++)
{
res[i] = Number(src.charCodeAt(i)) ^ i * 4;
} // end of for
for (i = 0; i < 4; i++)
{
for (j = 0; j < 4; j++)
{
tar[i * 4 + j] = (res[j * 4 + i] + 256) % 256;
} // end of for
} // end of for
return (tar);
} // End of the function
function array2HStr(src)
{
res = "";
for (i = 0; i < 16; i++)
{
res = res + (hex[src[i] >> 4] add hex[src[i] % 16]);
} // end of for
return (res);
} // End of the function
function encrypt(plain, pass)
{
ikey = md5(pass);
for (i = 0; i < 4; i++)
{
for (j = 0; j < 4; j++)
{
ikey[i * 4 + j] = ikey[i * 4 + j] ^ initKey[i * 4 + j];
} // end of for
} // end of for
return (array2HStr(rijndael(md5(plain), ikey)));
} // End of the function
initKey = new Array(232, 179, 9, 49, 17, 182, 147, 22, 67, 153, 48, 202, 41, 89, 251, 31);
hex = new Array("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F");
code = encrypt(r, _root.CodeWord);
myLoadVars = new LoadVars();
myLoadVars.code = code;
myLoadVars.send("/enter.pl", "_self", "POST");
stop ();
Если произвести перевод с "actionscript" на "jаvаscript", то в обычном браузере можно продемонстрировать в точности то, что делала программа из флешки. Например, если ваш 2 пароль = 1111, а значение ключа = 1244201195.28292 , то программа сгенерирует 32-разрядный 16-ричный код равный 23DEE2845DFB629D7973E527A8A505EC .
<html><body><script>\n
//ключ - 1244201195.28292 (генерируется каждый раз новый при вызове второго пароля)
//пароль - 1111
//на выходе - 23DEE2845DFB629D7973E527A8A505EC
for (i = 1; i < 11; i++)
{
for (j = 0; j < 4; j++)
{
for (k = 0; k < 4; k++)
{
b[k] = w[(i - (j == 0) ? (1) : (0)) * 16 + k * 4 + (j == 0 ? (3) : (j - 1))];
} // end of for
if (j == 0)
{
for (k = 0; k < 4; k++)
{
if (k < 3)
{
b[k] = sBox[b[k + 1]];
continue;
} // end if
b[k] = sBox[0] ^ rCon[i];
} // end of for
} // end if
for (k = 0; k < 4; k++)
{
w[i * 16 + k * 4 + j] = w[(i - 1) * 16 + k * 4 + j] ^ b[k];
} // end of for
} // end of for
} // end of for
for (i = 0; i < 4; i++)
{
for (j = 0; j < 4; j++)
{
tar[i * 4 + j] = src[i * 4 + j] ^ w[i * 4 + j];
} // end of for
} // end of for
for (i = 1; i < 4; i++)
{
for (l = 0; l < i; l++)
{
tmp = tar[i * 4];
for (j = 0; j < 3; j++)
{
tar[i * 4 + j] = tar[i * 4 + (j + 1) % 4];
} // end of for
tar[i * 4 + 3] = tmp;
} // end of for
} // end of for
if (k != 9)
{
for (j = 0; j < 4; j++)
{
for (i = 0; i < 4; i++)
{
tmp = tar[i * 4 + j] ^ tar[(i + 1) % 4 * 4 + j];
b[i] = tar[(i + 1) % 4 * 4 + j] ^ tar[(i + 2) % 4 * 4 + j] ^ tar[(i + 3) % 4 * 4 + j] ^ (tmp > 127 ? (tmp << 1 ^ 283) : (tmp << 1));
} // end of for
for (i = 0; i < 4; i++)
{
tar[i * 4 + j] = b[i];
} // end of for
} // end of for
} // end if
for (i = 0; i < 4; i++)
{
for (j = 0; j < 4; j++)
{
tar[i * 4 + j] = tar[i * 4 + j] ^ w[(k + 1) * 16 + i * 4 + j];
} // end of for
} // end of for
return (tar);
} // End of the function
function md5(src)
{
var str = new String(src);
tar = new Array(16);
res = new Array(16);
for (i = 0; i < src.length || i < 16; i++)
{
res[i] = Number(str.charCodeAt(i)) ^ i * 4;
} // end of for
for (i = 0; i < 4; i++)
{
for (j = 0; j < 4; j++)
{
tar[i * 4 + j] = (res[j * 4 + i] + 256) % 256;
} // end of for
} // end of for
return (tar);
} // End of the function
function array2HStr(src)
{
res = "";
for (i = 0; i < 16; i++)
{
res = res + (hex[src[i] >> 4] + hex[src[i] % 16]);
} // end of for
return (res);
} // End of the function
function encrypt(plain, pass)
{
ikey = md5(pass);
for (i = 0; i < 4; i++)
{
for (j = 0; j < 4; j++)
{
ikey[i * 4 + j] = ikey[i * 4 + j] ^ initKey[i * 4 + j];
} // end of for
} // end of for
return (array2HStr(rijndael(md5(plain), ikey)));
} // End of the function
initKey = new Array(232, 179, 9, 49, 17, 182, 147, 22, 67, 153, 48, 202, 41, 89, 251, 31);
hex = new Array("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F");
Однако, не так давно способ обработки второго пароля был изменён. Вместо флешки теперь клавиатура на jаvаscript. Внешний вид не блещет изяществом, зато можно перемешивать кнопки, чтобы какой-нибудь клавиатурно-мышковый шпион не просёк что вы там клацаете. А что же мы имеем с криптованием ? Давайте взглянем на исходный код страницы запрса второго пароля. Если посторочно разобрать код из странички, то увидим простое MD5 шифрование, описанное, например, тут: http://jаvаscript.ru/php/md5 , Автор: dev5er6, дата: 3 июня, 2013 - 10:17 "Сжатая версия функции md5".
Велосипед никто изобретать не захотел, и пошли по пути простому, короткому, и быстрому. В настоящий момент криптование пароля имеет такой синтаксис: cryptcode=md5(session+"pass"+pas), где параметр session, переданный сервером клиенту, выполняет роль ключа, а слово "pass" - добавленно для понта.
Вывод: Об улучшении криптозащиты в новой версии - говорить не приходится, а с другой стороны - нужна ли там мощная криптозащита ? В общем не особо то она и нужна, средненького криптования, вроде имеющегося, - с головой достаточно, чтобы отбить желание у взломщика перехватывать данные, а "перемешивание кнопок" - весьма полезная функция для ввода в заблуждение клавиатурно-мышкового шпиона, благодаря этому можно сказать, что новый вариант по функции защиты лучше предыдущего. Единственное замечание - внешний вид, - оформление оставляет желать лучшего.