protected function getIpAttribute($value) { if (!is_null($value)) { $value = inet_ntop(gmp_export(gmp_init($value))); } return $value; }
/** * Constructor * * @param number $flags Flags * @param int $width The number of flags. If width is larger than number of * bits in $flags, zeroes are prepended to flag field. */ public function __construct($flags, $width) { if (!$width) { $this->_flags = ""; } else { // calculate number of unused bits in last octet $last_octet_bits = $width % 8; $unused_bits = $last_octet_bits ? 8 - $last_octet_bits : 0; $num = gmp_init($flags); // mask bits outside bitfield width $mask = gmp_sub(gmp_init(1) << $width, 1); $num &= $mask; // shift towards MSB if needed $data = gmp_export($num << $unused_bits, 1, GMP_MSW_FIRST | GMP_BIG_ENDIAN); $octets = unpack("C*", $data); $bits = count($octets) * 8; // pad with zeroes while ($bits < $width) { array_unshift($octets, 0); $bits += 8; } $this->_flags = pack("C*", ...$octets); } $this->_width = $width; }
/** * Perform Integer-to-Octet-String Conversion. * * Defined in SEC 1 section 2.3.7. * * @param Integer $num * @param int $mlen Optional desired output length * @throws \UnexpectedValueException * @return OctetString */ public static function integerToOctetString(Integer $num, $mlen = null) { $gmp = gmp_init($num->number(), 10); $str = gmp_export($gmp, 1, GMP_MSW_FIRST | GMP_BIG_ENDIAN); if (null !== $mlen) { $len = strlen($str); if ($len > $mlen) { throw new \RangeException("Number is too large."); } // pad with zeroes if ($len < $mlen) { $str = str_repeat("", $mlen - $len) . $str; } } return new OctetString($str); }
public function checkAuth($nick, $passwd) { if (substr($this->pwdHash, 0, 3) === '#1#') { // 1st case: new, SHA256 SRP logins // https://tools.ietf.org/html/rfc2945#section-3 $pwdArr = explode('#', $this->pwdHash); $x = gmp_import(hash("sha256", base64_decode($pwdArr[2]) . hash("sha256", strtolower($nick) . ':' . $passwd, true), true), 1, GMP_MSW_FIRST | GMP_BIG_ENDIAN); $N = gmp_init("AC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC3192943DB56050A37329CBB4" . "A099ED8193E0757767A13DD52312AB4B03310DCD7F48A9DA04FD50E8083969EDB767B0CF60" . "95179A163AB3661A05FBD5FAAAE82918A9962F0B93B855F97993EC975EEAA80D740ADBF4FF" . "747359D041D5C33EA71D281E446B14773BCA97B43A23FB801676BD207A436C6481F1D2B907" . "8717461A5B9D32E688F87748544523B524B0D57D5EA77A2775D2ECFA032CFBDBF52FB37861" . "60279004E57AE6AF874E7303CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DB" . "FBB694B5C803D89F7AE435DE236D525F54759B65E372FCD68EF20FA7111F9E4AFF73", 16); $g = gmp_init(2); $v = gmp_powm($g, $x, $N); // strpos to check if the saved has is the same as our hash, minus the possible base64 padding return strpos(base64_encode(gmp_export($v, 1, GMP_MSW_FIRST | GMP_BIG_ENDIAN)), $pwdArr[3]) === 0; } else { // 2nd case: old, pre-SRP logins using salted SHA1 // src/util/auth.cpp#34 at rev 0bf1984d2c9fb3a9dc73303551c18906c3c9482b // https://github.com/minetest/minetest/blob/0bf1984d2c9fb3a9dc73303551c18906c3c9482b/src/util/auth.cpp#L34 return strpos(base64_encode(hash("sha1", $nick . $passwd, true)), $this->pwdHash) === 0; } return false; }
protected function round($K, $n, $T, $i, $B, $iv, $radix) { // $b is the length of the input when converted to radix=256, thus num of bytes (rounded) $b = (int) ceil(ceil(ceil($n / 2) * log($radix, 2)) / 8); $d = (int) (4 * ceil($b / 4)); // Input $Q = $T . str_repeat("", -strlen($T) - $b - 1 & 0xf) . chr($i) . $this->fixedLength(gmp_export(gmp_init($B, $radix)), $b); // Y = CBC-MAC_K(P·Q) // CBC-MAC is the same as the last block of cipher text of CBC mode and a zero iv (the iv used here is P') $Y = substr(openssl_encrypt($Q, $this->cipher . '-CBC', $K, \OPENSSL_RAW_DATA | \OPENSSL_ZERO_PADDING, $iv), -16); // Y = first d + 4 bytes of (Y · AES_K(Y ⊕ [1]16) · AES_K(Y ⊕ [2]16) · AES_K(Y ⊕ [3]16)·· ) $E = ''; for ($j = 1; $j * 16 < $d + 4; $j++) { $J = $this->fixedLength(gmp_export(gmp_init($j)), 16); $E .= openssl_encrypt($Y ^ $J, $this->cipher . '-ECB', $K, \OPENSSL_RAW_DATA | \OPENSSL_ZERO_PADDING); } $Y = substr($Y . $E, 0, $d + 4); // y = NUM_2(Y) $y = gmp_import($Y); $m = (int) ($i & 1 ? ceil($n / 2) : floor($n / 2)); // z = y mod radix^m is actually cropping the string length return $this->fixedLength(gmp_strval($y, $radix), $m, '0'); }
public function calculateSharedKey($publicKeyBin) { $length = strlen($publicKeyBin) - 1; if ($length % 2 != 0) { return; } $half = $length / 2; $x = substr($publicKeyBin, 1, $half); $gmpX = gmp_import($x, 1); $y = substr($publicKeyBin, $half + 1); $gmpY = gmp_import($y, 1); $curve = $this->getCurve(); $adapter = $this->getAdapter(); $gen = $this->getGenerator(); $ecdh = $this->getEcdh(); $point = $curve->getPoint($gmpX, $gmpY); $privateKey = $this->getPrivateKey(); $publicKey = new PublicKey($adapter, $gen, $point); $ecdh->setSenderKey($privateKey); $ecdh->setRecipientKey($publicKey); $sharedKey = $ecdh->calculateSharedKey(); return gmp_export($sharedKey); }
/** * Converts hexadecimal string into stream of bytes. * * @param string $hex Hexadecimal string. * * @return mixed Stream of bytes. */ public static function hexToRaw($hex) { $gmp = gmp_init($hex, 16); return gmp_export($gmp); }
/** * Convert GMP number to string. * * Returned string represents an unsigned integer with big endian order and * the most significant byte first. * * @param \GMP $num GMP number * @param int $size Width of the string in bytes * @return string Binary data */ public static function gmpToStr(\GMP $num, $size) { $data = gmp_export($num, 1, GMP_MSW_FIRST | GMP_BIG_ENDIAN); $len = strlen($data); if ($len < $size) { $data = str_repeat("", $size - $len) . $data; } return $data; }
/** * Encode negative integer to DER content. * * @param \GMP|resource $num * @return string */ private static function _encodeNegativeInteger($num) { $num = gmp_abs($num); // compute number of bytes required $width = 1; if ($num > 128) { $tmp = $num; do { $width++; $tmp >>= 8; } while ($tmp > 128); } // compute two's complement 2^n - x $num = gmp_pow("2", 8 * $width) - $num; $bin = gmp_export($num, 1, GMP_MSW_FIRST | GMP_BIG_ENDIAN); // if first bit is 0, prepend full inverted byte // to represent negative two's complement if (!(ord($bin[0]) & 0x80)) { $bin = chr(0xff) . $bin; } return $bin; }
<?php // Tests taken from GMPs own test suite. // format is [output, size, options, expected] $export = [['0', 1, GMP_BIG_ENDIAN, ''], ['0', 2, GMP_BIG_ENDIAN, ''], ['0', 3, GMP_BIG_ENDIAN, ''], ['12345678', 1, GMP_BIG_ENDIAN, '12345678'], ['12345678', 4, GMP_BIG_ENDIAN, '12345678'], ['12345678', 4, GMP_LSW_FIRST | GMP_BIG_ENDIAN, '12345678'], ['12345678', 1, GMP_LSW_FIRST | GMP_LITTLE_ENDIAN, '78563412'], ['12345678', 4, GMP_LITTLE_ENDIAN, '78563412'], ['12345678', 4, GMP_LSW_FIRST | GMP_LITTLE_ENDIAN, '78563412'], ['123456789ABC', 2, GMP_BIG_ENDIAN, '123456789abc'], ['123456789ABC', 2, GMP_LSW_FIRST | GMP_BIG_ENDIAN, '9abc56781234'], ['123456789ABC', 2, GMP_LITTLE_ENDIAN, '34127856bc9a'], ['123456789ABC', 2, GMP_LSW_FIRST | GMP_LITTLE_ENDIAN, 'bc9a78563412'], ['112233445566778899AABBCC', 4, GMP_BIG_ENDIAN, '112233445566778899aabbcc'], ['112233445566778899AABBCC', 4, GMP_LSW_FIRST | GMP_BIG_ENDIAN, '99aabbcc5566778811223344'], ['112233445566778899AABBCC', 4, GMP_LITTLE_ENDIAN, '4433221188776655ccbbaa99'], ['112233445566778899AABBCC', 4, GMP_LSW_FIRST | GMP_LITTLE_ENDIAN, 'ccbbaa998877665544332211'], ['100120023003400450056006700780089009A00AB00BC00C', 8, GMP_BIG_ENDIAN, '100120023003400450056006700780089009a00ab00bc00c'], ['100120023003400450056006700780089009A00AB00BC00C', 8, GMP_LSW_FIRST | GMP_BIG_ENDIAN, '9009a00ab00bc00c50056006700780081001200230034004'], ['100120023003400450056006700780089009A00AB00BC00C', 8, GMP_LITTLE_ENDIAN, '044003300220011008800770066005500cc00bb00aa00990'], ['100120023003400450056006700780089009A00AB00BC00C', 8, GMP_LSW_FIRST | GMP_LITTLE_ENDIAN, '0cc00bb00aa0099008800770066005500440033002200110']]; $passed = true; foreach ($export as $k => $test) { $gmp = gmp_init($test[0], 16); $str = gmp_export($gmp, $test[1], $test[2]); if (is_string($str)) { $result = bin2hex($str); if ($result !== $test[3]) { echo "{$k}: '{$result}' !== '{$test[3]}'\n"; $passed = false; } } else { $type = gettype($str); echo "{$k}: {$type} !== '{$test[3]}'\n"; } } var_dump($passed); // Invalid arguments (zpp failure) var_dump(gmp_export()); // Invalid word sizes var_dump(gmp_export(123, -1)); var_dump(gmp_export(123, 0)); // Invalid options var_dump(gmp_export(123, 1, GMP_MSW_FIRST | GMP_LSW_FIRST)); var_dump(gmp_export(123, 1, GMP_BIG_ENDIAN | GMP_LITTLE_ENDIAN));
/** * Convert to base256 string. * * @return string */ public function base256() { return gmp_export($this->_num, 1, GMP_MSW_FIRST | GMP_BIG_ENDIAN); }
/** * Sets test data. */ public static function setUpBeforeClass() { self::$convertData = ['2-digit integer' => ['decimal' => '10', 'hexadecimal' => 'a', 'binary' => '1010', 'raw' => gmp_export(gmp_init('10', 10))], '3-digit integer' => ['decimal' => '123', 'hexadecimal' => '7b', 'binary' => '1111011', 'raw' => gmp_export(gmp_init('123', 10))], '4-digit integer' => ['decimal' => '3328', 'hexadecimal' => 'd00', 'binary' => '110100000000', 'raw' => gmp_export(gmp_init('3328', 10))], '32-bit signed integer max value' => ['decimal' => '2147483647', 'hexadecimal' => '7' . str_repeat('f', 7), 'binary' => str_repeat('1', 31), 'raw' => gmp_export(gmp_init('2147483647', 10))], '64-bit signed integer max value' => ['decimal' => '9223372036854775807', 'hexadecimal' => '7' . str_repeat('f', 15), 'binary' => str_repeat('1', 63), 'raw' => gmp_export(gmp_init('9223372036854775807', 10))], '128-bit signed integer max value' => ['decimal' => '170141183460469231731687303715884105727', 'hexadecimal' => '7' . str_repeat('f', 31), 'binary' => str_repeat('1', 127), 'raw' => gmp_export(gmp_init('170141183460469231731687303715884105727', 10))]]; }