SHOW:
|
|
- or go back to the newest paste.
| 1 | <?php | |
| 2 | ||
| 3 | /** Êëàññ îñóùåñòâëÿþùèé ðàáîòó ñ øèôðîì ÃÎÑÒ 28147-89 (øèôðîâàíèå/äåøèôðîâàííèå äàííûõ) | |
| 4 | * | |
| 5 | * @author IntSys | |
| 6 | * @copyright Copyright (c) 2011-2013, IntSys, intsystem.org | |
| 7 | */ | |
| 8 | class ClassGost{
| |
| 9 | /** Êîëè÷åñòî èòòåðàöèé îñíîâíîãî øàãà êðèïòîîáðàçîâàíèÿ | |
| 10 | */ | |
| 11 | const CNT_MAIN_STEP=32; | |
| 12 | ||
| 13 | /** Òàáëèöà çàìåí | |
| 14 | * | |
| 15 | * @var array | |
| 16 | */ | |
| 17 | protected $s_block=array( | |
| 18 | array(6,12,7,1,5,15,13,8,4,10,9,14,0,3,11,2), | |
| 19 | array(14,11,4,12,6,13,15,10,2,3,8,1,0,7,5,9), | |
| 20 | array(13,11,4,1,3,15,5,9,0,10,14,7,6,8,2,12), | |
| 21 | array(7,13,10,1,0,8,9,15,14,4,6,12,11,2,5,3), | |
| 22 | array(1,15,13,0,5,7,10,4,9,2,3,14,6,11,8,12), | |
| 23 | array(4,10,9,2,13,8,0,14,6,11,1,12,7,15,5,3), | |
| 24 | array(4,11,10,0,7,2,1,13,3,6,8,5,9,12,15,14), | |
| 25 | array(5,8,1,13,10,3,4,2,14,15,12,7,6,0,9,11), | |
| 26 | ||
| 27 | ); | |
| 28 | ||
| 29 | /** Êëþ÷ | |
| 30 | * | |
| 31 | * @var array | |
| 32 | */ | |
| 33 | protected $k_block=array ( | |
| 34 | 0x00000000, | |
| 35 | 0x00000000, | |
| 36 | 0x00000000, | |
| 37 | 0x00000000, | |
| 38 | 0x00000000, | |
| 39 | 0x00000000, | |
| 40 | 0x00000000, | |
| 41 | 0x00000000, | |
| 42 | ); | |
| 43 | ||
| 44 | ||
| 45 | /** Çàøèôðîâàòü äàííûå | |
| 46 | * | |
| 47 | * @param string $data äàííûå äëÿ øèôðîâàíèÿ | |
| 48 | * @param mixed $key êëþ÷ øèôðîâàíèÿ | |
| 49 | * @param array $table òàáëèöà çàìåí | |
| 50 | * @return mixed âîçâðàùàåò çàøèôðîâàííóþ ñòðîêó, èëè false â ñëó÷àå íåóäà÷è | |
| 51 | */ | |
| 52 | function Encode($data, $key=null, $table=null){
| |
| 53 | if(!is_null($key)){
| |
| 54 | if(!$this->SetKey($key)){
| |
| 55 | return false; | |
| 56 | } | |
| 57 | } | |
| 58 | ||
| 59 | if(!is_null($table)){
| |
| 60 | if(!$this->SetTableReplace($table)){
| |
| 61 | return false; | |
| 62 | } | |
| 63 | } | |
| 64 | ||
| 65 | $blocks=$this->LoadData2Blocks($data); | |
| 66 | $keys=$this->LoadKeysArray(self::CNT_MAIN_STEP); | |
| 67 | ||
| 68 | $result=''; | |
| 69 | ||
| 70 | foreach($blocks as $block){
| |
| 71 | $result.=$this->Global_MainStep($block, $keys); | |
| 72 | ||
| 73 | } | |
| 74 | ||
| 75 | return $result; | |
| 76 | } | |
| 77 | ||
| 78 | /** Ðàñøèôðîâàòü äàííûå | |
| 79 | * | |
| 80 | * @param string $data çàøèôðîâàííûå äàííûå | |
| 81 | * @param mixed $key êëþ÷ øèôðîâàíèÿ | |
| 82 | * @param array $table òàáëèöà çàìåí | |
| 83 | * @return mixed âîçâðàùàåò èñõîäíûå äàííûå, èëè false â ñëó÷àå íåóäà÷è | |
| 84 | */ | |
| 85 | function Decode($data, $key=null, $table=null){
| |
| 86 | if(!is_null($key)){
| |
| 87 | if(!$this->SetKey($key)){
| |
| 88 | return false; | |
| 89 | } | |
| 90 | } | |
| 91 | ||
| 92 | if(!is_null($table)){
| |
| 93 | if(!$this->SetTableReplace($table)){
| |
| 94 | return false; | |
| 95 | } | |
| 96 | } | |
| 97 | ||
| 98 | $blocks=$this->LoadData2Blocks($data); | |
| 99 | $keys=array_reverse($this->LoadKeysArray(self::CNT_MAIN_STEP)); | |
| 100 | ||
| 101 | $result=''; | |
| 102 | foreach($blocks as $block){
| |
| 103 | $result.=$this->Global_MainStep($block, $keys); | |
| 104 | } | |
| 105 | ||
| 106 | return $result; | |
| 107 | } | |
| 108 | ||
| 109 | /** Óñòàíîâèòü êëþ÷ øèôðîâàíèÿ<br><br> | |
| 110 | * Âîçìîæíî óêàçàòü êëþ÷ â äâóõ ôîðìàòàõ:<br> | |
| 111 | * - Ñòðîêà äëèííîé â 32 áàéòà<br> | |
| 112 | * - Ìàññèâ èç 8 ýëåìåíòîâ, ãäå êàæäûé ýëåìåíò - 4 áàéòîâîå ÷èñëî integer<br><br> | |
| 113 | * Ïðè ýòîì ëþáîå îòêëîíåíèå îò äàííûõ ôîðìàòîâ áóäåò âûçûâàòü îøèáêó | |
| 114 | * | |
| 115 | * @param mixed $key êëþ÷ øèôðîâàíèÿ | |
| 116 | * @return boolen âîçâðàùàåò true åñëè óäàëîñü óñòàíîâèòü êëþ÷ øèôðîâàíèÿ, false - åñëè ïðîèçîøëà îøèáêà | |
| 117 | */ | |
| 118 | function SetKey($key){
| |
| 119 | if(is_string($key)){
| |
| 120 | if(strlen($key)!==32){
| |
| 121 | trigger_error(__METHOD__.': "$key" length must be equal to 256 bits (32 bytes)', E_USER_WARNING); | |
| 122 | return false; | |
| 123 | } | |
| 124 | ||
| 125 | $new_key=array(); | |
| 126 | for($i=0; $i<32; $i+=4){
| |
| 127 | // $tmp=(int)hexdec(bin2hex(substr($key, ($i*4), 4))); | |
| 128 | $tmp=(int)hexdec(bin2hex(substr($key, ($i), 4))); | |
| 129 | $new_key[]=$tmp; | |
| 130 | } | |
| 131 | ||
| 132 | $this->k_block=$new_key; | |
| 133 | return true; | |
| 134 | }elseif(is_array($key)){
| |
| 135 | if(count($key)!=8){
| |
| 136 | trigger_error(__METHOD__.': count of elements in the array "$key" must be equal to 8', E_USER_WARNING); | |
| 137 | return false; | |
| 138 | } | |
| 139 | $new_key=array(); | |
| 140 | foreach($key as $k => $val){
| |
| 141 | if(!is_integer($val)){
| |
| 142 | trigger_error(__METHOD__.': every element of the array "$key" must be integer. The array element "$table['.htmlspecialchars($k).']" is not an integer.', E_USER_WARNING); | |
| 143 | return false; | |
| 144 | } | |
| 145 | ||
| 146 | $new_key[]=$val; | |
| 147 | } | |
| 148 | ||
| 149 | $this->k_block=$new_key; | |
| 150 | return true; | |
| 151 | }else{
| |
| 152 | trigger_error(__METHOD__.': unknown "$Key" format. "$key" must be array[8] of integer or 32-bytes string.', E_USER_WARNING); | |
| 153 | return false; | |
| 154 | } | |
| 155 | } | |
| 156 | ||
| 157 | /** Óñòàíîâèòü òàáëèöó çàìåí.<br> | |
| 158 | * Ôîðìàò òàáëèöû çàìåí - ìàòðèöà ðàçìåðíîñòüþ 8x16, | |
| 159 | * êàæäûé åå ýëåìåíò áîëüøå ëèáî ðàâåí 0 è ìåíüøå ëèáî ðàâåí 15, | |
| 160 | * ïðè ýòîì â êàæäîé ñòðîêå íå äîëæíî áûòü ïîâòîðÿþùèõñÿ çíà÷åíèé.<br><br> | |
| 161 | * Òàêæå îáðàòèòå âíèìàíèå ÷òî íåïðàâèëüíûé âûáîð òàáëèöû çàìåí, ìîæåò | |
| 162 | * ïðèâåñòè ê ñíèæåíèþ ñòîéêîñòè øèôðà. | |
| 163 | * | |
| 164 | * @example | |
| 165 | * Ïðèìåð òàáëèöû:<br> | |
| 166 | * array(6 ,12,7 ,1 ,5 ,15,13,8 ,4 ,10,9 ,14,0 ,3 ,11,2 ),<br> | |
| 167 | * array(14,11,4 ,12,6 ,13,15,10,2 ,3 ,8 ,1 ,0 ,7 ,5 ,9 ),<br> | |
| 168 | * array(13,11,4 ,1 ,3 ,15,5 ,9 ,0 ,10,14,7 ,6 ,8 ,2 ,12),<br> | |
| 169 | * array(7 ,13,10,1 ,0 ,8 ,9 ,15,14,4 ,6 ,12,11,2 ,5 ,3 ),<br> | |
| 170 | * array(1 ,15,13,0 ,5 ,7 ,10,4 ,9 ,2 ,3 ,14,6 ,11,8 ,12),<br> | |
| 171 | * array(4 ,10,9 ,2 ,13,8 ,0 ,14,6 ,11,1 ,12,7 ,15,5 ,3 ),<br> | |
| 172 | * array(4 ,11,10,0 ,7 ,2 ,1 ,13,3 ,6 ,8 ,5 ,9 ,12,15,14),<br> | |
| 173 | * array(5 ,8 ,1 ,13,10,3 ,4 ,2 ,14,15,12,7 ,6 ,0 ,9 ,11),<br> | |
| 174 | * | |
| 175 | * @param array $table òàáëèöà çàìåí | |
| 176 | * @return boolean âîçâðàùàåò true åñëè óäàëîñü óñòàíîâèòü òàáëèöó çàìåí, false- åñëè ïðîèçîøëà îøèáêà | |
| 177 | */ | |
| 178 | function SetTableReplace($table){
| |
| 179 | if(!is_array($table)){
| |
| 180 | trigger_error(__METHOD__.': "$table" must be array', E_USER_WARNING); | |
| 181 | return false; | |
| 182 | } | |
| 183 | ||
| 184 | if(count($table)!=8){
| |
| 185 | trigger_error(__METHOD__.': count of elements in the array "$table" must be equal to 8', E_USER_WARNING); | |
| 186 | return false; | |
| 187 | } | |
| 188 | ||
| 189 | $i=0; | |
| 190 | $new_array=array(); | |
| 191 | foreach($table as $key => $val){
| |
| 192 | if(!is_array($val)){
| |
| 193 | trigger_error(__METHOD__.': $table['.htmlspecialchars($key).'] must be array', E_USER_WARNING); | |
| 194 | return false; | |
| 195 | } | |
| 196 | ||
| 197 | if(count($val)!=16){
| |
| 198 | trigger_error(__METHOD__.': count of elements in the array "$table['.htmlspecialchars($key).']" must be equal to 16', E_USER_WARNING); | |
| 199 | return false; | |
| 200 | } | |
| 201 | ||
| 202 | ||
| 203 | $new_val=array(); | |
| 204 | foreach($val as $int_key => $int_val){
| |
| 205 | if(!is_integer($int_val)){
| |
| 206 | trigger_error(__METHOD__.': every element of the array "$table['.htmlspecialchars($key).']" must be integer. The array element "$table['.htmlspecialchars($key).']['.htmlspecialchars($int_key).']" is not an integer.', E_USER_WARNING); | |
| 207 | return false; | |
| 208 | } | |
| 209 | ||
| 210 | if($int_val>15 || $int_val<0){
| |
| 211 | trigger_error(__METHOD__.': every element of the array "$table['.htmlspecialchars($key).']" must be greater than or equal to 0 and less than or equal to 15. The array element "$table['.htmlspecialchars($key).']['.htmlspecialchars($int_key).']" is not in this range.', E_USER_WARNING); | |
| 212 | return false; | |
| 213 | } | |
| 214 | $new_val[]=$int_val; | |
| 215 | } | |
| 216 | ||
| 217 | $new_array[$i]=$new_val; | |
| 218 | $i++; | |
| 219 | } | |
| 220 | ||
| 221 | ||
| 222 | $this->s_block=$new_array; | |
| 223 | return true; | |
| 224 | } | |
| 225 | ||
| 226 | /** Îñíîâíîé øàã øèôðîîáðàçîâàíèÿ | |
| 227 | * | |
| 228 | * @param string $block øèôðóåìûé áëîê | |
| 229 | * @param array $keys ïîäãîòîâëåííûé ìàññèâ ñ êëþ÷àìè | |
| 230 | * @param intger $cnt_repeat [îïöèîíàëüíî] êîëè÷åñòâî ïðåîáðàçîâàíèé | |
| 231 | * @return string | |
| 232 | */ | |
| 233 | protected function Global_MainStep($block, $keys, $cnt_repeat=self::CNT_MAIN_STEP){
| |
| 234 | $this->Global_BlockExplode($block, $n1, $n2); | |
| 235 | ||
| 236 | if(count($keys)<$cnt_repeat){
| |
| 237 | $cnt_repeat=count($keys); | |
| 238 | } | |
| 239 | ||
| 240 | for($i=0; $i<$cnt_repeat; $i++){
| |
| 241 | $val=$this->Global_SummMod32($n1, $keys[$i]); | |
| 242 | ||
| 243 | $val=$this->Global_BlockReplace($val); | |
| 244 | ||
| 245 | $val=$this->Global_BlockCycleShift($val, 21); | |
| 246 | ||
| 247 | $val=$val ^ $n2; | |
| 248 | ||
| 249 | $n2=$n1; | |
| 250 | $n1=$val; | |
| 251 | } | |
| 252 | ||
| 253 | $this->Global_BlockImplode($block, $n2, $n1); | |
| 254 | return $block; | |
| 255 | } | |
| 256 | ||
| 257 | /** Ôóíêöèÿ öèêëè÷íîãî ïîáèòîâîãî ñäâèãà âïðàâî | |
| 258 | * | |
| 259 | * @param integer $block | |
| 260 | * @param integer $bits êîëè÷åñòâî áèòîâ äëÿ ñäâèãà | |
| 261 | * @return integer | |
| 262 | */ | |
| 263 | protected function Global_BlockCycleShift($block, $bits){
| |
| 264 | if($bits>0){
| |
| 265 | $a=$bits; | |
| 266 | $b=32-$a; | |
| 267 | $block=(($block >> $a) & ~(-pow(2,$b)))^($block << $b); | |
| 268 | } | |
| 269 | return $block; | |
| 270 | } | |
| 271 | ||
| 272 | /** Çàìåíà ïî òàáëèöå çàìåí | |
| 273 | * | |
| 274 | * @param integer $block òåêóùèé áëîê äëÿ çàìåíû | |
| 275 | * @return integer | |
| 276 | */ | |
| 277 | protected function Global_BlockReplace($block){
| |
| 278 | $new_block=0; | |
| 279 | ||
| 280 | for($i=0; $i<8; $i++){
| |
| 281 | //Âû÷ëåíÿåì íóæíûå 4 áèòà ïîä çàìåíó | |
| 282 | $rem=$block>>(4*($i+1)); | |
| 283 | $rem=$rem<<(4*($i+1)); | |
| 284 | ||
| 285 | if($i==7){
| |
| 286 | $hex=$rem; | |
| 287 | }else{
| |
| 288 | $hex=$block-$rem; | |
| 289 | $block=$rem; | |
| 290 | } | |
| 291 | ||
| 292 | $hex=$this->Global_BlockCycleShift($hex,(4*$i)); | |
| 293 | ||
| 294 | //Íàõîäèì íà êàêîå ÷èñëî åãî çàìåíÿòü ïî òàáëèöå çàìåí | |
| 295 | $replace=$this->s_block[$i][$hex]; | |
| 296 | ||
| 297 | //Çàìåíÿåì | |
| 298 | $new_block=$new_block + (pow(16, $i)*$replace); | |
| 299 | } | |
| 300 | ||
| 301 | return $new_block; | |
| 302 | } | |
| 303 | ||
| 304 | /** Ñóììèðîâàíèå äâóõ ÷èñåë ïî ìîäóëþ 32 | |
| 305 | * | |
| 306 | * @param integer $bin1 ÷èñëî (4 áàéòà) | |
| 307 | * @param integer $bin2 ÷èñëî (4 áàéòà) | |
| 308 | * @return integer ðåçóëüòàò âû÷èñëåíèÿ (4 áàéòà) | |
| 309 | */ | |
| 310 | protected function Global_SummMod32($bin1, $bin2){
| |
| 311 | $summ=$this->NormalizeInteger32(intval($bin1 + $bin2)); | |
| 312 | ||
| 313 | return $summ; | |
| 314 | } | |
| 315 | ||
| 316 | /** Ðàçáèåíèå áëîêà íà "ïðàâóþ" è "ëåâóþ" ÷àñòü | |
| 317 | * | |
| 318 | * @param string $block âõîäíîé áëîê (8 áàéò) | |
| 319 | * @param &integer $left ëåâàÿ ÷àñòü (íàêîïèòåëü N1) (4 áàéòà) | |
| 320 | * @param &integer $right ïðàâàÿ ÷àñòü (íàêîïèòåëü N2) (4 áàéòà) | |
| 321 | */ | |
| 322 | protected function Global_BlockExplode($block, &$left, &$right){
| |
| 323 | $left=''; | |
| 324 | $right=''; | |
| 325 | ||
| 326 | $left=substr($block, 0, 4); | |
| 327 | $right=substr($block, 4, 4); | |
| 328 | ||
| 329 | $left =hexdec(bin2hex($left )); | |
| 330 | $right=hexdec(bin2hex($right)); | |
| 331 | } | |
| 332 | ||
| 333 | /** Ðàçáèåíèå áëîêà íà "ïðàâóþ" è "ëåâóþ" ÷àñòü | |
| 334 | * | |
| 335 | * @param &string $block âõîäíîé áëîê (8 áàéò) | |
| 336 | * @param integer $left ëåâàÿ ÷àñòü (íàêîïèòåëü N1) (4 áàéòà) | |
| 337 | * @param integer $right ïðàâàÿ ÷àñòü (íàêîïèòåëü N2) (4 áàéòà) | |
| 338 | */ | |
| 339 | protected function Global_BlockImplode(&$block, $left, $right){
| |
| 340 | $left =sprintf("%08x", $left );
| |
| 341 | $right=sprintf("%08x", $right);
| |
| 342 | ||
| 343 | $block=''; | |
| 344 | ||
| 345 | $arr=str_split($left, 2); | |
| 346 | foreach($arr as $hex){
| |
| 347 | $block.=chr(hexdec($hex)); | |
| 348 | } | |
| 349 | ||
| 350 | $arr=str_split($right, 2); | |
| 351 | foreach($arr as $hex){
| |
| 352 | $block.=chr(hexdec($hex)); | |
| 353 | } | |
| 354 | } | |
| 355 | ||
| 356 | /** Ãåíåðèðóåì ìàññèâ ñ êëþ÷àìè | |
| 357 | * | |
| 358 | * @param integer $cnt_repeat êîëè÷åñòâî êëþ÷åé | |
| 359 | * @return array | |
| 360 | */ | |
| 361 | protected function LoadKeysArray($cnt_repeat=self::CNT_MAIN_STEP){
| |
| 362 | $key_block=array(); | |
| 363 | for($i=0; $i<$cnt_repeat; $i++){
| |
| 364 | if($i<($cnt_repeat-8)){
| |
| 365 | $x=$i % 8; | |
| 366 | }else{
| |
| 367 | $x=7 - ($i % 8); | |
| 368 | } | |
| 369 | $key_block[]=$this->k_block[$x]; | |
| 370 | } | |
| 371 | ||
| 372 | return $key_block; | |
| 373 | } | |
| 374 | ||
| 375 | /** Ðàçáèâàåì äàííûå íà áëîêè ïî 64 áèòà (8 áàéò) | |
| 376 | * | |
| 377 | * @param string $data âõîäíûå äàííûå | |
| 378 | * @param integer $block_size [îïöèîíàëüíî] (64 - äåôîëò) ðàçìåðíîñòü áëîêîâ | |
| 379 | * @return array âûõîäíîé ìàññèâ ñ áëîêàìè | |
| 380 | */ | |
| 381 | protected function LoadData2Blocks($data, $block_size=64){
| |
| 382 | $blocks=array(); | |
| 383 | ||
| 384 | $block_len=(int)$block_size / 8; | |
| 385 | ||
| 386 | for($i=0, $x=(ceil(strlen($data)/$block_len)); $i<$x; $i++){
| |
| 387 | $blocks[$i]=substr($data, ($i*$block_len), $block_len); | |
| 388 | ||
| 389 | if($i==($x-1)){
| |
| 390 | //Åñëè ïîñëåäíèé áëîê íå ïîëîí, òî äîïîëíÿåì åãî íóëÿìè | |
| 391 | $blocks[$i]=str_pad($blocks[$i], $block_len, chr(0), STR_PAD_RIGHT); | |
| 392 | ||
| 393 | } | |
| 394 | } | |
| 395 | ||
| 396 | return $blocks; | |
| 397 | } | |
| 398 | ||
| 399 | /** Ïðåâåäåíèå 64áèòíîãî integer ê "32áèòíîìó" íà 64áèòíûõ ñèñòåìàõ | |
| 400 | * | |
| 401 | * @param integer $number | |
| 402 | */ | |
| 403 | private function NormalizeInteger32($number){
| |
| 404 | static $is_64bit=null; | |
| 405 | ||
| 406 | $number=intval($number); | |
| 407 | ||
| 408 | if(is_null($is_64bit)){
| |
| 409 | if(intval(2147483647+1)>0){
| |
| 410 | $is_64bit=true; | |
| 411 | }else{
| |
| 412 | $is_64bit=false; | |
| 413 | } | |
| 414 | } | |
| 415 | ||
| 416 | if($is_64bit){
| |
| 417 | static $int=null; | |
| 418 | ||
| 419 | if(is_null($int)){
| |
| 420 | $int=0; | |
| 421 | ||
| 422 | //Ãåíåðèðóåì ÷èñëî ó êîòîðîãî â äâîè÷íîì ïðåäñòàâëåíèè ìëàäøèå 32 áèòà - åäèíèöû, îñòàëüíûå - íóëè | |
| 423 | // | |
| 424 | // 32-áèòíûõ ñèñòåìàõ ýòî ÷èñëî "-1" | |
| 425 | //Â 64-áèòíûõ - "4294967295" | |
| 426 | for($i=0; $i<32; $i++){
| |
| 427 | $int=$int | (1<<$i); | |
| 428 | } | |
| 429 | } | |
| 430 | ||
| 431 | //Ïîáèòîâîå AND | |
| 432 | $number=intval($number & $int); | |
| 433 | } | |
| 434 | ||
| 435 | return $number; | |
| 436 | } | |
| 437 | } |