МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ
НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ «ЛЬВІВСЬКА ПОЛІТЕХНІКА»
Кафедра БІТ
Практична робота № 2
Симетричний алгоритм блокового шифрування AES
з навчальної дисципліни: “Прикладна криптологія”
Львів – 2011
Завдання
Написати програму, яка здійснює шифрування і розшифрування тексту за допомогою блокового шифру AES
Теоретичний вступ
Advanced Encryption Standard (AES), також відомий під назвою Rijndael - симетричний алгоритм блочного шифрування (розмір блока 128 біт, ключ 128/192/256 біт), фіналіст конкурсу AES і прийнятий в якості американского стандарту шифрування урядом США. Вибір припав на AES з розрахуванням на широке використання і активний аналіз алгоритму, як це було із його попередником, DES. Державний інститут стандартів і технологій (англ. National Institute of Standards and Technology, NIST) США опублікував попередню специфікацію AES 26 жовтня 2001 року, після п'ятилітньої підготовки. 26 травня 2002 року AES оголошено стандартом шифрування. Станом на 2006 рік AES є одним із найпоширеніших алгоритмів симетричного шифрування.
Потреба у новому стандарті шифрування постала у середині 90-х років. Наявний тоді стандарт DES, довжиною ключа 56 біт, дозволяв застосувати метод грубої сили для дешифрування даних. Успішні злами даних стались уже в кінці 90-х. Крім того архітектура DES орієнтувалась на апаратну реалізацію, а програмна реалізація на платформах із обмеженими ресурсами не давала необхідної швидкості застосування. Модифікація DES 3- DES мала достатню довжину ключа, але при цьому була ще повільнішою.
12 жовтня 1997 р. NIST оголосила конкурс на обрання спадкоємця для DES, що був американським стандартом ще з 1977 року. Перед претендентами поставили такі основні вимоги:
• блочний шифр
• довжина блоку 128 біт
• ключі довжиною 128, 192 і 256 біт.
Вибір алгоритму проходив у три етапи. 20 серпня 1998 року на 1-й конференції AES було оголошено список з 15 кандидатів. В серпні 1999 року на 2-й конференції AES список скоротився до п'яти фіналістів: MARS, RC6, Rijndael, Serpent и Twofish. За результатами доповідей 3-ї конференції, що проходила у Нью Йорку 13-14 квітня 2000 року, 2 жовтня 2000 алгоритм, запропонований бельгійськими криптографами Д. Деймоном та В. Ріджменом, був оголошений переможцем конкурсу і почалась процедура стандартизації[1]. 26 травня 2002 року AES був прийнятий як стандарт.
Текст програми
<?php
echo '
<html>
<head>
<meta charset="utf-8">
<title>AES</title>
<link rel="stylesheet" type="text/css" title="default" media="screen" href="main.css">
<script type="text/javascript" src="parse.js"></script>
</head>
<body onload="check();">
<div class="workfield" id="workfield">
<form name="io" method="post">
<input style="float:left" type="text" id="phrase" name="inputPhrase" value="'.$_COOKIE['text'].'">
<input style="float:left" type="text" id="key" name="key" maxlength="42" value="'.$_COOKIE['key'].'">
<input type="hidden" id="tmp" value="" />
<center>
<input type="radio" name="keyLength" value="128" /> 128
<input type="radio" name="keyLength" value="192" /> 192
<input type="radio" name="keyLength" value="256" checked="true"/> 256
</center>
<input type="submit" name="button" value="Rjindael" class="button" onclick="temp.php">
</form>
';
echo '<div id="output" class="output">';
$text = $_POST['inputPhrase'];
$password = $_POST['key'];
$blocksize = $_POST['keyLength']; // can be 128, 192, 256;
setcookie('text', $text, time() + 3600*24*7);
setcookie('key', $password, time() + 3600*24*7);
setcookie('blocksize', $blocksize, time() + 3600*24*7);
echo 'text = '.$text;
echo "<br />block size = $blocksize";
$crypted = AES::encrypt( $text, $password, $blocksize );
echo '<br />crypted = ';AES::array_show($tre = str_split($crypted, 16));
// do something ...
$decrypted = AES::decrypt( $crypted, $password, $blocksize );
echo '<br />decrypted = '.$decrypted;
/* aes.php Copyright © 2005-2008 Chris Veness. Right of free use is granted for all
* commercial or non-commercial use. No warranty of any form is offered.
*/
class AES {
/** Sbox is pre-computed multiplicative inverse in GF(2^8) used in SubBytes and KeyExpansion [§5.1.1] */
protected static $Sbox = array(
0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,
0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,
0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,
0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,
0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,
0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,
0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,
0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,
0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,
0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,
0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,
0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,
0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,
0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,
0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,
0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16
);
protected static $ISbox = array(
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
);
public static function fix($str){
//echo '<br />$str = '.$str;
$sad = str_replace(" ", ", 0x", $str);
//echo "<hr /> sda = $sad";
return 0;
}
/** Rcon is Round Constant used for the Key Expansion [1st col is 2^(r-1) in GF(2^8)] [§5.2] */
protected static $Rcon = array(
array(0x00, 0x00, 0x00, 0x00),
array(0x01, 0x00, 0x00, 0x00),
array(0x02, 0x00, 0x00, 0x00),
array(0x04, 0x00, 0x00, 0x00),
array(0x08, 0x00, 0x00, 0x00),
array(0x10, 0x00, 0x00, 0x00),
array(0x20, 0x00, 0x00, 0x00),
array(0x40, 0x00, 0x00, 0x00),
array(0x80, 0x00, 0x00, 0x00),
array(0x1b, 0x00, 0x00, 0x00),
array(0x36, 0x00, 0x00, 0x00),
);
/**
* AES Cipher function: encrypt 'input' with Rijndael algorithm
*
* @param input message as byte-array (16 bytes)
* @param w key schedule as 2D byte-array (Nr+1 x Nb bytes) -
* generated from the cipher key by KeyExpansion()
* @return ciphertext as byte-array (16 bytes)
*/
protected static function Cipher($input, $w) { // main Cipher function [§5.1]
$Nb = 4; // block size (in words): no of columns in state (fixed at 4 for AES)
$Nr = count($w)/$Nb - 1; // no of rounds: 10/12/14 for 128/192/256-bit keys
$state = array(); // initialise 4xNb byte-array 'state' with input [§3.4]
// 1 2 3 4 5 6 7 8 9 -> 1 5 9 ..
// 2 6
// 3 7
// 4 8
for ($i = 0; $i < 4 * $Nb; $i++) $state[$i % $Nb][floor($i / $Nb)] = $input[$i];
$state = self::AddRoundKey($state, $w, 0, $Nb);
for ($round = 1; $round < $Nr; $round++) { // apply Nr rounds
$state = self::SubBytes($state, $Nb);
$state = self::ShiftRows($state, $Nb);
$state = self::MixColumns($state, $Nb);
$state = self::AddRoundKey($state, $w, $round, $Nb);
}
$state = self::SubBytes($state, $Nb);
$state = self::ShiftRows($state, $Nb);
$state = self::AddRoundKey($state, $w, $Nr, $Nb);
$output = array(); // convert state to 1-d array before returning [§3.4]
for ($i = 0; $i < 4 * $Nb; $i++) $output[$i] = $state[$i % 4][floor($i / 4)];
return $output;
}
protected static function Decipher($input, $w) { // main Cipher function [§5.1]
$Nb = 4; // block size (in words): no of columns in state (fixed at 4 for AES)
$Nr = count($w)/$Nb - 1; // no of rounds: 10/12/14 for 128/192/256-bit keys
//echo '<br />input = ';self::array_show($input);
//echo '<br /> key = ';self::array_show($w);
$state = array(); // initialise 4xNb byte-array 'state' with input [§3.4]
// 1 2 3 4 5 6 7 8 9 -> 1 5 9 ..
// 2 6
// 3 7
// 4 8
for ($i = 0; $i < 4 * $Nb; $i++) $state[$i % $Nb][floor($i / $Nb)] = $input[$i];
$state = self::AddRoundKey($state, $w, $Nr, $Nb);
for ($round = $Nr - 1; $round >= 1; $round--) { // apply Nr rounds
$state = self::InvShiftRows($state, $Nb);
$state = self::InvSubBytes ($state, $Nb);
$state = self::AddRoundKey ($state, $w, $round, $Nb);
$state = self::InvMixColumns($state, $Nb);
}
$state = self::InvShiftRows($state, $Nb);
$state = self::InvSubBytes ($state, $Nb);
$state = self::AddRoundKey ($state, $w, 0, $Nb);
$output = array(); // convert state to 1-d array before returning [§3.4]
for ($i = 0; $i < 4*$Nb; $i++) $output[$i] = $state[$i%4][floor($i/4)];
return $output;
}
protected static function AddRoundKey($state, $w, $rnd, $Nb) { // xor Round Key into state S [§5.1.4]
for ($r=0; $r<4; $r++) {
for ($c=0; $c<$Nb; $c++) $state[$r][$c] ^= $w[$rnd*4+$c][$r];
}
return $state;
}
protected static function SubBytes($s, $Nb) { // apply SBox to state S [§5.1.1]
for ($r=0; $r<4; $r++) {
for ($c=0; $c<$Nb; $c++) $s[$r][$c] = self::$Sbox[$s[$r][$c]];
}
return $s;
}
protected static function InvSubBytes($s, $Nb) { // apply SBox to state S [§5.1.1]
for ($r=0; $r<4; $r++) {
for ($c=0; $c<$Nb; $c++) $s[$r][$c] = self::$ISbox[$s[$r][$c]];
}
return $s;
}
/**
* shift row r of state S left by r bytes [§5.1.2]
* @param $s
* @param $Nb
* @return
*/
protected static function ShiftRows($s, $Nb) {
$t = array();
for ($r = 1; $r < 4; $r++) {
for ($c = 0; $c < $Nb; $c++) {
//echo "<br />t[$c] = s[$r][($c+$r)%$Nb]"; // shift into temp copy
$t[$c] = $s[$r][($c + $r) % $Nb]; // shift into temp copy
}
for ($c = 0; $c < $Nb; $c++) {
//echo "<br />s[$r][$c] = t[$c]"; // and copy back
$s[$r][$c] = $t[$c]; // and copy back
}
} // note that this will work for Nb=4,5,6, but not 7,8 (always 4 for AES):
return $s;
}
protected static function InvShiftRows($s, $Nb) {
$t = array();
for ($r = 1; $r < 4; $r++) {
for ($c = 0; $c < $Nb; $c++) {
//echo "<br />t[".($c + $r) % $Nb."] = s[$r][$c]"; // shift into temp copy
$t[($c + $r) % $Nb] = $s[$r][$c]; // shift into temp copy
}
for ($c = 0; $c < $Nb; $c++) {
//echo "<br />s[$r][$c] = t[$c] == $t[$c]"; // and copy back
$s[$r][$c] = $t[$c]; // and copy back
}
} // note that this will work for Nb=4,5,6, but not 7,8 (always 4 for AES):
return $s;
}
protected static $multiplyOf2 = array(
0x00,0x02,0x04,0x06,0x08,0x0a,0x0c,0x0e,0x10,0x12,0x14,0x16,0x18,0x1a,0x1c,0x1e,
0x20,0x22,0x24,0x26,0x28,0x2a,0x2c,0x2e,0x30,0x32,0x34,0x36,0x38,0x3a,0x3c,0x3e,
0x40,0x42,0x44,0x46,0x48,0x4a,0x4c,0x4e,0x50,0x52,0x54,0x56,0x58,0x5a,0x5c,0x5e,
0x60,0x62,0x64,0x66,0x68,0x6a,0x6c,0x6e,0x70,0x72,0x74,0x76,0x78,0x7a,0x7c,0x7e,
0x80,0x82,0x84,0x86,0x88,0x8a,0x8c,0x8e,0x90,0x92,0x94,0x96,0x98,0x9a,0x9c,0x9e,
0xa0,0xa2,0xa4,0xa6,0xa8,0xaa,0xac,0xae,0xb0,0xb2,0xb4,0xb6,0xb8,0xba,0xbc,0xbe,
0xc0,0xc2,0xc4,0xc6,0xc8,0xca,0xcc,0xce,0xd0,0xd2,0xd4,0xd6,0xd8,0xda,0xdc,0xde,
0xe0,0xe2,0xe4,0xe6,0xe8,0xea,0xec,0xee,0xf0,0xf2,0xf4,0xf6,0xf8,0xfa,0xfc,0xfe,
0x1b,0x19,0x1f,0x1d,0x13,0x11,0x17,0x15,0x0b,0x09,0x0f,0x0d,0x03,0x01,0x07,0x05,
0x3b,0x39,0x3f,0x3d,0x33,0x31,0x37,0x35,0x2b,0x29,0x2f,0x2d,0x23,0x21,0x27,0x25,
0x5b,0x59,0x5f,0x5d,0x53,0x51,0x57,0x55,0x4b,0x49,0x4f,0x4d,0x43,0x41,0x47,0x45,
0x7b,0x79,0x7f,0x7d,0x73,0x71,0x77,0x75,0x6b,0x69,0x6f,0x6d,0x63,0x61,0x67,0x65,
0x9b,0x99,0x9f,0x9d,0x93,0x91,0x97,0x95,0x8b,0x89,0x8f,0x8d,0x83,0x81,0x87,0x85,
0xbb,0xb9,0xbf,0xbd,0xb3,0xb1,0xb7,0xb5,0xab,0xa9,0xaf,0xad,0xa3,0xa1,0xa7,0xa5,
0xdb,0xd9,0xdf,0xdd,0xd3,0xd1,0xd7,0xd5,0xcb,0xc9,0xcf,0xcd,0xc3,0xc1,0xc7,0xc5,
0xfb,0xf9,0xff,0xfd,0xf3,0xf1,0xf7,0xf5,0xeb,0xe9,0xef,0xed,0xe3,0xe1,0xe7,0xe5
);
protected static $multiplyOf3 = array(
0x00,0x03,0x06,0x05,0x0c,0x0f,0x0a,0x09,0x18,0x1b,0x1e,0x1d,0x14,0x17,0x12,0x11,
0x30,0x33,0x36,0x35,0x3c,0x3f,0x3a,0x39,0x28,0x2b,0x2e,0x2d,0x24,0x27,0x22,0x21,
0x60,0x63,0x66,0x65,0x6c,0x6f,0x6a,0x69,0x78,0x7b,0x7e,0x7d,0x74,0x77,0x72,0x71,
0x50,0x53,0x56,0x55,0x5c,0x5f,0x5a,0x59,0x48,0x4b,0x4e,0x4d,0x44,0x47,0x42,0x41,
0xc0,0xc3,0xc6,0xc5,0xcc,0xcf,0xca,0xc9,0xd8,0xdb,0xde,0xdd,0xd4,0xd7,0xd2,0xd1,
0xf0,0xf3,0xf6,0xf5,0xfc,0xff,0xfa,0xf9,0xe8,0xeb,0xee,0xed,0xe4,0xe7,0xe2,0xe1,
0xa0,0xa3,0xa6,0xa5,0xac,0xaf,0xaa,0xa9,0xb8,0xbb,0xbe,0xbd,0xb4,0xb7,0xb2,0xb1,
0x90,0x93,0x96,0x95,0x9c,0x9f,0x9a,0x99,0x88,0x8b,0x8e,0x8d,0x84,0x87,0x82,0x81,
0x9b,0x98,0x9d,0x9e,0x97,0x94,0x91,0x92,0x83,0x80,0x85,0x86,0x8f,0x8c,0x89,0x8a,
0xab,0xa8,0xad,0xae,0xa7,0xa4,0xa1,0xa2,0xb3,0xb0,0xb5,0xb6,0xbf,0xbc,0xb9,0xba,
0xfb,0xf8,0xfd,0xfe,0xf7,0xf4,0xf1,0xf2,0xe3,0xe0,0xe5,0xe6,0xef,0xec,0xe9,0xea,
0xcb,0xc8,0xcd,0xce,0xc7,0xc4,0xc1,0xc2,0xd3,0xd0,0xd5,0xd6,0xdf,0xdc,0xd9,0xda,
0x5b,0x58,0x5d,0x5e,0x57,0x54,0x51,0x52,0x43,0x40,0x45,0x46,0x4f,0x4c,0x49,0x4a,
0x6b,0x68,0x6d,0x6e,0x67,0x64,0x61,0x62,0x73,0x70,0x75,0x76,0x7f,0x7c,0x79,0x7a,
0x3b,0x38,0x3d,0x3e,0x37,0x34,0x31,0x32,0x23,0x20,0x25,0x26,0x2f,0x2c,0x29,0x2a,
0x0b,0x08,0x0d,0x0e,0x07,0x04,0x01,0x02,0x13,0x10,0x15,0x16,0x1f,0x1c,0x19,0x1a
);
protected static $multiplyOf9 = array(
0x00,0x09,0x12,0x1b,0x24,0x2d,0x36,0x3f,0x48,0x41,0x5a,0x53,0x6c,0x65,0x7e,0x77,
0x90,0x99,0x82,0x8b,0xb4,0xbd,0xa6,0xaf,0xd8,0xd1,0xca,0xc3,0xfc,0xf5,0xee,0xe7,
0x3b,0x32,0x29,0x20,0x1f,0x16,0x0d,0x04,0x73,0x7a,0x61,0x68,0x57,0x5e,0x45,0x4c,
0xab,0xa2,0xb9,0xb0,0x8f,0x86,0x9d,0x94,0xe3,0xea,0xf1,0xf8,0xc7,0xce,0xd5,0xdc,
0x76,0x7f,0x64,0x6d,0x52,0x5b,0x40,0x49,0x3e,0x37,0x2c,0x25,0x1a,0x13,0x08,0x01,
0xe6,0xef,0xf4,0xfd,0xc2,0xcb,0xd0,0xd9,0xae,0xa7,0xbc,0xb5,0x8a,0x83,0x98,0x91,
0x4d,0x44,0x5f,0x56,0x69,0x60,0x7b,0x72,0x05,0x0c,0x17,0x1e,0x21,0x28,0x33,0x3a,
0xdd,0xd4,0xcf,0xc6,0xf9,0xf0,0xeb,0xe2,0x95,0x9c,0x87,0x8e,0xb1,0xb8,0xa3,0xaa,
0xec,0xe5,0xfe,0xf7,0xc8,0xc1,0xda,0xd3,0xa4,0xad,0xb6,0xbf,0x80,0x89,0x92,0x9b,
0x7c,0x75,0x6e,0x67,0x58,0x51,0x4a,0x43,0x34,0x3d,0x26,0x2f,0x10,0x19,0x02,0x0b,
0xd7,0xde,0xc5,0xcc,0xf3,0xfa,0xe1,0xe8,0x9f,0x96,0x8d,0x84,0xbb,0xb2,0xa9,0xa0,
0x47,0x4e,0x55,0x5c,0x63,0x6a,0x71,0x78,0x0f,0x06,0x1d,0x14,0x2b,0x22,0x39,0x30,
0x9a,0x93,0x88,0x81,0xbe,0xb7,0xac,0xa5,0xd2,0xdb,0xc0,0xc9,0xf6,0xff,0xe4,0xed,
0x0a,0x03,0x18,0x11,0x2e,0x27,0x3c,0x35,0x42,0x4b,0x50,0x59,0x66,0x6f,0x74,0x7d,
0xa1,0xa8,0xb3,0xba,0x85,0x8c,0x97,0x9e,0xe9,0xe0,0xfb,0xf2,0xcd,0xc4,0xdf,0xd6,
0x31,0x38,0x23,0x2a,0x15,0x1c,0x07,0x0e,0x79,0x70,0x6b,0x62,0x5d,0x54,0x4f,0x46
);
protected static $multiplyOf11 = array(
0x00,0x0b,0x16,0x1d,0x2c,0x27,0x3a,0x31,0x58,0x53,0x4e,0x45,0x74,0x7f,0x62,0x69,
0xb0,0xbb,0xa6,0xad,0x9c,0x97,0x8a,0x81,0xe8,0xe3,0xfe,0xf5,0xc4,0xcf,0xd2,0xd9,
0x7b,0x70,0x6d,0x66,0x57,0x5c,0x41,0x4a,0x23,0x28,0x35,0x3e,0x0f,0x04,0x19,0x12,
0xcb,0xc0,0xdd,0xd6,0xe7,0xec,0xf1,0xfa,0x93,0x98,0x85,0x8e,0xbf,0xb4,0xa9,0xa2,
0xf6,0xfd,0xe0,0xeb,0xda,0xd1,0xcc,0xc7,0xae,0xa5,0xb8,0xb3,0x82,0x89,0x94,0x9f,
0x46,0x4d,0x50,0x5b,0x6a,0x61,0x7c,0x77,0x1e,0x15,0x08,0x03,0x32,0x39,0x24,0x2f,
0x8d,0x86,0x9b,0x90,0xa1,0xaa,0xb7,0xbc,0xd5,0xde,0xc3,0xc8,0xf9,0xf2,0xef,0xe4,
0x3d,0x36,