mirror of
https://github.com/phpseclib/phpseclib.git
synced 2024-11-05 21:17:53 +00:00
- fixes to Math_BigInteger::_barrett()
- speed ups based on <http://blog.libssh2.org/index.php?/archives/21-Compiled-Variables.html>. git-svn-id: http://phpseclib.svn.sourceforge.net/svnroot/phpseclib/trunk@74 21d32557-59b3-4da0-833f-c5933fad653e
This commit is contained in:
parent
e16ba96789
commit
7ecd481002
@ -56,7 +56,7 @@
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright MMVIII Jim Wigginton
|
||||
* @license http://www.gnu.org/licenses/lgpl.txt
|
||||
* @version $Id: AES.php,v 1.5 2009-11-23 19:06:06 terrafrost Exp $
|
||||
* @version $Id: AES.php,v 1.6 2010-01-04 07:59:01 terrafrost Exp $
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
||||
@ -332,12 +332,19 @@ class Crypt_AES extends Crypt_Rijndael {
|
||||
{
|
||||
$state = unpack('N*word', $in);
|
||||
|
||||
$Nr = $this->Nr;
|
||||
$w = $this->w;
|
||||
$t0 = $this->t0;
|
||||
$t1 = $this->t1;
|
||||
$t2 = $this->t2;
|
||||
$t3 = $this->t3;
|
||||
|
||||
// addRoundKey and reindex $state
|
||||
$state = array(
|
||||
$state['word1'] ^ $this->w[0][0],
|
||||
$state['word2'] ^ $this->w[0][1],
|
||||
$state['word3'] ^ $this->w[0][2],
|
||||
$state['word4'] ^ $this->w[0][3]
|
||||
$state['word1'] ^ $w[0][0],
|
||||
$state['word2'] ^ $w[0][1],
|
||||
$state['word3'] ^ $w[0][2],
|
||||
$state['word4'] ^ $w[0][3]
|
||||
);
|
||||
|
||||
// shiftRows + subWord + mixColumns + addRoundKey
|
||||
@ -345,10 +352,10 @@ class Crypt_AES extends Crypt_Rijndael {
|
||||
// only a marginal improvement. since that also, imho, hinders the readability of the code, i've opted not to do it.
|
||||
for ($round = 1; $round < $this->Nr; $round++) {
|
||||
$state = array(
|
||||
$this->t0[$state[0] & 0xFF000000] ^ $this->t1[$state[1] & 0x00FF0000] ^ $this->t2[$state[2] & 0x0000FF00] ^ $this->t3[$state[3] & 0x000000FF] ^ $this->w[$round][0],
|
||||
$this->t0[$state[1] & 0xFF000000] ^ $this->t1[$state[2] & 0x00FF0000] ^ $this->t2[$state[3] & 0x0000FF00] ^ $this->t3[$state[0] & 0x000000FF] ^ $this->w[$round][1],
|
||||
$this->t0[$state[2] & 0xFF000000] ^ $this->t1[$state[3] & 0x00FF0000] ^ $this->t2[$state[0] & 0x0000FF00] ^ $this->t3[$state[1] & 0x000000FF] ^ $this->w[$round][2],
|
||||
$this->t0[$state[3] & 0xFF000000] ^ $this->t1[$state[0] & 0x00FF0000] ^ $this->t2[$state[1] & 0x0000FF00] ^ $this->t3[$state[2] & 0x000000FF] ^ $this->w[$round][3]
|
||||
$t0[$state[0] & 0xFF000000] ^ $t1[$state[1] & 0x00FF0000] ^ $t2[$state[2] & 0x0000FF00] ^ $t3[$state[3] & 0x000000FF] ^ $w[$round][0],
|
||||
$t0[$state[1] & 0xFF000000] ^ $t1[$state[2] & 0x00FF0000] ^ $t2[$state[3] & 0x0000FF00] ^ $t3[$state[0] & 0x000000FF] ^ $w[$round][1],
|
||||
$t0[$state[2] & 0xFF000000] ^ $t1[$state[3] & 0x00FF0000] ^ $t2[$state[0] & 0x0000FF00] ^ $t3[$state[1] & 0x000000FF] ^ $w[$round][2],
|
||||
$t0[$state[3] & 0xFF000000] ^ $t1[$state[0] & 0x00FF0000] ^ $t2[$state[1] & 0x0000FF00] ^ $t3[$state[2] & 0x000000FF] ^ $w[$round][3]
|
||||
);
|
||||
|
||||
}
|
||||
@ -386,31 +393,38 @@ class Crypt_AES extends Crypt_Rijndael {
|
||||
{
|
||||
$state = unpack('N*word', $in);
|
||||
|
||||
$Nr = $this->Nr;
|
||||
$dw = $this->dw;
|
||||
$dt0 = $this->dt0;
|
||||
$dt1 = $this->dt1;
|
||||
$dt2 = $this->dt2;
|
||||
$dt3 = $this->dt3;
|
||||
|
||||
// addRoundKey and reindex $state
|
||||
$state = array(
|
||||
$state['word1'] ^ $this->dw[$this->Nr][0],
|
||||
$state['word2'] ^ $this->dw[$this->Nr][1],
|
||||
$state['word3'] ^ $this->dw[$this->Nr][2],
|
||||
$state['word4'] ^ $this->dw[$this->Nr][3]
|
||||
$state['word1'] ^ $dw[$this->Nr][0],
|
||||
$state['word2'] ^ $dw[$this->Nr][1],
|
||||
$state['word3'] ^ $dw[$this->Nr][2],
|
||||
$state['word4'] ^ $dw[$this->Nr][3]
|
||||
);
|
||||
|
||||
|
||||
// invShiftRows + invSubBytes + invMixColumns + addRoundKey
|
||||
for ($round = $this->Nr - 1; $round > 0; $round--) {
|
||||
$state = array(
|
||||
$this->dt0[$state[0] & 0xFF000000] ^ $this->dt1[$state[3] & 0x00FF0000] ^ $this->dt2[$state[2] & 0x0000FF00] ^ $this->dt3[$state[1] & 0x000000FF] ^ $this->dw[$round][0],
|
||||
$this->dt0[$state[1] & 0xFF000000] ^ $this->dt1[$state[0] & 0x00FF0000] ^ $this->dt2[$state[3] & 0x0000FF00] ^ $this->dt3[$state[2] & 0x000000FF] ^ $this->dw[$round][1],
|
||||
$this->dt0[$state[2] & 0xFF000000] ^ $this->dt1[$state[1] & 0x00FF0000] ^ $this->dt2[$state[0] & 0x0000FF00] ^ $this->dt3[$state[3] & 0x000000FF] ^ $this->dw[$round][2],
|
||||
$this->dt0[$state[3] & 0xFF000000] ^ $this->dt1[$state[2] & 0x00FF0000] ^ $this->dt2[$state[1] & 0x0000FF00] ^ $this->dt3[$state[0] & 0x000000FF] ^ $this->dw[$round][3]
|
||||
$dt0[$state[0] & 0xFF000000] ^ $dt1[$state[3] & 0x00FF0000] ^ $dt2[$state[2] & 0x0000FF00] ^ $dt3[$state[1] & 0x000000FF] ^ $dw[$round][0],
|
||||
$dt0[$state[1] & 0xFF000000] ^ $dt1[$state[0] & 0x00FF0000] ^ $dt2[$state[3] & 0x0000FF00] ^ $dt3[$state[2] & 0x000000FF] ^ $dw[$round][1],
|
||||
$dt0[$state[2] & 0xFF000000] ^ $dt1[$state[1] & 0x00FF0000] ^ $dt2[$state[0] & 0x0000FF00] ^ $dt3[$state[3] & 0x000000FF] ^ $dw[$round][2],
|
||||
$dt0[$state[3] & 0xFF000000] ^ $dt1[$state[2] & 0x00FF0000] ^ $dt2[$state[1] & 0x0000FF00] ^ $dt3[$state[0] & 0x000000FF] ^ $dw[$round][3]
|
||||
);
|
||||
}
|
||||
|
||||
// invShiftRows + invSubWord + addRoundKey
|
||||
$state = array(
|
||||
$this->_invSubWord(($state[0] & 0xFF000000) ^ ($state[3] & 0x00FF0000) ^ ($state[2] & 0x0000FF00) ^ ($state[1] & 0x000000FF)) ^ $this->dw[0][0],
|
||||
$this->_invSubWord(($state[1] & 0xFF000000) ^ ($state[0] & 0x00FF0000) ^ ($state[3] & 0x0000FF00) ^ ($state[2] & 0x000000FF)) ^ $this->dw[0][1],
|
||||
$this->_invSubWord(($state[2] & 0xFF000000) ^ ($state[1] & 0x00FF0000) ^ ($state[0] & 0x0000FF00) ^ ($state[3] & 0x000000FF)) ^ $this->dw[0][2],
|
||||
$this->_invSubWord(($state[3] & 0xFF000000) ^ ($state[2] & 0x00FF0000) ^ ($state[1] & 0x0000FF00) ^ ($state[0] & 0x000000FF)) ^ $this->dw[0][3]
|
||||
$this->_invSubWord(($state[0] & 0xFF000000) ^ ($state[3] & 0x00FF0000) ^ ($state[2] & 0x0000FF00) ^ ($state[1] & 0x000000FF)) ^ $dw[0][0],
|
||||
$this->_invSubWord(($state[1] & 0xFF000000) ^ ($state[0] & 0x00FF0000) ^ ($state[3] & 0x0000FF00) ^ ($state[2] & 0x000000FF)) ^ $dw[0][1],
|
||||
$this->_invSubWord(($state[2] & 0xFF000000) ^ ($state[1] & 0x00FF0000) ^ ($state[0] & 0x0000FF00) ^ ($state[3] & 0x000000FF)) ^ $dw[0][2],
|
||||
$this->_invSubWord(($state[3] & 0xFF000000) ^ ($state[2] & 0x00FF0000) ^ ($state[1] & 0x0000FF00) ^ ($state[0] & 0x000000FF)) ^ $dw[0][3]
|
||||
);
|
||||
|
||||
return pack('N*', $state[0], $state[1], $state[2], $state[3]);
|
||||
|
@ -53,7 +53,7 @@
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright MMVII Jim Wigginton
|
||||
* @license http://www.gnu.org/licenses/lgpl.txt
|
||||
* @version $Id: DES.php,v 1.10 2009-12-06 07:26:52 terrafrost Exp $
|
||||
* @version $Id: DES.php,v 1.11 2010-01-04 07:59:01 terrafrost Exp $
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
||||
@ -613,6 +613,8 @@ class Crypt_DES {
|
||||
)
|
||||
);
|
||||
|
||||
$keys = $this->keys;
|
||||
|
||||
$temp = unpack('Na/Nb', $block);
|
||||
$block = array($temp['a'], $temp['b']);
|
||||
|
||||
@ -667,14 +669,14 @@ class Crypt_DES {
|
||||
for ($i = 0; $i < 16; $i++) {
|
||||
// start of "the Feistel (F) function" - see the following URL:
|
||||
// http://en.wikipedia.org/wiki/Image:Data_Encryption_Standard_InfoBox_Diagram.png
|
||||
$temp = (($sbox[0][((($block[1] >> 27) & 0x1F) | (($block[1] & 1) << 5)) ^ $this->keys[$mode][$i][0]]) << 28)
|
||||
| (($sbox[1][(($block[1] & 0x1F800000) >> 23) ^ $this->keys[$mode][$i][1]]) << 24)
|
||||
| (($sbox[2][(($block[1] & 0x01F80000) >> 19) ^ $this->keys[$mode][$i][2]]) << 20)
|
||||
| (($sbox[3][(($block[1] & 0x001F8000) >> 15) ^ $this->keys[$mode][$i][3]]) << 16)
|
||||
| (($sbox[4][(($block[1] & 0x0001F800) >> 11) ^ $this->keys[$mode][$i][4]]) << 12)
|
||||
| (($sbox[5][(($block[1] & 0x00001F80) >> 7) ^ $this->keys[$mode][$i][5]]) << 8)
|
||||
| (($sbox[6][(($block[1] & 0x000001F8) >> 3) ^ $this->keys[$mode][$i][6]]) << 4)
|
||||
| ( $sbox[7][((($block[1] & 0x1F) << 1) | (($block[1] >> 31) & 1)) ^ $this->keys[$mode][$i][7]]);
|
||||
$temp = (($sbox[0][((($block[1] >> 27) & 0x1F) | (($block[1] & 1) << 5)) ^ $keys[$mode][$i][0]]) << 28)
|
||||
| (($sbox[1][(($block[1] & 0x1F800000) >> 23) ^ $keys[$mode][$i][1]]) << 24)
|
||||
| (($sbox[2][(($block[1] & 0x01F80000) >> 19) ^ $keys[$mode][$i][2]]) << 20)
|
||||
| (($sbox[3][(($block[1] & 0x001F8000) >> 15) ^ $keys[$mode][$i][3]]) << 16)
|
||||
| (($sbox[4][(($block[1] & 0x0001F800) >> 11) ^ $keys[$mode][$i][4]]) << 12)
|
||||
| (($sbox[5][(($block[1] & 0x00001F80) >> 7) ^ $keys[$mode][$i][5]]) << 8)
|
||||
| (($sbox[6][(($block[1] & 0x000001F8) >> 3) ^ $keys[$mode][$i][6]]) << 4)
|
||||
| ( $sbox[7][((($block[1] & 0x1F) << 1) | (($block[1] >> 31) & 1)) ^ $keys[$mode][$i][7]]);
|
||||
|
||||
$msb = ($temp >> 31) & 1;
|
||||
$temp &= 0x7FFFFFFF;
|
||||
|
@ -64,7 +64,7 @@
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright MMVIII Jim Wigginton
|
||||
* @license http://www.gnu.org/licenses/lgpl.txt
|
||||
* @version $Id: Rijndael.php,v 1.9 2009-12-06 07:26:52 terrafrost Exp $
|
||||
* @version $Id: Rijndael.php,v 1.10 2010-01-04 07:59:01 terrafrost Exp $
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
||||
@ -369,10 +369,20 @@ class Crypt_Rijndael {
|
||||
$this->mode = CRYPT_RIJNDAEL_MODE_CBC;
|
||||
}
|
||||
|
||||
$t3 = &$this->t3;
|
||||
$t2 = &$this->t2;
|
||||
$t1 = &$this->t1;
|
||||
$t0 = &$this->t0;
|
||||
|
||||
$dt3 = &$this->dt3;
|
||||
$dt2 = &$this->dt2;
|
||||
$dt1 = &$this->dt1;
|
||||
$dt0 = &$this->dt0;
|
||||
|
||||
// according to <http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=19> (section 5.2.1),
|
||||
// precomputed tables can be used in the mixColumns phase. in that example, they're assigned t0...t3, so
|
||||
// those are the names we'll use.
|
||||
$this->t3 = array(
|
||||
$t3 = array(
|
||||
0x6363A5C6, 0x7C7C84F8, 0x777799EE, 0x7B7B8DF6, 0xF2F20DFF, 0x6B6BBDD6, 0x6F6FB1DE, 0xC5C55491,
|
||||
0x30305060, 0x01010302, 0x6767A9CE, 0x2B2B7D56, 0xFEFE19E7, 0xD7D762B5, 0xABABE64D, 0x76769AEC,
|
||||
0xCACA458F, 0x82829D1F, 0xC9C94089, 0x7D7D87FA, 0xFAFA15EF, 0x5959EBB2, 0x4747C98E, 0xF0F00BFB,
|
||||
@ -407,7 +417,7 @@ class Crypt_Rijndael {
|
||||
0x4141C382, 0x9999B029, 0x2D2D775A, 0x0F0F111E, 0xB0B0CB7B, 0x5454FCA8, 0xBBBBD66D, 0x16163A2C
|
||||
);
|
||||
|
||||
$this->dt3 = array(
|
||||
$dt3 = array(
|
||||
0xF4A75051, 0x4165537E, 0x17A4C31A, 0x275E963A, 0xAB6BCB3B, 0x9D45F11F, 0xFA58ABAC, 0xE303934B,
|
||||
0x30FA5520, 0x766DF6AD, 0xCC769188, 0x024C25F5, 0xE5D7FC4F, 0x2ACBD7C5, 0x35448026, 0x62A38FB5,
|
||||
0xB15A49DE, 0xBA1B6725, 0xEA0E9845, 0xFEC0E15D, 0x2F7502C3, 0x4CF01281, 0x4697A38D, 0xD3F9C66B,
|
||||
@ -443,13 +453,13 @@ class Crypt_Rijndael {
|
||||
);
|
||||
|
||||
for ($i = 0; $i < 256; $i++) {
|
||||
$this->t2[$i << 8] = (($this->t3[$i] << 8) & 0xFFFFFF00) | (($this->t3[$i] >> 24) & 0x000000FF);
|
||||
$this->t1[$i << 16] = (($this->t3[$i] << 16) & 0xFFFF0000) | (($this->t3[$i] >> 16) & 0x0000FFFF);
|
||||
$this->t0[$i << 24] = (($this->t3[$i] << 24) & 0xFF000000) | (($this->t3[$i] >> 8) & 0x00FFFFFF);
|
||||
$t2[$i << 8] = (($t3[$i] << 8) & 0xFFFFFF00) | (($t3[$i] >> 24) & 0x000000FF);
|
||||
$t1[$i << 16] = (($t3[$i] << 16) & 0xFFFF0000) | (($t3[$i] >> 16) & 0x0000FFFF);
|
||||
$t0[$i << 24] = (($t3[$i] << 24) & 0xFF000000) | (($t3[$i] >> 8) & 0x00FFFFFF);
|
||||
|
||||
$this->dt2[$i << 8] = (($this->dt3[$i] << 8) & 0xFFFFFF00) | (($this->dt3[$i] >> 24) & 0x000000FF);
|
||||
$this->dt1[$i << 16] = (($this->dt3[$i] << 16) & 0xFFFF0000) | (($this->dt3[$i] >> 16) & 0x0000FFFF);
|
||||
$this->dt0[$i << 24] = (($this->dt3[$i] << 24) & 0xFF000000) | (($this->dt3[$i] >> 8) & 0x00FFFFFF);
|
||||
$dt2[$i << 8] = (($this->dt3[$i] << 8) & 0xFFFFFF00) | (($dt3[$i] >> 24) & 0x000000FF);
|
||||
$dt1[$i << 16] = (($this->dt3[$i] << 16) & 0xFFFF0000) | (($dt3[$i] >> 16) & 0x0000FFFF);
|
||||
$dt0[$i << 24] = (($this->dt3[$i] << 24) & 0xFF000000) | (($dt3[$i] >> 8) & 0x00FFFFFF);
|
||||
}
|
||||
}
|
||||
|
||||
@ -629,9 +639,19 @@ class Crypt_Rijndael {
|
||||
$state = array();
|
||||
$words = unpack('N*word', $in);
|
||||
|
||||
$w = $this->w;
|
||||
$t0 = $this->t0;
|
||||
$t1 = $this->t1;
|
||||
$t2 = $this->t2;
|
||||
$t3 = $this->t3;
|
||||
$Nb = $this->Nb;
|
||||
$Nr = $this->Nr;
|
||||
$c = $this->c;
|
||||
|
||||
// addRoundKey
|
||||
$i = 0;
|
||||
foreach ($words as $word) {
|
||||
$state[] = $word ^ $this->w[0][count($state)];
|
||||
$state[] = $word ^ $w[0][$i++];
|
||||
}
|
||||
|
||||
// fips-197.pdf#page=19, "Figure 5. Pseudo Code for the Cipher", states that this loop has four components -
|
||||
@ -643,49 +663,49 @@ class Crypt_Rijndael {
|
||||
|
||||
// [1] http://fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.v316.pdf
|
||||
$temp = array();
|
||||
for ($round = 1; $round < $this->Nr; $round++) {
|
||||
$i = 0; // $this->c[0] == 0
|
||||
$j = $this->c[1];
|
||||
$k = $this->c[2];
|
||||
$l = $this->c[3];
|
||||
for ($round = 1; $round < $Nr; $round++) {
|
||||
$i = 0; // $c[0] == 0
|
||||
$j = $c[1];
|
||||
$k = $c[2];
|
||||
$l = $c[3];
|
||||
|
||||
while ($i < $this->Nb) {
|
||||
$temp[$i] = $this->t0[$state[$i] & 0xFF000000] ^
|
||||
$this->t1[$state[$j] & 0x00FF0000] ^
|
||||
$this->t2[$state[$k] & 0x0000FF00] ^
|
||||
$this->t3[$state[$l] & 0x000000FF] ^
|
||||
$this->w[$round][$i];
|
||||
$temp[$i] = $t0[$state[$i] & 0xFF000000] ^
|
||||
$t1[$state[$j] & 0x00FF0000] ^
|
||||
$t2[$state[$k] & 0x0000FF00] ^
|
||||
$t3[$state[$l] & 0x000000FF] ^
|
||||
$w[$round][$i];
|
||||
$i++;
|
||||
$j = ($j + 1) % $this->Nb;
|
||||
$k = ($k + 1) % $this->Nb;
|
||||
$l = ($l + 1) % $this->Nb;
|
||||
$j = ($j + 1) % $Nb;
|
||||
$k = ($k + 1) % $Nb;
|
||||
$l = ($l + 1) % $Nb;
|
||||
}
|
||||
|
||||
for ($i = 0; $i < $this->Nb; $i++) {
|
||||
for ($i = 0; $i < $Nb; $i++) {
|
||||
$state[$i] = $temp[$i];
|
||||
}
|
||||
}
|
||||
|
||||
// subWord
|
||||
for ($i = 0; $i < $this->Nb; $i++) {
|
||||
for ($i = 0; $i < $Nb; $i++) {
|
||||
$state[$i] = $this->_subWord($state[$i]);
|
||||
}
|
||||
|
||||
// shiftRows + addRoundKey
|
||||
$i = 0; // $this->c[0] == 0
|
||||
$j = $this->c[1];
|
||||
$k = $this->c[2];
|
||||
$l = $this->c[3];
|
||||
$i = 0; // $c[0] == 0
|
||||
$j = $c[1];
|
||||
$k = $c[2];
|
||||
$l = $c[3];
|
||||
while ($i < $this->Nb) {
|
||||
$temp[$i] = ($state[$i] & 0xFF000000) ^
|
||||
($state[$j] & 0x00FF0000) ^
|
||||
($state[$k] & 0x0000FF00) ^
|
||||
($state[$l] & 0x000000FF) ^
|
||||
$this->w[$this->Nr][$i];
|
||||
$w[$Nr][$i];
|
||||
$i++;
|
||||
$j = ($j + 1) % $this->Nb;
|
||||
$k = ($k + 1) % $this->Nb;
|
||||
$l = ($l + 1) % $this->Nb;
|
||||
$j = ($j + 1) % $Nb;
|
||||
$k = ($k + 1) % $Nb;
|
||||
$l = ($l + 1) % $Nb;
|
||||
}
|
||||
$state = $temp;
|
||||
|
||||
@ -706,51 +726,62 @@ class Crypt_Rijndael {
|
||||
$state = array();
|
||||
$words = unpack('N*word', $in);
|
||||
|
||||
$num_states = count($state);
|
||||
$dw = $this->dw;
|
||||
$dt0 = $this->dt0;
|
||||
$dt1 = $this->dt1;
|
||||
$dt2 = $this->dt2;
|
||||
$dt3 = $this->dt3;
|
||||
$Nb = $this->Nb;
|
||||
$Nr = $this->Nr;
|
||||
$c = $this->c;
|
||||
|
||||
// addRoundKey
|
||||
$i = 0;
|
||||
foreach ($words as $word) {
|
||||
$state[] = $word ^ $this->dw[0][count($state)];
|
||||
$state[] = $word ^ $dw[$Nr][$i++];
|
||||
}
|
||||
|
||||
$temp = array();
|
||||
for ($round = $this->Nr - 1; $round > 0; $round--) {
|
||||
$i = 0; // $this->c[0] == 0
|
||||
$j = $this->Nb - $this->c[1];
|
||||
$k = $this->Nb - $this->c[2];
|
||||
$l = $this->Nb - $this->c[3];
|
||||
for ($round = $Nr - 1; $round > 0; $round--) {
|
||||
$i = 0; // $c[0] == 0
|
||||
$j = $Nb - $c[1];
|
||||
$k = $Nb - $c[2];
|
||||
$l = $Nb - $c[3];
|
||||
|
||||
while ($i < $this->Nb) {
|
||||
$temp[$i] = $this->dt0[$state[$i] & 0xFF000000] ^
|
||||
$this->dt1[$state[$j] & 0x00FF0000] ^
|
||||
$this->dt2[$state[$k] & 0x0000FF00] ^
|
||||
$this->dt3[$state[$l] & 0x000000FF] ^
|
||||
$this->dw[$round][$i];
|
||||
while ($i < $Nb) {
|
||||
$temp[$i] = $dt0[$state[$i] & 0xFF000000] ^
|
||||
$dt1[$state[$j] & 0x00FF0000] ^
|
||||
$dt2[$state[$k] & 0x0000FF00] ^
|
||||
$dt3[$state[$l] & 0x000000FF] ^
|
||||
$dw[$round][$i];
|
||||
$i++;
|
||||
$j = ($j + 1) % $this->Nb;
|
||||
$k = ($k + 1) % $this->Nb;
|
||||
$l = ($l + 1) % $this->Nb;
|
||||
$j = ($j + 1) % $Nb;
|
||||
$k = ($k + 1) % $Nb;
|
||||
$l = ($l + 1) % $Nb;
|
||||
}
|
||||
|
||||
for ($i = 0; $i < $this->Nb; $i++) {
|
||||
for ($i = 0; $i < $Nb; $i++) {
|
||||
$state[$i] = $temp[$i];
|
||||
}
|
||||
}
|
||||
|
||||
// invShiftRows + invSubWord + addRoundKey
|
||||
$i = 0; // $this->c[0] == 0
|
||||
$j = $this->Nb - $this->c[1];
|
||||
$k = $this->Nb - $this->c[2];
|
||||
$l = $this->Nb - $this->c[3];
|
||||
$i = 0; // $c[0] == 0
|
||||
$j = $Nb - $c[1];
|
||||
$k = $Nb - $c[2];
|
||||
$l = $Nb - $c[3];
|
||||
|
||||
while ($i < $this->Nb) {
|
||||
$temp[$i] = $this->dw[0][$i] ^
|
||||
while ($i < $Nb) {
|
||||
$temp[$i] = $dw[0][$i] ^
|
||||
$this->_invSubWord(($state[$i] & 0xFF000000) |
|
||||
($state[$j] & 0x00FF0000) |
|
||||
($state[$k] & 0x0000FF00) |
|
||||
($state[$l] & 0x000000FF));
|
||||
$i++;
|
||||
$j = ($j + 1) % $this->Nb;
|
||||
$k = ($k + 1) % $this->Nb;
|
||||
$l = ($l + 1) % $this->Nb;
|
||||
$j = ($j + 1) % $Nb;
|
||||
$k = ($k + 1) % $Nb;
|
||||
$l = ($l + 1) % $Nb;
|
||||
}
|
||||
|
||||
$state = $temp;
|
||||
@ -1049,6 +1080,7 @@ class Crypt_Rijndael {
|
||||
$length = ord($text[strlen($text) - 1]);
|
||||
|
||||
if (!$length || $length > $this->block_size) {
|
||||
echo "RETURNING FALSE ($length)\r\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,7 @@
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright MMVII Jim Wigginton
|
||||
* @license http://www.gnu.org/licenses/lgpl.txt
|
||||
* @version $Id: TripleDES.php,v 1.10 2009-12-06 07:26:52 terrafrost Exp $
|
||||
* @version $Id: TripleDES.php,v 1.11 2010-01-04 07:59:01 terrafrost Exp $
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
||||
@ -348,14 +348,16 @@ class Crypt_TripleDES {
|
||||
// "The data is padded with "\0" to make sure the length of the data is n * blocksize."
|
||||
$plaintext = str_pad($plaintext, ceil(strlen($plaintext) / 8) * 8, chr(0));
|
||||
|
||||
$des = $this->des;
|
||||
|
||||
$ciphertext = '';
|
||||
switch ($this->mode) {
|
||||
case CRYPT_DES_MODE_ECB:
|
||||
for ($i = 0; $i < strlen($plaintext); $i+=8) {
|
||||
$block = substr($plaintext, $i, 8);
|
||||
$block = $this->des[0]->_processBlock($block, CRYPT_DES_ENCRYPT);
|
||||
$block = $this->des[1]->_processBlock($block, CRYPT_DES_DECRYPT);
|
||||
$block = $this->des[2]->_processBlock($block, CRYPT_DES_ENCRYPT);
|
||||
$block = $des[0]->_processBlock($block, CRYPT_DES_ENCRYPT);
|
||||
$block = $des[1]->_processBlock($block, CRYPT_DES_DECRYPT);
|
||||
$block = $des[2]->_processBlock($block, CRYPT_DES_ENCRYPT);
|
||||
$ciphertext.= $block;
|
||||
}
|
||||
break;
|
||||
@ -363,9 +365,9 @@ class Crypt_TripleDES {
|
||||
$xor = $this->encryptIV;
|
||||
for ($i = 0; $i < strlen($plaintext); $i+=8) {
|
||||
$block = substr($plaintext, $i, 8) ^ $xor;
|
||||
$block = $this->des[0]->_processBlock($block, CRYPT_DES_ENCRYPT);
|
||||
$block = $this->des[1]->_processBlock($block, CRYPT_DES_DECRYPT);
|
||||
$block = $this->des[2]->_processBlock($block, CRYPT_DES_ENCRYPT);
|
||||
$block = $des[0]->_processBlock($block, CRYPT_DES_ENCRYPT);
|
||||
$block = $des[1]->_processBlock($block, CRYPT_DES_DECRYPT);
|
||||
$block = $des[2]->_processBlock($block, CRYPT_DES_ENCRYPT);
|
||||
$xor = $block;
|
||||
$ciphertext.= $block;
|
||||
}
|
||||
@ -417,14 +419,16 @@ class Crypt_TripleDES {
|
||||
return $this->_unpad($this->des[0]->decrypt($plaintext));
|
||||
}
|
||||
|
||||
$des = $this->des;
|
||||
|
||||
$plaintext = '';
|
||||
switch ($this->mode) {
|
||||
case CRYPT_DES_MODE_ECB:
|
||||
for ($i = 0; $i < strlen($ciphertext); $i+=8) {
|
||||
$block = substr($ciphertext, $i, 8);
|
||||
$block = $this->des[2]->_processBlock($block, CRYPT_DES_DECRYPT);
|
||||
$block = $this->des[1]->_processBlock($block, CRYPT_DES_ENCRYPT);
|
||||
$block = $this->des[0]->_processBlock($block, CRYPT_DES_DECRYPT);
|
||||
$block = $des[2]->_processBlock($block, CRYPT_DES_DECRYPT);
|
||||
$block = $des[1]->_processBlock($block, CRYPT_DES_ENCRYPT);
|
||||
$block = $des[0]->_processBlock($block, CRYPT_DES_DECRYPT);
|
||||
$plaintext.= $block;
|
||||
}
|
||||
break;
|
||||
@ -432,9 +436,9 @@ class Crypt_TripleDES {
|
||||
$xor = $this->decryptIV;
|
||||
for ($i = 0; $i < strlen($ciphertext); $i+=8) {
|
||||
$orig = $block = substr($ciphertext, $i, 8);
|
||||
$block = $this->des[2]->_processBlock($block, CRYPT_DES_DECRYPT);
|
||||
$block = $this->des[1]->_processBlock($block, CRYPT_DES_ENCRYPT);
|
||||
$block = $this->des[0]->_processBlock($block, CRYPT_DES_DECRYPT);
|
||||
$block = $des[2]->_processBlock($block, CRYPT_DES_DECRYPT);
|
||||
$block = $des[1]->_processBlock($block, CRYPT_DES_ENCRYPT);
|
||||
$block = $des[0]->_processBlock($block, CRYPT_DES_DECRYPT);
|
||||
$plaintext.= $block ^ $xor;
|
||||
$xor = $orig;
|
||||
}
|
||||
|
@ -72,7 +72,7 @@
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright MMVI Jim Wigginton
|
||||
* @license http://www.gnu.org/licenses/lgpl.txt
|
||||
* @version $Id: BigInteger.php,v 1.21 2009-12-31 06:11:07 terrafrost Exp $
|
||||
* @version $Id: BigInteger.php,v 1.22 2010-01-04 07:59:01 terrafrost Exp $
|
||||
* @link http://pear.php.net/package/Math_BigInteger
|
||||
*/
|
||||
|
||||
@ -748,6 +748,7 @@ class Math_BigInteger {
|
||||
}
|
||||
|
||||
$result = new Math_BigInteger();
|
||||
$result_value = &$result->value;
|
||||
$carry = 0;
|
||||
|
||||
$size = max($this_size, $y_size);
|
||||
@ -763,12 +764,12 @@ class Math_BigInteger {
|
||||
|
||||
$temp = floor($sum / 0x4000000);
|
||||
|
||||
$result->value[] = $sum - 0x4000000 * $temp; // eg. a faster alternative to fmod($sum, 0x4000000)
|
||||
$result->value[] = $temp;
|
||||
$result_value[] = $sum - 0x4000000 * $temp; // eg. a faster alternative to fmod($sum, 0x4000000)
|
||||
$result_value[] = $temp;
|
||||
}
|
||||
|
||||
if ($carry) {
|
||||
$result->value[] = (int) $carry;
|
||||
$result_value[] = (int) $carry;
|
||||
}
|
||||
|
||||
$result->is_negative = $this->is_negative;
|
||||
@ -861,6 +862,7 @@ class Math_BigInteger {
|
||||
}
|
||||
|
||||
$result = new Math_BigInteger();
|
||||
$result_value = &$result->value;
|
||||
$carry = 0;
|
||||
|
||||
$size = max($this_size, $y_size);
|
||||
@ -876,8 +878,8 @@ class Math_BigInteger {
|
||||
|
||||
$temp = floor($sum / 0x4000000);
|
||||
|
||||
$result->value[] = $sum - 0x4000000 * $temp;
|
||||
$result->value[] = $temp;
|
||||
$result_value[] = $sum - 0x4000000 * $temp;
|
||||
$result_value[] = $temp;
|
||||
}
|
||||
|
||||
// $carry shouldn't be anything other than zero, at this point, since we already made sure that $this
|
||||
@ -971,7 +973,11 @@ class Math_BigInteger {
|
||||
}
|
||||
|
||||
$product = new Math_BigInteger();
|
||||
$product->value = $this->_array_repeat(0, $this_length + $x_length);
|
||||
$product_value = &$product->value;
|
||||
$product_value = $this->_array_repeat(0, $this_length + $x_length);
|
||||
|
||||
$this_value = $this->value;
|
||||
$x_value = $x->value;
|
||||
|
||||
// the following for loop could be removed if the for loop following it
|
||||
// (the one with nested for loops) initially set $i to 0, but
|
||||
@ -984,10 +990,10 @@ class Math_BigInteger {
|
||||
for ($j = 0; $j < $this_length; $j++) { // ie. $i = 0
|
||||
$temp = $this->value[$j] * $x->value[0] + $carry; // $product->value[$k] == 0
|
||||
$carry = floor($temp / 0x4000000);
|
||||
$product->value[$j] = $temp - 0x4000000 * $carry;
|
||||
$product_value[$j] = $temp - 0x4000000 * $carry;
|
||||
}
|
||||
|
||||
$product->value[$j] = $carry;
|
||||
$product_value[$j] = $carry;
|
||||
|
||||
// the above for loop is what the previous comment was talking about. the
|
||||
// following for loop is the "one with nested for loops"
|
||||
@ -995,12 +1001,12 @@ class Math_BigInteger {
|
||||
$carry = 0;
|
||||
|
||||
for ($j = 0, $k = $i; $j < $this_length; $j++, $k++) {
|
||||
$temp = $product->value[$k] + $this->value[$j] * $x->value[$i] + $carry;
|
||||
$temp = $product_value[$k] + $this_value[$j] * $x_value[$i] + $carry;
|
||||
$carry = floor($temp / 0x4000000);
|
||||
$product->value[$k] = $temp - 0x4000000 * $carry;
|
||||
$product_value[$k] = $temp - 0x4000000 * $carry;
|
||||
}
|
||||
|
||||
$product->value[$k] = $carry;
|
||||
$product_value[$k] = $carry;
|
||||
}
|
||||
|
||||
$product->is_negative = $this->is_negative != $x->is_negative;
|
||||
@ -1022,21 +1028,27 @@ class Math_BigInteger {
|
||||
{
|
||||
$x = $this->copy();
|
||||
|
||||
$m = min(count($x->value) >> 1, count($y->value) >> 1);
|
||||
$x_value = $x->value;
|
||||
$y_value = $y->value;
|
||||
|
||||
$m = min(count($x_value) >> 1, count($y_value) >> 1);
|
||||
|
||||
if ($m < MATH_BIGINTEGER_KARATSUBA_CUTOFF) {
|
||||
return $x->_multiply($y);
|
||||
}
|
||||
|
||||
$x1 = new Math_BigInteger();
|
||||
$x0 = new Math_BigInteger();
|
||||
$y1 = new Math_BigInteger();
|
||||
$y0 = new Math_BigInteger();
|
||||
static $x1, $x0, $y1, $y0;
|
||||
if (!isset($x1)) {
|
||||
$x1 = new Math_BigInteger();
|
||||
$x0 = new Math_BigInteger();
|
||||
$y1 = new Math_BigInteger();
|
||||
$y0 = new Math_BigInteger();
|
||||
}
|
||||
|
||||
$x1->value = array_slice($x->value, $m);
|
||||
$x0->value = array_slice($x->value, 0, $m);
|
||||
$y1->value = array_slice($y->value, $m);
|
||||
$y0->value = array_slice($y->value, 0, $m);
|
||||
$x1->value = array_slice($x_value, $m);
|
||||
$x0->value = array_slice($x_value, 0, $m);
|
||||
$y1->value = array_slice($y_value, $m);
|
||||
$y0->value = array_slice($y_value, 0, $m);
|
||||
|
||||
$z2 = $x1->_karatsuba($y1);
|
||||
$z0 = $x0->_karatsuba($y0);
|
||||
@ -1045,8 +1057,11 @@ class Math_BigInteger {
|
||||
$z1 = $z1->_karatsuba($y1->add($y0));
|
||||
$z1 = $z1->subtract($z2->add($z0));
|
||||
|
||||
$z2->value = array_merge(array_fill(0, 2 * $m, 0), $z2->value);
|
||||
$z1->value = array_merge(array_fill(0, $m, 0), $z1->value);
|
||||
$z1_value = &$z1->value;
|
||||
$z2_value = &$z2->value;
|
||||
|
||||
$z2_value = array_merge(array_fill(0, 2 * $m, 0), $z2_value);
|
||||
$z1_value = array_merge(array_fill(0, $m, 0), $z1_value);
|
||||
|
||||
$xy = $z2->add($z1);
|
||||
$xy = $xy->add($z0);
|
||||
@ -1087,25 +1102,28 @@ class Math_BigInteger {
|
||||
}
|
||||
|
||||
$square = new Math_BigInteger();
|
||||
$square->value = $this->_array_repeat(0, 2 * count($this->value));
|
||||
$square_value = &$square->value;
|
||||
$square_value = $this->_array_repeat(0, 2 * count($this->value));
|
||||
|
||||
for ($i = 0, $max_index = count($this->value) - 1; $i <= $max_index; $i++) {
|
||||
$this_value = &$this->value;
|
||||
|
||||
for ($i = 0, $max_index = count($this_value) - 1; $i <= $max_index; $i++) {
|
||||
$i2 = 2 * $i;
|
||||
|
||||
$temp = $square->value[$i2] + $this->value[$i] * $this->value[$i];
|
||||
$temp = $square_value[$i2] + $this_value[$i] * $this_value[$i];
|
||||
$carry = floor($temp / 0x4000000);
|
||||
$square->value[$i2] = $temp - 0x4000000 * $carry;
|
||||
$square_value[$i2] = $temp - 0x4000000 * $carry;
|
||||
|
||||
// note how we start from $i+1 instead of 0 as we do in multiplication.
|
||||
for ($j = $i + 1, $k = $i2 + 1; $j <= $max_index; $j++, $k++) {
|
||||
$temp = $square->value[$k] + 2 * $this->value[$j] * $this->value[$i] + $carry;
|
||||
$temp = $square_value[$k] + 2 * $this_value[$j] * $this_value[$i] + $carry;
|
||||
$carry = floor($temp / 0x4000000);
|
||||
$square->value[$k] = $temp - 0x4000000 * $carry;
|
||||
$square_value[$k] = $temp - 0x4000000 * $carry;
|
||||
}
|
||||
|
||||
// the following line can yield values larger 2**15. at this point, PHP should switch
|
||||
// over to floats.
|
||||
$square->value[$i + $max_index + 1] = $carry;
|
||||
$square_value[$i + $max_index + 1] = $carry;
|
||||
}
|
||||
|
||||
return $square;
|
||||
@ -1123,17 +1141,22 @@ class Math_BigInteger {
|
||||
*/
|
||||
function _karatsubaSquare()
|
||||
{
|
||||
$m = count($this->value) >> 1;
|
||||
$value = $this->value;
|
||||
|
||||
$m = count($value) >> 1;
|
||||
|
||||
if ($m < MATH_BIGINTEGER_KARATSUBA_CUTOFF) {
|
||||
return $this->_square();
|
||||
}
|
||||
|
||||
$x1 = new Math_BigInteger();
|
||||
$x0 = new Math_BigInteger();
|
||||
static $x1, $x0;
|
||||
if (!isset($x1)) {
|
||||
$x1 = new Math_BigInteger();
|
||||
$x0 = new Math_BigInteger();
|
||||
}
|
||||
|
||||
$x1->value = array_slice($this->value, $m);
|
||||
$x0->value = array_slice($this->value, 0, $m);
|
||||
$x1->value = array_slice($value, $m);
|
||||
$x0->value = array_slice($value, 0, $m);
|
||||
|
||||
$z2 = $x1->_karatsubaSquare();
|
||||
$z0 = $x0->_karatsubaSquare();
|
||||
@ -1142,8 +1165,11 @@ class Math_BigInteger {
|
||||
$z1 = $z1->_karatsubaSquare();
|
||||
$z1 = $z1->subtract($z2->add($z0));
|
||||
|
||||
$z2->value = array_merge(array_fill(0, 2 * $m, 0), $z2->value);
|
||||
$z1->value = array_merge(array_fill(0, $m, 0), $z1->value);
|
||||
$z1_value = &$z1->value;
|
||||
$z2_value = &$z2->value;
|
||||
|
||||
$z2_value = array_merge(array_fill(0, 2 * $m, 0), $z2_value);
|
||||
$z1_value = array_merge(array_fill(0, $m, 0), $z1_value);
|
||||
|
||||
$xx = $z2->add($z1);
|
||||
$xx = $xx->add($z0);
|
||||
@ -1251,80 +1277,87 @@ class Math_BigInteger {
|
||||
}
|
||||
$x->_lshift($shift);
|
||||
$y->_lshift($shift);
|
||||
$y_value = &$y->value;
|
||||
|
||||
$x_max = count($x->value) - 1;
|
||||
$y_max = count($y->value) - 1;
|
||||
|
||||
$quotient = new Math_BigInteger();
|
||||
$quotient->value = $this->_array_repeat(0, $x_max - $y_max + 1);
|
||||
$quotient_value = &$quotient->value;
|
||||
$quotient_value = $this->_array_repeat(0, $x_max - $y_max + 1);
|
||||
|
||||
static $temp, $lhs, $rhs;
|
||||
if (!isset($temp)) {
|
||||
$temp = new Math_BigInteger();
|
||||
$lhs = new Math_BigInteger();
|
||||
$rhs = new Math_BigInteger();
|
||||
}
|
||||
$temp_value = &$temp->value;
|
||||
$rhs_value = &$rhs->value;
|
||||
|
||||
// $temp = $y << ($x_max - $y_max-1) in base 2**26
|
||||
$temp = new Math_BigInteger();
|
||||
$temp->value = array_merge($this->_array_repeat(0, $x_max - $y_max), $y->value);
|
||||
$temp_value = array_merge($this->_array_repeat(0, $x_max - $y_max), $y_value);
|
||||
|
||||
while ( $x->compare($temp) >= 0 ) {
|
||||
// calculate the "common residue"
|
||||
$quotient->value[$x_max - $y_max]++;
|
||||
$quotient_value[$x_max - $y_max]++;
|
||||
$x = $x->subtract($temp);
|
||||
$x_max = count($x->value) - 1;
|
||||
}
|
||||
|
||||
for ($i = $x_max; $i >= $y_max + 1; $i--) {
|
||||
$x_value = array(
|
||||
isset($x->value[$i]) ? $x->value[$i] : 0,
|
||||
isset($x->value[$i - 1]) ? $x->value[$i - 1] : 0,
|
||||
isset($x->value[$i - 2]) ? $x->value[$i - 2] : 0
|
||||
$x_value = &$x->value;
|
||||
$x_window = array(
|
||||
isset($x_value[$i]) ? $x_value[$i] : 0,
|
||||
isset($x_value[$i - 1]) ? $x_value[$i - 1] : 0,
|
||||
isset($x_value[$i - 2]) ? $x_value[$i - 2] : 0
|
||||
);
|
||||
$y_value = array(
|
||||
$y->value[$y_max],
|
||||
( $y_max > 0 ) ? $y->value[$y_max - 1] : 0
|
||||
$y_window = array(
|
||||
$y_value[$y_max],
|
||||
( $y_max > 0 ) ? $y_value[$y_max - 1] : 0
|
||||
);
|
||||
|
||||
$q_index = $i - $y_max - 1;
|
||||
if ($x_value[0] == $y_value[0]) {
|
||||
$quotient->value[$q_index] = 0x3FFFFFF;
|
||||
if ($x_window[0] == $y_window[0]) {
|
||||
$quotient_value[$q_index] = 0x3FFFFFF;
|
||||
} else {
|
||||
$quotient->value[$q_index] = floor(
|
||||
($x_value[0] * 0x4000000 + $x_value[1])
|
||||
$quotient_value[$q_index] = floor(
|
||||
($x_window[0] * 0x4000000 + $x_window[1])
|
||||
/
|
||||
$y_value[0]
|
||||
$y_window[0]
|
||||
);
|
||||
}
|
||||
|
||||
$temp = new Math_BigInteger();
|
||||
$temp->value = array($y_value[1], $y_value[0]);
|
||||
$temp_value = array($y_window[1], $y_window[0]);
|
||||
|
||||
$lhs = new Math_BigInteger();
|
||||
$lhs->value = array($quotient->value[$q_index]);
|
||||
$lhs->value = array($quotient_value[$q_index]);
|
||||
$lhs = $lhs->multiply($temp);
|
||||
|
||||
$rhs = new Math_BigInteger();
|
||||
$rhs->value = array($x_value[2], $x_value[1], $x_value[0]);
|
||||
$rhs_value = array($x_window[2], $x_window[1], $x_window[0]);
|
||||
|
||||
while ( $lhs->compare($rhs) > 0 ) {
|
||||
$quotient->value[$q_index]--;
|
||||
$quotient_value[$q_index]--;
|
||||
|
||||
$lhs = new Math_BigInteger();
|
||||
$lhs->value = array($quotient->value[$q_index]);
|
||||
$lhs->value = array($quotient_value[$q_index]);
|
||||
$lhs = $lhs->multiply($temp);
|
||||
}
|
||||
|
||||
$adjust = $this->_array_repeat(0, $q_index);
|
||||
$temp = new Math_BigInteger();
|
||||
$temp->value = array($quotient->value[$q_index]);
|
||||
$temp_value = array($quotient_value[$q_index]);
|
||||
$temp = $temp->multiply($y);
|
||||
$temp->value = array_merge($adjust, $temp->value);
|
||||
$temp_value = &$temp->value;
|
||||
$temp_value = array_merge($adjust, $temp_value);
|
||||
|
||||
$x = $x->subtract($temp);
|
||||
|
||||
if ($x->compare($zero) < 0) {
|
||||
$temp->value = array_merge($adjust, $y->value);
|
||||
$temp_value = array_merge($adjust, $y_value);
|
||||
$x = $x->add($temp);
|
||||
|
||||
$quotient->value[$q_index]--;
|
||||
$quotient_value[$q_index]--;
|
||||
}
|
||||
|
||||
$x_max = count($x->value) - 1;
|
||||
$x_max = count($x_value) - 1;
|
||||
}
|
||||
|
||||
// unnormalize the remainder
|
||||
@ -1354,11 +1387,14 @@ class Math_BigInteger {
|
||||
{
|
||||
$carry = 0;
|
||||
$result = new Math_BigInteger();
|
||||
$result_value = &$result->value;
|
||||
|
||||
$this_value = &$this->value;
|
||||
|
||||
for ($i = count($this->value) - 1; $i >= 0; $i--) {
|
||||
$temp = 0x4000000 * $carry + $this->value[$i];
|
||||
$result->value[$i] = floor($temp / $divisor);
|
||||
$carry = fmod($temp, $divisor);
|
||||
$temp = 0x4000000 * $carry + $this_value[$i];
|
||||
$result_value[$i] = floor($temp / $divisor);
|
||||
$carry = $temp - $divisor * $result_value[$i];
|
||||
}
|
||||
|
||||
$remainder = new Math_BigInteger();
|
||||
@ -1531,10 +1567,11 @@ class Math_BigInteger {
|
||||
static $window_ranges = array(7, 25, 81, 241, 673, 1793); // from BigInteger.java's oddModPow function
|
||||
//static $window_ranges = array(0, 7, 36, 140, 450, 1303, 3529); // from MPM 7.3.1
|
||||
|
||||
$e_length = count($e->value) - 1;
|
||||
$e_bits = decbin($e->value[$e_length]);
|
||||
$e_value = $e->value;
|
||||
$e_length = count($e_value) - 1;
|
||||
$e_bits = decbin($e_value[$e_length]);
|
||||
for ($i = $e_length - 1; $i >= 0; $i--) {
|
||||
$e_bits.= str_pad(decbin($e->value[$i]), 26, '0', STR_PAD_LEFT);
|
||||
$e_bits.= str_pad(decbin($e_value[$i]), 26, '0', STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
$e_length = strlen($e_bits);
|
||||
@ -1698,8 +1735,11 @@ class Math_BigInteger {
|
||||
* it, "the idea [behind folding] is to find a value x' such that x (mod m) = x' (mod m), with x' being smaller than x."
|
||||
*
|
||||
* Unfortunately, the "Barrett Reduction with Folding" algorithm described in thesis-149.pdf is not, as written, all that
|
||||
* usable on account of its not using reasonable radix points as discussed in
|
||||
* {@link http://math.libtomcrypt.com/files/tommath.pdf#page=162 MPM 6.2.2}.
|
||||
* usable on account of (1) its not using reasonable radix points as discussed in
|
||||
* {@link http://math.libtomcrypt.com/files/tommath.pdf#page=162 MPM 6.2.2} and (2) the fact that, even with reasonable
|
||||
* radix points, it only works when there are an even number of digits in the denominator. The reason for (2) is that
|
||||
* (x >> 1) + (x >> 1) != x / 2 + x / 2. If x is even, they're the same, but if x is odd, they're not. See the in-line
|
||||
* comments for details.
|
||||
*
|
||||
* @see _slidingWindow()
|
||||
* @access private
|
||||
@ -1713,53 +1753,78 @@ class Math_BigInteger {
|
||||
MATH_BIGINTEGER_DATA => array()
|
||||
);
|
||||
|
||||
// "given an n-bit modulus, M, ..."
|
||||
$n_length = count($m->value);
|
||||
$m_value = $m->value;
|
||||
$m_length = count($m_value);
|
||||
|
||||
if (count($this->value) > 2 * $n_length) {// || count($this->value) < count($m->value)) {
|
||||
if ($m_length & 1) {
|
||||
$m_value[] = 0;
|
||||
$m_length++;
|
||||
}
|
||||
|
||||
// if ($this->compare($m->_square()) >= 0) {
|
||||
if (count($this->value) > 2 * $m_length) {
|
||||
list(, $temp) = $this->divide($m);
|
||||
return $temp;
|
||||
}
|
||||
|
||||
$n = $this->copy();
|
||||
$temp = new Math_BigInteger();
|
||||
$temp2= new Math_BigInteger();
|
||||
// if (m.length >> 1) + 2 <= m.length then m is too small and n can't be reduced
|
||||
if ($m_length < 5) {
|
||||
return $this->_regularBarrett($m);
|
||||
}
|
||||
|
||||
if ( ($key = array_search($m->value, $cache[MATH_BIGINTEGER_VARIABLE])) === false ) {
|
||||
$n = $this->copy(); // 2 * m.length
|
||||
static $temp;
|
||||
if (!isset($temp)) {
|
||||
$temp = new Math_BigInteger();
|
||||
}
|
||||
$temp_value = &$temp->value;
|
||||
|
||||
if ( ($key = array_search($m_value, $cache[MATH_BIGINTEGER_VARIABLE])) === false ) {
|
||||
$key = count($cache[MATH_BIGINTEGER_VARIABLE]);
|
||||
$cache[MATH_BIGINTEGER_VARIABLE][] = $m->value;
|
||||
$cache[MATH_BIGINTEGER_VARIABLE][] = $m_value;
|
||||
|
||||
$temp->value = $this->_array_repeat(0, $n_length + ($n_length >> 1));
|
||||
$temp->value[] = 1;
|
||||
$temp_value = $this->_array_repeat(0, $m_length + ($m_length >> 1));
|
||||
$temp_value[] = 1;
|
||||
|
||||
list($u, $m1) = $temp->divide($m);
|
||||
|
||||
$cache[MATH_BIGINTEGER_DATA][] = array(
|
||||
'u' => $u,
|
||||
'm1'=> $m1
|
||||
'u' => $u, // m.length >> 1 (technically (m.length >> 1) + 1)
|
||||
'm1'=> $m1 // m.length
|
||||
);
|
||||
} else {
|
||||
extract($cache[MATH_BIGINTEGER_DATA][$key]);
|
||||
}
|
||||
|
||||
extract($cache[MATH_BIGINTEGER_DATA][$key]);
|
||||
$n_value = $n->value;
|
||||
|
||||
$cutoff = $n_length + ($n_length >> 1);
|
||||
$cutoff = $m_length + ($m_length >> 1);
|
||||
$msd = new Math_BigInteger();
|
||||
$lsd = new Math_BigInteger();
|
||||
$lsd->value = array_slice($n->value, 0, $cutoff);
|
||||
$msd->value = array_slice($n->value, $cutoff);
|
||||
$lsd->value = array_slice($n_value, 0, $cutoff); // m.length + (m.length >> 1)
|
||||
$msd->value = array_slice($n_value, $cutoff); // m.length >> 1
|
||||
$lsd->_trim();
|
||||
$n = $lsd->add($msd->multiply($m1));
|
||||
$n = $lsd->add($msd->multiply($m1)); // m.length + (m.length >> 1) + 1
|
||||
|
||||
/* at this point, given list($a, $b) = $n->divide($m) and list($c, $d) = $this->divide($m),
|
||||
we can safely assume $b == $d (even though $a != $c). */
|
||||
|
||||
$temp = new Math_BigInteger();
|
||||
$temp->value = array_slice($n->value, $n_length - 1);
|
||||
// (m.length + (m.length >> 1) + 1) - (m.length - 1) == (m.length >> 1) + 2
|
||||
$temp_value = array_slice($n->value, $m_length - 1);
|
||||
// if even: ((m.length >> 1) + 2) + (m.length >> 1) == m.length + 2
|
||||
// if odd: ((m.length >> 1) + 2) + (m.length >> 1) == (m.length - 1) + 2 == m.length + 1
|
||||
$temp = $temp->multiply($u);
|
||||
$temp->value = array_slice($temp->value, ($n_length >> 1) + 1);
|
||||
$temp_value = &$temp->value;
|
||||
// if even: (m.length + 2) - ((m.length >> 1) + 1) = m.length - (m.length >> 1) + 1
|
||||
// if odd: (m.length + 1) - ((m.length >> 1) + 1) = m.length - (m.length >> 1)
|
||||
$temp_value = array_slice($temp_value, ($m_length >> 1) + 1);
|
||||
// if even: (m.length - (m.length >> 1) + 1) + m.length = 2 * m.length - (m.length >> 1) + 1
|
||||
// if odd: (m.length - (m.length >> 1)) + m.length = 2 * m.length - (m.length >> 1)
|
||||
$temp = $temp->multiply($m);
|
||||
|
||||
// at this point, if m had an odd number of digits, we'd be subtracting a 2 * m.length - (m.length >> 1) digit
|
||||
// number from a m.length + (m.length >> 1) + 1 digit number. ie. there'd be an extra digit and the while loop
|
||||
// following this comment would loop a lot (hence our conditionally adding a 0 as the most significant digit).
|
||||
|
||||
$result = $n->subtract($temp);
|
||||
|
||||
while ($result->compare($m) >= 0) {
|
||||
$result = $result->subtract($m);
|
||||
}
|
||||
@ -1767,6 +1832,148 @@ class Math_BigInteger {
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* (Regular) Barrett Modular Reduction
|
||||
*
|
||||
* For numbers with more than four digits Math_BigInteger::_barrett() is faster. The difference between that and this
|
||||
* is that this function does not fold the denominator into a smaller form.
|
||||
*
|
||||
* @see _slidingWindow()
|
||||
* @access private
|
||||
* @param Math_BigInteger
|
||||
* @return Math_BigInteger
|
||||
*/
|
||||
function _regularBarrett($n)
|
||||
{
|
||||
static $cache = array(
|
||||
MATH_BIGINTEGER_VARIABLE => array(),
|
||||
MATH_BIGINTEGER_DATA => array()
|
||||
);
|
||||
|
||||
$n_value = $n->value;
|
||||
|
||||
$n_length = count($n_value);
|
||||
|
||||
if (count($this->value) > 2 * $n_length) {
|
||||
list(, $temp) = $this->divide($n);
|
||||
return $temp;
|
||||
}
|
||||
|
||||
static $temp;
|
||||
if (!isset($temp)) {
|
||||
$temp = new Math_BigInteger();
|
||||
}
|
||||
|
||||
if ( ($key = array_search($n_value, $cache[MATH_BIGINTEGER_VARIABLE])) === false ) {
|
||||
$key = count($cache[MATH_BIGINTEGER_VARIABLE]);
|
||||
$cache[MATH_BIGINTEGER_VARIABLE][] = $n_value;
|
||||
$temp_value = &$temp->value;
|
||||
$temp_value = $this->_array_repeat(0, 2 * $n_length);
|
||||
$temp_value[] = 1;
|
||||
list($cache[MATH_BIGINTEGER_DATA][], ) = $temp->divide($n);
|
||||
}
|
||||
|
||||
$this_value = $this->value;
|
||||
|
||||
$temp->value = array_slice($this_value, $n_length - 1);
|
||||
$temp = $temp->multiply($cache[MATH_BIGINTEGER_DATA][$key]);
|
||||
$temp_value = &$temp->value;
|
||||
$temp_value = array_slice($temp_value, $n_length + 1);
|
||||
|
||||
$result = new Math_BigInteger();
|
||||
$result->value = array_slice($this_value, 0, $n_length + 1);
|
||||
$temp = $temp->_multiplyLower($n, $n_length + 1);
|
||||
// $temp->value == array_slice($temp->multiply($n)->value, 0, $n_length + 1)
|
||||
|
||||
if ($result->compare($temp) < 0) {
|
||||
static $corrector;
|
||||
if (!isset($corrector)) {
|
||||
$corrector = new Math_BigInteger();
|
||||
}
|
||||
$corrector_value = &$corrector->value;
|
||||
$corrector_value = $this->_array_repeat(0, $n_length + 1);
|
||||
$corrector_value[] = 1;
|
||||
$result = $result->add($corrector);
|
||||
}
|
||||
|
||||
$result = $result->subtract($temp);
|
||||
while ($result->compare($n) > 0) {
|
||||
$result = $result->subtract($n);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs long multiplication up to $stop digits
|
||||
*
|
||||
* If you're going to be doing array_slice($product->value, 0, $stop), some cycles can be saved.
|
||||
*
|
||||
* @see _regularBarrett()
|
||||
* @param Math_BigInteger $x
|
||||
* @return Math_BigInteger
|
||||
* @access private
|
||||
*/
|
||||
function _multiplyLower($x, $stop)
|
||||
{
|
||||
$this_value = $this->value;
|
||||
$x_value = $x->value;
|
||||
|
||||
$this_length = count($this_value);
|
||||
$x_length = count($x_value);
|
||||
|
||||
if ( !$this_length || !$x_length ) { // a 0 is being multiplied
|
||||
return new Math_BigInteger();
|
||||
}
|
||||
|
||||
if ( $this_length < $x_length ) {
|
||||
return $x->_multiplyLower($this, $stop);
|
||||
}
|
||||
|
||||
$product = new Math_BigInteger();
|
||||
$product_value = &$product->value;
|
||||
$product_value = $this->_array_repeat(0, $this_length + $x_length);
|
||||
|
||||
// the following for loop could be removed if the for loop following it
|
||||
// (the one with nested for loops) initially set $i to 0, but
|
||||
// doing so would also make the result in one set of unnecessary adds,
|
||||
// since on the outermost loops first pass, $product->value[$k] is going
|
||||
// to always be 0
|
||||
|
||||
$carry = 0;
|
||||
|
||||
for ($j = 0; $j < $this_length; $j++) { // ie. $i = 0, $k = $i
|
||||
$temp = $this_value[$j] * $x_value[0] + $carry; // $product_value[$k] == 0
|
||||
$carry = floor($temp / 0x4000000);
|
||||
$product_value[$j] = $temp - 0x4000000 * $carry;
|
||||
}
|
||||
|
||||
if ($j < $stop) {
|
||||
$product_value[$j] = $carry;
|
||||
}
|
||||
|
||||
// the above for loop is what the previous comment was talking about. the
|
||||
// following for loop is the "one with nested for loops"
|
||||
|
||||
for ($i = 1; $i < $x_length; $i++) {
|
||||
$carry = 0;
|
||||
|
||||
for ($j = 0, $k = $i; $j < $this_length && $k < $stop; $j++, $k++) {
|
||||
$temp = $product_value[$k] + $this_value[$j] * $x_value[$i] + $carry;
|
||||
$carry = floor($temp / 0x4000000);
|
||||
$product_value[$k] = $temp - 0x4000000 * $carry;
|
||||
}
|
||||
|
||||
if ($k < $stop) {
|
||||
$product_value[$k] = $carry;
|
||||
}
|
||||
}
|
||||
|
||||
$product->is_negative = $this->is_negative != $x->is_negative;
|
||||
|
||||
return $product;
|
||||
}
|
||||
|
||||
/**
|
||||
* Montgomery Modular Reduction
|
||||
*
|
||||
@ -2082,7 +2289,7 @@ class Math_BigInteger {
|
||||
$d = new Math_BigInteger();
|
||||
|
||||
$a->value = $d->value = $g->value = array(1);
|
||||
$b->value = $c->value = array();
|
||||
$b->value = $c->value = array(0);
|
||||
|
||||
while ( !empty($u->value) ) {
|
||||
while ( !($u->value[0] & 1) ) {
|
||||
@ -2204,7 +2411,9 @@ class Math_BigInteger {
|
||||
}
|
||||
|
||||
$x = $this->_normalize($this->copy());
|
||||
$x_value = &$x->value;
|
||||
$y = $this->_normalize($y);
|
||||
$y_value = &$y->value;
|
||||
|
||||
if ( $x->is_negative != $y->is_negative ) {
|
||||
return ( !$x->is_negative && $y->is_negative ) ? 1 : -1;
|
||||
@ -2212,13 +2421,13 @@ class Math_BigInteger {
|
||||
|
||||
$result = $x->is_negative ? -1 : 1;
|
||||
|
||||
if ( count($x->value) != count($y->value) ) {
|
||||
return ( count($x->value) > count($y->value) ) ? $result : -$result;
|
||||
if ( count($x_value) != count($y_value) ) {
|
||||
return ( count($x_value) > count($y_value) ) ? $result : -$result;
|
||||
}
|
||||
|
||||
for ($i = count($x->value) - 1; $i >= 0; $i--) {
|
||||
if ($x->value[$i] != $y->value[$i]) {
|
||||
return ( $x->value[$i] > $y->value[$i] ) ? $result : -$result;
|
||||
for ($i = count($x_value) - 1; $i >= 0; $i--) {
|
||||
if ($x_value[$i] != $y_value[$i]) {
|
||||
return ( $x_value[$i] > $y_value[$i] ) ? $result : -$result;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2835,6 +3044,7 @@ class Math_BigInteger {
|
||||
$n_2 = $n->subtract($two);
|
||||
|
||||
$r = $n_1->copy();
|
||||
$r_value = $r->value;
|
||||
// ie. $s = gmp_scan1($n, 0) and $r = gmp_div_q($n, gmp_pow(gmp_init('2'), $s));
|
||||
if ( MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_BCMATH ) {
|
||||
$s = 0;
|
||||
@ -2844,8 +3054,8 @@ class Math_BigInteger {
|
||||
$s++;
|
||||
}
|
||||
} else {
|
||||
for ($i = 0; $i < count($r->value); $i++) {
|
||||
$temp = ~$r->value[$i] & 0xFFFFFF;
|
||||
for ($i = 0, $r_length = count($r_value); $i < $r_length; $i++) {
|
||||
$temp = ~$r_value[$i] & 0xFFFFFF;
|
||||
for ($j = 1; ($temp >> $j) & 1; $j++);
|
||||
if ($j != 25) {
|
||||
break;
|
||||
@ -2856,8 +3066,7 @@ class Math_BigInteger {
|
||||
}
|
||||
|
||||
for ($i = 0; $i < $t; $i++) {
|
||||
$a = new Math_BigInteger();
|
||||
$a = $a->random($two, $n_2);
|
||||
$a = $this->random($two, $n_2);
|
||||
$y = $a->modPow($r, $n);
|
||||
|
||||
if (!$y->equals($one) && !$y->equals($n_1)) {
|
||||
@ -2973,22 +3182,23 @@ class Math_BigInteger {
|
||||
return $result;
|
||||
}
|
||||
|
||||
if ( !count($result->value) ) {
|
||||
$value = &$result->value;
|
||||
|
||||
if ( !count($value) ) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
$result->_trim();
|
||||
|
||||
if (!empty($result->bitmask->value)) {
|
||||
$length = min(count($result->value), count($this->bitmask->value));
|
||||
$result->value = array_slice($result->value, 0, $length);
|
||||
$length = min(count($value), count($this->bitmask->value));
|
||||
$value = array_slice($value, 0, $length);
|
||||
|
||||
for ($i = 0; $i < $length; $i++) {
|
||||
$result->value[$i] = $result->value[$i] & $this->bitmask->value[$i];
|
||||
$value[$i] = $value[$i] & $this->bitmask->value[$i];
|
||||
}
|
||||
}
|
||||
|
||||
//return $result->copy();
|
||||
return $result;
|
||||
}
|
||||
|
||||
@ -3002,11 +3212,12 @@ class Math_BigInteger {
|
||||
*/
|
||||
function _trim()
|
||||
{
|
||||
for ($i = count($this->value) - 1; $i >= 0; $i--) {
|
||||
if ( $this->value[$i] ) {
|
||||
$value = &$this->value;
|
||||
for ($i = count($value) - 1; $i >= 0; $i--) {
|
||||
if ( $value[$i] ) {
|
||||
break;
|
||||
}
|
||||
unset($this->value[$i]);
|
||||
unset($value[$i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user