[securemail] Bump phpseclib dependency to version 3.0.19
[friendica-addons.git/.git] / securemail / vendor / phpseclib / phpseclib / phpseclib / Math / BinaryField.php
1 <?php
2
3 /**
4  * Binary Finite Fields
5  *
6  * Utilizes the factory design pattern
7  *
8  * PHP version 5 and 7
9  *
10  * @author    Jim Wigginton <terrafrost@php.net>
11  * @copyright 2017 Jim Wigginton
12  * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
13  */
14
15 namespace phpseclib3\Math;
16
17 use phpseclib3\Common\Functions\Strings;
18 use phpseclib3\Math\BinaryField\Integer;
19 use phpseclib3\Math\Common\FiniteField;
20
21 /**
22  * Binary Finite Fields
23  *
24  * @author  Jim Wigginton <terrafrost@php.net>
25  */
26 class BinaryField extends FiniteField
27 {
28     /**
29      * Instance Counter
30      *
31      * @var int
32      */
33     private static $instanceCounter = 0;
34
35     /**
36      * Keeps track of current instance
37      *
38      * @var int
39      */
40     protected $instanceID;
41
42     /** @var BigInteger */
43     private $randomMax;
44
45     /**
46      * Default constructor
47      */
48     public function __construct(...$indices)
49     {
50         $m = array_shift($indices);
51         $val = str_repeat('0', $m) . '1';
52         foreach ($indices as $index) {
53             $val[$index] = '1';
54         }
55         $modulo = static::base2ToBase256(strrev($val));
56
57         $mStart = 2 * $m - 2;
58         $t = ceil($m / 8);
59         $finalMask = chr((1 << ($m % 8)) - 1);
60         if ($finalMask == "\0") {
61             $finalMask = "\xFF";
62         }
63         $bitLen = $mStart + 1;
64         $pad = ceil($bitLen / 8);
65         $h = $bitLen & 7;
66         $h = $h ? 8 - $h : 0;
67
68         $r = rtrim(substr($val, 0, -1), '0');
69         $u = [static::base2ToBase256(strrev($r))];
70         for ($i = 1; $i < 8; $i++) {
71             $u[] = static::base2ToBase256(strrev(str_repeat('0', $i) . $r));
72         }
73
74         // implements algorithm 2.40 (in section 2.3.5) in "Guide to Elliptic Curve Cryptography"
75         // with W = 8
76         $reduce = function ($c) use ($u, $mStart, $m, $t, $finalMask, $pad, $h) {
77             $c = str_pad($c, $pad, "\0", STR_PAD_LEFT);
78             for ($i = $mStart; $i >= $m;) {
79                 $g = $h >> 3;
80                 $mask = $h & 7;
81                 $mask = $mask ? 1 << (7 - $mask) : 0x80;
82                 for (; $mask > 0; $mask >>= 1, $i--, $h++) {
83                     if (ord($c[$g]) & $mask) {
84                         $temp = $i - $m;
85                         $j = $temp >> 3;
86                         $k = $temp & 7;
87                         $t1 = $j ? substr($c, 0, -$j) : $c;
88                         $length = strlen($t1);
89                         if ($length) {
90                             $t2 = str_pad($u[$k], $length, "\0", STR_PAD_LEFT);
91                             $temp = $t1 ^ $t2;
92                             $c = $j ? substr_replace($c, $temp, 0, $length) : $temp;
93                         }
94                     }
95                 }
96             }
97             $c = substr($c, -$t);
98             if (strlen($c) == $t) {
99                 $c[0] = $c[0] & $finalMask;
100             }
101             return ltrim($c, "\0");
102         };
103
104         $this->instanceID = self::$instanceCounter++;
105         Integer::setModulo($this->instanceID, $modulo);
106         Integer::setRecurringModuloFunction($this->instanceID, $reduce);
107
108         $this->randomMax = new BigInteger($modulo, 2);
109     }
110
111     /**
112      * Returns an instance of a dynamically generated PrimeFieldInteger class
113      *
114      * @param string $num
115      * @return Integer
116      */
117     public function newInteger($num)
118     {
119         return new Integer($this->instanceID, $num instanceof BigInteger ? $num->toBytes() : $num);
120     }
121
122     /**
123      * Returns an integer on the finite field between one and the prime modulo
124      *
125      * @return Integer
126      */
127     public function randomInteger()
128     {
129         static $one;
130         if (!isset($one)) {
131             $one = new BigInteger(1);
132         }
133
134         return new Integer($this->instanceID, BigInteger::randomRange($one, $this->randomMax)->toBytes());
135     }
136
137     /**
138      * Returns the length of the modulo in bytes
139      *
140      * @return int
141      */
142     public function getLengthInBytes()
143     {
144         return strlen(Integer::getModulo($this->instanceID));
145     }
146
147     /**
148      * Returns the length of the modulo in bits
149      *
150      * @return int
151      */
152     public function getLength()
153     {
154         return strlen(Integer::getModulo($this->instanceID)) << 3;
155     }
156
157     /**
158      * Converts a base-2 string to a base-256 string
159      *
160      * @param string $x
161      * @param int|null $size
162      * @return string
163      */
164     public static function base2ToBase256($x, $size = null)
165     {
166         $str = Strings::bits2bin($x);
167
168         $pad = strlen($x) >> 3;
169         if (strlen($x) & 3) {
170             $pad++;
171         }
172         $str = str_pad($str, $pad, "\0", STR_PAD_LEFT);
173         if (isset($size)) {
174             $str = str_pad($str, $size, "\0", STR_PAD_LEFT);
175         }
176
177         return $str;
178     }
179
180     /**
181      * Converts a base-256 string to a base-2 string
182      *
183      * @param string $x
184      * @return string
185      */
186     public static function base256ToBase2($x)
187     {
188         if (function_exists('gmp_import')) {
189             return gmp_strval(gmp_import($x), 2);
190         }
191
192         return Strings::bin2bits($x);
193     }
194 }