/** * Creates the subkeys $_mkey (the masking key) and * $_rkey (the rotate key) which are 16 bytes each. These are * created from the original key. The original key is null * padded up to 16 bytes and expanded to 32 bytes. It is then * split in half to create $_mkey and $_rkey * * @return void */ private function createSubKeys() { $x = $this->key(); $z = ""; // init to 16 bytes $skey = array(); // the max length of the key is 16 bytes, however if it is // less, pad it with null to get ito to 16 bytes if ($this->keySize() < self::BYTES_KEY_MAX) { $x = str_pad($x, self::BYTES_KEY_MAX, "", STR_PAD_RIGHT); } /* * NOW FOR THE UGLY PART, THIS IS TAKEN FROM PAGE 3-4 OF * http://tools.ietf.org/html/rfc2144 */ // two loops, each loop does 16 bytes for a total of 32 bytes for ($i = 0; $i < 2; ++$i) { // z0z1z2z3 = x0x1x2x3 ^ S5[xD] ^ S6[xF] ^ S7[xC] ^ S8[xE] ^ S7[x8] $tmp = substr($x, 0x0, 4); $tmp = parent::dec2Str(parent::uInt32(parent::str2Dec($tmp) ^ self::$_s5[ord($x[0xd])] ^ self::$_s6[ord($x[0xf])] ^ self::$_s7[ord($x[0xc])] ^ self::$_s8[ord($x[0xe])] ^ self::$_s7[ord($x[0x8])]), 4); $z = substr_replace($z, $tmp, 0x0, 4); //print "Z0: ".parent::str2Hex($z)." (".strlen($z).")\n"; // z4z5z6z7 = x8x9xAxB ^ S5[z0] ^ S6[z2] ^ S7[z1] ^ S8[z3] ^ S8[xA] $tmp = substr($x, 0x8, 4); $tmp = parent::dec2Str(parent::uInt32(parent::str2Dec($tmp) ^ self::$_s5[ord($z[0x0])] ^ self::$_s6[ord($z[0x2])] ^ self::$_s7[ord($z[0x1])] ^ self::$_s8[ord($z[0x3])] ^ self::$_s8[ord($x[0xa])]), 4); $z = substr_replace($z, $tmp, 0x4, 4); // z8z9zAzB = xCxDxExF ^ S5[z7] ^ S6[z6] ^ S7[z5] ^ S8[z4] ^ S5[x9] $tmp = substr($x, 0xc, 4); $tmp = parent::dec2Str(parent::uInt32(parent::str2Dec($tmp) ^ self::$_s5[ord($z[0x7])] ^ self::$_s6[ord($z[0x6])] ^ self::$_s7[ord($z[0x5])] ^ self::$_s8[ord($z[0x4])] ^ self::$_s5[ord($x[0x9])]), 4); $z = substr_replace($z, $tmp, 0x8, 4); // zCzDzEzF = x4x5x6x7 ^ S5[zA] ^ S6[z9] ^ S7[zB] ^ S8[z8] ^ S6[xB] $tmp = substr($x, 0x4, 4); $tmp = parent::dec2Str(parent::uInt32(parent::str2Dec($tmp) ^ self::$_s5[ord($z[0xa])] ^ self::$_s6[ord($z[0x9])] ^ self::$_s7[ord($z[0xb])] ^ self::$_s8[ord($z[0x8])] ^ self::$_s6[ord($x[0xb])]), 4); $z = substr_replace($z, $tmp, 0xc, 4); //print "Z: ".parent::str2Hex($z)." (".strlen($z).")\n"; // K1 = S5[z8] ^ S6[z9] ^ S7[z7] ^ S8[z6] ^ S5[z2] $skey[] = parent::uInt32(self::$_s5[ord($z[0x8])] ^ self::$_s6[ord($z[0x9])] ^ self::$_s7[ord($z[0x7])] ^ self::$_s8[ord($z[0x6])] ^ self::$_s5[ord($z[0x2])]); // K2 = S5[zA] ^ S6[zB] ^ S7[z5] ^ S8[z4] ^ S6[z6] $skey[] = parent::uInt32(self::$_s5[ord($z[0xa])] ^ self::$_s6[ord($z[0xb])] ^ self::$_s7[ord($z[0x5])] ^ self::$_s8[ord($z[0x4])] ^ self::$_s6[ord($z[0x6])]); // K3 = S5[zC] ^ S6[zD] ^ S7[z3] ^ S8[z2] ^ S7[z9] $skey[] = parent::uInt32(self::$_s5[ord($z[0xc])] ^ self::$_s6[ord($z[0xd])] ^ self::$_s7[ord($z[0x3])] ^ self::$_s8[ord($z[0x2])] ^ self::$_s7[ord($z[0x9])]); // K4 = S5[zE] ^ S6[zF] ^ S7[z1] ^ S8[z0] ^ S8[zC] $skey[] = parent::uInt32(self::$_s5[ord($z[0xe])] ^ self::$_s6[ord($z[0xf])] ^ self::$_s7[ord($z[0x1])] ^ self::$_s8[ord($z[0x0])] ^ self::$_s8[ord($z[0xc])]); // x0x1x2x3 = z8z9zAzB ^ S5[z5] ^ S6[z7] ^ S7[z4] ^ S8[z6] ^ S7[z0] $tmp = substr($z, 0x8, 4); $tmp = parent::dec2Str(parent::uInt32(parent::str2Dec($tmp) ^ self::$_s5[ord($z[0x5])] ^ self::$_s6[ord($z[0x7])] ^ self::$_s7[ord($z[0x4])] ^ self::$_s8[ord($z[0x6])] ^ self::$_s7[ord($z[0x0])]), 4); $x = substr_replace($x, $tmp, 0x0, 4); // x4x5x6x7 = z0z1z2z3 ^ S5[x0] ^ S6[x2] ^ S7[x1] ^ S8[x3] ^ S8[z2] $tmp = substr($z, 0x0, 4); $tmp = parent::dec2Str(parent::uInt32(parent::str2Dec($tmp) ^ self::$_s5[ord($x[0x0])] ^ self::$_s6[ord($x[0x2])] ^ self::$_s7[ord($x[0x1])] ^ self::$_s8[ord($x[0x3])] ^ self::$_s8[ord($z[0x2])]), 4); $x = substr_replace($x, $tmp, 0x4, 4); // x8x9xAxB = z4z5z6z7 ^ S5[x7] ^ S6[x6] ^ S7[x5] ^ S8[x4] ^ S5[z1] $tmp = substr($z, 0x4, 4); $tmp = parent::dec2Str(parent::uInt32(parent::str2Dec($tmp) ^ self::$_s5[ord($x[0x7])] ^ self::$_s6[ord($x[0x6])] ^ self::$_s7[ord($x[0x5])] ^ self::$_s8[ord($x[0x4])] ^ self::$_s5[ord($z[0x1])]), 4); $x = substr_replace($x, $tmp, 0x8, 4); // xCxDxExF = zCzDzEzF ^ S5[xA] ^ S6[x9] ^ S7[xB] ^ S8[x8] ^ S6[z3] $tmp = substr($z, 0xc, 4); $tmp = parent::dec2Str(parent::uInt32(parent::str2Dec($tmp) ^ self::$_s5[ord($x[0xa])] ^ self::$_s6[ord($x[0x9])] ^ self::$_s7[ord($x[0xb])] ^ self::$_s8[ord($x[0x8])] ^ self::$_s6[ord($z[0x3])]), 4); $x = substr_replace($x, $tmp, 0xc, 4); // K5 = S5[x3] ^ S6[x2] ^ S7[xC] ^ S8[xD] ^ S5[x8] $skey[] = parent::uInt32(self::$_s5[ord($x[0x3])] ^ self::$_s6[ord($x[0x2])] ^ self::$_s7[ord($x[0xc])] ^ self::$_s8[ord($x[0xd])] ^ self::$_s5[ord($x[0x8])]); // K6 = S5[x1] ^ S6[x0] ^ S7[xE] ^ S8[xF] ^ S6[xD] $skey[] = parent::uInt32(self::$_s5[ord($x[0x1])] ^ self::$_s6[ord($x[0x0])] ^ self::$_s7[ord($x[0xe])] ^ self::$_s8[ord($x[0xf])] ^ self::$_s6[ord($x[0xd])]); // K7 = S5[x7] ^ S6[x6] ^ S7[x8] ^ S8[x9] ^ S7[x3] $skey[] = parent::uInt32(self::$_s5[ord($x[0x7])] ^ self::$_s6[ord($x[0x6])] ^ self::$_s7[ord($x[0x8])] ^ self::$_s8[ord($x[0x9])] ^ self::$_s7[ord($x[0x3])]); // K8 = S5[x5] ^ S6[x4] ^ S7[xA] ^ S8[xB] ^ S8[x7] $skey[] = parent::uInt32(self::$_s5[ord($x[0x5])] ^ self::$_s6[ord($x[0x4])] ^ self::$_s7[ord($x[0xa])] ^ self::$_s8[ord($x[0xb])] ^ self::$_s8[ord($x[0x7])]); // z0z1z2z3 = x0x1x2x3 ^ S5[xD] ^ S6[xF] ^ S7[xC] ^ S8[xE] ^ S7[x8] $tmp = substr($x, 0x0, 4); $tmp = parent::dec2Str(parent::uInt32(parent::str2Dec($tmp) ^ self::$_s5[ord($x[0xd])] ^ self::$_s6[ord($x[0xf])] ^ self::$_s7[ord($x[0xc])] ^ self::$_s8[ord($x[0xe])] ^ self::$_s7[ord($x[0x8])]), 4); $z = substr_replace($z, $tmp, 0x0, 4); // z4z5z6z7 = x8x9xAxB ^ S5[z0] ^ S6[z2] ^ S7[z1] ^ S8[z3] ^ S8[xA] $tmp = substr($x, 0x8, 4); $tmp = parent::dec2Str(parent::uInt32(parent::str2Dec($tmp) ^ self::$_s5[ord($z[0x0])] ^ self::$_s6[ord($z[0x2])] ^ self::$_s7[ord($z[0x1])] ^ self::$_s8[ord($z[0x3])] ^ self::$_s8[ord($x[0xa])]), 4); $z = substr_replace($z, $tmp, 0x4, 4); // z8z9zAzB = xCxDxExF ^ S5[z7] ^ S6[z6] ^ S7[z5] ^ S8[z4] ^ S5[x9] $tmp = substr($x, 0xc, 4); $tmp = parent::dec2Str(parent::uInt32(parent::str2Dec($tmp) ^ self::$_s5[ord($z[0x7])] ^ self::$_s6[ord($z[0x6])] ^ self::$_s7[ord($z[0x5])] ^ self::$_s8[ord($z[0x4])] ^ self::$_s5[ord($x[0x9])]), 4); $z = substr_replace($z, $tmp, 0x8, 4); // zCzDzEzF = x4x5x6x7 ^ S5[zA] ^ S6[z9] ^ S7[zB] ^ S8[z8] ^ S6[xB] $tmp = substr($x, 0x4, 4); $tmp = parent::dec2Str(parent::uInt32(parent::str2Dec($tmp) ^ self::$_s5[ord($z[0xa])] ^ self::$_s6[ord($z[0x9])] ^ self::$_s7[ord($z[0xb])] ^ self::$_s8[ord($z[0x8])] ^ self::$_s6[ord($x[0xb])]), 4); $z = substr_replace($z, $tmp, 0xc, 4); // K9 = S5[z3] ^ S6[z2] ^ S7[zC] ^ S8[zD] ^ S5[z9] $skey[] = parent::uInt32(self::$_s5[ord($z[0x3])] ^ self::$_s6[ord($z[0x2])] ^ self::$_s7[ord($z[0xc])] ^ self::$_s8[ord($z[0xd])] ^ self::$_s5[ord($z[0x9])]); // K10 = S5[z1] ^ S6[z0] ^ S7[zE] ^ S8[zF] ^ S6[zC] $skey[] = parent::uInt32(self::$_s5[ord($z[0x1])] ^ self::$_s6[ord($z[0x0])] ^ self::$_s7[ord($z[0xe])] ^ self::$_s8[ord($z[0xf])] ^ self::$_s6[ord($z[0xc])]); // K11 = S5[z7] ^ S6[z6] ^ S7[z8] ^ S8[z9] ^ S7[z2] $skey[] = parent::uInt32(self::$_s5[ord($z[0x7])] ^ self::$_s6[ord($z[0x6])] ^ self::$_s7[ord($z[0x8])] ^ self::$_s8[ord($z[0x9])] ^ self::$_s7[ord($z[0x2])]); // K12 = S5[z5] ^ S6[z4] ^ S7[zA] ^ S8[zB] ^ S8[z6] $skey[] = parent::uInt32(self::$_s5[ord($z[0x5])] ^ self::$_s6[ord($z[0x4])] ^ self::$_s7[ord($z[0xa])] ^ self::$_s8[ord($z[0xb])] ^ self::$_s8[ord($z[0x6])]); // x0x1x2x3 = z8z9zAzB ^ S5[z5] ^ S6[z7] ^ S7[z4] ^ S8[z6] ^ S7[z0] $tmp = substr($z, 0x8, 4); $tmp = parent::dec2Str(parent::uInt32(parent::str2Dec($tmp) ^ self::$_s5[ord($z[0x5])] ^ self::$_s6[ord($z[0x7])] ^ self::$_s7[ord($z[0x4])] ^ self::$_s8[ord($z[0x6])] ^ self::$_s7[ord($z[0x0])]), 4); $x = substr_replace($x, $tmp, 0x0, 4); // x4x5x6x7 = z0z1z2z3 ^ S5[x0] ^ S6[x2] ^ S7[x1] ^ S8[x3] ^ S8[z2] $tmp = substr($z, 0x0, 4); $tmp = parent::dec2Str(parent::uInt32(parent::str2Dec($tmp) ^ self::$_s5[ord($x[0x0])] ^ self::$_s6[ord($x[0x2])] ^ self::$_s7[ord($x[0x1])] ^ self::$_s8[ord($x[0x3])] ^ self::$_s8[ord($z[0x2])]), 4); $x = substr_replace($x, $tmp, 0x4, 4); // x8x9xAxB = z4z5z6z7 ^ S5[x7] ^ S6[x6] ^ S7[x5] ^ S8[x4] ^ S5[z1] $tmp = substr($z, 0x4, 4); $tmp = parent::dec2Str(parent::uInt32(parent::str2Dec($tmp) ^ self::$_s5[ord($x[0x7])] ^ self::$_s6[ord($x[0x6])] ^ self::$_s7[ord($x[0x5])] ^ self::$_s8[ord($x[0x4])] ^ self::$_s5[ord($z[0x1])]), 4); $x = substr_replace($x, $tmp, 0x8, 4); // xCxDxExF = zCzDzEzF ^ S5[xA] ^ S6[x9] ^ S7[xB] ^ S8[x8] ^ S6[z3] $tmp = substr($z, 0xc, 4); $tmp = parent::dec2Str(parent::uInt32(parent::str2Dec($tmp) ^ self::$_s5[ord($x[0xa])] ^ self::$_s6[ord($x[0x9])] ^ self::$_s7[ord($x[0xb])] ^ self::$_s8[ord($x[0x8])] ^ self::$_s6[ord($z[0x3])]), 4); $x = substr_replace($x, $tmp, 0xc, 4); // K13 = S5[x8] ^ S6[x9] ^ S7[x7] ^ S8[x6] ^ S5[x3] $skey[] = parent::uInt32(self::$_s5[ord($x[0x8])] ^ self::$_s6[ord($x[0x9])] ^ self::$_s7[ord($x[0x7])] ^ self::$_s8[ord($x[0x6])] ^ self::$_s5[ord($x[0x3])]); // K14 = S5[xA] ^ S6[xB] ^ S7[x5] ^ S8[x4] ^ S6[x7] $skey[] = parent::uInt32(self::$_s5[ord($x[0xa])] ^ self::$_s6[ord($x[0xb])] ^ self::$_s7[ord($x[0x5])] ^ self::$_s8[ord($x[0x4])] ^ self::$_s6[ord($x[0x7])]); // K15 = S5[xC] ^ S6[xD] ^ S7[x3] ^ S8[x2] ^ S7[x8] $skey[] = parent::uInt32(self::$_s5[ord($x[0xc])] ^ self::$_s6[ord($x[0xd])] ^ self::$_s7[ord($x[0x3])] ^ self::$_s8[ord($x[0x2])] ^ self::$_s7[ord($x[0x8])]); // K16 = S5[xE] ^ S6[xF] ^ S7[x1] ^ S8[x0] ^ S8[xD] $skey[] = parent::uInt32(self::$_s5[ord($x[0xe])] ^ self::$_s6[ord($x[0xf])] ^ self::$_s7[ord($x[0x1])] ^ self::$_s8[ord($x[0x0])] ^ self::$_s8[ord($x[0xd])]); } // create the 16 byte masking and rotate subkeys $this->_mkey = array_slice($skey, 0, 16); $this->_rkey = array_slice($skey, 16, 16); // $_rkey only uses the least significant 5 bits $this->_rkey = array_map(function ($v) { return $v &= 31; }, $this->_rkey); // there is 4kb in the s5 - s8 sboxes, which are not needed after we // create the subkeys, so free up the memory. unset() doesn't work here for ($i = 5; $i <= 8; ++$i) { self::${"_s{$i}"} = null; } }
/** * Decrypt a RC2 encrypted string * * @param string $text A RC2 encrypted string * @return boolean Returns true */ public function decrypt(&$text) { $this->operation(parent::DECRYPT); // first split up the message into four 16 bit parts (2 bytes), // then convert each array element to an integer $w = self::splitBytes($text); $k = self::splitBytes($this->xkey); $j = 0; // the key index for ($i = 15; $i >= 0; --$i) { $j = $i * 4; /* This is where it gets ugly, RC2 relies on unsigned ints. PHP does * not have a nice way to handle unsigned ints, so we have to rely on sprintf. * To make RC2 compatible with mCrypt, I also forced everything to 32 bit * When I test against mcrypt and the original rc2 C source, I get 32 bit * results, even on a 64 bit platform */ $w[3] &= 65535; $w[3] = parent::uInt($w[3] << 11) + parent::uInt($w[3] >> 5); $w[3] -= parent::uInt($w[0] & ~$w[2]) + parent::uInt($w[1] & $w[2]) + $k[$j + 3]; $w[3] = parent::uInt32($w[3]); $w[2] &= 65535; $w[2] = parent::uInt($w[2] << 13) + parent::uInt($w[2] >> 3); $w[2] -= parent::uInt($w[3] & ~$w[1]) + parent::uInt($w[0] & $w[1]) + $k[$j + 2]; $w[2] = parent::uInt32($w[2]); $w[1] &= 65535; $w[1] = parent::uInt($w[1] << 14) + parent::uInt($w[1] >> 2); $w[1] -= parent::uInt($w[2] & ~$w[0]) + parent::uInt($w[3] & $w[0]) + $k[$j + 1]; $w[1] = parent::uInt32($w[1]); $w[0] &= 65535; $w[0] = parent::uInt($w[0] << 15) + parent::uInt($w[0] >> 1); $w[0] -= parent::uInt($w[1] & ~$w[3]) + parent::uInt($w[2] & $w[3]) + $k[$j + 0]; $w[0] = parent::uInt32($w[0]); if ($i == 5 || $i == 11) { $w[3] -= $k[$w[2] & 63]; $w[2] -= $k[$w[1] & 63]; $w[1] -= $k[$w[0] & 63]; $w[0] -= $k[$w[3] & 63]; } } /* I am not clear why this is required. It was not mentioned * in any of the documentation I read, however reading the original RC2 C * source code, this was done and in order for me to get the * correct results in PHP I needed to do this as well */ $max = count($w); for ($i = 0; $i < $max; ++$i) { $pos = $i * 2; $text[$pos] = chr($w[$i]); $text[$pos + 1] = chr($w[$i] >> 8); } return true; }
/** * 3Way's PI_2 function * This was taken from mcrypt's 3-way pi_2() function * * @param array $d A 3 element 32 bit integer array * @return void */ private function pi2(&$d) { $d[0] = parent::uInt32($d[0] << 1 ^ $d[0] >> 31); $d[2] = parent::uInt32($d[2] >> 10 ^ $d[2] << 22); }
/** * Creates the subkeys $_mkey (the masking key) and * $_rkey (the rotate key) which are 16 bytes each. These are * created from the original key. The original key is null * padded up to 16 bytes and expanded to 32 bytes. It is then * split in half to create $_mkey and $_rkey * * @return void */ private function createSubKeys() { $cm = 0x5a827999; $mm = 0x6ed9eba1; $cr = 19; $mr = 17; $tm = array(); $tr = array(); $xkey = $this->key(); $tmpkey = array(); // if the key is less than 32 bytes, pad it to 32 bytes // for the key expansion if ($this->keySize() < 32) { $xkey = str_pad($xkey, 32, "", STR_PAD_RIGHT); } // split the key up into 4 byte parts, reverse the string, // then convert each part into a 32 bit integer $xkey = str_split($xkey, 4); $xkey = array_map("strrev", $xkey); $xkey = array_map("parent::str2Dec", $xkey); // set up the values need for creating round and masking keys for ($i = 0; $i < 24; ++$i) { $tm[$i] = array(); $tr[$i] = array(); for ($j = 0; $j < 8; ++$j) { $tm[$i][$j] = $cm; $cm = parent::uInt32($cm + $mm); $tr[$i][$j] = $cr; $cr = parent::uInt32($cr + $mr); } } // now create the round and masking keys for ($i = 0; $i < 12; ++$i) { $j = 2 * $i; $xkey[6] = parent::uInt32($xkey[6] ^ $this->f1($xkey[7], $tm[$j][0], $tr[$j][0])); $xkey[5] = parent::uInt32($xkey[5] ^ $this->f2($xkey[6], $tm[$j][1], $tr[$j][1])); $xkey[4] = parent::uInt32($xkey[4] ^ $this->f3($xkey[5], $tm[$j][2], $tr[$j][2])); $xkey[3] = parent::uInt32($xkey[3] ^ $this->f1($xkey[4], $tm[$j][3], $tr[$j][3])); $xkey[2] = parent::uInt32($xkey[2] ^ $this->f2($xkey[3], $tm[$j][4], $tr[$j][4])); $xkey[1] = parent::uInt32($xkey[1] ^ $this->f3($xkey[2], $tm[$j][5], $tr[$j][5])); $xkey[0] = parent::uInt32($xkey[0] ^ $this->f1($xkey[1], $tm[$j][6], $tr[$j][6])); $xkey[7] = parent::uInt32($xkey[7] ^ $this->f2($xkey[0], $tm[$j][7], $tr[$j][7])); $j = 2 * $i + 1; $xkey[6] = parent::uInt32($xkey[6] ^ $this->f1($xkey[7], $tm[$j][0], $tr[$j][0])); $xkey[5] = parent::uInt32($xkey[5] ^ $this->f2($xkey[6], $tm[$j][1], $tr[$j][1])); $xkey[4] = parent::uInt32($xkey[4] ^ $this->f3($xkey[5], $tm[$j][2], $tr[$j][2])); $xkey[3] = parent::uInt32($xkey[3] ^ $this->f1($xkey[4], $tm[$j][3], $tr[$j][3])); $xkey[2] = parent::uInt32($xkey[2] ^ $this->f2($xkey[3], $tm[$j][4], $tr[$j][4])); $xkey[1] = parent::uInt32($xkey[1] ^ $this->f3($xkey[2], $tm[$j][5], $tr[$j][5])); $xkey[0] = parent::uInt32($xkey[0] ^ $this->f1($xkey[1], $tm[$j][6], $tr[$j][6])); $xkey[7] = parent::uInt32($xkey[7] ^ $this->f2($xkey[0], $tm[$j][7], $tr[$j][7])); // take the least 5 significant bits of each $xkey byte below and assign it // to the round key $this->_rkey[$i][0] = $xkey[0] & 31; $this->_rkey[$i][1] = $xkey[2] & 31; $this->_rkey[$i][2] = $xkey[4] & 31; $this->_rkey[$i][3] = $xkey[6] & 31; // now create 32 byte masking keys $this->_mkey[$i][0] = $xkey[7]; $this->_mkey[$i][1] = $xkey[5]; $this->_mkey[$i][2] = $xkey[3]; $this->_mkey[$i][3] = $xkey[1]; } }
/** * Blowfish's F() function * * @param string $i A 32 bit integer */ private function F($i) { // split the 32 bits into four 8 bit parts $x[0] = $i & 0xff; // first byte $x[1] = $i >> 8 & 0xff; // second byte $x[2] = $i >> 16 & 0xff; // third byte $x[3] = $i >> 24 & 0xff; // fourth byte // perform F(), make sure all values returned are // unsigned 32 bit $f = parent::uInt32(self::$_sbox1[$x[3]] + self::$_sbox2[$x[2]]); $f = parent::uInt32($f ^ self::$_sbox3[$x[1]]); $f = parent::uInt32($f + self::$_sbox4[$x[0]]); return $f; }