forked from GNUsocial/gnu-social
phpseclib extlib updated from phpseclib.sf.net
This commit is contained in:
parent
49b755912f
commit
f7719b57f2
@ -36,34 +36,38 @@
|
||||
* ?>
|
||||
* </code>
|
||||
*
|
||||
* LICENSE: This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @category Crypt
|
||||
* @package Crypt_AES
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright MMVIII Jim Wigginton
|
||||
* @license http://www.gnu.org/licenses/lgpl.txt
|
||||
* @version $Id: AES.php,v 1.7 2010/02/09 06:10:25 terrafrost Exp $
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
||||
/**
|
||||
* Include Crypt_Rijndael
|
||||
*/
|
||||
require_once 'Rijndael.php';
|
||||
if (!class_exists('Crypt_Rijndael')) {
|
||||
require_once 'Rijndael.php';
|
||||
}
|
||||
|
||||
/**#@+
|
||||
* @access public
|
||||
@ -90,6 +94,18 @@ define('CRYPT_AES_MODE_ECB', 1);
|
||||
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
|
||||
*/
|
||||
define('CRYPT_AES_MODE_CBC', 2);
|
||||
/**
|
||||
* Encrypt / decrypt using the Cipher Feedback mode.
|
||||
*
|
||||
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
|
||||
*/
|
||||
define('CRYPT_AES_MODE_CFB', 3);
|
||||
/**
|
||||
* Encrypt / decrypt using the Cipher Feedback mode.
|
||||
*
|
||||
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
|
||||
*/
|
||||
define('CRYPT_AES_MODE_OFB', 4);
|
||||
/**#@-*/
|
||||
|
||||
/**#@+
|
||||
@ -139,6 +155,16 @@ class Crypt_AES extends Crypt_Rijndael {
|
||||
*/
|
||||
var $demcrypt;
|
||||
|
||||
/**
|
||||
* mcrypt resource for CFB mode
|
||||
*
|
||||
* @see Crypt_AES::encrypt()
|
||||
* @see Crypt_AES::decrypt()
|
||||
* @var String
|
||||
* @access private
|
||||
*/
|
||||
var $ecb;
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
*
|
||||
@ -153,10 +179,7 @@ class Crypt_AES extends Crypt_Rijndael {
|
||||
{
|
||||
if ( !defined('CRYPT_AES_MODE') ) {
|
||||
switch (true) {
|
||||
case extension_loaded('mcrypt'):
|
||||
// i'd check to see if aes was supported, by doing in_array('des', mcrypt_list_algorithms('')),
|
||||
// but since that can be changed after the object has been created, there doesn't seem to be
|
||||
// a lot of point...
|
||||
case extension_loaded('mcrypt') && in_array('rijndael-128', mcrypt_list_algorithms()):
|
||||
define('CRYPT_AES_MODE', CRYPT_AES_MODE_MCRYPT);
|
||||
break;
|
||||
default:
|
||||
@ -168,6 +191,7 @@ class Crypt_AES extends Crypt_Rijndael {
|
||||
case CRYPT_AES_MODE_MCRYPT:
|
||||
switch ($mode) {
|
||||
case CRYPT_AES_MODE_ECB:
|
||||
$this->paddable = true;
|
||||
$this->mode = MCRYPT_MODE_ECB;
|
||||
break;
|
||||
case CRYPT_AES_MODE_CTR:
|
||||
@ -177,8 +201,15 @@ class Crypt_AES extends Crypt_Rijndael {
|
||||
$this->mode = 'ctr';
|
||||
//$this->mode = in_array('ctr', mcrypt_list_modes()) ? 'ctr' : CRYPT_AES_MODE_CTR;
|
||||
break;
|
||||
case CRYPT_AES_MODE_CFB:
|
||||
$this->mode = 'ncfb';
|
||||
break;
|
||||
case CRYPT_AES_MODE_OFB:
|
||||
$this->mode = MCRYPT_MODE_NOFB;
|
||||
break;
|
||||
case CRYPT_AES_MODE_CBC:
|
||||
default:
|
||||
$this->paddable = true;
|
||||
$this->mode = MCRYPT_MODE_CBC;
|
||||
}
|
||||
|
||||
@ -186,13 +217,21 @@ class Crypt_AES extends Crypt_Rijndael {
|
||||
default:
|
||||
switch ($mode) {
|
||||
case CRYPT_AES_MODE_ECB:
|
||||
$this->paddable = true;
|
||||
$this->mode = CRYPT_RIJNDAEL_MODE_ECB;
|
||||
break;
|
||||
case CRYPT_AES_MODE_CTR:
|
||||
$this->mode = CRYPT_RIJNDAEL_MODE_CTR;
|
||||
break;
|
||||
case CRYPT_AES_MODE_CFB:
|
||||
$this->mode = CRYPT_RIJNDAEL_MODE_CFB;
|
||||
break;
|
||||
case CRYPT_AES_MODE_OFB:
|
||||
$this->mode = CRYPT_RIJNDAEL_MODE_OFB;
|
||||
break;
|
||||
case CRYPT_AES_MODE_CBC:
|
||||
default:
|
||||
$this->paddable = true;
|
||||
$this->mode = CRYPT_RIJNDAEL_MODE_CBC;
|
||||
}
|
||||
}
|
||||
@ -200,6 +239,7 @@ class Crypt_AES extends Crypt_Rijndael {
|
||||
if (CRYPT_AES_MODE == CRYPT_AES_MODE_INTERNAL) {
|
||||
parent::Crypt_Rijndael($this->mode);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -215,6 +255,23 @@ class Crypt_AES extends Crypt_Rijndael {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the initialization vector. (optional)
|
||||
*
|
||||
* SetIV is not required when CRYPT_RIJNDAEL_MODE_ECB is being used. If not explictly set, it'll be assumed
|
||||
* to be all zero's.
|
||||
*
|
||||
* @access public
|
||||
* @param String $iv
|
||||
*/
|
||||
function setIV($iv)
|
||||
{
|
||||
parent::setIV($iv);
|
||||
if ( CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT ) {
|
||||
$this->changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts a message.
|
||||
*
|
||||
@ -236,19 +293,63 @@ class Crypt_AES extends Crypt_Rijndael {
|
||||
{
|
||||
if ( CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT ) {
|
||||
$this->_mcryptSetup();
|
||||
/*
|
||||
if ($this->mode == CRYPT_AES_MODE_CTR) {
|
||||
$iv = $this->encryptIV;
|
||||
$xor = mcrypt_generic($this->enmcrypt, $this->_generate_xor(strlen($plaintext), $iv));
|
||||
$ciphertext = $plaintext ^ $xor;
|
||||
if ($this->continuousBuffer) {
|
||||
$this->encryptIV = $iv;
|
||||
|
||||
// re: http://phpseclib.sourceforge.net/cfb-demo.phps
|
||||
// using mcrypt's default handing of CFB the above would output two different things. using phpseclib's
|
||||
// rewritten CFB implementation the above outputs the same thing twice.
|
||||
if ($this->mode == 'ncfb' && $this->continuousBuffer) {
|
||||
$iv = &$this->encryptIV;
|
||||
$pos = &$this->enbuffer['pos'];
|
||||
$len = strlen($plaintext);
|
||||
$ciphertext = '';
|
||||
$i = 0;
|
||||
if ($pos) {
|
||||
$orig_pos = $pos;
|
||||
$max = 16 - $pos;
|
||||
if ($len >= $max) {
|
||||
$i = $max;
|
||||
$len-= $max;
|
||||
$pos = 0;
|
||||
} else {
|
||||
$i = $len;
|
||||
$pos+= $len;
|
||||
$len = 0;
|
||||
}
|
||||
$ciphertext = substr($iv, $orig_pos) ^ $plaintext;
|
||||
$iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
|
||||
$this->enbuffer['enmcrypt_init'] = true;
|
||||
}
|
||||
if ($len >= 16) {
|
||||
if ($this->enbuffer['enmcrypt_init'] === false || $len > 280) {
|
||||
if ($this->enbuffer['enmcrypt_init'] === true) {
|
||||
mcrypt_generic_init($this->enmcrypt, $this->key, $iv);
|
||||
$this->enbuffer['enmcrypt_init'] = false;
|
||||
}
|
||||
$ciphertext.= mcrypt_generic($this->enmcrypt, substr($plaintext, $i, $len - $len % 16));
|
||||
$iv = substr($ciphertext, -16);
|
||||
$len%= 16;
|
||||
} else {
|
||||
while ($len >= 16) {
|
||||
$iv = mcrypt_generic($this->ecb, $iv) ^ substr($plaintext, $i, 16);
|
||||
$ciphertext.= $iv;
|
||||
$len-= 16;
|
||||
$i+= 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($len) {
|
||||
$iv = mcrypt_generic($this->ecb, $iv);
|
||||
$block = $iv ^ substr($plaintext, -$len);
|
||||
$iv = substr_replace($iv, $block, 0, $len);
|
||||
$ciphertext.= $block;
|
||||
$pos = $len;
|
||||
}
|
||||
|
||||
return $ciphertext;
|
||||
}
|
||||
*/
|
||||
|
||||
if ($this->mode != 'ctr') {
|
||||
if ($this->paddable) {
|
||||
$plaintext = $this->_pad($plaintext);
|
||||
}
|
||||
|
||||
@ -277,19 +378,46 @@ class Crypt_AES extends Crypt_Rijndael {
|
||||
{
|
||||
if ( CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT ) {
|
||||
$this->_mcryptSetup();
|
||||
/*
|
||||
if ($this->mode == CRYPT_AES_MODE_CTR) {
|
||||
$iv = $this->decryptIV;
|
||||
$xor = mcrypt_generic($this->enmcrypt, $this->_generate_xor(strlen($ciphertext), $iv));
|
||||
$plaintext = $ciphertext ^ $xor;
|
||||
if ($this->continuousBuffer) {
|
||||
$this->decryptIV = $iv;
|
||||
|
||||
if ($this->mode == 'ncfb' && $this->continuousBuffer) {
|
||||
$iv = &$this->decryptIV;
|
||||
$pos = &$this->debuffer['pos'];
|
||||
$len = strlen($ciphertext);
|
||||
$plaintext = '';
|
||||
$i = 0;
|
||||
if ($pos) {
|
||||
$orig_pos = $pos;
|
||||
$max = 16 - $pos;
|
||||
if ($len >= $max) {
|
||||
$i = $max;
|
||||
$len-= $max;
|
||||
$pos = 0;
|
||||
} else {
|
||||
$i = $len;
|
||||
$pos+= $len;
|
||||
$len = 0;
|
||||
}
|
||||
// ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
|
||||
$plaintext = substr($iv, $orig_pos) ^ $ciphertext;
|
||||
$iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
|
||||
}
|
||||
if ($len >= 16) {
|
||||
$cb = substr($ciphertext, $i, $len - $len % 16);
|
||||
$plaintext.= mcrypt_generic($this->ecb, $iv . $cb) ^ $cb;
|
||||
$iv = substr($cb, -16);
|
||||
$len%= 16;
|
||||
}
|
||||
if ($len) {
|
||||
$iv = mcrypt_generic($this->ecb, $iv);
|
||||
$plaintext.= $iv ^ substr($ciphertext, -$len);
|
||||
$iv = substr_replace($iv, substr($ciphertext, -$len), 0, $len);
|
||||
$pos = $len;
|
||||
}
|
||||
|
||||
return $plaintext;
|
||||
}
|
||||
*/
|
||||
|
||||
if ($this->mode != 'ctr') {
|
||||
if ($this->paddable) {
|
||||
// we pad with chr(0) since that's what mcrypt_generic does. to quote from http://php.net/function.mcrypt-generic :
|
||||
// "The data is padded with "\0" to make sure the length of the data is n * blocksize."
|
||||
$ciphertext = str_pad($ciphertext, (strlen($ciphertext) + 15) & 0xFFFFFFF0, chr(0));
|
||||
@ -301,7 +429,7 @@ class Crypt_AES extends Crypt_Rijndael {
|
||||
mcrypt_generic_init($this->demcrypt, $this->key, $this->iv);
|
||||
}
|
||||
|
||||
return $this->mode != 'ctr' ? $this->_unpad($plaintext) : $plaintext;
|
||||
return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
|
||||
}
|
||||
|
||||
return parent::decrypt($ciphertext);
|
||||
@ -345,7 +473,7 @@ class Crypt_AES extends Crypt_Rijndael {
|
||||
$this->key_size = 32;
|
||||
}
|
||||
|
||||
$this->key = substr($this->key, 0, $this->key_size);
|
||||
$this->key = str_pad(substr($this->key, 0, $this->key_size), $this->key_size, chr(0));
|
||||
$this->encryptIV = $this->decryptIV = $this->iv = str_pad(substr($this->iv, 0, 16), 16, chr(0));
|
||||
|
||||
if (!isset($this->enmcrypt)) {
|
||||
@ -354,124 +482,57 @@ class Crypt_AES extends Crypt_Rijndael {
|
||||
|
||||
$this->demcrypt = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', $mode, '');
|
||||
$this->enmcrypt = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', $mode, '');
|
||||
|
||||
if ($mode == 'ncfb') {
|
||||
$this->ecb = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_ECB, '');
|
||||
}
|
||||
|
||||
} // else should mcrypt_generic_deinit be called?
|
||||
|
||||
mcrypt_generic_init($this->demcrypt, $this->key, $this->iv);
|
||||
mcrypt_generic_init($this->enmcrypt, $this->key, $this->iv);
|
||||
|
||||
if ($this->mode == 'ncfb') {
|
||||
mcrypt_generic_init($this->ecb, $this->key, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
|
||||
}
|
||||
|
||||
$this->changed = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts a block
|
||||
* Treat consecutive "packets" as if they are a continuous buffer.
|
||||
*
|
||||
* Optimized over Crypt_Rijndael's implementation by means of loop unrolling.
|
||||
* The default behavior.
|
||||
*
|
||||
* @see Crypt_Rijndael::_encryptBlock()
|
||||
* @access private
|
||||
* @param String $in
|
||||
* @return String
|
||||
* @see Crypt_Rijndael::disableContinuousBuffer()
|
||||
* @access public
|
||||
*/
|
||||
function _encryptBlock($in)
|
||||
function enableContinuousBuffer()
|
||||
{
|
||||
$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'] ^ $w[0][0],
|
||||
$state['word2'] ^ $w[0][1],
|
||||
$state['word3'] ^ $w[0][2],
|
||||
$state['word4'] ^ $w[0][3]
|
||||
);
|
||||
|
||||
// shiftRows + subWord + mixColumns + addRoundKey
|
||||
// we could loop unroll this and use if statements to do more rounds as necessary, but, in my tests, that yields
|
||||
// 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(
|
||||
$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]
|
||||
);
|
||||
parent::enableContinuousBuffer();
|
||||
|
||||
if (CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT) {
|
||||
$this->enbuffer['enmcrypt_init'] = true;
|
||||
$this->debuffer['demcrypt_init'] = true;
|
||||
}
|
||||
|
||||
// subWord
|
||||
$state = array(
|
||||
$this->_subWord($state[0]),
|
||||
$this->_subWord($state[1]),
|
||||
$this->_subWord($state[2]),
|
||||
$this->_subWord($state[3])
|
||||
);
|
||||
|
||||
// shiftRows + addRoundKey
|
||||
$state = array(
|
||||
($state[0] & 0xFF000000) ^ ($state[1] & 0x00FF0000) ^ ($state[2] & 0x0000FF00) ^ ($state[3] & 0x000000FF) ^ $this->w[$this->Nr][0],
|
||||
($state[1] & 0xFF000000) ^ ($state[2] & 0x00FF0000) ^ ($state[3] & 0x0000FF00) ^ ($state[0] & 0x000000FF) ^ $this->w[$this->Nr][1],
|
||||
($state[2] & 0xFF000000) ^ ($state[3] & 0x00FF0000) ^ ($state[0] & 0x0000FF00) ^ ($state[1] & 0x000000FF) ^ $this->w[$this->Nr][2],
|
||||
($state[3] & 0xFF000000) ^ ($state[0] & 0x00FF0000) ^ ($state[1] & 0x0000FF00) ^ ($state[2] & 0x000000FF) ^ $this->w[$this->Nr][3]
|
||||
);
|
||||
|
||||
return pack('N*', $state[0], $state[1], $state[2], $state[3]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts a block
|
||||
* Treat consecutive packets as if they are a discontinuous buffer.
|
||||
*
|
||||
* Optimized over Crypt_Rijndael's implementation by means of loop unrolling.
|
||||
* The default behavior.
|
||||
*
|
||||
* @see Crypt_Rijndael::_decryptBlock()
|
||||
* @access private
|
||||
* @param String $in
|
||||
* @return String
|
||||
* @see Crypt_Rijndael::enableContinuousBuffer()
|
||||
* @access public
|
||||
*/
|
||||
function _decryptBlock($in)
|
||||
function disableContinuousBuffer()
|
||||
{
|
||||
$state = unpack('N*word', $in);
|
||||
parent::disableContinuousBuffer();
|
||||
|
||||
$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'] ^ $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(
|
||||
$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]
|
||||
);
|
||||
if (CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT) {
|
||||
mcrypt_generic_init($this->enmcrypt, $this->key, $this->iv);
|
||||
mcrypt_generic_init($this->demcrypt, $this->key, $this->iv);
|
||||
}
|
||||
|
||||
// invShiftRows + invSubWord + addRoundKey
|
||||
$state = array(
|
||||
$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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
1468
plugins/OStatus/extlib/Crypt/Blowfish.php
Normal file
1468
plugins/OStatus/extlib/Crypt/Blowfish.php
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -29,27 +29,29 @@
|
||||
* ?>
|
||||
* </code>
|
||||
*
|
||||
* LICENSE: This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @category Crypt
|
||||
* @package Crypt_Hash
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright MMVII Jim Wigginton
|
||||
* @license http://www.gnu.org/licenses/lgpl.txt
|
||||
* @version $Id: Hash.php,v 1.6 2009/11/23 23:37:07 terrafrost Exp $
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
||||
@ -114,7 +116,7 @@ class Crypt_Hash {
|
||||
* @var String
|
||||
* @access private
|
||||
*/
|
||||
var $key = '';
|
||||
var $key = false;
|
||||
|
||||
/**
|
||||
* Outer XOR (Internal HMAC)
|
||||
@ -165,9 +167,9 @@ class Crypt_Hash {
|
||||
* Keys can be of any length.
|
||||
*
|
||||
* @access public
|
||||
* @param String $key
|
||||
* @param optional String $key
|
||||
*/
|
||||
function setKey($key)
|
||||
function setKey($key = false)
|
||||
{
|
||||
$this->key = $key;
|
||||
}
|
||||
@ -180,6 +182,7 @@ class Crypt_Hash {
|
||||
*/
|
||||
function setHash($hash)
|
||||
{
|
||||
$hash = strtolower($hash);
|
||||
switch ($hash) {
|
||||
case 'md5-96':
|
||||
case 'sha1-96':
|
||||
@ -204,7 +207,8 @@ class Crypt_Hash {
|
||||
|
||||
switch ($hash) {
|
||||
case 'md2':
|
||||
$mode = CRYPT_HASH_MODE_INTERNAL;
|
||||
$mode = CRYPT_HASH_MODE == CRYPT_HASH_MODE_HASH && in_array('md2', hash_algos()) ?
|
||||
CRYPT_HASH_MODE_HASH : CRYPT_HASH_MODE_INTERNAL;
|
||||
break;
|
||||
case 'sha384':
|
||||
case 'sha512':
|
||||
@ -236,6 +240,7 @@ class Crypt_Hash {
|
||||
case 'md5-96':
|
||||
$this->hash = 'md5';
|
||||
return;
|
||||
case 'md2':
|
||||
case 'sha256':
|
||||
case 'sha384':
|
||||
case 'sha512':
|
||||
@ -290,7 +295,7 @@ class Crypt_Hash {
|
||||
{
|
||||
$mode = is_array($this->hash) ? CRYPT_HASH_MODE_INTERNAL : CRYPT_HASH_MODE;
|
||||
|
||||
if (!empty($this->key)) {
|
||||
if (!empty($this->key) || is_string($this->key)) {
|
||||
switch ( $mode ) {
|
||||
case CRYPT_HASH_MODE_MHASH:
|
||||
$output = mhash($this->hash, $text, $this->key);
|
||||
@ -303,7 +308,7 @@ class Crypt_Hash {
|
||||
resultant L byte string as the actual key to HMAC."
|
||||
|
||||
-- http://tools.ietf.org/html/rfc2104#section-2 */
|
||||
$key = strlen($this->key) > $this->b ? call_user_func($this->$hash, $this->key) : $this->key;
|
||||
$key = strlen($this->key) > $this->b ? call_user_func($this->hash, $this->key) : $this->key;
|
||||
|
||||
$key = str_pad($key, $this->b, chr(0)); // step 1
|
||||
$temp = $this->ipad ^ $key; // step 2
|
||||
@ -332,7 +337,7 @@ class Crypt_Hash {
|
||||
/**
|
||||
* Returns the hash length (in bytes)
|
||||
*
|
||||
* @access private
|
||||
* @access public
|
||||
* @return Integer
|
||||
*/
|
||||
function getLength()
|
||||
@ -344,7 +349,7 @@ class Crypt_Hash {
|
||||
* Wrapper for MD5
|
||||
*
|
||||
* @access private
|
||||
* @param String $text
|
||||
* @param String $m
|
||||
*/
|
||||
function _md5($m)
|
||||
{
|
||||
@ -355,7 +360,7 @@ class Crypt_Hash {
|
||||
* Wrapper for SHA1
|
||||
*
|
||||
* @access private
|
||||
* @param String $text
|
||||
* @param String $m
|
||||
*/
|
||||
function _sha1($m)
|
||||
{
|
||||
@ -368,7 +373,7 @@ class Crypt_Hash {
|
||||
* See {@link http://tools.ietf.org/html/rfc1319 RFC1319}.
|
||||
*
|
||||
* @access private
|
||||
* @param String $text
|
||||
* @param String $m
|
||||
*/
|
||||
function _md2($m)
|
||||
{
|
||||
@ -404,7 +409,10 @@ class Crypt_Hash {
|
||||
$l = chr(0);
|
||||
for ($i = 0; $i < $length; $i+= 16) {
|
||||
for ($j = 0; $j < 16; $j++) {
|
||||
$c[$j] = chr($s[ord($m[$i + $j] ^ $l)]);
|
||||
// RFC1319 incorrectly states that C[j] should be set to S[c xor L]
|
||||
//$c[$j] = chr($s[ord($m[$i + $j] ^ $l)]);
|
||||
// per <http://www.rfc-editor.org/errata_search.php?rfc=1319>, however, C[j] should be set to S[c xor L] xor C[j]
|
||||
$c[$j] = chr($s[ord($m[$i + $j] ^ $l)] ^ ord($c[$j]));
|
||||
$l = $c[$j];
|
||||
}
|
||||
}
|
||||
@ -441,7 +449,7 @@ class Crypt_Hash {
|
||||
* See {@link http://en.wikipedia.org/wiki/SHA_hash_functions#SHA-256_.28a_SHA-2_variant.29_pseudocode SHA-256 (a SHA-2 variant) pseudocode - Wikipedia}.
|
||||
*
|
||||
* @access private
|
||||
* @param String $text
|
||||
* @param String $m
|
||||
*/
|
||||
function _sha256($m)
|
||||
{
|
||||
@ -546,7 +554,7 @@ class Crypt_Hash {
|
||||
* Pure-PHP implementation of SHA384 and SHA512
|
||||
*
|
||||
* @access private
|
||||
* @param String $text
|
||||
* @param String $m
|
||||
*/
|
||||
function _sha512($m)
|
||||
{
|
||||
@ -775,9 +783,8 @@ class Crypt_Hash {
|
||||
* _sha256() adds multiple unsigned 32-bit integers. Since PHP doesn't support unsigned integers and since the
|
||||
* possibility of overflow exists, care has to be taken. Math_BigInteger() could be used but this should be faster.
|
||||
*
|
||||
* @param String $string
|
||||
* @param optional Integer $index
|
||||
* @return String
|
||||
* @param Integer $...
|
||||
* @return Integer
|
||||
* @see _sha256()
|
||||
* @access private
|
||||
*/
|
||||
|
@ -14,7 +14,7 @@
|
||||
* - {@link http://en.wikipedia.org/wiki/RC4 - Wikipedia: RC4}
|
||||
*
|
||||
* RC4 is also known as ARCFOUR or ARC4. The reason is elaborated upon at Wikipedia. This class is named RC4 and not
|
||||
* ARCFOUR or ARC4 because RC4 is how it is refered to in the SSH1 specification.
|
||||
* ARCFOUR or ARC4 because RC4 is how it is referred to in the SSH1 specification.
|
||||
*
|
||||
* Here's a short example of how to use this library:
|
||||
* <code>
|
||||
@ -35,27 +35,29 @@
|
||||
* ?>
|
||||
* </code>
|
||||
*
|
||||
* LICENSE: This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @category Crypt
|
||||
* @package Crypt_RC4
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright MMVII Jim Wigginton
|
||||
* @license http://www.gnu.org/licenses/lgpl.txt
|
||||
* @version $Id: RC4.php,v 1.8 2009/06/09 04:00:38 terrafrost Exp $
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
||||
@ -139,15 +141,6 @@ class Crypt_RC4 {
|
||||
*/
|
||||
var $decryptIndex = 0;
|
||||
|
||||
/**
|
||||
* MCrypt parameters
|
||||
*
|
||||
* @see Crypt_RC4::setMCrypt()
|
||||
* @var Array
|
||||
* @access private
|
||||
*/
|
||||
var $mcrypt = array('', '');
|
||||
|
||||
/**
|
||||
* The Encryption Algorithm
|
||||
*
|
||||
@ -159,12 +152,20 @@ class Crypt_RC4 {
|
||||
*/
|
||||
var $mode;
|
||||
|
||||
/**
|
||||
* Continuous Buffer status
|
||||
*
|
||||
* @see Crypt_RC4::enableContinuousBuffer()
|
||||
* @var Boolean
|
||||
* @access private
|
||||
*/
|
||||
var $continuousBuffer = false;
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
*
|
||||
* Determines whether or not the mcrypt extension should be used.
|
||||
*
|
||||
* @param optional Integer $mode
|
||||
* @return Crypt_RC4
|
||||
* @access public
|
||||
*/
|
||||
@ -172,10 +173,7 @@ class Crypt_RC4 {
|
||||
{
|
||||
if ( !defined('CRYPT_RC4_MODE') ) {
|
||||
switch (true) {
|
||||
case extension_loaded('mcrypt') && (defined('MCRYPT_ARCFOUR') || defined('MCRYPT_RC4')):
|
||||
// i'd check to see if rc4 was supported, by doing in_array('arcfour', mcrypt_list_algorithms('')),
|
||||
// but since that can be changed after the object has been created, there doesn't seem to be
|
||||
// a lot of point...
|
||||
case extension_loaded('mcrypt') && (defined('MCRYPT_ARCFOUR') || defined('MCRYPT_RC4')) && in_array('arcfour', mcrypt_list_algorithms()):
|
||||
define('CRYPT_RC4_MODE', CRYPT_RC4_MODE_MCRYPT);
|
||||
break;
|
||||
default:
|
||||
@ -192,6 +190,9 @@ class Crypt_RC4 {
|
||||
case defined('MCRYPT_RC4');
|
||||
$this->mode = MCRYPT_RC4;
|
||||
}
|
||||
$this->encryptStream = mcrypt_module_open($this->mode, '', MCRYPT_MODE_STREAM, '');
|
||||
$this->decryptStream = mcrypt_module_open($this->mode, '', MCRYPT_MODE_STREAM, '');
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -209,6 +210,8 @@ class Crypt_RC4 {
|
||||
$this->key = $key;
|
||||
|
||||
if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT ) {
|
||||
mcrypt_generic_init($this->encryptStream, $this->key, '');
|
||||
mcrypt_generic_init($this->decryptStream, $this->key, '');
|
||||
return;
|
||||
}
|
||||
|
||||
@ -229,6 +232,62 @@ class Crypt_RC4 {
|
||||
$this->encryptStream = $this->decryptStream = $keyStream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the password.
|
||||
*
|
||||
* Depending on what $method is set to, setPassword()'s (optional) parameters are as follows:
|
||||
* {@link http://en.wikipedia.org/wiki/PBKDF2 pbkdf2}:
|
||||
* $hash, $salt, $count, $dkLen
|
||||
*
|
||||
* @param String $password
|
||||
* @param optional String $method
|
||||
* @access public
|
||||
*/
|
||||
function setPassword($password, $method = 'pbkdf2')
|
||||
{
|
||||
$key = '';
|
||||
|
||||
switch ($method) {
|
||||
default: // 'pbkdf2'
|
||||
list(, , $hash, $salt, $count) = func_get_args();
|
||||
if (!isset($hash)) {
|
||||
$hash = 'sha1';
|
||||
}
|
||||
// WPA and WPA2 use the SSID as the salt
|
||||
if (!isset($salt)) {
|
||||
$salt = 'phpseclib/salt';
|
||||
}
|
||||
// RFC2898#section-4.2 uses 1,000 iterations by default
|
||||
// WPA and WPA2 use 4,096.
|
||||
if (!isset($count)) {
|
||||
$count = 1000;
|
||||
}
|
||||
if (!isset($dkLen)) {
|
||||
$dkLen = 128;
|
||||
}
|
||||
|
||||
if (!class_exists('Crypt_Hash')) {
|
||||
require_once('Crypt/Hash.php');
|
||||
}
|
||||
|
||||
$i = 1;
|
||||
while (strlen($key) < $dkLen) {
|
||||
//$dk.= $this->_pbkdf($password, $salt, $count, $i++);
|
||||
$hmac = new Crypt_Hash();
|
||||
$hmac->setHash($hash);
|
||||
$hmac->setKey($password);
|
||||
$f = $u = $hmac->hash($salt . pack('N', $i++));
|
||||
for ($j = 2; $j <= $count; $j++) {
|
||||
$u = $hmac->hash($u);
|
||||
$f^= $u;
|
||||
}
|
||||
$key.= $f;
|
||||
}
|
||||
}
|
||||
|
||||
$this->setKey(substr($key, 0, $dkLen));
|
||||
}
|
||||
|
||||
/**
|
||||
* Dummy function.
|
||||
*
|
||||
@ -252,24 +311,6 @@ class Crypt_RC4 {
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets MCrypt parameters. (optional)
|
||||
*
|
||||
* If MCrypt is being used, empty strings will be used, unless otherwise specified.
|
||||
*
|
||||
* @link http://php.net/function.mcrypt-module-open#function.mcrypt-module-open
|
||||
* @access public
|
||||
* @param optional Integer $algorithm_directory
|
||||
* @param optional Integer $mode_directory
|
||||
*/
|
||||
function setMCrypt($algorithm_directory = '', $mode_directory = '')
|
||||
{
|
||||
if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT ) {
|
||||
$this->mcrypt = array($algorithm_directory, $mode_directory);
|
||||
$this->_closeMCrypt();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts a message.
|
||||
*
|
||||
@ -311,18 +352,11 @@ class Crypt_RC4 {
|
||||
if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT ) {
|
||||
$keyStream = $mode == CRYPT_RC4_ENCRYPT ? 'encryptStream' : 'decryptStream';
|
||||
|
||||
if ($this->$keyStream === false) {
|
||||
$this->$keyStream = mcrypt_module_open($this->mode, $this->mcrypt[0], MCRYPT_MODE_STREAM, $this->mcrypt[1]);
|
||||
mcrypt_generic_init($this->$keyStream, $this->key, '');
|
||||
} else if (!$this->continuousBuffer) {
|
||||
mcrypt_generic_init($this->$keyStream, $this->key, '');
|
||||
}
|
||||
$newText = mcrypt_generic($this->$keyStream, $text);
|
||||
if (!$this->continuousBuffer) {
|
||||
mcrypt_generic_deinit($this->$keyStream);
|
||||
mcrypt_generic_init($this->$keyStream, $this->key, '');
|
||||
}
|
||||
|
||||
return $newText;
|
||||
return mcrypt_generic($this->$keyStream, $text);
|
||||
}
|
||||
|
||||
if ($this->encryptStream === false) {
|
||||
@ -404,6 +438,11 @@ class Crypt_RC4 {
|
||||
*/
|
||||
function enableContinuousBuffer()
|
||||
{
|
||||
if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT ) {
|
||||
mcrypt_generic_init($this->encryptStream, $this->key, '');
|
||||
mcrypt_generic_init($this->decryptStream, $this->key, '');
|
||||
}
|
||||
|
||||
$this->continuousBuffer = true;
|
||||
}
|
||||
|
||||
@ -419,7 +458,7 @@ class Crypt_RC4 {
|
||||
{
|
||||
if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_INTERNAL ) {
|
||||
$this->encryptIndex = $this->decryptIndex = array(0, 0);
|
||||
$this->setKey($this->key);
|
||||
$this->encryptStream = $this->decryptStream = false;
|
||||
}
|
||||
|
||||
$this->continuousBuffer = false;
|
||||
@ -447,47 +486,7 @@ class Crypt_RC4 {
|
||||
function disablePadding()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Class destructor.
|
||||
*
|
||||
* Will be called, automatically, if you're using PHP5. If you're using PHP4, call it yourself. Only really
|
||||
* needs to be called if mcrypt is being used.
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function __destruct()
|
||||
{
|
||||
if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT ) {
|
||||
$this->_closeMCrypt();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Properly close the MCrypt objects.
|
||||
*
|
||||
* @access prviate
|
||||
*/
|
||||
function _closeMCrypt()
|
||||
{
|
||||
if ( $this->encryptStream !== false ) {
|
||||
if ( $this->continuousBuffer ) {
|
||||
mcrypt_generic_deinit($this->encryptStream);
|
||||
}
|
||||
|
||||
mcrypt_module_close($this->encryptStream);
|
||||
|
||||
$this->encryptStream = false;
|
||||
}
|
||||
|
||||
if ( $this->decryptStream !== false ) {
|
||||
if ( $this->continuousBuffer ) {
|
||||
mcrypt_generic_deinit($this->decryptStream);
|
||||
}
|
||||
|
||||
mcrypt_module_close($this->decryptStream);
|
||||
|
||||
$this->decryptStream = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// vim: ts=4:sw=4:et:
|
||||
// vim6: fdl=1:
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -11,93 +11,184 @@
|
||||
* <?php
|
||||
* include('Crypt/Random.php');
|
||||
*
|
||||
* echo crypt_random();
|
||||
* echo bin2hex(crypt_random_string(8));
|
||||
* ?>
|
||||
* </code>
|
||||
*
|
||||
* LICENSE: This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @category Crypt
|
||||
* @package Crypt_Random
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright MMVII Jim Wigginton
|
||||
* @license http://www.gnu.org/licenses/lgpl.txt
|
||||
* @version $Id: Random.php,v 1.6 2010/02/28 05:28:38 terrafrost Exp $
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
||||
/**
|
||||
* Generate a random value.
|
||||
* "Is Windows" test
|
||||
*
|
||||
* On 32-bit machines, the largest distance that can exist between $min and $max is 2**31.
|
||||
* If $min and $max are farther apart than that then the last ($max - range) numbers.
|
||||
* @access private
|
||||
*/
|
||||
define('CRYPT_RANDOM_IS_WINDOWS', strtoupper(substr(PHP_OS, 0, 3)) === 'WIN');
|
||||
|
||||
/**
|
||||
* Generate a random string.
|
||||
*
|
||||
* Depending on how this is being used, it may be worth while to write a replacement. For example,
|
||||
* a PHP-based web app that stores its data in an SQL database can collect more entropy than this function
|
||||
* can.
|
||||
* Although microoptimizations are generally discouraged as they impair readability this function is ripe with
|
||||
* microoptimizations because this function has the potential of being called a huge number of times.
|
||||
* eg. for RSA key generation.
|
||||
*
|
||||
* @param optional Integer $min
|
||||
* @param optional Integer $max
|
||||
* @return Integer
|
||||
* @param Integer $length
|
||||
* @return String
|
||||
* @access public
|
||||
*/
|
||||
function crypt_random($min = 0, $max = 0x7FFFFFFF)
|
||||
function crypt_random_string($length)
|
||||
{
|
||||
if ($min == $max) {
|
||||
return $min;
|
||||
}
|
||||
|
||||
// see http://en.wikipedia.org/wiki//dev/random
|
||||
if (file_exists('/dev/urandom')) {
|
||||
$fp = fopen('/dev/urandom', 'rb');
|
||||
extract(unpack('Nrandom', fread($fp, 4)));
|
||||
fclose($fp);
|
||||
|
||||
// say $min = 0 and $max = 3. if we didn't do abs() then we could have stuff like this:
|
||||
// -4 % 3 + 0 = -1, even though -1 < $min
|
||||
return abs($random) % ($max - $min) + $min;
|
||||
}
|
||||
|
||||
/* Prior to PHP 4.2.0, mt_srand() had to be called before mt_rand() could be called.
|
||||
Prior to PHP 5.2.6, mt_rand()'s automatic seeding was subpar, as elaborated here:
|
||||
|
||||
http://www.suspekt.org/2008/08/17/mt_srand-and-not-so-random-numbers/
|
||||
|
||||
The seeding routine is pretty much ripped from PHP's own internal GENERATE_SEED() macro:
|
||||
|
||||
http://svn.php.net/viewvc/php/php-src/branches/PHP_5_3_2/ext/standard/php_rand.h?view=markup */
|
||||
if (version_compare(PHP_VERSION, '5.2.5', '<=')) {
|
||||
static $seeded;
|
||||
if (!isset($seeded)) {
|
||||
$seeded = true;
|
||||
mt_srand(fmod(time() * getmypid(), 0x7FFFFFFF) ^ fmod(1000000 * lcg_value(), 0x7FFFFFFF));
|
||||
if (CRYPT_RANDOM_IS_WINDOWS) {
|
||||
// method 1. prior to PHP 5.3 this would call rand() on windows hence the function_exists('class_alias') call.
|
||||
// ie. class_alias is a function that was introduced in PHP 5.3
|
||||
if (function_exists('mcrypt_create_iv') && function_exists('class_alias')) {
|
||||
return mcrypt_create_iv($length);
|
||||
}
|
||||
// method 2. openssl_random_pseudo_bytes was introduced in PHP 5.3.0 but prior to PHP 5.3.4 there was,
|
||||
// to quote <http://php.net/ChangeLog-5.php#5.3.4>, "possible blocking behavior". as of 5.3.4
|
||||
// openssl_random_pseudo_bytes and mcrypt_create_iv do the exact same thing on Windows. ie. they both
|
||||
// call php_win32_get_random_bytes():
|
||||
//
|
||||
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/openssl/openssl.c#L5008
|
||||
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/mcrypt/mcrypt.c#L1392
|
||||
//
|
||||
// php_win32_get_random_bytes() is defined thusly:
|
||||
//
|
||||
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/win32/winutil.c#L80
|
||||
//
|
||||
// we're calling it, all the same, in the off chance that the mcrypt extension is not available
|
||||
if (function_exists('openssl_random_pseudo_bytes') && version_compare(PHP_VERSION, '5.3.4', '>=')) {
|
||||
return openssl_random_pseudo_bytes($length);
|
||||
}
|
||||
} else {
|
||||
// method 1. the fastest
|
||||
if (function_exists('openssl_random_pseudo_bytes')) {
|
||||
return openssl_random_pseudo_bytes($length);
|
||||
}
|
||||
// method 2
|
||||
static $fp = true;
|
||||
if ($fp === true) {
|
||||
// warning's will be output unles the error suppression operator is used. errors such as
|
||||
// "open_basedir restriction in effect", "Permission denied", "No such file or directory", etc.
|
||||
$fp = @fopen('/dev/urandom', 'rb');
|
||||
}
|
||||
if ($fp !== true && $fp !== false) { // surprisingly faster than !is_bool() or is_resource()
|
||||
return fread($fp, $length);
|
||||
}
|
||||
// method 3. pretty much does the same thing as method 2 per the following url:
|
||||
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/mcrypt/mcrypt.c#L1391
|
||||
// surprisingly slower than method 2. maybe that's because mcrypt_create_iv does a bunch of error checking that we're
|
||||
// not doing. regardless, this'll only be called if this PHP script couldn't open /dev/urandom due to open_basedir
|
||||
// restrictions or some such
|
||||
if (function_exists('mcrypt_create_iv')) {
|
||||
return mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
|
||||
}
|
||||
}
|
||||
// at this point we have no choice but to use a pure-PHP CSPRNG
|
||||
|
||||
static $crypto;
|
||||
|
||||
// The CSPRNG's Yarrow and Fortuna periodically reseed. This function can be reseeded by hitting F5
|
||||
// in the browser and reloading the page.
|
||||
|
||||
if (!isset($crypto)) {
|
||||
$key = $iv = '';
|
||||
for ($i = 0; $i < 8; $i++) {
|
||||
$key.= pack('n', mt_rand(0, 0xFFFF));
|
||||
$iv .= pack('n', mt_rand(0, 0xFFFF));
|
||||
// cascade entropy across multiple PHP instances by fixing the session and collecting all
|
||||
// environmental variables, including the previous session data and the current session
|
||||
// data.
|
||||
//
|
||||
// mt_rand seeds itself by looking at the PID and the time, both of which are (relatively)
|
||||
// easy to guess at. linux uses mouse clicks, keyboard timings, etc, as entropy sources, but
|
||||
// PHP isn't low level to be able to use those as sources and on a web server there's not likely
|
||||
// going to be a ton of keyboard or mouse action. web servers do have one thing that we can use
|
||||
// however. a ton of people visiting the website. obviously you don't want to base your seeding
|
||||
// soley on parameters a potential attacker sends but (1) not everything in $_SERVER is controlled
|
||||
// by the user and (2) this isn't just looking at the data sent by the current user - it's based
|
||||
// on the data sent by all users. one user requests the page and a hash of their info is saved.
|
||||
// another user visits the page and the serialization of their data is utilized along with the
|
||||
// server envirnment stuff and a hash of the previous http request data (which itself utilizes
|
||||
// a hash of the session data before that). certainly an attacker should be assumed to have
|
||||
// full control over his own http requests. he, however, is not going to have control over
|
||||
// everyone's http requests.
|
||||
static $crypto = false, $v;
|
||||
if ($crypto === false) {
|
||||
// save old session data
|
||||
$old_session_id = session_id();
|
||||
$old_use_cookies = ini_get('session.use_cookies');
|
||||
$old_session_cache_limiter = session_cache_limiter();
|
||||
if (isset($_SESSION)) {
|
||||
$_OLD_SESSION = $_SESSION;
|
||||
}
|
||||
if ($old_session_id != '') {
|
||||
session_write_close();
|
||||
}
|
||||
|
||||
session_id(1);
|
||||
ini_set('session.use_cookies', 0);
|
||||
session_cache_limiter('');
|
||||
session_start();
|
||||
|
||||
$v = $seed = $_SESSION['seed'] = pack('H*', sha1(
|
||||
serialize($_SERVER) .
|
||||
serialize($_POST) .
|
||||
serialize($_GET) .
|
||||
serialize($_COOKIE) .
|
||||
serialize($GLOBALS) .
|
||||
serialize($_SESSION) .
|
||||
serialize($_OLD_SESSION)
|
||||
));
|
||||
if (!isset($_SESSION['count'])) {
|
||||
$_SESSION['count'] = 0;
|
||||
}
|
||||
$_SESSION['count']++;
|
||||
|
||||
session_write_close();
|
||||
|
||||
// restore old session data
|
||||
if ($old_session_id != '') {
|
||||
session_id($old_session_id);
|
||||
session_start();
|
||||
ini_set('session.use_cookies', $old_use_cookies);
|
||||
session_cache_limiter($old_session_cache_limiter);
|
||||
} else {
|
||||
if (isset($_OLD_SESSION)) {
|
||||
$_SESSION = $_OLD_SESSION;
|
||||
unset($_OLD_SESSION);
|
||||
} else {
|
||||
unset($_SESSION);
|
||||
}
|
||||
}
|
||||
|
||||
// in SSH2 a shared secret and an exchange hash are generated through the key exchange process.
|
||||
// the IV client to server is the hash of that "nonce" with the letter A and for the encryption key it's the letter C.
|
||||
// if the hash doesn't produce enough a key or an IV that's long enough concat successive hashes of the
|
||||
// original hash and the current hash. we'll be emulating that. for more info see the following URL:
|
||||
//
|
||||
// http://tools.ietf.org/html/rfc4253#section-7.2
|
||||
//
|
||||
// see the is_string($crypto) part for an example of how to expand the keys
|
||||
$key = pack('H*', sha1($seed . 'A'));
|
||||
$iv = pack('H*', sha1($seed . 'C'));
|
||||
|
||||
// ciphers are used as per the nist.gov link below. also, see this link:
|
||||
//
|
||||
// http://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator#Designs_based_on_cryptographic_primitives
|
||||
switch (true) {
|
||||
case class_exists('Crypt_AES'):
|
||||
$crypto = new Crypt_AES(CRYPT_AES_MODE_CTR);
|
||||
@ -112,14 +203,47 @@ function crypt_random($min = 0, $max = 0x7FFFFFFF)
|
||||
$crypto = new Crypt_RC4();
|
||||
break;
|
||||
default:
|
||||
extract(unpack('Nrandom', pack('H*', sha1(mt_rand(0, 0x7FFFFFFF)))));
|
||||
return abs($random) % ($max - $min) + $min;
|
||||
$crypto = $seed;
|
||||
return crypt_random_string($length);
|
||||
}
|
||||
|
||||
$crypto->setKey($key);
|
||||
$crypto->setIV($iv);
|
||||
$crypto->enableContinuousBuffer();
|
||||
}
|
||||
|
||||
extract(unpack('Nrandom', $crypto->encrypt("\0\0\0\0")));
|
||||
return abs($random) % ($max - $min) + $min;
|
||||
if (is_string($crypto)) {
|
||||
// the following is based off of ANSI X9.31:
|
||||
//
|
||||
// http://csrc.nist.gov/groups/STM/cavp/documents/rng/931rngext.pdf
|
||||
//
|
||||
// OpenSSL uses that same standard for it's random numbers:
|
||||
//
|
||||
// http://www.opensource.apple.com/source/OpenSSL/OpenSSL-38/openssl/fips-1.0/rand/fips_rand.c
|
||||
// (do a search for "ANS X9.31 A.2.4")
|
||||
//
|
||||
// ANSI X9.31 recommends ciphers be used and phpseclib does use them if they're available (see
|
||||
// later on in the code) but if they're not we'll use sha1
|
||||
$result = '';
|
||||
while (strlen($result) < $length) { // each loop adds 20 bytes
|
||||
// microtime() isn't packed as "densely" as it could be but then neither is that the idea.
|
||||
// the idea is simply to ensure that each "block" has a unique element to it.
|
||||
$i = pack('H*', sha1(microtime()));
|
||||
$r = pack('H*', sha1($i ^ $v));
|
||||
$v = pack('H*', sha1($r ^ $i));
|
||||
$result.= $r;
|
||||
}
|
||||
return substr($result, 0, $length);
|
||||
}
|
||||
|
||||
//return $crypto->encrypt(str_repeat("\0", $length));
|
||||
|
||||
$result = '';
|
||||
while (strlen($result) < $length) {
|
||||
$i = $crypto->encrypt(microtime());
|
||||
$r = $crypto->encrypt($i ^ $v);
|
||||
$v = $crypto->encrypt($r ^ $i);
|
||||
$result.= $r;
|
||||
}
|
||||
return substr($result, 0, $length);
|
||||
}
|
||||
?>
|
File diff suppressed because it is too large
Load Diff
@ -27,41 +27,45 @@
|
||||
* ?>
|
||||
* </code>
|
||||
*
|
||||
* LICENSE: This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @category Crypt
|
||||
* @package Crypt_TripleDES
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright MMVII Jim Wigginton
|
||||
* @license http://www.gnu.org/licenses/lgpl.txt
|
||||
* @version $Id: TripleDES.php,v 1.13 2010/02/26 03:40:25 terrafrost Exp $
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
||||
/**
|
||||
* Include Crypt_DES
|
||||
*/
|
||||
require_once 'DES.php';
|
||||
if (!class_exists('Crypt_DES')) {
|
||||
require_once('DES.php');
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypt / decrypt using inner chaining
|
||||
*
|
||||
* Inner chaining is used by SSH-1 and is generally considered to be less secure then outer chaining (CRYPT_DES_MODE_CBC3).
|
||||
*/
|
||||
define('CRYPT_DES_MODE_3CBC', 3);
|
||||
define('CRYPT_DES_MODE_3CBC', -2);
|
||||
|
||||
/**
|
||||
* Encrypt / decrypt using outer chaining
|
||||
@ -78,70 +82,7 @@ define('CRYPT_DES_MODE_CBC3', CRYPT_DES_MODE_CBC);
|
||||
* @access public
|
||||
* @package Crypt_TerraDES
|
||||
*/
|
||||
class Crypt_TripleDES {
|
||||
/**
|
||||
* The Three Keys
|
||||
*
|
||||
* @see Crypt_TripleDES::setKey()
|
||||
* @var String
|
||||
* @access private
|
||||
*/
|
||||
var $key = "\0\0\0\0\0\0\0\0";
|
||||
|
||||
/**
|
||||
* The Encryption Mode
|
||||
*
|
||||
* @see Crypt_TripleDES::Crypt_TripleDES()
|
||||
* @var Integer
|
||||
* @access private
|
||||
*/
|
||||
var $mode = CRYPT_DES_MODE_CBC;
|
||||
|
||||
/**
|
||||
* Continuous Buffer status
|
||||
*
|
||||
* @see Crypt_TripleDES::enableContinuousBuffer()
|
||||
* @var Boolean
|
||||
* @access private
|
||||
*/
|
||||
var $continuousBuffer = false;
|
||||
|
||||
/**
|
||||
* Padding status
|
||||
*
|
||||
* @see Crypt_TripleDES::enablePadding()
|
||||
* @var Boolean
|
||||
* @access private
|
||||
*/
|
||||
var $padding = true;
|
||||
|
||||
/**
|
||||
* The Initialization Vector
|
||||
*
|
||||
* @see Crypt_TripleDES::setIV()
|
||||
* @var String
|
||||
* @access private
|
||||
*/
|
||||
var $iv = "\0\0\0\0\0\0\0\0";
|
||||
|
||||
/**
|
||||
* A "sliding" Initialization Vector
|
||||
*
|
||||
* @see Crypt_TripleDES::enableContinuousBuffer()
|
||||
* @var String
|
||||
* @access private
|
||||
*/
|
||||
var $encryptIV = "\0\0\0\0\0\0\0\0";
|
||||
|
||||
/**
|
||||
* A "sliding" Initialization Vector
|
||||
*
|
||||
* @see Crypt_TripleDES::enableContinuousBuffer()
|
||||
* @var String
|
||||
* @access private
|
||||
*/
|
||||
var $decryptIV = "\0\0\0\0\0\0\0\0";
|
||||
|
||||
class Crypt_TripleDES extends Crypt_DES {
|
||||
/**
|
||||
* The Crypt_DES objects
|
||||
*
|
||||
@ -150,40 +91,6 @@ class Crypt_TripleDES {
|
||||
*/
|
||||
var $des;
|
||||
|
||||
/**
|
||||
* mcrypt resource for encryption
|
||||
*
|
||||
* The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
|
||||
* Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
|
||||
*
|
||||
* @see Crypt_AES::encrypt()
|
||||
* @var String
|
||||
* @access private
|
||||
*/
|
||||
var $enmcrypt;
|
||||
|
||||
/**
|
||||
* mcrypt resource for decryption
|
||||
*
|
||||
* The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
|
||||
* Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
|
||||
*
|
||||
* @see Crypt_AES::decrypt()
|
||||
* @var String
|
||||
* @access private
|
||||
*/
|
||||
var $demcrypt;
|
||||
|
||||
/**
|
||||
* Does the (en|de)mcrypt resource need to be (re)initialized?
|
||||
*
|
||||
* @see setKey()
|
||||
* @see setIV()
|
||||
* @var Boolean
|
||||
* @access private
|
||||
*/
|
||||
var $changed = true;
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
*
|
||||
@ -198,10 +105,7 @@ class Crypt_TripleDES {
|
||||
{
|
||||
if ( !defined('CRYPT_DES_MODE') ) {
|
||||
switch (true) {
|
||||
case extension_loaded('mcrypt'):
|
||||
// i'd check to see if des was supported, by doing in_array('des', mcrypt_list_algorithms('')),
|
||||
// but since that can be changed after the object has been created, there doesn't seem to be
|
||||
// a lot of point...
|
||||
case extension_loaded('mcrypt') && in_array('tripledes', mcrypt_list_algorithms()):
|
||||
define('CRYPT_DES_MODE', CRYPT_DES_MODE_MCRYPT);
|
||||
break;
|
||||
default:
|
||||
@ -216,6 +120,7 @@ class Crypt_TripleDES {
|
||||
new Crypt_DES(CRYPT_DES_MODE_CBC),
|
||||
new Crypt_DES(CRYPT_DES_MODE_CBC)
|
||||
);
|
||||
$this->paddable = true;
|
||||
|
||||
// we're going to be doing the padding, ourselves, so disable it in the Crypt_DES objects
|
||||
$this->des[0]->disablePadding();
|
||||
@ -229,15 +134,26 @@ class Crypt_TripleDES {
|
||||
case CRYPT_DES_MODE_MCRYPT:
|
||||
switch ($mode) {
|
||||
case CRYPT_DES_MODE_ECB:
|
||||
$this->paddable = true;
|
||||
$this->mode = MCRYPT_MODE_ECB;
|
||||
break;
|
||||
case CRYPT_DES_MODE_CTR:
|
||||
$this->mode = 'ctr';
|
||||
break;
|
||||
case CRYPT_DES_MODE_CFB:
|
||||
$this->mode = 'ncfb';
|
||||
$this->ecb = mcrypt_module_open(MCRYPT_3DES, '', MCRYPT_MODE_ECB, '');
|
||||
break;
|
||||
case CRYPT_DES_MODE_OFB:
|
||||
$this->mode = MCRYPT_MODE_NOFB;
|
||||
break;
|
||||
case CRYPT_DES_MODE_CBC:
|
||||
default:
|
||||
$this->paddable = true;
|
||||
$this->mode = MCRYPT_MODE_CBC;
|
||||
}
|
||||
$this->enmcrypt = mcrypt_module_open(MCRYPT_3DES, '', $this->mode, '');
|
||||
$this->demcrypt = mcrypt_module_open(MCRYPT_3DES, '', $this->mode, '');
|
||||
|
||||
break;
|
||||
default:
|
||||
@ -254,13 +170,23 @@ class Crypt_TripleDES {
|
||||
|
||||
switch ($mode) {
|
||||
case CRYPT_DES_MODE_ECB:
|
||||
case CRYPT_DES_MODE_CTR:
|
||||
case CRYPT_DES_MODE_CBC:
|
||||
$this->paddable = true;
|
||||
$this->mode = $mode;
|
||||
break;
|
||||
case CRYPT_DES_MODE_CTR:
|
||||
case CRYPT_DES_MODE_CFB:
|
||||
case CRYPT_DES_MODE_OFB:
|
||||
$this->mode = $mode;
|
||||
break;
|
||||
default:
|
||||
$this->paddable = true;
|
||||
$this->mode = CRYPT_DES_MODE_CBC;
|
||||
}
|
||||
if (function_exists('create_function') && is_callable('create_function')) {
|
||||
$this->inline_crypt_setup(3);
|
||||
$this->use_inline_crypt = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -285,6 +211,8 @@ class Crypt_TripleDES {
|
||||
// if $key is between 64 and 128-bits, use the first 64-bits as the last, per this:
|
||||
// http://php.net/function.mcrypt-encrypt#47973
|
||||
//$key = $length <= 16 ? substr_replace($key, substr($key, 0, 8), 16) : substr($key, 0, 24);
|
||||
} else {
|
||||
$key = str_pad($key, 8, chr(0));
|
||||
}
|
||||
$this->key = $key;
|
||||
switch (true) {
|
||||
@ -293,8 +221,76 @@ class Crypt_TripleDES {
|
||||
$this->des[0]->setKey(substr($key, 0, 8));
|
||||
$this->des[1]->setKey(substr($key, 8, 8));
|
||||
$this->des[2]->setKey(substr($key, 16, 8));
|
||||
|
||||
// Merge the three DES-1-dim-key-arrays for 3DES-inline-en/decrypting
|
||||
if ($this->use_inline_crypt && $this->mode != CRYPT_DES_MODE_3CBC) {
|
||||
$this->keys = array(
|
||||
CRYPT_DES_ENCRYPT_1DIM => array_merge(
|
||||
$this->des[0]->keys[CRYPT_DES_ENCRYPT_1DIM],
|
||||
$this->des[1]->keys[CRYPT_DES_DECRYPT_1DIM],
|
||||
$this->des[2]->keys[CRYPT_DES_ENCRYPT_1DIM]
|
||||
),
|
||||
CRYPT_DES_DECRYPT_1DIM => array_merge(
|
||||
$this->des[2]->keys[CRYPT_DES_DECRYPT_1DIM],
|
||||
$this->des[1]->keys[CRYPT_DES_ENCRYPT_1DIM],
|
||||
$this->des[0]->keys[CRYPT_DES_DECRYPT_1DIM]
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
$this->changed = true;
|
||||
$this->enchanged = $this->dechanged = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the password.
|
||||
*
|
||||
* Depending on what $method is set to, setPassword()'s (optional) parameters are as follows:
|
||||
* {@link http://en.wikipedia.org/wiki/PBKDF2 pbkdf2}:
|
||||
* $hash, $salt, $method
|
||||
*
|
||||
* @param String $password
|
||||
* @param optional String $method
|
||||
* @access public
|
||||
*/
|
||||
function setPassword($password, $method = 'pbkdf2')
|
||||
{
|
||||
$key = '';
|
||||
|
||||
switch ($method) {
|
||||
default: // 'pbkdf2'
|
||||
list(, , $hash, $salt, $count) = func_get_args();
|
||||
if (!isset($hash)) {
|
||||
$hash = 'sha1';
|
||||
}
|
||||
// WPA and WPA2 use the SSID as the salt
|
||||
if (!isset($salt)) {
|
||||
$salt = 'phpseclib';
|
||||
}
|
||||
// RFC2898#section-4.2 uses 1,000 iterations by default
|
||||
// WPA and WPA2 use 4,096.
|
||||
if (!isset($count)) {
|
||||
$count = 1000;
|
||||
}
|
||||
|
||||
if (!class_exists('Crypt_Hash')) {
|
||||
require_once('Crypt/Hash.php');
|
||||
}
|
||||
|
||||
$i = 1;
|
||||
while (strlen($key) < 24) { // $dkLen == 24
|
||||
$hmac = new Crypt_Hash();
|
||||
$hmac->setHash($hash);
|
||||
$hmac->setKey($password);
|
||||
$f = $u = $hmac->hash($salt . pack('N', $i++));
|
||||
for ($j = 2; $j <= $count; $j++) {
|
||||
$u = $hmac->hash($u);
|
||||
$f^= $u;
|
||||
}
|
||||
$key.= $f;
|
||||
}
|
||||
}
|
||||
|
||||
$this->setKey($key);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -314,45 +310,7 @@ class Crypt_TripleDES {
|
||||
$this->des[1]->setIV($iv);
|
||||
$this->des[2]->setIV($iv);
|
||||
}
|
||||
$this->changed = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate CTR XOR encryption key
|
||||
*
|
||||
* Encrypt the output of this and XOR it against the ciphertext / plaintext to get the
|
||||
* plaintext / ciphertext in CTR mode.
|
||||
*
|
||||
* @see Crypt_DES::decrypt()
|
||||
* @see Crypt_DES::encrypt()
|
||||
* @access public
|
||||
* @param Integer $length
|
||||
* @param String $iv
|
||||
*/
|
||||
function _generate_xor($length, &$iv)
|
||||
{
|
||||
$xor = '';
|
||||
$num_blocks = ($length + 7) >> 3;
|
||||
for ($i = 0; $i < $num_blocks; $i++) {
|
||||
$xor.= $iv;
|
||||
for ($j = 4; $j <= 8; $j+=4) {
|
||||
$temp = substr($iv, -$j, 4);
|
||||
switch ($temp) {
|
||||
case "\xFF\xFF\xFF\xFF":
|
||||
$iv = substr_replace($iv, "\x00\x00\x00\x00", -$j, 4);
|
||||
break;
|
||||
case "\x7F\xFF\xFF\xFF":
|
||||
$iv = substr_replace($iv, "\x80\x00\x00\x00", -$j, 4);
|
||||
break 2;
|
||||
default:
|
||||
extract(unpack('Ncount', $temp));
|
||||
$iv = substr_replace($iv, pack('N', $count + 1), -$j, 4);
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $xor;
|
||||
$this->enchanged = $this->dechanged = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -363,7 +321,7 @@ class Crypt_TripleDES {
|
||||
*/
|
||||
function encrypt($plaintext)
|
||||
{
|
||||
if ($this->mode != CRYPT_DES_MODE_CTR && $this->mode != 'ctr') {
|
||||
if ($this->paddable) {
|
||||
$plaintext = $this->_pad($plaintext);
|
||||
}
|
||||
|
||||
@ -375,15 +333,66 @@ class Crypt_TripleDES {
|
||||
}
|
||||
|
||||
if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) {
|
||||
if ($this->changed) {
|
||||
if (!isset($this->enmcrypt)) {
|
||||
$this->enmcrypt = mcrypt_module_open(MCRYPT_3DES, '', $this->mode, '');
|
||||
}
|
||||
if ($this->enchanged) {
|
||||
mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
|
||||
$this->changed = false;
|
||||
if ($this->mode == 'ncfb') {
|
||||
mcrypt_generic_init($this->ecb, $this->key, "\0\0\0\0\0\0\0\0");
|
||||
}
|
||||
$this->enchanged = false;
|
||||
}
|
||||
|
||||
$ciphertext = mcrypt_generic($this->enmcrypt, $plaintext);
|
||||
if ($this->mode != 'ncfb' || !$this->continuousBuffer) {
|
||||
$ciphertext = mcrypt_generic($this->enmcrypt, $plaintext);
|
||||
} else {
|
||||
$iv = &$this->encryptIV;
|
||||
$pos = &$this->enbuffer['pos'];
|
||||
$len = strlen($plaintext);
|
||||
$ciphertext = '';
|
||||
$i = 0;
|
||||
if ($pos) {
|
||||
$orig_pos = $pos;
|
||||
$max = 8 - $pos;
|
||||
if ($len >= $max) {
|
||||
$i = $max;
|
||||
$len-= $max;
|
||||
$pos = 0;
|
||||
} else {
|
||||
$i = $len;
|
||||
$pos+= $len;
|
||||
$len = 0;
|
||||
}
|
||||
$ciphertext = substr($iv, $orig_pos) ^ $plaintext;
|
||||
$iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
|
||||
$this->enbuffer['enmcrypt_init'] = true;
|
||||
}
|
||||
if ($len >= 8) {
|
||||
if ($this->enbuffer['enmcrypt_init'] === false || $len > 950) {
|
||||
if ($this->enbuffer['enmcrypt_init'] === true) {
|
||||
mcrypt_generic_init($this->enmcrypt, $this->key, $iv);
|
||||
$this->enbuffer['enmcrypt_init'] = false;
|
||||
}
|
||||
$ciphertext.= mcrypt_generic($this->enmcrypt, substr($plaintext, $i, $len - $len % 8));
|
||||
$iv = substr($ciphertext, -8);
|
||||
$i = strlen($ciphertext);
|
||||
$len%= 8;
|
||||
} else {
|
||||
while ($len >= 8) {
|
||||
$iv = mcrypt_generic($this->ecb, $iv) ^ substr($plaintext, $i, 8);
|
||||
$ciphertext.= $iv;
|
||||
$len-= 8;
|
||||
$i+= 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($len) {
|
||||
$iv = mcrypt_generic($this->ecb, $iv);
|
||||
$block = $iv ^ substr($plaintext, $i);
|
||||
$iv = substr_replace($iv, $block, 0, $len);
|
||||
$ciphertext.= $block;
|
||||
$pos = $len;
|
||||
}
|
||||
return $ciphertext;
|
||||
}
|
||||
|
||||
if (!$this->continuousBuffer) {
|
||||
mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
|
||||
@ -398,17 +407,26 @@ class Crypt_TripleDES {
|
||||
return $this->des[0]->encrypt($plaintext);
|
||||
}
|
||||
|
||||
// we pad with chr(0) since that's what mcrypt_generic does. to quote from http://php.net/function.mcrypt-generic :
|
||||
// "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));
|
||||
if ($this->use_inline_crypt) {
|
||||
$inline = $this->inline_crypt;
|
||||
return $inline('encrypt', $this, $plaintext);
|
||||
}
|
||||
|
||||
$des = $this->des;
|
||||
|
||||
$buffer = &$this->enbuffer;
|
||||
$continuousBuffer = $this->continuousBuffer;
|
||||
$ciphertext = '';
|
||||
switch ($this->mode) {
|
||||
case CRYPT_DES_MODE_ECB:
|
||||
for ($i = 0; $i < strlen($plaintext); $i+=8) {
|
||||
$block = substr($plaintext, $i, 8);
|
||||
// all of these _processBlock calls could, in theory, be put in a function - say Crypt_TripleDES::_ede_encrypt() or something.
|
||||
// only problem with that: it would slow encryption and decryption down. $this->des would have to be called every time that
|
||||
// function is called, instead of once for the whole string of text that's being encrypted, which would, in turn, make
|
||||
// encryption and decryption take more time, per this:
|
||||
//
|
||||
// http://blog.libssh2.org/index.php?/archives/21-Compiled-Variables.html
|
||||
$block = $des[0]->_processBlock($block, CRYPT_DES_ENCRYPT);
|
||||
$block = $des[1]->_processBlock($block, CRYPT_DES_DECRYPT);
|
||||
$block = $des[2]->_processBlock($block, CRYPT_DES_ENCRYPT);
|
||||
@ -431,16 +449,97 @@ class Crypt_TripleDES {
|
||||
break;
|
||||
case CRYPT_DES_MODE_CTR:
|
||||
$xor = $this->encryptIV;
|
||||
for ($i = 0; $i < strlen($plaintext); $i+=8) {
|
||||
$key = $this->_generate_xor(8, $xor);
|
||||
$key = $des[0]->_processBlock($key, CRYPT_DES_ENCRYPT);
|
||||
$key = $des[1]->_processBlock($key, CRYPT_DES_DECRYPT);
|
||||
$key = $des[2]->_processBlock($key, CRYPT_DES_ENCRYPT);
|
||||
$block = substr($plaintext, $i, 8);
|
||||
$ciphertext.= $block ^ $key;
|
||||
if (strlen($buffer['encrypted'])) {
|
||||
for ($i = 0; $i < strlen($plaintext); $i+=8) {
|
||||
$block = substr($plaintext, $i, 8);
|
||||
if (strlen($block) > strlen($buffer['encrypted'])) {
|
||||
$key = $this->_generate_xor($xor);
|
||||
$key = $des[0]->_processBlock($key, CRYPT_DES_ENCRYPT);
|
||||
$key = $des[1]->_processBlock($key, CRYPT_DES_DECRYPT);
|
||||
$key = $des[2]->_processBlock($key, CRYPT_DES_ENCRYPT);
|
||||
$buffer['encrypted'].= $key;
|
||||
}
|
||||
$key = $this->_string_shift($buffer['encrypted']);
|
||||
$ciphertext.= $block ^ $key;
|
||||
}
|
||||
} else {
|
||||
for ($i = 0; $i < strlen($plaintext); $i+=8) {
|
||||
$block = substr($plaintext, $i, 8);
|
||||
$key = $this->_generate_xor($xor);
|
||||
$key = $des[0]->_processBlock($key, CRYPT_DES_ENCRYPT);
|
||||
$key = $des[1]->_processBlock($key, CRYPT_DES_DECRYPT);
|
||||
$key = $des[2]->_processBlock($key, CRYPT_DES_ENCRYPT);
|
||||
$ciphertext.= $block ^ $key;
|
||||
}
|
||||
}
|
||||
if ($this->continuousBuffer) {
|
||||
$this->encryptIV = $xor;
|
||||
if ($start = strlen($plaintext) & 7) {
|
||||
$buffer['encrypted'] = substr($key, $start) . $buffer['encrypted'];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CRYPT_DES_MODE_CFB:
|
||||
if (strlen($buffer['xor'])) {
|
||||
$ciphertext = $plaintext ^ $buffer['xor'];
|
||||
$iv = $buffer['encrypted'] . $ciphertext;
|
||||
$start = strlen($ciphertext);
|
||||
$buffer['encrypted'].= $ciphertext;
|
||||
$buffer['xor'] = substr($buffer['xor'], strlen($ciphertext));
|
||||
} else {
|
||||
$ciphertext = '';
|
||||
$iv = $this->encryptIV;
|
||||
$start = 0;
|
||||
}
|
||||
|
||||
for ($i = $start; $i < strlen($plaintext); $i+=8) {
|
||||
$block = substr($plaintext, $i, 8);
|
||||
$iv = $des[0]->_processBlock($iv, CRYPT_DES_ENCRYPT);
|
||||
$iv = $des[1]->_processBlock($iv, CRYPT_DES_DECRYPT);
|
||||
$xor= $des[2]->_processBlock($iv, CRYPT_DES_ENCRYPT);
|
||||
|
||||
$iv = $block ^ $xor;
|
||||
if ($continuousBuffer && strlen($iv) != 8) {
|
||||
$buffer = array(
|
||||
'encrypted' => $iv,
|
||||
'xor' => substr($xor, strlen($iv))
|
||||
);
|
||||
}
|
||||
$ciphertext.= $iv;
|
||||
}
|
||||
|
||||
if ($this->continuousBuffer) {
|
||||
$this->encryptIV = $iv;
|
||||
}
|
||||
break;
|
||||
case CRYPT_DES_MODE_OFB:
|
||||
$xor = $this->encryptIV;
|
||||
if (strlen($buffer['xor'])) {
|
||||
for ($i = 0; $i < strlen($plaintext); $i+=8) {
|
||||
$block = substr($plaintext, $i, 8);
|
||||
if (strlen($block) > strlen($buffer['xor'])) {
|
||||
$xor = $des[0]->_processBlock($xor, CRYPT_DES_ENCRYPT);
|
||||
$xor = $des[1]->_processBlock($xor, CRYPT_DES_DECRYPT);
|
||||
$xor = $des[2]->_processBlock($xor, CRYPT_DES_ENCRYPT);
|
||||
$buffer['xor'].= $xor;
|
||||
}
|
||||
$key = $this->_string_shift($buffer['xor']);
|
||||
$ciphertext.= $block ^ $key;
|
||||
}
|
||||
} else {
|
||||
for ($i = 0; $i < strlen($plaintext); $i+=8) {
|
||||
$xor = $des[0]->_processBlock($xor, CRYPT_DES_ENCRYPT);
|
||||
$xor = $des[1]->_processBlock($xor, CRYPT_DES_DECRYPT);
|
||||
$xor = $des[2]->_processBlock($xor, CRYPT_DES_ENCRYPT);
|
||||
$ciphertext.= substr($plaintext, $i, 8) ^ $xor;
|
||||
}
|
||||
$key = $xor;
|
||||
}
|
||||
if ($this->continuousBuffer) {
|
||||
$this->encryptIV = $xor;
|
||||
if ($start = strlen($plaintext) & 7) {
|
||||
$buffer['xor'] = substr($key, $start) . $buffer['xor'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -461,36 +560,82 @@ class Crypt_TripleDES {
|
||||
return $this->_unpad($plaintext);
|
||||
}
|
||||
|
||||
// we pad with chr(0) since that's what mcrypt_generic does. to quote from http://php.net/function.mcrypt-generic :
|
||||
// "The data is padded with "\0" to make sure the length of the data is n * blocksize."
|
||||
$ciphertext = str_pad($ciphertext, (strlen($ciphertext) + 7) & 0xFFFFFFF8, chr(0));
|
||||
if ($this->paddable) {
|
||||
// we pad with chr(0) since that's what mcrypt_generic does. to quote from http://php.net/function.mcrypt-generic :
|
||||
// "The data is padded with "\0" to make sure the length of the data is n * blocksize."
|
||||
$ciphertext = str_pad($ciphertext, (strlen($ciphertext) + 7) & 0xFFFFFFF8, chr(0));
|
||||
}
|
||||
|
||||
if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) {
|
||||
if ($this->changed) {
|
||||
if (!isset($this->demcrypt)) {
|
||||
$this->demcrypt = mcrypt_module_open(MCRYPT_3DES, '', $this->mode, '');
|
||||
}
|
||||
if ($this->dechanged) {
|
||||
mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
|
||||
$this->changed = false;
|
||||
if ($this->mode == 'ncfb') {
|
||||
mcrypt_generic_init($this->ecb, $this->key, "\0\0\0\0\0\0\0\0");
|
||||
}
|
||||
$this->dechanged = false;
|
||||
}
|
||||
|
||||
$plaintext = mdecrypt_generic($this->demcrypt, $ciphertext);
|
||||
if ($this->mode != 'ncfb' || !$this->continuousBuffer) {
|
||||
$plaintext = mdecrypt_generic($this->demcrypt, $ciphertext);
|
||||
} else {
|
||||
$iv = &$this->decryptIV;
|
||||
$pos = &$this->debuffer['pos'];
|
||||
$len = strlen($ciphertext);
|
||||
$plaintext = '';
|
||||
$i = 0;
|
||||
if ($pos) {
|
||||
$orig_pos = $pos;
|
||||
$max = 8 - $pos;
|
||||
if ($len >= $max) {
|
||||
$i = $max;
|
||||
$len-= $max;
|
||||
$pos = 0;
|
||||
} else {
|
||||
$i = $len;
|
||||
$pos+= $len;
|
||||
$len = 0;
|
||||
}
|
||||
$plaintext = substr($iv, $orig_pos) ^ $ciphertext;
|
||||
$iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
|
||||
}
|
||||
if ($len >= 8) {
|
||||
$cb = substr($ciphertext, $i, $len - $len % 8);
|
||||
$plaintext.= mcrypt_generic($this->ecb, $iv . $cb) ^ $cb;
|
||||
$iv = substr($cb, -8);
|
||||
$len%= 8;
|
||||
}
|
||||
if ($len) {
|
||||
$iv = mcrypt_generic($this->ecb, $iv);
|
||||
$cb = substr($ciphertext, -$len);
|
||||
$plaintext.= $iv ^ $cb;
|
||||
$iv = substr_replace($iv, $cb, 0, $len);
|
||||
$pos = $len;
|
||||
}
|
||||
return $plaintext;
|
||||
}
|
||||
|
||||
if (!$this->continuousBuffer) {
|
||||
mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
|
||||
}
|
||||
|
||||
return $this->mode != 'ctr' ? $this->_unpad($plaintext) : $plaintext;
|
||||
return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
|
||||
}
|
||||
|
||||
if (strlen($this->key) <= 8) {
|
||||
$this->des[0]->mode = $this->mode;
|
||||
$plaintext = $this->des[0]->decrypt($ciphertext);
|
||||
return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
|
||||
}
|
||||
|
||||
return $this->_unpad($this->des[0]->decrypt($plaintext));
|
||||
if ($this->use_inline_crypt) {
|
||||
$inline = $this->inline_crypt;
|
||||
return $inline('decrypt', $this, $ciphertext);
|
||||
}
|
||||
|
||||
$des = $this->des;
|
||||
|
||||
$buffer = &$this->debuffer;
|
||||
$continuousBuffer = $this->continuousBuffer;
|
||||
$plaintext = '';
|
||||
switch ($this->mode) {
|
||||
case CRYPT_DES_MODE_ECB:
|
||||
@ -518,20 +663,106 @@ class Crypt_TripleDES {
|
||||
break;
|
||||
case CRYPT_DES_MODE_CTR:
|
||||
$xor = $this->decryptIV;
|
||||
for ($i = 0; $i < strlen($ciphertext); $i+=8) {
|
||||
$key = $this->_generate_xor(8, $xor);
|
||||
$key = $des[0]->_processBlock($key, CRYPT_DES_ENCRYPT);
|
||||
$key = $des[1]->_processBlock($key, CRYPT_DES_DECRYPT);
|
||||
$key = $des[2]->_processBlock($key, CRYPT_DES_ENCRYPT);
|
||||
$block = substr($ciphertext, $i, 8);
|
||||
$plaintext.= $block ^ $key;
|
||||
if (strlen($buffer['ciphertext'])) {
|
||||
for ($i = 0; $i < strlen($ciphertext); $i+=8) {
|
||||
$block = substr($ciphertext, $i, 8);
|
||||
if (strlen($block) > strlen($buffer['ciphertext'])) {
|
||||
$key = $this->_generate_xor($xor);
|
||||
$key = $des[0]->_processBlock($key, CRYPT_DES_ENCRYPT);
|
||||
$key = $des[1]->_processBlock($key, CRYPT_DES_DECRYPT);
|
||||
$key = $des[2]->_processBlock($key, CRYPT_DES_ENCRYPT);
|
||||
$buffer['ciphertext'].= $key;
|
||||
}
|
||||
$key = $this->_string_shift($buffer['ciphertext']);
|
||||
$plaintext.= $block ^ $key;
|
||||
}
|
||||
} else {
|
||||
for ($i = 0; $i < strlen($ciphertext); $i+=8) {
|
||||
$block = substr($ciphertext, $i, 8);
|
||||
$key = $this->_generate_xor($xor);
|
||||
$key = $des[0]->_processBlock($key, CRYPT_DES_ENCRYPT);
|
||||
$key = $des[1]->_processBlock($key, CRYPT_DES_DECRYPT);
|
||||
$key = $des[2]->_processBlock($key, CRYPT_DES_ENCRYPT);
|
||||
$plaintext.= $block ^ $key;
|
||||
}
|
||||
}
|
||||
if ($this->continuousBuffer) {
|
||||
$this->decryptIV = $xor;
|
||||
if ($start = strlen($plaintext) & 7) {
|
||||
$buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext'];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CRYPT_DES_MODE_CFB:
|
||||
if (strlen($buffer['ciphertext'])) {
|
||||
$plaintext = $ciphertext ^ substr($this->decryptIV, strlen($buffer['ciphertext']));
|
||||
$buffer['ciphertext'].= substr($ciphertext, 0, strlen($plaintext));
|
||||
if (strlen($buffer['ciphertext']) != 8) {
|
||||
$block = $this->decryptIV;
|
||||
} else {
|
||||
$block = $buffer['ciphertext'];
|
||||
$xor = $des[0]->_processBlock($buffer['ciphertext'], CRYPT_DES_ENCRYPT);
|
||||
$xor = $des[1]->_processBlock($xor, CRYPT_DES_DECRYPT);
|
||||
$xor = $des[2]->_processBlock($xor, CRYPT_DES_ENCRYPT);
|
||||
$buffer['ciphertext'] = '';
|
||||
}
|
||||
$start = strlen($plaintext);
|
||||
} else {
|
||||
$plaintext = '';
|
||||
$xor = $des[0]->_processBlock($this->decryptIV, CRYPT_DES_ENCRYPT);
|
||||
$xor = $des[1]->_processBlock($xor, CRYPT_DES_DECRYPT);
|
||||
$xor = $des[2]->_processBlock($xor, CRYPT_DES_ENCRYPT);
|
||||
$start = 0;
|
||||
}
|
||||
|
||||
for ($i = $start; $i < strlen($ciphertext); $i+=8) {
|
||||
$block = substr($ciphertext, $i, 8);
|
||||
$plaintext.= $block ^ $xor;
|
||||
if ($continuousBuffer && strlen($block) != 8) {
|
||||
$buffer['ciphertext'].= $block;
|
||||
$block = $xor;
|
||||
} else if (strlen($block) == 8) {
|
||||
$xor = $des[0]->_processBlock($block, CRYPT_DES_ENCRYPT);
|
||||
$xor = $des[1]->_processBlock($xor, CRYPT_DES_DECRYPT);
|
||||
$xor = $des[2]->_processBlock($xor, CRYPT_DES_ENCRYPT);
|
||||
}
|
||||
}
|
||||
if ($this->continuousBuffer) {
|
||||
$this->decryptIV = $block;
|
||||
}
|
||||
break;
|
||||
case CRYPT_DES_MODE_OFB:
|
||||
$xor = $this->decryptIV;
|
||||
if (strlen($buffer['xor'])) {
|
||||
for ($i = 0; $i < strlen($ciphertext); $i+=8) {
|
||||
$block = substr($ciphertext, $i, 8);
|
||||
if (strlen($block) > strlen($buffer['xor'])) {
|
||||
$xor = $des[0]->_processBlock($xor, CRYPT_DES_ENCRYPT);
|
||||
$xor = $des[1]->_processBlock($xor, CRYPT_DES_DECRYPT);
|
||||
$xor = $des[2]->_processBlock($xor, CRYPT_DES_ENCRYPT);
|
||||
$buffer['xor'].= $xor;
|
||||
}
|
||||
$key = $this->_string_shift($buffer['xor']);
|
||||
$plaintext.= $block ^ $key;
|
||||
}
|
||||
} else {
|
||||
for ($i = 0; $i < strlen($ciphertext); $i+=8) {
|
||||
$xor = $des[0]->_processBlock($xor, CRYPT_DES_ENCRYPT);
|
||||
$xor = $des[1]->_processBlock($xor, CRYPT_DES_DECRYPT);
|
||||
$xor = $des[2]->_processBlock($xor, CRYPT_DES_ENCRYPT);
|
||||
$plaintext.= substr($ciphertext, $i, 8) ^ $xor;
|
||||
}
|
||||
$key = $xor;
|
||||
}
|
||||
if ($this->continuousBuffer) {
|
||||
$this->decryptIV = $xor;
|
||||
if ($start = strlen($ciphertext) & 7) {
|
||||
$buffer['xor'] = substr($key, $start) . $buffer['xor'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->mode != CRYPT_DES_MODE_CTR ? $this->_unpad($plaintext) : $plaintext;
|
||||
return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -594,6 +825,10 @@ class Crypt_TripleDES {
|
||||
$this->continuousBuffer = false;
|
||||
$this->encryptIV = $this->iv;
|
||||
$this->decryptIV = $this->iv;
|
||||
$this->enchanged = true;
|
||||
$this->dechanged = true;
|
||||
$this->enbuffer = array('encrypted' => '', 'xor' => '', 'pos' => 0, 'enmcrypt_init' => true);
|
||||
$this->debuffer = array('ciphertext' => '', 'xor' => '', 'pos' => 0, 'demcrypt_init' => true);
|
||||
|
||||
if ($this->mode == CRYPT_DES_MODE_3CBC) {
|
||||
$this->des[0]->disableContinuousBuffer();
|
||||
@ -601,89 +836,6 @@ class Crypt_TripleDES {
|
||||
$this->des[2]->disableContinuousBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pad "packets".
|
||||
*
|
||||
* DES works by encrypting eight bytes at a time. If you ever need to encrypt or decrypt something that's not
|
||||
* a multiple of eight, it becomes necessary to pad the input so that it's length is a multiple of eight.
|
||||
*
|
||||
* Padding is enabled by default. Sometimes, however, it is undesirable to pad strings. Such is the case in SSH1,
|
||||
* where "packets" are padded with random bytes before being encrypted. Unpad these packets and you risk stripping
|
||||
* away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is
|
||||
* transmitted separately)
|
||||
*
|
||||
* @see Crypt_TripleDES::disablePadding()
|
||||
* @access public
|
||||
*/
|
||||
function enablePadding()
|
||||
{
|
||||
$this->padding = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not pad packets.
|
||||
*
|
||||
* @see Crypt_TripleDES::enablePadding()
|
||||
* @access public
|
||||
*/
|
||||
function disablePadding()
|
||||
{
|
||||
$this->padding = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pads a string
|
||||
*
|
||||
* Pads a string using the RSA PKCS padding standards so that its length is a multiple of the blocksize (8).
|
||||
* 8 - (strlen($text) & 7) bytes are added, each of which is equal to chr(8 - (strlen($text) & 7)
|
||||
*
|
||||
* If padding is disabled and $text is not a multiple of the blocksize, the string will be padded regardless
|
||||
* and padding will, hence forth, be enabled.
|
||||
*
|
||||
* @see Crypt_TripleDES::_unpad()
|
||||
* @access private
|
||||
*/
|
||||
function _pad($text)
|
||||
{
|
||||
$length = strlen($text);
|
||||
|
||||
if (!$this->padding) {
|
||||
if (($length & 7) == 0) {
|
||||
return $text;
|
||||
} else {
|
||||
user_error("The plaintext's length ($length) is not a multiple of the block size (8)", E_USER_NOTICE);
|
||||
$this->padding = true;
|
||||
}
|
||||
}
|
||||
|
||||
$pad = 8 - ($length & 7);
|
||||
return str_pad($text, $length + $pad, chr($pad));
|
||||
}
|
||||
|
||||
/**
|
||||
* Unpads a string
|
||||
*
|
||||
* If padding is enabled and the reported padding length is invalid the encryption key will be assumed to be wrong
|
||||
* and false will be returned.
|
||||
*
|
||||
* @see Crypt_TripleDES::_pad()
|
||||
* @access private
|
||||
*/
|
||||
function _unpad($text)
|
||||
{
|
||||
if (!$this->padding) {
|
||||
return $text;
|
||||
}
|
||||
|
||||
$length = ord($text[strlen($text) - 1]);
|
||||
|
||||
if (!$length || $length > 8) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return substr($text, 0, -$length);
|
||||
}
|
||||
}
|
||||
|
||||
// vim: ts=4:sw=4:et:
|
||||
|
1664
plugins/OStatus/extlib/Crypt/Twofish.php
Normal file
1664
plugins/OStatus/extlib/Crypt/Twofish.php
Normal file
File diff suppressed because it is too large
Load Diff
@ -47,27 +47,29 @@
|
||||
* ?>
|
||||
* </code>
|
||||
*
|
||||
* LICENSE: This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @category Math
|
||||
* @package Math_BigInteger
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright MMVI Jim Wigginton
|
||||
* @license http://www.gnu.org/licenses/lgpl.txt
|
||||
* @version $Id: BigInteger.php,v 1.33 2010/03/22 22:32:03 terrafrost Exp $
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://pear.php.net/package/Math_BigInteger
|
||||
*/
|
||||
|
||||
@ -159,16 +161,6 @@ define('MATH_BIGINTEGER_MODE_BCMATH', 2);
|
||||
define('MATH_BIGINTEGER_MODE_GMP', 3);
|
||||
/**#@-*/
|
||||
|
||||
/**
|
||||
* The largest digit that may be used in addition / subtraction
|
||||
*
|
||||
* (we do pow(2, 52) instead of using 4503599627370496, directly, because some PHP installations
|
||||
* will truncate 4503599627370496)
|
||||
*
|
||||
* @access private
|
||||
*/
|
||||
define('MATH_BIGINTEGER_MAX_DIGIT52', pow(2, 52));
|
||||
|
||||
/**
|
||||
* Karatsuba Cutoff
|
||||
*
|
||||
@ -229,7 +221,7 @@ class Math_BigInteger {
|
||||
var $bitmask = false;
|
||||
|
||||
/**
|
||||
* Mode independant value used for serialization.
|
||||
* Mode independent value used for serialization.
|
||||
*
|
||||
* If the bcmath or gmp extensions are installed $this->value will be a non-serializable resource, hence the need for
|
||||
* a variable that'll be serializable regardless of whether or not extensions are being used. Unlike $this->value,
|
||||
@ -243,20 +235,20 @@ class Math_BigInteger {
|
||||
var $hex;
|
||||
|
||||
/**
|
||||
* Converts base-2, base-10, base-16, and binary strings (eg. base-256) to BigIntegers.
|
||||
* Converts base-2, base-10, base-16, and binary strings (base-256) to BigIntegers.
|
||||
*
|
||||
* If the second parameter - $base - is negative, then it will be assumed that the number's are encoded using
|
||||
* two's compliment. The sole exception to this is -10, which is treated the same as 10 is.
|
||||
*
|
||||
* Here's an example:
|
||||
* <code>
|
||||
* <?php
|
||||
* <?php
|
||||
* include('Math/BigInteger.php');
|
||||
*
|
||||
* $a = new Math_BigInteger('0x32', 16); // 50 in base-16
|
||||
*
|
||||
* echo $a->toString(); // outputs 50
|
||||
* ?>
|
||||
* ?>
|
||||
* </code>
|
||||
*
|
||||
* @param optional $x base-10 number or base-$base number if $base set.
|
||||
@ -279,6 +271,43 @@ class Math_BigInteger {
|
||||
}
|
||||
}
|
||||
|
||||
if (function_exists('openssl_public_encrypt') && !defined('MATH_BIGINTEGER_OPENSSL_DISABLE') && !defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) {
|
||||
define('MATH_BIGINTEGER_OPENSSL_ENABLED', true);
|
||||
}
|
||||
|
||||
if (!defined('PHP_INT_SIZE')) {
|
||||
define('PHP_INT_SIZE', 4);
|
||||
}
|
||||
|
||||
if (!defined('MATH_BIGINTEGER_BASE') && MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_INTERNAL) {
|
||||
switch (PHP_INT_SIZE) {
|
||||
case 8: // use 64-bit integers if int size is 8 bytes
|
||||
define('MATH_BIGINTEGER_BASE', 31);
|
||||
define('MATH_BIGINTEGER_BASE_FULL', 0x80000000);
|
||||
define('MATH_BIGINTEGER_MAX_DIGIT', 0x7FFFFFFF);
|
||||
define('MATH_BIGINTEGER_MSB', 0x40000000);
|
||||
// 10**9 is the closest we can get to 2**31 without passing it
|
||||
define('MATH_BIGINTEGER_MAX10', 1000000000);
|
||||
define('MATH_BIGINTEGER_MAX10_LEN', 9);
|
||||
// the largest digit that may be used in addition / subtraction
|
||||
define('MATH_BIGINTEGER_MAX_DIGIT2', pow(2, 62));
|
||||
break;
|
||||
//case 4: // use 64-bit floats if int size is 4 bytes
|
||||
default:
|
||||
define('MATH_BIGINTEGER_BASE', 26);
|
||||
define('MATH_BIGINTEGER_BASE_FULL', 0x4000000);
|
||||
define('MATH_BIGINTEGER_MAX_DIGIT', 0x3FFFFFF);
|
||||
define('MATH_BIGINTEGER_MSB', 0x2000000);
|
||||
// 10**7 is the closest to 2**26 without passing it
|
||||
define('MATH_BIGINTEGER_MAX10', 10000000);
|
||||
define('MATH_BIGINTEGER_MAX10_LEN', 7);
|
||||
// the largest digit that may be used in addition / subtraction
|
||||
// we do pow(2, 52) instead of using 4503599627370496 directly because some
|
||||
// PHP installations will truncate 4503599627370496.
|
||||
define('MATH_BIGINTEGER_MAX_DIGIT2', pow(2, 52));
|
||||
}
|
||||
}
|
||||
|
||||
switch ( MATH_BIGINTEGER_MODE ) {
|
||||
case MATH_BIGINTEGER_MODE_GMP:
|
||||
if (is_resource($x) && get_resource_type($x) == 'GMP integer') {
|
||||
@ -294,7 +323,9 @@ class Math_BigInteger {
|
||||
$this->value = array();
|
||||
}
|
||||
|
||||
if (empty($x)) {
|
||||
// '0' counts as empty() but when the base is 256 '0' is equal to ord('0') or 48
|
||||
// '0' is the only value like this per http://php.net/empty
|
||||
if (empty($x) && (abs($base) != 256 || $x !== '0')) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -329,7 +360,7 @@ class Math_BigInteger {
|
||||
// converts a base-2**8 (big endian / msb) number to base-2**26 (little endian / lsb)
|
||||
default:
|
||||
while (strlen($x)) {
|
||||
$this->value[] = $this->_bytes2int($this->_base256_rshift($x, 26));
|
||||
$this->value[] = $this->_bytes2int($this->_base256_rshift($x, MATH_BIGINTEGER_BASE));
|
||||
}
|
||||
}
|
||||
|
||||
@ -381,7 +412,10 @@ class Math_BigInteger {
|
||||
break;
|
||||
case 10:
|
||||
case -10:
|
||||
$x = preg_replace('#^(-?[0-9]*).*#', '$1', $x);
|
||||
// (?<!^)(?:-).*: find any -'s that aren't at the beginning and then any characters that follow that
|
||||
// (?<=^|-)0*: find any 0's that are preceded by the start of the string or by a - (ie. octals)
|
||||
// [^-0-9].*: find any non-numeric characters and then any characters that follow that
|
||||
$x = preg_replace('#(?<!^)(?:-).*|(?<=^|-)0*|[^-0-9].*#', '', $x);
|
||||
|
||||
switch ( MATH_BIGINTEGER_MODE ) {
|
||||
case MATH_BIGINTEGER_MODE_GMP:
|
||||
@ -390,26 +424,25 @@ class Math_BigInteger {
|
||||
case MATH_BIGINTEGER_MODE_BCMATH:
|
||||
// explicitly casting $x to a string is necessary, here, since doing $x[0] on -1 yields different
|
||||
// results then doing it on '-1' does (modInverse does $x[0])
|
||||
$this->value = (string) $x;
|
||||
$this->value = $x === '-' ? '0' : (string) $x;
|
||||
break;
|
||||
default:
|
||||
$temp = new Math_BigInteger();
|
||||
|
||||
// array(10000000) is 10**7 in base-2**26. 10**7 is the closest to 2**26 we can get without passing it.
|
||||
$multiplier = new Math_BigInteger();
|
||||
$multiplier->value = array(10000000);
|
||||
$multiplier->value = array(MATH_BIGINTEGER_MAX10);
|
||||
|
||||
if ($x[0] == '-') {
|
||||
$this->is_negative = true;
|
||||
$x = substr($x, 1);
|
||||
}
|
||||
|
||||
$x = str_pad($x, strlen($x) + (6 * strlen($x)) % 7, 0, STR_PAD_LEFT);
|
||||
$x = str_pad($x, strlen($x) + ((MATH_BIGINTEGER_MAX10_LEN - 1) * strlen($x)) % MATH_BIGINTEGER_MAX10_LEN, 0, STR_PAD_LEFT);
|
||||
|
||||
while (strlen($x)) {
|
||||
$temp = $temp->multiply($multiplier);
|
||||
$temp = $temp->add(new Math_BigInteger($this->_int2bytes(substr($x, 0, 7)), 256));
|
||||
$x = substr($x, 7);
|
||||
$temp = $temp->add(new Math_BigInteger($this->_int2bytes(substr($x, 0, MATH_BIGINTEGER_MAX10_LEN)), 256));
|
||||
$x = substr($x, MATH_BIGINTEGER_MAX10_LEN);
|
||||
}
|
||||
|
||||
$this->value = $temp->value;
|
||||
@ -534,7 +567,7 @@ class Math_BigInteger {
|
||||
$temp = $this->copy();
|
||||
|
||||
for ($i = count($temp->value) - 2; $i >= 0; --$i) {
|
||||
$temp->_base256_lshift($result, 26);
|
||||
$temp->_base256_lshift($result, MATH_BIGINTEGER_BASE);
|
||||
$result = $result | str_pad($temp->_int2bytes($temp->value[$i]), strlen($result), chr(0), STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
@ -596,10 +629,19 @@ class Math_BigInteger {
|
||||
{
|
||||
$hex = $this->toHex($twos_compliment);
|
||||
$bits = '';
|
||||
for ($i = 0; $i < strlen($hex); $i+=8) {
|
||||
$bits.= str_pad(decbin(hexdec(substr($hex, $i, 8))), 32, '0', STR_PAD_LEFT);
|
||||
for ($i = strlen($hex) - 8, $start = strlen($hex) & 7; $i >= $start; $i-=8) {
|
||||
$bits = str_pad(decbin(hexdec(substr($hex, $i, 8))), 32, '0', STR_PAD_LEFT) . $bits;
|
||||
}
|
||||
return $this->precision > 0 ? substr($bits, -$this->precision) : ltrim($bits, '0');
|
||||
if ($start) { // hexdec('') == 0
|
||||
$bits = str_pad(decbin(hexdec(substr($hex, 0, $start))), 8, '0', STR_PAD_LEFT) . $bits;
|
||||
}
|
||||
$result = $this->precision > 0 ? substr($bits, -$this->precision) : ltrim($bits, '0');
|
||||
|
||||
if ($twos_compliment && $this->compare(new Math_BigInteger()) > 0 && $this->precision <= 0) {
|
||||
return '0' . $result;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -641,11 +683,11 @@ class Math_BigInteger {
|
||||
$temp->is_negative = false;
|
||||
|
||||
$divisor = new Math_BigInteger();
|
||||
$divisor->value = array(10000000); // eg. 10**7
|
||||
$divisor->value = array(MATH_BIGINTEGER_MAX10);
|
||||
$result = '';
|
||||
while (count($temp->value)) {
|
||||
list($temp, $mod) = $temp->divide($divisor);
|
||||
$result = str_pad(isset($mod->value[0]) ? $mod->value[0] : '', 7, '0', STR_PAD_LEFT) . $result;
|
||||
$result = str_pad(isset($mod->value[0]) ? $mod->value[0] : '', MATH_BIGINTEGER_MAX10_LEN, '0', STR_PAD_LEFT) . $result;
|
||||
}
|
||||
$result = ltrim($result, '0');
|
||||
if (empty($result)) {
|
||||
@ -856,25 +898,25 @@ class Math_BigInteger {
|
||||
|
||||
$carry = 0;
|
||||
for ($i = 0, $j = 1; $j < $size; $i+=2, $j+=2) {
|
||||
$sum = $x_value[$j] * 0x4000000 + $x_value[$i] + $y_value[$j] * 0x4000000 + $y_value[$i] + $carry;
|
||||
$carry = $sum >= MATH_BIGINTEGER_MAX_DIGIT52; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1
|
||||
$sum = $carry ? $sum - MATH_BIGINTEGER_MAX_DIGIT52 : $sum;
|
||||
$sum = $x_value[$j] * MATH_BIGINTEGER_BASE_FULL + $x_value[$i] + $y_value[$j] * MATH_BIGINTEGER_BASE_FULL + $y_value[$i] + $carry;
|
||||
$carry = $sum >= MATH_BIGINTEGER_MAX_DIGIT2; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1
|
||||
$sum = $carry ? $sum - MATH_BIGINTEGER_MAX_DIGIT2 : $sum;
|
||||
|
||||
$temp = (int) ($sum / 0x4000000);
|
||||
$temp = (int) ($sum / MATH_BIGINTEGER_BASE_FULL);
|
||||
|
||||
$value[$i] = (int) ($sum - 0x4000000 * $temp); // eg. a faster alternative to fmod($sum, 0x4000000)
|
||||
$value[$i] = (int) ($sum - MATH_BIGINTEGER_BASE_FULL * $temp); // eg. a faster alternative to fmod($sum, 0x4000000)
|
||||
$value[$j] = $temp;
|
||||
}
|
||||
|
||||
if ($j == $size) { // ie. if $y_size is odd
|
||||
$sum = $x_value[$i] + $y_value[$i] + $carry;
|
||||
$carry = $sum >= 0x4000000;
|
||||
$value[$i] = $carry ? $sum - 0x4000000 : $sum;
|
||||
$carry = $sum >= MATH_BIGINTEGER_BASE_FULL;
|
||||
$value[$i] = $carry ? $sum - MATH_BIGINTEGER_BASE_FULL : $sum;
|
||||
++$i; // ie. let $i = $j since we've just done $value[$i]
|
||||
}
|
||||
|
||||
if ($carry) {
|
||||
for (; $value[$i] == 0x3FFFFFF; ++$i) {
|
||||
for (; $value[$i] == MATH_BIGINTEGER_MAX_DIGIT; ++$i) {
|
||||
$value[$i] = 0;
|
||||
}
|
||||
++$value[$i];
|
||||
@ -992,26 +1034,26 @@ class Math_BigInteger {
|
||||
|
||||
$carry = 0;
|
||||
for ($i = 0, $j = 1; $j < $y_size; $i+=2, $j+=2) {
|
||||
$sum = $x_value[$j] * 0x4000000 + $x_value[$i] - $y_value[$j] * 0x4000000 - $y_value[$i] - $carry;
|
||||
$sum = $x_value[$j] * MATH_BIGINTEGER_BASE_FULL + $x_value[$i] - $y_value[$j] * MATH_BIGINTEGER_BASE_FULL - $y_value[$i] - $carry;
|
||||
$carry = $sum < 0; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1
|
||||
$sum = $carry ? $sum + MATH_BIGINTEGER_MAX_DIGIT52 : $sum;
|
||||
$sum = $carry ? $sum + MATH_BIGINTEGER_MAX_DIGIT2 : $sum;
|
||||
|
||||
$temp = (int) ($sum / 0x4000000);
|
||||
$temp = (int) ($sum / MATH_BIGINTEGER_BASE_FULL);
|
||||
|
||||
$x_value[$i] = (int) ($sum - 0x4000000 * $temp);
|
||||
$x_value[$i] = (int) ($sum - MATH_BIGINTEGER_BASE_FULL * $temp);
|
||||
$x_value[$j] = $temp;
|
||||
}
|
||||
|
||||
if ($j == $y_size) { // ie. if $y_size is odd
|
||||
$sum = $x_value[$i] - $y_value[$i] - $carry;
|
||||
$carry = $sum < 0;
|
||||
$x_value[$i] = $carry ? $sum + 0x4000000 : $sum;
|
||||
$x_value[$i] = $carry ? $sum + MATH_BIGINTEGER_BASE_FULL : $sum;
|
||||
++$i;
|
||||
}
|
||||
|
||||
if ($carry) {
|
||||
for (; !$x_value[$i]; ++$i) {
|
||||
$x_value[$i] = 0x3FFFFFF;
|
||||
$x_value[$i] = MATH_BIGINTEGER_MAX_DIGIT;
|
||||
}
|
||||
--$x_value[$i];
|
||||
}
|
||||
@ -1144,8 +1186,8 @@ class Math_BigInteger {
|
||||
|
||||
for ($j = 0; $j < $x_length; ++$j) { // ie. $i = 0
|
||||
$temp = $x_value[$j] * $y_value[0] + $carry; // $product_value[$k] == 0
|
||||
$carry = (int) ($temp / 0x4000000);
|
||||
$product_value[$j] = (int) ($temp - 0x4000000 * $carry);
|
||||
$carry = (int) ($temp / MATH_BIGINTEGER_BASE_FULL);
|
||||
$product_value[$j] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $carry);
|
||||
}
|
||||
|
||||
$product_value[$j] = $carry;
|
||||
@ -1157,8 +1199,8 @@ class Math_BigInteger {
|
||||
|
||||
for ($j = 0, $k = $i; $j < $x_length; ++$j, ++$k) {
|
||||
$temp = $product_value[$k] + $x_value[$j] * $y_value[$i] + $carry;
|
||||
$carry = (int) ($temp / 0x4000000);
|
||||
$product_value[$k] = (int) ($temp - 0x4000000 * $carry);
|
||||
$carry = (int) ($temp / MATH_BIGINTEGER_BASE_FULL);
|
||||
$product_value[$k] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $carry);
|
||||
}
|
||||
|
||||
$product_value[$k] = $carry;
|
||||
@ -1245,14 +1287,14 @@ class Math_BigInteger {
|
||||
$i2 = $i << 1;
|
||||
|
||||
$temp = $square_value[$i2] + $value[$i] * $value[$i];
|
||||
$carry = (int) ($temp / 0x4000000);
|
||||
$square_value[$i2] = (int) ($temp - 0x4000000 * $carry);
|
||||
$carry = (int) ($temp / MATH_BIGINTEGER_BASE_FULL);
|
||||
$square_value[$i2] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $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 * $value[$j] * $value[$i] + $carry;
|
||||
$carry = (int) ($temp / 0x4000000);
|
||||
$square_value[$k] = (int) ($temp - 0x4000000 * $carry);
|
||||
$carry = (int) ($temp / MATH_BIGINTEGER_BASE_FULL);
|
||||
$square_value[$k] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $carry);
|
||||
}
|
||||
|
||||
// the following line can yield values larger 2**15. at this point, PHP should switch
|
||||
@ -1400,7 +1442,7 @@ class Math_BigInteger {
|
||||
|
||||
// normalize $x and $y as described in HAC 14.23 / 14.24
|
||||
$msb = $y->value[count($y->value) - 1];
|
||||
for ($shift = 0; !($msb & 0x2000000); ++$shift) {
|
||||
for ($shift = 0; !($msb & MATH_BIGINTEGER_MSB); ++$shift) {
|
||||
$msb <<= 1;
|
||||
}
|
||||
$x->_lshift($shift);
|
||||
@ -1447,10 +1489,10 @@ class Math_BigInteger {
|
||||
|
||||
$q_index = $i - $y_max - 1;
|
||||
if ($x_window[0] == $y_window[0]) {
|
||||
$quotient_value[$q_index] = 0x3FFFFFF;
|
||||
$quotient_value[$q_index] = MATH_BIGINTEGER_MAX_DIGIT;
|
||||
} else {
|
||||
$quotient_value[$q_index] = (int) (
|
||||
($x_window[0] * 0x4000000 + $x_window[1])
|
||||
($x_window[0] * MATH_BIGINTEGER_BASE_FULL + $x_window[1])
|
||||
/
|
||||
$y_window[0]
|
||||
);
|
||||
@ -1518,7 +1560,7 @@ class Math_BigInteger {
|
||||
$result = array();
|
||||
|
||||
for ($i = count($dividend) - 1; $i >= 0; --$i) {
|
||||
$temp = 0x4000000 * $carry + $dividend[$i];
|
||||
$temp = MATH_BIGINTEGER_BASE_FULL * $carry + $dividend[$i];
|
||||
$result[$i] = (int) ($temp / $divisor);
|
||||
$carry = (int) ($temp - $divisor * $result[$i]);
|
||||
}
|
||||
@ -1583,13 +1625,54 @@ class Math_BigInteger {
|
||||
return $this->_normalize($temp->modPow($e, $n));
|
||||
}
|
||||
|
||||
switch ( MATH_BIGINTEGER_MODE ) {
|
||||
case MATH_BIGINTEGER_MODE_GMP:
|
||||
$temp = new Math_BigInteger();
|
||||
$temp->value = gmp_powm($this->value, $e->value, $n->value);
|
||||
if ( MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_GMP ) {
|
||||
$temp = new Math_BigInteger();
|
||||
$temp->value = gmp_powm($this->value, $e->value, $n->value);
|
||||
|
||||
return $this->_normalize($temp);
|
||||
case MATH_BIGINTEGER_MODE_BCMATH:
|
||||
return $this->_normalize($temp);
|
||||
}
|
||||
|
||||
if ($this->compare(new Math_BigInteger()) < 0 || $this->compare($n) > 0) {
|
||||
list(, $temp) = $this->divide($n);
|
||||
return $temp->modPow($e, $n);
|
||||
}
|
||||
|
||||
if (defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) {
|
||||
$components = array(
|
||||
'modulus' => $n->toBytes(true),
|
||||
'publicExponent' => $e->toBytes(true)
|
||||
);
|
||||
|
||||
$components = array(
|
||||
'modulus' => pack('Ca*a*', 2, $this->_encodeASN1Length(strlen($components['modulus'])), $components['modulus']),
|
||||
'publicExponent' => pack('Ca*a*', 2, $this->_encodeASN1Length(strlen($components['publicExponent'])), $components['publicExponent'])
|
||||
);
|
||||
|
||||
$RSAPublicKey = pack('Ca*a*a*',
|
||||
48, $this->_encodeASN1Length(strlen($components['modulus']) + strlen($components['publicExponent'])),
|
||||
$components['modulus'], $components['publicExponent']
|
||||
);
|
||||
|
||||
$rsaOID = pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA
|
||||
$RSAPublicKey = chr(0) . $RSAPublicKey;
|
||||
$RSAPublicKey = chr(3) . $this->_encodeASN1Length(strlen($RSAPublicKey)) . $RSAPublicKey;
|
||||
|
||||
$encapsulated = pack('Ca*a*',
|
||||
48, $this->_encodeASN1Length(strlen($rsaOID . $RSAPublicKey)), $rsaOID . $RSAPublicKey
|
||||
);
|
||||
|
||||
$RSAPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" .
|
||||
chunk_split(base64_encode($encapsulated)) .
|
||||
'-----END PUBLIC KEY-----';
|
||||
|
||||
$plaintext = str_pad($this->toBytes(), strlen($n->toBytes(true)) - 1, "\0", STR_PAD_LEFT);
|
||||
|
||||
if (openssl_public_encrypt($plaintext, $result, $RSAPublicKey, OPENSSL_NO_PADDING)) {
|
||||
return new Math_BigInteger($result, 256);
|
||||
}
|
||||
}
|
||||
|
||||
if ( MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_BCMATH ) {
|
||||
$temp = new Math_BigInteger();
|
||||
$temp->value = bcpowmod($this->value, $e->value, $n->value, 0);
|
||||
|
||||
@ -1695,7 +1778,7 @@ class Math_BigInteger {
|
||||
$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]), MATH_BIGINTEGER_BASE, '0', STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
$e_length = strlen($e_bits);
|
||||
@ -2030,7 +2113,7 @@ class Math_BigInteger {
|
||||
if ($this->_compare($result, false, $temp[MATH_BIGINTEGER_VALUE], $temp[MATH_BIGINTEGER_SIGN]) < 0) {
|
||||
$corrector_value = $this->_array_repeat(0, $n_length + 1);
|
||||
$corrector_value[] = 1;
|
||||
$result = $this->_add($result, false, $corrector, false);
|
||||
$result = $this->_add($result, false, $corrector_value, false);
|
||||
$result = $result[MATH_BIGINTEGER_VALUE];
|
||||
}
|
||||
|
||||
@ -2053,6 +2136,7 @@ class Math_BigInteger {
|
||||
* @param Boolean $x_negative
|
||||
* @param Array $y_value
|
||||
* @param Boolean $y_negative
|
||||
* @param Integer $stop
|
||||
* @return Array
|
||||
* @access private
|
||||
*/
|
||||
@ -2089,8 +2173,8 @@ class Math_BigInteger {
|
||||
|
||||
for ($j = 0; $j < $x_length; ++$j) { // ie. $i = 0, $k = $i
|
||||
$temp = $x_value[$j] * $y_value[0] + $carry; // $product_value[$k] == 0
|
||||
$carry = (int) ($temp / 0x4000000);
|
||||
$product_value[$j] = (int) ($temp - 0x4000000 * $carry);
|
||||
$carry = (int) ($temp / MATH_BIGINTEGER_BASE_FULL);
|
||||
$product_value[$j] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $carry);
|
||||
}
|
||||
|
||||
if ($j < $stop) {
|
||||
@ -2105,8 +2189,8 @@ class Math_BigInteger {
|
||||
|
||||
for ($j = 0, $k = $i; $j < $x_length && $k < $stop; ++$j, ++$k) {
|
||||
$temp = $product_value[$k] + $x_value[$j] * $y_value[$i] + $carry;
|
||||
$carry = (int) ($temp / 0x4000000);
|
||||
$product_value[$k] = (int) ($temp - 0x4000000 * $carry);
|
||||
$carry = (int) ($temp / MATH_BIGINTEGER_BASE_FULL);
|
||||
$product_value[$k] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $carry);
|
||||
}
|
||||
|
||||
if ($k < $stop) {
|
||||
@ -2154,7 +2238,7 @@ class Math_BigInteger {
|
||||
|
||||
for ($i = 0; $i < $k; ++$i) {
|
||||
$temp = $result[MATH_BIGINTEGER_VALUE][$i] * $cache[MATH_BIGINTEGER_DATA][$key];
|
||||
$temp = (int) ($temp - 0x4000000 * ((int) ($temp / 0x4000000)));
|
||||
$temp = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * ((int) ($temp / MATH_BIGINTEGER_BASE_FULL)));
|
||||
$temp = $this->_regularMultiply(array($temp), $n);
|
||||
$temp = array_merge($this->_array_repeat(0, $i), $temp);
|
||||
$result = $this->_add($result[MATH_BIGINTEGER_VALUE], false, $temp, false);
|
||||
@ -2206,9 +2290,9 @@ class Math_BigInteger {
|
||||
$a = array(MATH_BIGINTEGER_VALUE => $this->_array_repeat(0, $n + 1));
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$temp = $a[MATH_BIGINTEGER_VALUE][0] + $x[$i] * $y[0];
|
||||
$temp = (int) ($temp - 0x4000000 * ((int) ($temp / 0x4000000)));
|
||||
$temp = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * ((int) ($temp / MATH_BIGINTEGER_BASE_FULL)));
|
||||
$temp = $temp * $cache[MATH_BIGINTEGER_DATA][$key];
|
||||
$temp = (int) ($temp - 0x4000000 * ((int) ($temp / 0x4000000)));
|
||||
$temp = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * ((int) ($temp / MATH_BIGINTEGER_BASE_FULL)));
|
||||
$temp = $this->_add($this->_regularMultiply(array($x[$i]), $y), false, $this->_regularMultiply(array($temp), $m), false);
|
||||
$a = $this->_add($a[MATH_BIGINTEGER_VALUE], false, $temp[MATH_BIGINTEGER_VALUE], false);
|
||||
$a[MATH_BIGINTEGER_VALUE] = array_slice($a[MATH_BIGINTEGER_VALUE], 1);
|
||||
@ -2266,15 +2350,15 @@ class Math_BigInteger {
|
||||
* @param Array $x
|
||||
* @return Integer
|
||||
*/
|
||||
function _modInverse67108864($x) // 2**26 == 67108864
|
||||
function _modInverse67108864($x) // 2**26 == 67,108,864
|
||||
{
|
||||
$x = -$x[0];
|
||||
$result = $x & 0x3; // x**-1 mod 2**2
|
||||
$result = ($result * (2 - $x * $result)) & 0xF; // x**-1 mod 2**4
|
||||
$result = ($result * (2 - ($x & 0xFF) * $result)) & 0xFF; // x**-1 mod 2**8
|
||||
$result = ($result * ((2 - ($x & 0xFFFF) * $result) & 0xFFFF)) & 0xFFFF; // x**-1 mod 2**16
|
||||
$result = fmod($result * (2 - fmod($x * $result, 0x4000000)), 0x4000000); // x**-1 mod 2**26
|
||||
return $result & 0x3FFFFFF;
|
||||
$result = fmod($result * (2 - fmod($x * $result, MATH_BIGINTEGER_BASE_FULL)), MATH_BIGINTEGER_BASE_FULL); // x**-1 mod 2**26
|
||||
return $result & MATH_BIGINTEGER_MAX_DIGIT;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2322,13 +2406,13 @@ class Math_BigInteger {
|
||||
$one = new Math_BigInteger(1);
|
||||
}
|
||||
|
||||
// $x mod $n == $x mod -$n.
|
||||
// $x mod -$n == $x mod $n.
|
||||
$n = $n->abs();
|
||||
|
||||
if ($this->compare($zero) < 0) {
|
||||
$temp = $this->abs();
|
||||
$temp = $temp->modInverse($n);
|
||||
return $negated === false ? false : $this->_normalize($n->subtract($temp));
|
||||
return $this->_normalize($n->subtract($temp));
|
||||
}
|
||||
|
||||
extract($this->extendedGCD($n));
|
||||
@ -2343,12 +2427,12 @@ class Math_BigInteger {
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the greatest common divisor and Bézout's identity.
|
||||
* Calculates the greatest common divisor and Bezout's identity.
|
||||
*
|
||||
* Say you have 693 and 609. The GCD is 21. Bézout's identity states that there exist integers x and y such that
|
||||
* Say you have 693 and 609. The GCD is 21. Bezout's identity states that there exist integers x and y such that
|
||||
* 693*x + 609*y == 21. In point of fact, there are actually an infinite number of x and y combinations and which
|
||||
* combination is returned is dependant upon which mode is in use. See
|
||||
* {@link http://en.wikipedia.org/wiki/B%C3%A9zout%27s_identity Bézout's identity - Wikipedia} for more information.
|
||||
* {@link http://en.wikipedia.org/wiki/B%C3%A9zout%27s_identity Bezout's identity - Wikipedia} for more information.
|
||||
*
|
||||
* Here's an example:
|
||||
* <code>
|
||||
@ -2545,8 +2629,8 @@ class Math_BigInteger {
|
||||
*
|
||||
* Note how the same comparison operator is used. If you want to test for equality, use $x->equals($y).
|
||||
*
|
||||
* @param Math_BigInteger $x
|
||||
* @return Integer < 0 if $this is less than $x; > 0 if $this is greater than $x, and 0 if they are equal.
|
||||
* @param Math_BigInteger $y
|
||||
* @return Integer < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal.
|
||||
* @access public
|
||||
* @see equals()
|
||||
* @internal Could return $this->subtract($x), but that's not as fast as what we do do.
|
||||
@ -2625,9 +2709,8 @@ class Math_BigInteger {
|
||||
* Some bitwise operations give different results depending on the precision being used. Examples include left
|
||||
* shift, not, and rotates.
|
||||
*
|
||||
* @param Math_BigInteger $x
|
||||
* @param Integer $bits
|
||||
* @access public
|
||||
* @return Math_BigInteger
|
||||
*/
|
||||
function setPrecision($bits)
|
||||
{
|
||||
@ -2677,7 +2760,7 @@ class Math_BigInteger {
|
||||
$result->value = array_slice($result->value, 0, $length);
|
||||
|
||||
for ($i = 0; $i < $length; ++$i) {
|
||||
$result->value[$i] = $result->value[$i] & $x->value[$i];
|
||||
$result->value[$i]&= $x->value[$i];
|
||||
}
|
||||
|
||||
return $this->_normalize($result);
|
||||
@ -2713,11 +2796,11 @@ class Math_BigInteger {
|
||||
|
||||
$length = max(count($this->value), count($x->value));
|
||||
$result = $this->copy();
|
||||
$result->value = array_pad($result->value, 0, $length);
|
||||
$x->value = array_pad($x->value, 0, $length);
|
||||
$result->value = array_pad($result->value, $length, 0);
|
||||
$x->value = array_pad($x->value, $length, 0);
|
||||
|
||||
for ($i = 0; $i < $length; ++$i) {
|
||||
$result->value[$i] = $this->value[$i] | $x->value[$i];
|
||||
$result->value[$i]|= $x->value[$i];
|
||||
}
|
||||
|
||||
return $this->_normalize($result);
|
||||
@ -2753,11 +2836,11 @@ class Math_BigInteger {
|
||||
|
||||
$length = max(count($this->value), count($x->value));
|
||||
$result = $this->copy();
|
||||
$result->value = array_pad($result->value, 0, $length);
|
||||
$x->value = array_pad($x->value, 0, $length);
|
||||
$result->value = array_pad($result->value, $length, 0);
|
||||
$x->value = array_pad($x->value, $length, 0);
|
||||
|
||||
for ($i = 0; $i < $length; ++$i) {
|
||||
$result->value[$i] = $this->value[$i] ^ $x->value[$i];
|
||||
$result->value[$i]^= $x->value[$i];
|
||||
}
|
||||
|
||||
return $this->_normalize($result);
|
||||
@ -2936,20 +3019,13 @@ class Math_BigInteger {
|
||||
/**
|
||||
* Set random number generator function
|
||||
*
|
||||
* $generator should be the name of a random generating function whose first parameter is the minimum
|
||||
* value and whose second parameter is the maximum value. If this function needs to be seeded, it should
|
||||
* be seeded prior to calling Math_BigInteger::random() or Math_BigInteger::randomPrime()
|
||||
* This function is deprecated.
|
||||
*
|
||||
* If the random generating function is not explicitly set, it'll be assumed to be mt_rand().
|
||||
*
|
||||
* @see random()
|
||||
* @see randomPrime()
|
||||
* @param optional String $generator
|
||||
* @param String $generator
|
||||
* @access public
|
||||
*/
|
||||
function setRandomGenerator($generator)
|
||||
{
|
||||
$this->generator = $generator;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2981,32 +3057,46 @@ class Math_BigInteger {
|
||||
$min = $temp;
|
||||
}
|
||||
|
||||
$generator = $this->generator;
|
||||
|
||||
$max = $max->subtract($min);
|
||||
$max = ltrim($max->toBytes(), chr(0));
|
||||
$size = strlen($max) - 1;
|
||||
$random = '';
|
||||
|
||||
$bytes = $size & 1;
|
||||
for ($i = 0; $i < $bytes; ++$i) {
|
||||
$random.= chr($generator(0, 255));
|
||||
}
|
||||
|
||||
$blocks = $size >> 1;
|
||||
for ($i = 0; $i < $blocks; ++$i) {
|
||||
// mt_rand(-2147483648, 0x7FFFFFFF) always produces -2147483648 on some systems
|
||||
$random.= pack('n', $generator(0, 0xFFFF));
|
||||
}
|
||||
|
||||
$temp = new Math_BigInteger($random, 256);
|
||||
if ($temp->compare(new Math_BigInteger(substr($max, 1), 256)) > 0) {
|
||||
$random = chr($generator(0, ord($max[0]) - 1)) . $random;
|
||||
$crypt_random = function_exists('crypt_random_string') || (!class_exists('Crypt_Random') && function_exists('crypt_random_string'));
|
||||
if ($crypt_random) {
|
||||
$random = crypt_random_string($size);
|
||||
} else {
|
||||
$random = chr($generator(0, ord($max[0]) )) . $random;
|
||||
$random = '';
|
||||
|
||||
if ($size & 1) {
|
||||
$random.= chr(mt_rand(0, 255));
|
||||
}
|
||||
|
||||
$blocks = $size >> 1;
|
||||
for ($i = 0; $i < $blocks; ++$i) {
|
||||
// mt_rand(-2147483648, 0x7FFFFFFF) always produces -2147483648 on some systems
|
||||
$random.= pack('n', mt_rand(0, 0xFFFF));
|
||||
}
|
||||
}
|
||||
|
||||
$random = new Math_BigInteger($random, 256);
|
||||
$fragment = new Math_BigInteger($random, 256);
|
||||
$leading = $fragment->compare(new Math_BigInteger(substr($max, 1), 256)) > 0 ?
|
||||
ord($max[0]) - 1 : ord($max[0]);
|
||||
|
||||
if (!$crypt_random) {
|
||||
$msb = chr(mt_rand(0, $leading));
|
||||
} else {
|
||||
$cutoff = floor(0xFF / $leading) * $leading;
|
||||
while (true) {
|
||||
$msb = ord(crypt_random_string(1));
|
||||
if ($msb <= $cutoff) {
|
||||
$msb%= $leading;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$msb = chr($msb);
|
||||
}
|
||||
|
||||
$random = new Math_BigInteger($msb . $random, 256);
|
||||
|
||||
return $this->_normalize($random->add($min));
|
||||
}
|
||||
@ -3026,10 +3116,18 @@ class Math_BigInteger {
|
||||
*/
|
||||
function randomPrime($min = false, $max = false, $timeout = false)
|
||||
{
|
||||
if ($min === false) {
|
||||
$min = new Math_BigInteger(0);
|
||||
}
|
||||
|
||||
if ($max === false) {
|
||||
$max = new Math_BigInteger(0x7FFFFFFF);
|
||||
}
|
||||
|
||||
$compare = $max->compare($min);
|
||||
|
||||
if (!$compare) {
|
||||
return $min;
|
||||
return $min->isPrime() ? $min : false;
|
||||
} else if ($compare < 0) {
|
||||
// if $min is bigger then $max, swap $min and $max
|
||||
$temp = $max;
|
||||
@ -3037,36 +3135,6 @@ class Math_BigInteger {
|
||||
$min = $temp;
|
||||
}
|
||||
|
||||
// gmp_nextprime() requires PHP 5 >= 5.2.0 per <http://php.net/gmp-nextprime>.
|
||||
if ( MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_GMP && function_exists('gmp_nextprime') ) {
|
||||
// we don't rely on Math_BigInteger::random()'s min / max when gmp_nextprime() is being used since this function
|
||||
// does its own checks on $max / $min when gmp_nextprime() is used. When gmp_nextprime() is not used, however,
|
||||
// the same $max / $min checks are not performed.
|
||||
if ($min === false) {
|
||||
$min = new Math_BigInteger(0);
|
||||
}
|
||||
|
||||
if ($max === false) {
|
||||
$max = new Math_BigInteger(0x7FFFFFFF);
|
||||
}
|
||||
|
||||
$x = $this->random($min, $max);
|
||||
|
||||
$x->value = gmp_nextprime($x->value);
|
||||
|
||||
if ($x->compare($max) <= 0) {
|
||||
return $x;
|
||||
}
|
||||
|
||||
$x->value = gmp_nextprime($min->value);
|
||||
|
||||
if ($x->compare($max) <= 0) {
|
||||
return $x;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static $one, $two;
|
||||
if (!isset($one)) {
|
||||
$one = new Math_BigInteger(1);
|
||||
@ -3076,6 +3144,22 @@ class Math_BigInteger {
|
||||
$start = time();
|
||||
|
||||
$x = $this->random($min, $max);
|
||||
|
||||
// gmp_nextprime() requires PHP 5 >= 5.2.0 per <http://php.net/gmp-nextprime>.
|
||||
if ( MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_GMP && function_exists('gmp_nextprime') ) {
|
||||
$p->value = gmp_nextprime($x->value);
|
||||
|
||||
if ($p->compare($max) <= 0) {
|
||||
return $p;
|
||||
}
|
||||
|
||||
if (!$min->equals($x)) {
|
||||
$x = $x->subtract($one);
|
||||
}
|
||||
|
||||
return $x->randomPrime($min, $x);
|
||||
}
|
||||
|
||||
if ($x->equals($two)) {
|
||||
return $x;
|
||||
}
|
||||
@ -3307,16 +3391,16 @@ class Math_BigInteger {
|
||||
return;
|
||||
}
|
||||
|
||||
$num_digits = (int) ($shift / 26);
|
||||
$shift %= 26;
|
||||
$num_digits = (int) ($shift / MATH_BIGINTEGER_BASE);
|
||||
$shift %= MATH_BIGINTEGER_BASE;
|
||||
$shift = 1 << $shift;
|
||||
|
||||
$carry = 0;
|
||||
|
||||
for ($i = 0; $i < count($this->value); ++$i) {
|
||||
$temp = $this->value[$i] * $shift + $carry;
|
||||
$carry = (int) ($temp / 0x4000000);
|
||||
$this->value[$i] = (int) ($temp - $carry * 0x4000000);
|
||||
$carry = (int) ($temp / MATH_BIGINTEGER_BASE_FULL);
|
||||
$this->value[$i] = (int) ($temp - $carry * MATH_BIGINTEGER_BASE_FULL);
|
||||
}
|
||||
|
||||
if ( $carry ) {
|
||||
@ -3342,9 +3426,9 @@ class Math_BigInteger {
|
||||
return;
|
||||
}
|
||||
|
||||
$num_digits = (int) ($shift / 26);
|
||||
$shift %= 26;
|
||||
$carry_shift = 26 - $shift;
|
||||
$num_digits = (int) ($shift / MATH_BIGINTEGER_BASE);
|
||||
$shift %= MATH_BIGINTEGER_BASE;
|
||||
$carry_shift = MATH_BIGINTEGER_BASE - $shift;
|
||||
$carry_mask = (1 << $shift) - 1;
|
||||
|
||||
if ( $num_digits ) {
|
||||
@ -3417,6 +3501,7 @@ class Math_BigInteger {
|
||||
*
|
||||
* Removes leading zeros
|
||||
*
|
||||
* @param Array $value
|
||||
* @return Math_BigInteger
|
||||
* @access private
|
||||
*/
|
||||
@ -3542,4 +3627,24 @@ class Math_BigInteger {
|
||||
$temp = unpack('Nint', str_pad($x, 4, chr(0), STR_PAD_LEFT));
|
||||
return $temp['int'];
|
||||
}
|
||||
|
||||
/**
|
||||
* DER-encode an integer
|
||||
*
|
||||
* The ability to DER-encode integers is needed to create RSA public keys for use with OpenSSL
|
||||
*
|
||||
* @see modPow()
|
||||
* @access private
|
||||
* @param Integer $length
|
||||
* @return String
|
||||
*/
|
||||
function _encodeASN1Length($length)
|
||||
{
|
||||
if ($length <= 0x7F) {
|
||||
return chr($length);
|
||||
}
|
||||
|
||||
$temp = ltrim(pack('N', $length), chr(0));
|
||||
return pack('Ca*', 0x80 | strlen($temp), $temp);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user