2018-10-25 03:00:37 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Binary Finite Fields
|
|
|
|
*
|
|
|
|
* Utilizes the factory design pattern
|
|
|
|
*
|
|
|
|
* PHP version 5 and 7
|
|
|
|
*
|
|
|
|
* @category Math
|
|
|
|
* @package BigInteger
|
|
|
|
* @author Jim Wigginton <terrafrost@php.net>
|
|
|
|
* @copyright 2017 Jim Wigginton
|
|
|
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
|
|
|
*/
|
|
|
|
|
|
|
|
namespace phpseclib\Math;
|
|
|
|
|
|
|
|
use ParagonIE\ConstantTime\Hex;
|
|
|
|
use phpseclib\Math\Common\FiniteField;
|
|
|
|
use phpseclib\Math\BinaryField\Integer;
|
|
|
|
use phpseclib\Common\Functions\Strings;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Binary Finite Fields
|
|
|
|
*
|
|
|
|
* @package Math
|
|
|
|
* @author Jim Wigginton <terrafrost@php.net>
|
|
|
|
* @access public
|
|
|
|
*/
|
|
|
|
class BinaryField extends FiniteField
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* Instance Counter
|
|
|
|
*
|
|
|
|
* @var int
|
|
|
|
*/
|
|
|
|
private static $instanceCounter = 0;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Keeps track of current instance
|
|
|
|
*
|
|
|
|
* @var int
|
|
|
|
*/
|
|
|
|
protected $instanceID;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Default constructor
|
|
|
|
*/
|
|
|
|
public function __construct(...$indices)
|
|
|
|
{
|
|
|
|
$m = array_shift($indices);
|
|
|
|
$val = str_repeat('0', $m) . '1';
|
|
|
|
foreach ($indices as $index) {
|
|
|
|
$val[$index] = '1';
|
|
|
|
}
|
|
|
|
$modulo = static::base2ToBase256(strrev($val));
|
|
|
|
|
|
|
|
$mStart = 2 * $m - 2;
|
|
|
|
$t = ceil($m / 8);
|
|
|
|
$finalMask = chr((1 << ($m % 8)) - 1);
|
2018-12-27 15:31:35 +01:00
|
|
|
if ($finalMask == "\0") {
|
|
|
|
$finalMask = "\xFF";
|
|
|
|
}
|
2018-10-25 03:00:37 +02:00
|
|
|
$bitLen = $mStart + 1;
|
|
|
|
$pad = ceil($bitLen / 8);
|
|
|
|
$h = $bitLen & 7;
|
|
|
|
$h = $h ? 8 - $h : 0;
|
|
|
|
|
|
|
|
$r = rtrim(substr($val, 0, -1), '0');
|
|
|
|
$u = [static::base2ToBase256(strrev($r))];
|
|
|
|
for ($i = 1; $i < 8; $i++) {
|
|
|
|
$u[] = static::base2ToBase256(strrev(str_repeat('0', $i) . $r));
|
|
|
|
}
|
|
|
|
|
|
|
|
// implements algorithm 2.40 (in section 2.3.5) in "Guide to Elliptic Curve Cryptography"
|
|
|
|
// with W = 8
|
|
|
|
$reduce = function($c) use ($u, $mStart, $m, $t, $finalMask, $pad, $h) {
|
|
|
|
$c = str_pad($c, $pad, "\0", STR_PAD_LEFT);
|
|
|
|
for ($i = $mStart; $i >= $m;) {
|
|
|
|
$g = $h >> 3;
|
|
|
|
$mask = $h & 7;
|
|
|
|
$mask = $mask ? 1 << (7 - $mask) : 0x80;
|
|
|
|
for (; $mask > 0; $mask >>= 1, $i--, $h++) {
|
|
|
|
if (ord($c[$g]) & $mask) {
|
|
|
|
$temp = $i - $m;
|
|
|
|
$j = $temp >> 3;
|
|
|
|
$k = $temp & 7;
|
|
|
|
$t1 = $j ? substr($c, 0, -$j) : $c;
|
|
|
|
$length = strlen($t1);
|
|
|
|
if ($length) {
|
|
|
|
$t2 = str_pad($u[$k], $length, "\0", STR_PAD_LEFT);
|
|
|
|
$temp = $t1 ^ $t2;
|
|
|
|
$c = $j ? substr_replace($c, $temp, 0, $length) : $temp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$c = substr($c, -$t);
|
|
|
|
if (strlen($c) == $t) {
|
|
|
|
$c[0] = $c[0] & $finalMask;
|
|
|
|
}
|
|
|
|
return ltrim($c, "\0");
|
|
|
|
};
|
|
|
|
|
|
|
|
$this->instanceID = self::$instanceCounter++;
|
|
|
|
Integer::setModulo($this->instanceID, $modulo);
|
|
|
|
Integer::setRecurringModuloFunction($this->instanceID, $reduce);
|
|
|
|
|
|
|
|
$this->randomMax = new BigInteger($modulo, 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns an instance of a dynamically generated PrimeFieldInteger class
|
|
|
|
*
|
|
|
|
* @param string $num
|
|
|
|
* @return object
|
|
|
|
*/
|
|
|
|
public function newInteger($num)
|
|
|
|
{
|
|
|
|
return new Integer($this->instanceID, $num instanceof BigInteger ? $num->toBytes() : $num);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns an integer on the finite field between one and the prime modulo
|
|
|
|
*
|
|
|
|
* @return object
|
|
|
|
*/
|
|
|
|
public function randomInteger()
|
|
|
|
{
|
|
|
|
static $one;
|
|
|
|
if (!isset($one)) {
|
|
|
|
$one = new BigInteger(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return new Integer($this->instanceID, BigInteger::randomRange($one, $this->randomMax)->toBytes());
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the length of the modulo in bytes
|
|
|
|
*
|
|
|
|
* @return integer
|
|
|
|
*/
|
|
|
|
public function getLengthInBytes()
|
|
|
|
{
|
|
|
|
return strlen(Integer::getModulo($this->instanceID));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the length of the modulo in bits
|
|
|
|
*
|
|
|
|
* @return integer
|
|
|
|
*/
|
|
|
|
public function getLength()
|
|
|
|
{
|
|
|
|
return strlen(Integer::getModulo($this->instanceID)) << 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Converts a base-2 string to a base-256 string
|
|
|
|
*
|
|
|
|
* @param string $x
|
|
|
|
* @param integer $size
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
public static function base2ToBase256($x, $size = null)
|
|
|
|
{
|
|
|
|
$str = Strings::bits2bin($x);
|
|
|
|
|
|
|
|
$pad = strlen($x) >> 3;
|
|
|
|
if (strlen($x) & 3) {
|
|
|
|
$pad++;
|
|
|
|
}
|
|
|
|
$str = str_pad($str, $pad, "\0", STR_PAD_LEFT);
|
|
|
|
if (isset($size)) {
|
|
|
|
$str = str_pad($str, $size, "\0", STR_PAD_LEFT);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $str;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Converts a base-256 string to a base-2 string
|
|
|
|
*
|
|
|
|
* @param string $x
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
public static function base256ToBase2($x)
|
|
|
|
{
|
|
|
|
if (function_exists('gmp_import')) {
|
|
|
|
return gmp_strval(gmp_import($x), 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
return Strings::bin2bits($x);
|
|
|
|
}
|
|
|
|
}
|