public static function BitTest($Number, $Bit) { if (is_resource($Number) !== true) { $Number = gmp_init($Number); } return gmp_testbit($Number, $Bit - 1); }
public function __construct($cipher, $key, $taglen) { $logging = \Plop\Plop::getInstance(); $this->cipher = mcrypt_module_open($cipher, null, 'ecb', null); mcrypt_generic_init($this->cipher, $key, str_repeat("", 16)); $this->taglen = $taglen; $logging->debug('Pre-computing GCM table'); $H = gmp_init(bin2hex(mcrypt_generic($this->cipher, str_repeat("", 16))), 16); $H = str_pad(gmp_strval($H, 2), 128, '0', STR_PAD_LEFT); $R = gmp_init('E1000000000000000000000000000000', 16); $this->table = array(); for ($i = 0; $i < 16; $i++) { $this->table[$i] = array(); for ($j = 0; $j < 256; $j++) { $V = gmp_init(dechex($j) . str_repeat("00", $i), 16); $Z = gmp_init(0); for ($k = 0; $k < 128; $k++) { // Compute Z_n+1 if ($H[$k]) { $Z = gmp_xor($Z, $V); } // Compute V_n+1 $odd = gmp_testbit($V, 0); $V = gmp_div_q($V, 2); if ($odd) { $V = gmp_xor($V, $R); } } $this->table[$i][$j] = pack('H*', str_pad(gmp_strval($Z, 16), 32, 0, STR_PAD_LEFT)); } } $logging->debug('Done pre-computing GCM table'); }
/** * @return array */ public function getValues() { $values = []; for ($i = 0; $i < 8; $i++) { if (gmp_testbit($this->bits, $i)) { $values[] = $i; } } return $values; }
public function has($value) { $hashes = $this->_hashes($value); if (function_exists('gmp_testbit')) { foreach ($hashes as $hash) { if (!gmp_testbit($this->_gmp, $hash)) { return false; } } } else { foreach ($hashes as $hash) { if (gmp_scan1($this->_gmp, $hash) !== $hash) { return false; } } } return true; }
<?php var_dump(gmp_testbit("abc", 1));
list($sqrt2, $sqrt2rem) = gmp_sqrtrem("7"); list($sqrt3, $sqrt3rem) = gmp_sqrtrem("1048576"); echo gmp_strval($sqrt1) . ", " . gmp_strval($sqrt1rem) . "\n"; echo gmp_strval($sqrt2) . ", " . gmp_strval($sqrt2rem) . "\n"; echo gmp_strval($sqrt3) . ", " . gmp_strval($sqrt3rem) . "\n"; // gmp_strval $a = gmp_init("0x41682179fbf5"); printf("Decimal: %s, 36-based: %s" . PHP_EOL, gmp_strval($a), gmp_strval($a, 36)); // gmp_sub $sub = gmp_sub("281474976710656", "4294967296"); // 2^48 - 2^32 echo gmp_strval($sub) . "\n"; // gmp_testbit $n = gmp_init("1000000"); var_dump(gmp_testbit($n, 1)); gmp_setbit($n, 1); var_dump(gmp_testbit($n, 1)); // gmp_xor $xor1 = gmp_init("1101101110011101", 2); $xor2 = gmp_init("0110011001011001", 2); $xor3 = gmp_xor($xor1, $xor2); echo gmp_strval($xor3, 2) . "\n"; // misc $someBigNumber = '521384146951941511609433057270365759591953092186117381932611' . '7931051185480744623799627495673518857527248912279381830119491298336733624' . '4065664308602139494639522473719070217986094370277293176752384674818467669' . '4051320005681271452635608277857713427577896091736371787214684409012654958' . '5371050792279689258923542019956112129021960864034418159813629774771309960' . '5187072113497804995105973173281609631859502445945534690830264252230825334' . '4685035261931188171010003137835332083814206171776691473035982534904287554' . '687311595628638823537875937519577818577805321712'; $a = gmp_init($someBigNumber, 10); var_dump(gmp_strval($a) == $someBigNumber); var_dump(gmp_strval($a, 32)); $b = gmp_init(0xffffff, 16); var_dump(gmp_strval($b)); $c = gmp_init($b); var_dump(gmp_strval($c, 16));
<?php $n = gmp_init(0); var_dump(gmp_testbit($n, -10)); var_dump(gmp_testbit($n, 0)); var_dump(gmp_testbit($n, 1)); var_dump(gmp_testbit($n, 100)); $n = gmp_init(-1); var_dump(gmp_testbit($n, 1)); var_dump(gmp_testbit($n, -1)); $n = gmp_init("1000000"); var_dump(gmp_testbit($n, 1)); gmp_setbit($n, 1); var_dump(gmp_testbit($n, 1)); var_dump(gmp_strval($n)); gmp_setbit($n, 5); var_dump(gmp_testbit($n, 5)); var_dump(gmp_strval($n)); $n = gmp_init("238462734628347239571823641234"); var_dump(gmp_testbit($n, 5)); gmp_setbit($n, 5); var_dump(gmp_testbit($n, 5)); var_dump(gmp_strval($n)); gmp_clrbit($n, 5); var_dump(gmp_testbit($n, 5)); var_dump(gmp_strval($n)); echo "Done\n";
/** * @interal Only works up to shift 63 (doesn't wrap bits around). * @param resource|int|string $g * @param int $shift number of bits to shift left * @return resource $g shifted left */ static function shift_left($g, $shift) { if (0 == $shift) { return $g; } if (0 > gmp_sign($g)) { $g = self::gmp_twos_complement($g); } $m = gmp_mul($g, gmp_pow(self::gmp_2(), $shift)); $m = gmp_and($m, self::gmp_0xfs()); if (gmp_testbit($m, 63)) { $m = gmp_neg(gmp_add(gmp_and(gmp_com($m), self::gmp_0xfs()), self::gmp_1())); } return $m; }
protected function readTextRecordInner(&$content, &$pos, $recordType) { switch ($recordType) { case Constants::RECORD_TYPE_ZERO_TEXT: case Constants::RECORD_TYPE_ZERO_TEXT_WITH_END_ELEMENT: return '0'; break; case Constants::RECORD_TYPE_ONE_TEXT: case Constants::RECORD_TYPE_ONE_TEXT_WITH_END_ELEMENT: return '1'; break; case Constants::RECORD_TYPE_FALSE_TEXT: case Constants::RECORD_TYPE_FALSE_TEXT_WITH_END_ELEMENT: return 'false'; break; case Constants::RECORD_TYPE_TRUE_TEXT: case Constants::RECORD_TYPE_TRUE_TEXT_WITH_END_ELEMENT: return 'true'; break; case Constants::RECORD_TYPE_INT8_TEXT: case Constants::RECORD_TYPE_INT8_TEXT_WITH_END_ELEMENT: $record = unpack('c*', $content[$pos]); $pos += 1; return (string) $record[1]; break; case Constants::RECORD_TYPE_INT16_TEXT: case Constants::RECORD_TYPE_INT16_TEXT_WITH_END_ELEMENT: $record = unpack('s*', substr($content, $pos, 2)); $pos += 2; return (string) $record[1]; break; case Constants::RECORD_TYPE_INT32_TEXT: case Constants::RECORD_TYPE_INT32_TEXT_WITH_END_ELEMENT: $record = unpack('l*', substr($content, $pos, 4)); $pos += 4; return (string) $record[1]; break; case Constants::RECORD_TYPE_INT64_TEXT: case Constants::RECORD_TYPE_INT64_TEXT_WITH_END_ELEMENT: if (!function_exists('gmp_init')) { throw new DecodingException('Int64 requires GMP extension'); } list(, $int64Hex) = unpack('H*', strrev(substr($content, $pos, 8))); $pos += 8; return (string) gmp_strval(gmp_init($int64Hex, 16), 10); break; case Constants::RECORD_TYPE_FLOAT_TEXT: case Constants::RECORD_TYPE_FLOAT_TEXT_WITH_END_ELEMENT: $record = unpack('f*', substr($content, $pos, 4)); $pos += 4; return (string) $record[1]; break; case Constants::RECORD_TYPE_DOUBLE_TEXT: case Constants::RECORD_TYPE_DOUBLE_TEXT_WITH_END_ELEMENT: $record = unpack('d*', substr($content, $pos, 8)); $pos += 8; return (string) $record[1]; break; case Constants::RECORD_TYPE_DECIMAL_TEXT: case Constants::RECORD_TYPE_DECIMAL_TEXT_WITH_END_ELEMENT: if (!function_exists('gmp_init')) { throw new DecodingException('Decimal requires GMP extension'); } $pos += 2; // First 2 bytes reserved $scale = ord($content[$pos]); $pos += 1; $sign = ord($content[$pos]); $pos += 1; list(, $hi32Hex) = unpack('H*', strrev(substr($content, $pos, 4))); $pos += 4; $hi32 = gmp_init($hi32Hex, 16); list(, $lo64Hex) = unpack('H*', strrev(substr($content, $pos, 8))); $pos += 8; $lo64 = gmp_init($lo64Hex, 16); $value = gmp_add(gmp_mul($hi32, gmp_pow(2, 64)), $lo64); $record = gmp_strval($value, 10); if ($scale > 0) { if ($scale > strlen($record)) { $record = str_repeat('0', $scale - strlen($record)) . $record; } $record = substr($record, 0, strlen($record) - $scale) . '.' . substr($record, $scale * -1); $record = trim($record, '0'); if ($record[0] == '.') { $record = '0' . $record; } } if ($sign == 0x80) { $record = '-' . $record; } return $record; break; case Constants::RECORD_TYPE_DATETIME_TEXT: case Constants::RECORD_TYPE_DATETIME_TEXT_WITH_END_ELEMENT: if (!function_exists('gmp_init')) { throw new DecodingException('Datetime requires GMP extension'); } $binary = ''; for ($i = 0; $i < 8; ++$i) { list(, $byteint) = unpack('C*', $content[$pos + $i]); $binary = sprintf('%08b', $byteint) . $binary; } $pos += 8; $value = gmp_init(substr($binary, 2, 62), 2); // Only calc with seconds, since PHP datetime doesn't support fractions $secsRemaining = gmp_div($value, '10000000'); // Compensate for using unix timestamp $epochSecsRemaining = gmp_sub($secsRemaining, '62135596800'); // Load PHP datetime with seconds remaining $datetime = new DateTime('@' . gmp_strval($epochSecsRemaining, 10), new DateTimeZone('UTC')); $date = $datetime->format('Y-m-d'); $time = $datetime->format('H:i:s'); // Get fractions $fraction = substr(gmp_strval($value, 10), -7); // Join different time elements if ($fraction !== '0000000') { $record = "{$date}T{$time}.{$fraction}"; } elseif ($time !== '00:00:00') { $record = "{$date}T{$time}"; } else { $record = "{$date}"; } // Add timezone info $tz = gmp_intval(gmp_init(substr($binary, 0, 2), 2)); if ($tz == 2) { // TODO: local time handling } elseif ($tz == 1) { $record .= 'Z'; } return $record; break; case Constants::RECORD_TYPE_CHARS8_TEXT: case Constants::RECORD_TYPE_CHARS8_TEXT_WITH_END_ELEMENT: list(, $recordLength) = unpack('C*', $content[$pos]); $pos += 1; $record = substr($content, $pos, $recordLength); $pos += $recordLength; return $record; break; case Constants::RECORD_TYPE_CHARS16_TEXT: case Constants::RECORD_TYPE_CHARS16_TEXT_WITH_END_ELEMENT: list(, $recordLength) = unpack('S*', substr($content, $pos, 2)); $pos += 2; $record = substr($content, $pos, $recordLength); $pos += $recordLength; return $record; break; case Constants::RECORD_TYPE_CHARS32_TEXT: case Constants::RECORD_TYPE_CHARS32_TEXT_WITH_END_ELEMENT: list(, $recordLength) = unpack('l*', substr($content, $pos, 4)); $pos += 4; $record = substr($content, $pos, $recordLength); $pos += $recordLength; return $record; break; case Constants::RECORD_TYPE_BYTES8_TEXT: case Constants::RECORD_TYPE_BYTES8_TEXT_WITH_END_ELEMENT: list(, $recordLength) = unpack('C*', $content[$pos]); $pos += 1; $record = substr($content, $pos, $recordLength); $pos += $recordLength; return base64_encode($record); break; case Constants::RECORD_TYPE_BYTES16_TEXT: case Constants::RECORD_TYPE_BYTES16_TEXT_WITH_END_ELEMENT: list(, $recordLength) = unpack('S*', substr($content, $pos, 2)); $pos += 2; $record = substr($content, $pos, $recordLength); $pos += $recordLength; return base64_encode($record); break; case Constants::RECORD_TYPE_BYTES32_TEXT: case Constants::RECORD_TYPE_BYTES32_TEXT_WITH_END_ELEMENT: list(, $recordLength) = unpack('l*', substr($content, $pos, 4)); $pos += 4; $record = substr($content, $pos, $recordLength); $pos += $recordLength; return base64_encode($record); break; case Constants::RECORD_TYPE_START_LIST_TEXT: $record = ''; while (ord($content[$pos]) != Constants::RECORD_TYPE_END_LIST_TEXT) { if ($record !== '') { $record .= ' '; } $record .= $this->readTextRecord($content, $pos); } $pos += 1; // skip 1 for end list return $record; break; case Constants::RECORD_TYPE_EMPTY_TEXT: case Constants::RECORD_TYPE_EMPTY_TEXT_WITH_END_ELEMENT: return ''; break; case Constants::RECORD_TYPE_DICTIONARY_TEXT: case Constants::RECORD_TYPE_DICTIONARY_TEXT_WITH_END_ELEMENT: return $this->readDictionaryString($content, $pos); break; case Constants::RECORD_TYPE_UNIQUEID_TEXT: case Constants::RECORD_TYPE_UNIQUEID_TEXT_WITH_END_ELEMENT: case Constants::RECORD_TYPE_UUID_TEXT: case Constants::RECORD_TYPE_UUID_TEXT_WITH_END_ELEMENT: list(, $data1) = unpack('H*', strrev(substr($content, $pos, 4))); $pos += 4; list(, $data2) = unpack('H*', strrev(substr($content, $pos, 2))); $pos += 2; list(, $data3) = unpack('H*', strrev(substr($content, $pos, 2))); $pos += 2; list(, $data4) = unpack('H*', substr($content, $pos, 2)); $pos += 2; list(, $data5) = unpack('H*', substr($content, $pos, 6)); $pos += 6; $record = "{$data1}-{$data2}-{$data3}-{$data4}-{$data5}"; if ($recordType == Constants::RECORD_TYPE_UNIQUEID_TEXT || $recordType == Constants::RECORD_TYPE_UNIQUEID_TEXT_WITH_END_ELEMENT) { $record = 'urn:uuid:' . $record; } return $record; break; case Constants::RECORD_TYPE_TIMESPAN_TEXT: case Constants::RECORD_TYPE_TIMESPAN_TEXT_WITH_END_ELEMENT: if (!function_exists('gmp_init')) { throw new DecodingException('Timespan requires GMP extension'); } $value = ''; for ($i = 0; $i < 8; $i++) { list(, $byte) = unpack('C*', $content[$pos + $i]); $value = sprintf('%08b', $byte) . $value; } $pos += 8; $value = gmp_init($value, 2); $minus = false; if (gmp_testbit($value, 63)) { $minus = true; $mask = gmp_init(str_repeat('1', 64), '2'); $value = gmp_and(gmp_com($value), $mask); $value = gmp_add($value, 1); } $remaining = gmp_abs($value); list($days, $remaining) = gmp_div_qr($remaining, gmp_init('864000000000')); list($hours, $remaining) = gmp_div_qr($remaining, gmp_init('36000000000')); list($mins, $remaining) = gmp_div_qr($remaining, gmp_init('600000000')); list($secs, $remaining) = gmp_div_qr($remaining, gmp_init('10000000')); $fracs = $remaining; $days = gmp_intval($days); $hours = gmp_intval($hours); $mins = gmp_intval($mins); $secs = gmp_intval($secs); $fracs = gmp_intval($fracs); $record = $minus ? '-P' : 'P'; if ($days > 0) { $record .= $days . 'D'; } if ($hours > 0 || $mins > 0 || $secs > 0 || $fracs > 0) { $record .= 'T'; if ($hours > 0) { $record .= $hours . 'H'; } if ($mins > 0) { $record .= $mins . 'M'; } if ($secs > 0 || $fracs > 0) { $record .= $secs; if ($fracs > 0) { $record .= '.' . $fracs; } $record .= 'S'; } } return $record; break; case Constants::RECORD_TYPE_UINT64_TEXT: case Constants::RECORD_TYPE_UINT64_TEXT_WITH_END_ELEMENT: if (!function_exists('gmp_init')) { throw new DecodingException('Uint64 requires GMP extension'); } list(, $uint64Hex) = unpack('H*', strrev(substr($content, $pos, 8))); $pos += 8; return (string) gmp_strval(gmp_init($uint64Hex, 16), 10); break; case Constants::RECORD_TYPE_BOOL_TEXT: case Constants::RECORD_TYPE_BOOL_TEXT_WITH_END_ELEMENT: $record = ord($content[$pos]); $pos += 1; switch ($record) { case 0: return 'false'; break; case 1: return 'true'; break; } throw new DecodingException(sprintf('Unknown boolean value 0x%02X at position %d.', $record, $pos)); break; case Constants::RECORD_TYPE_UNICODECHARS8_TEXT: case Constants::RECORD_TYPE_UNICODECHARS8_TEXT_WITH_END_ELEMENT: list(, $recordLength) = unpack('C*', $content[$pos]); $pos += 1; $record = substr($content, $pos, $recordLength); $pos += $recordLength; return mb_convert_encoding($record, 'UTF-8', 'UTF-16'); break; case Constants::RECORD_TYPE_UNICODECHARS16_TEXT: case Constants::RECORD_TYPE_UNICODECHARS16_TEXT_WITH_END_ELEMENT: list(, $recordLength) = unpack('S*', substr($content, $pos, 2)); $pos += 2; $record = substr($content, $pos, $recordLength); $pos += $recordLength; return mb_convert_encoding($record, 'UTF-8', 'UTF-16'); break; case Constants::RECORD_TYPE_UNICODECHARS32_TEXT: case Constants::RECORD_TYPE_UNICODECHARS32_TEXT_WITH_END_ELEMENT: list(, $recordLength) = unpack('l*', substr($content, $pos, 4)); $pos += 4; $record = substr($content, $pos, $recordLength); $pos += $recordLength; return mb_convert_encoding($record, 'UTF-8', 'UTF-16'); break; case Constants::RECORD_TYPE_QNAMEDICTIONARY_TEXT: case Constants::RECORD_TYPE_QNAMEDICTIONARY_TEXT_WITH_END_ELEMENT: $prefix = chr(97 + ord($content[$pos])); $pos += 1; $name = $this->readDictionaryString($content, $pos); return $prefix . ':' . $name; break; default: throw new DecodingException(sprintf('Unknown record type 0x%02X at position %d.', $recordType, $pos)); break; } }
private static function inet_gmpton( $gmp ) { // 16*8 == 128 $addr = ''; for( $bits = 0; $bits < 16; $bits++ ) { $byte = 0; for( $b = 0; $b < 8; $b++ ) { if( gmp_testbit( $gmp, (15-$bits)*8+$b )) { $byte |= 1<<$b; } } $addr .= chr( $byte ); } // echo gmp_strval( $gmp, 16 ).' -> '.inet_ntop( $addr )."<br />\n"; return $addr; }