added phpseclib

This commit is contained in:
Roland Gruber 2010-05-14 14:06:17 +00:00
parent e3bffe6b7a
commit 722daabb64
16 changed files with 15556 additions and 5 deletions

View File

@ -135,8 +135,8 @@ D:
Programs and licenses with other licenses and/or authors than the
main license and authors:
lib/fpdf.php A 2003 Olivier Plathey
lib/font/Vera* B 2003 Bitstream, Inc.
templates/lib/wz_tooltip.js C Walter Zorn
templates/lib/jquery*.js D 2009 John Resig
lib/fpdf.php A 2003 Olivier Plathey
lib/font/Vera* B 2003 Bitstream, Inc.
templates/lib/wz_tooltip.js C Walter Zorn
templates/lib/jquery*.js D 2009 John Resig
lib/3rdParty/phpseclib C Jim Wigginton

479
lam/lib/3rdParty/phpseclib/Crypt/AES.php vendored Normal file
View File

@ -0,0 +1,479 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* Pure-PHP implementation of AES.
*
* Uses mcrypt, if available, and an internal implementation, otherwise.
*
* PHP versions 4 and 5
*
* If {@link Crypt_AES::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
* {@link Crypt_AES::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's 136-bits
* it'll be null-padded to 160-bits and 160 bits will be the key length until {@link Crypt_Rijndael::setKey() setKey()}
* is called, again, at which point, it'll be recalculated.
*
* Since Crypt_AES extends Crypt_Rijndael, some functions are available to be called that, in the context of AES, don't
* make a whole lot of sense. {@link Crypt_AES::setBlockLength() setBlockLength()}, for instance. Calling that function,
* however possible, won't do anything (AES has a fixed block length whereas Rijndael has a variable one).
*
* Here's a short example of how to use this library:
* <code>
* <?php
* include('Crypt/AES.php');
*
* $aes = new Crypt_AES();
*
* $aes->setKey('abcdefghijklmnop');
*
* $size = 10 * 1024;
* $plaintext = '';
* for ($i = 0; $i < $size; $i++) {
* $plaintext.= 'a';
* }
*
* echo $aes->decrypt($aes->encrypt($plaintext));
* ?>
* </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.
*
* 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.
*
* 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
*
* @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$
* @link http://phpseclib.sourceforge.net
*/
/**
* Include Crypt_Rijndael
*/
require_once 'Rijndael.php';
/**#@+
* @access public
* @see Crypt_AES::encrypt()
* @see Crypt_AES::decrypt()
*/
/**
* Encrypt / decrypt using the Counter mode.
*
* Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
*/
define('CRYPT_AES_MODE_CTR', -1);
/**
* Encrypt / decrypt using the Electronic Code Book mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
*/
define('CRYPT_AES_MODE_ECB', 1);
/**
* Encrypt / decrypt using the Code Book Chaining mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
*/
define('CRYPT_AES_MODE_CBC', 2);
/**#@-*/
/**#@+
* @access private
* @see Crypt_AES::Crypt_AES()
*/
/**
* Toggles the internal implementation
*/
define('CRYPT_AES_MODE_INTERNAL', 1);
/**
* Toggles the mcrypt implementation
*/
define('CRYPT_AES_MODE_MCRYPT', 2);
/**#@-*/
/**
* Pure-PHP implementation of AES.
*
* @author Jim Wigginton <terrafrost@php.net>
* @version 0.1.0
* @access public
* @package Crypt_AES
*/
class Crypt_AES extends Crypt_Rijndael {
/**
* 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;
/**
* Default Constructor.
*
* Determines whether or not the mcrypt extension should be used. $mode should only, at present, be
* CRYPT_AES_MODE_ECB or CRYPT_AES_MODE_CBC. If not explictly set, CRYPT_AES_MODE_CBC will be used.
*
* @param optional Integer $mode
* @return Crypt_AES
* @access public
*/
function Crypt_AES($mode = CRYPT_AES_MODE_CBC)
{
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...
define('CRYPT_AES_MODE', CRYPT_AES_MODE_MCRYPT);
break;
default:
define('CRYPT_AES_MODE', CRYPT_AES_MODE_INTERNAL);
}
}
switch ( CRYPT_AES_MODE ) {
case CRYPT_AES_MODE_MCRYPT:
switch ($mode) {
case CRYPT_AES_MODE_ECB:
$this->mode = MCRYPT_MODE_ECB;
break;
case CRYPT_AES_MODE_CTR:
// ctr doesn't have a constant associated with it even though it appears to be fairly widely
// supported. in lieu of knowing just how widely supported it is, i've, for now, opted not to
// include a compatibility layer. the layer has been implemented but, for now, is commented out.
$this->mode = 'ctr';
//$this->mode = in_array('ctr', mcrypt_list_modes()) ? 'ctr' : CRYPT_AES_MODE_CTR;
break;
case CRYPT_AES_MODE_CBC:
default:
$this->mode = MCRYPT_MODE_CBC;
}
break;
default:
switch ($mode) {
case CRYPT_AES_MODE_ECB:
$this->mode = CRYPT_RIJNDAEL_MODE_ECB;
break;
case CRYPT_AES_MODE_CTR:
$this->mode = CRYPT_RIJNDAEL_MODE_CTR;
break;
case CRYPT_AES_MODE_CBC:
default:
$this->mode = CRYPT_RIJNDAEL_MODE_CBC;
}
}
if (CRYPT_AES_MODE == CRYPT_AES_MODE_INTERNAL) {
parent::Crypt_Rijndael($this->mode);
}
}
/**
* Dummy function
*
* Since Crypt_AES extends Crypt_Rijndael, this function is, technically, available, but it doesn't do anything.
*
* @access public
* @param Integer $length
*/
function setBlockLength($length)
{
return;
}
/**
* Encrypts a message.
*
* $plaintext will be padded with up to 16 additional bytes. Other AES implementations may or may not pad in the
* same manner. Other common approaches to padding and the reasons why it's necessary are discussed in the following
* URL:
*
* {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html}
*
* An alternative to padding is to, separately, send the length of the file. This is what SSH, in fact, does.
* strlen($plaintext) will still need to be a multiple of 16, however, arbitrary values can be added to make it that
* length.
*
* @see Crypt_AES::decrypt()
* @access public
* @param String $plaintext
*/
function encrypt($plaintext)
{
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;
}
return $ciphertext;
}
*/
if ($this->mode != 'ctr') {
$plaintext = $this->_pad($plaintext);
}
$ciphertext = mcrypt_generic($this->enmcrypt, $plaintext);
if (!$this->continuousBuffer) {
mcrypt_generic_init($this->enmcrypt, $this->key, $this->iv);
}
return $ciphertext;
}
return parent::encrypt($plaintext);
}
/**
* Decrypts a message.
*
* If strlen($ciphertext) is not a multiple of 16, null bytes will be added to the end of the string until it is.
*
* @see Crypt_AES::encrypt()
* @access public
* @param String $ciphertext
*/
function decrypt($ciphertext)
{
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;
}
return $plaintext;
}
*/
if ($this->mode != 'ctr') {
// 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));
}
$plaintext = mdecrypt_generic($this->demcrypt, $ciphertext);
if (!$this->continuousBuffer) {
mcrypt_generic_init($this->demcrypt, $this->key, $this->iv);
}
return $this->mode != 'ctr' ? $this->_unpad($plaintext) : $plaintext;
}
return parent::decrypt($ciphertext);
}
/**
* Setup mcrypt
*
* Validates all the variables.
*
* @access private
*/
function _mcryptSetup()
{
if (!$this->changed) {
return;
}
if (!$this->explicit_key_length) {
// this just copied from Crypt_Rijndael::_setup()
$length = strlen($this->key) >> 2;
if ($length > 8) {
$length = 8;
} else if ($length < 4) {
$length = 4;
}
$this->Nk = $length;
$this->key_size = $length << 2;
}
switch ($this->Nk) {
case 4: // 128
$this->key_size = 16;
break;
case 5: // 160
case 6: // 192
$this->key_size = 24;
break;
case 7: // 224
case 8: // 256
$this->key_size = 32;
}
$this->key = substr($this->key, 0, $this->key_size);
$this->encryptIV = $this->decryptIV = $this->iv = str_pad(substr($this->iv, 0, 16), 16, chr(0));
if (!isset($this->enmcrypt)) {
$mode = $this->mode;
//$mode = $this->mode == CRYPT_AES_MODE_CTR ? MCRYPT_MODE_ECB : $this->mode;
$this->demcrypt = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', $mode, '');
$this->enmcrypt = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', $mode, '');
} // 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);
$this->changed = false;
}
/**
* Encrypts a block
*
* Optimized over Crypt_Rijndael's implementation by means of loop unrolling.
*
* @see Crypt_Rijndael::_encryptBlock()
* @access private
* @param String $in
* @return String
*/
function _encryptBlock($in)
{
$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]
);
}
// 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
*
* Optimized over Crypt_Rijndael's implementation by means of loop unrolling.
*
* @see Crypt_Rijndael::_decryptBlock()
* @access private
* @param String $in
* @return String
*/
function _decryptBlock($in)
{
$state = unpack('N*word', $in);
$Nr = $this->Nr;
$dw = $this->dw;
$dt0 = $this->dt0;
$dt1 = $this->dt1;
$dt2 = $this->dt2;
$dt3 = $this->dt3;
// addRoundKey and reindex $state
$state = array(
$state['word1'] ^ $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]
);
}
// 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]);
}
}
// vim: ts=4:sw=4:et:
// vim6: fdl=1:

945
lam/lib/3rdParty/phpseclib/Crypt/DES.php vendored Normal file
View File

@ -0,0 +1,945 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* Pure-PHP implementation of DES.
*
* Uses mcrypt, if available, and an internal implementation, otherwise.
*
* PHP versions 4 and 5
*
* Useful resources are as follows:
*
* - {@link http://en.wikipedia.org/wiki/DES_supplementary_material Wikipedia: DES supplementary material}
* - {@link http://www.itl.nist.gov/fipspubs/fip46-2.htm FIPS 46-2 - (DES), Data Encryption Standard}
* - {@link http://www.cs.eku.edu/faculty/styer/460/Encrypt/JS-DES.html JavaScript DES Example}
*
* Here's a short example of how to use this library:
* <code>
* <?php
* include('Crypt/DES.php');
*
* $des = new Crypt_DES();
*
* $des->setKey('abcdefgh');
*
* $size = 10 * 1024;
* $plaintext = '';
* for ($i = 0; $i < $size; $i++) {
* $plaintext.= 'a';
* }
*
* echo $des->decrypt($des->encrypt($plaintext));
* ?>
* </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.
*
* 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.
*
* 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
*
* @category Crypt
* @package Crypt_DES
* @author Jim Wigginton <terrafrost@php.net>
* @copyright MMVII Jim Wigginton
* @license http://www.gnu.org/licenses/lgpl.txt
* @version $Id$
* @link http://phpseclib.sourceforge.net
*/
/**#@+
* @access private
* @see Crypt_DES::_prepareKey()
* @see Crypt_DES::_processBlock()
*/
/**
* Contains array_reverse($keys[CRYPT_DES_DECRYPT])
*/
define('CRYPT_DES_ENCRYPT', 0);
/**
* Contains array_reverse($keys[CRYPT_DES_ENCRYPT])
*/
define('CRYPT_DES_DECRYPT', 1);
/**#@-*/
/**#@+
* @access public
* @see Crypt_DES::encrypt()
* @see Crypt_DES::decrypt()
*/
/**
* Encrypt / decrypt using the Counter mode.
*
* Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
*/
define('CRYPT_DES_MODE_CTR', -1);
/**
* Encrypt / decrypt using the Electronic Code Book mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
*/
define('CRYPT_DES_MODE_ECB', 1);
/**
* Encrypt / decrypt using the Code Book Chaining mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
*/
define('CRYPT_DES_MODE_CBC', 2);
/**#@-*/
/**#@+
* @access private
* @see Crypt_DES::Crypt_DES()
*/
/**
* Toggles the internal implementation
*/
define('CRYPT_DES_MODE_INTERNAL', 1);
/**
* Toggles the mcrypt implementation
*/
define('CRYPT_DES_MODE_MCRYPT', 2);
/**#@-*/
/**
* Pure-PHP implementation of DES.
*
* @author Jim Wigginton <terrafrost@php.net>
* @version 0.1.0
* @access public
* @package Crypt_DES
*/
class Crypt_DES {
/**
* The Key Schedule
*
* @see Crypt_DES::setKey()
* @var Array
* @access private
*/
var $keys = "\0\0\0\0\0\0\0\0";
/**
* The Encryption Mode
*
* @see Crypt_DES::Crypt_DES()
* @var Integer
* @access private
*/
var $mode;
/**
* Continuous Buffer status
*
* @see Crypt_DES::enableContinuousBuffer()
* @var Boolean
* @access private
*/
var $continuousBuffer = false;
/**
* Padding status
*
* @see Crypt_DES::enablePadding()
* @var Boolean
* @access private
*/
var $padding = true;
/**
* The Initialization Vector
*
* @see Crypt_DES::setIV()
* @var String
* @access private
*/
var $iv = "\0\0\0\0\0\0\0\0";
/**
* A "sliding" Initialization Vector
*
* @see Crypt_DES::enableContinuousBuffer()
* @var String
* @access private
*/
var $encryptIV = "\0\0\0\0\0\0\0\0";
/**
* A "sliding" Initialization Vector
*
* @see Crypt_DES::enableContinuousBuffer()
* @var String
* @access private
*/
var $decryptIV = "\0\0\0\0\0\0\0\0";
/**
* 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.
*
* Determines whether or not the mcrypt extension should be used. $mode should only, at present, be
* CRYPT_DES_MODE_ECB or CRYPT_DES_MODE_CBC. If not explictly set, CRYPT_DES_MODE_CBC will be used.
*
* @param optional Integer $mode
* @return Crypt_DES
* @access public
*/
function Crypt_DES($mode = CRYPT_MODE_DES_CBC)
{
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...
define('CRYPT_DES_MODE', CRYPT_DES_MODE_MCRYPT);
break;
default:
define('CRYPT_DES_MODE', CRYPT_DES_MODE_INTERNAL);
}
}
switch ( CRYPT_DES_MODE ) {
case CRYPT_DES_MODE_MCRYPT:
switch ($mode) {
case CRYPT_DES_MODE_ECB:
$this->mode = MCRYPT_MODE_ECB;
break;
case CRYPT_DES_MODE_CTR:
$this->mode = 'ctr';
//$this->mode = in_array('ctr', mcrypt_list_modes()) ? 'ctr' : CRYPT_DES_MODE_CTR;
break;
case CRYPT_DES_MODE_CBC:
default:
$this->mode = MCRYPT_MODE_CBC;
}
break;
default:
switch ($mode) {
case CRYPT_DES_MODE_ECB:
case CRYPT_DES_MODE_CTR:
case CRYPT_DES_MODE_CBC:
$this->mode = $mode;
break;
default:
$this->mode = CRYPT_DES_MODE_CBC;
}
}
}
/**
* Sets the key.
*
* Keys can be of any length. DES, itself, uses 64-bit keys (eg. strlen($key) == 8), however, we
* only use the first eight, if $key has more then eight characters in it, and pad $key with the
* null byte if it is less then eight characters long.
*
* DES also requires that every eighth bit be a parity bit, however, we'll ignore that.
*
* If the key is not explicitly set, it'll be assumed to be all zero's.
*
* @access public
* @param String $key
*/
function setKey($key)
{
$this->keys = ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) ? substr($key, 0, 8) : $this->_prepareKey($key);
$this->changed = true;
}
/**
* Sets the initialization vector. (optional)
*
* SetIV is not required when CRYPT_DES_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)
{
$this->encryptIV = $this->decryptIV = $this->iv = str_pad(substr($iv, 0, 8), 8, chr(0));
$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;
}
/**
* Encrypts a message.
*
* $plaintext will be padded with up to 8 additional bytes. Other DES implementations may or may not pad in the
* same manner. Other common approaches to padding and the reasons why it's necessary are discussed in the following
* URL:
*
* {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html}
*
* An alternative to padding is to, separately, send the length of the file. This is what SSH, in fact, does.
* strlen($plaintext) will still need to be a multiple of 8, however, arbitrary values can be added to make it that
* length.
*
* @see Crypt_DES::decrypt()
* @access public
* @param String $plaintext
*/
function encrypt($plaintext)
{
if ($this->mode != CRYPT_DES_MODE_CTR && $this->mode != 'ctr') {
$plaintext = $this->_pad($plaintext);
}
if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) {
if ($this->changed) {
if (!isset($this->enmcrypt)) {
$this->enmcrypt = mcrypt_module_open(MCRYPT_DES, '', $this->mode, '');
}
mcrypt_generic_init($this->enmcrypt, $this->keys, $this->encryptIV);
$this->changed = false;
}
$ciphertext = mcrypt_generic($this->enmcrypt, $plaintext);
if (!$this->continuousBuffer) {
mcrypt_generic_init($this->enmcrypt, $this->keys, $this->encryptIV);
}
return $ciphertext;
}
if (!is_array($this->keys)) {
$this->keys = $this->_prepareKey("\0\0\0\0\0\0\0\0");
}
$ciphertext = '';
switch ($this->mode) {
case CRYPT_DES_MODE_ECB:
for ($i = 0; $i < strlen($plaintext); $i+=8) {
$ciphertext.= $this->_processBlock(substr($plaintext, $i, 8), CRYPT_DES_ENCRYPT);
}
break;
case CRYPT_DES_MODE_CBC:
$xor = $this->encryptIV;
for ($i = 0; $i < strlen($plaintext); $i+=8) {
$block = substr($plaintext, $i, 8);
$block = $this->_processBlock($block ^ $xor, CRYPT_DES_ENCRYPT);
$xor = $block;
$ciphertext.= $block;
}
if ($this->continuousBuffer) {
$this->encryptIV = $xor;
}
break;
case CRYPT_DES_MODE_CTR:
$xor = $this->encryptIV;
for ($i = 0; $i < strlen($plaintext); $i+=8) {
$block = substr($plaintext, $i, 8);
$key = $this->_processBlock($this->_generate_xor(8, $xor), CRYPT_DES_ENCRYPT);
$ciphertext.= $block ^ $key;
}
if ($this->continuousBuffer) {
$this->encryptIV = $xor;
}
}
return $ciphertext;
}
/**
* Decrypts a message.
*
* If strlen($ciphertext) is not a multiple of 8, null bytes will be added to the end of the string until it is.
*
* @see Crypt_DES::encrypt()
* @access public
* @param String $ciphertext
*/
function decrypt($ciphertext)
{
if ($this->mode != CRYPT_DES_MODE_CTR && $this->mode != 'ctr') {
// 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_DES, '', $this->mode, '');
}
mcrypt_generic_init($this->demcrypt, $this->keys, $this->decryptIV);
$this->changed = false;
}
$plaintext = mdecrypt_generic($this->demcrypt, $ciphertext);
if (!$this->continuousBuffer) {
mcrypt_generic_init($this->demcrypt, $this->keys, $this->decryptIV);
}
return $this->mode != 'ctr' ? $this->_unpad($plaintext) : $plaintext;
}
if (!is_array($this->keys)) {
$this->keys = $this->_prepareKey("\0\0\0\0\0\0\0\0");
}
$plaintext = '';
switch ($this->mode) {
case CRYPT_DES_MODE_ECB:
for ($i = 0; $i < strlen($ciphertext); $i+=8) {
$plaintext.= $this->_processBlock(substr($ciphertext, $i, 8), CRYPT_DES_DECRYPT);
}
break;
case CRYPT_DES_MODE_CBC:
$xor = $this->decryptIV;
for ($i = 0; $i < strlen($ciphertext); $i+=8) {
$block = substr($ciphertext, $i, 8);
$plaintext.= $this->_processBlock($block, CRYPT_DES_DECRYPT) ^ $xor;
$xor = $block;
}
if ($this->continuousBuffer) {
$this->decryptIV = $xor;
}
break;
case CRYPT_DES_MODE_CTR:
$xor = $this->decryptIV;
for ($i = 0; $i < strlen($ciphertext); $i+=8) {
$block = substr($ciphertext, $i, 8);
$key = $this->_processBlock($this->_generate_xor(8, $xor), CRYPT_DES_ENCRYPT);
$plaintext.= $block ^ $key;
}
if ($this->continuousBuffer) {
$this->decryptIV = $xor;
}
}
return $this->mode != CRYPT_DES_MODE_CTR ? $this->_unpad($plaintext) : $plaintext;
}
/**
* Treat consecutive "packets" as if they are a continuous buffer.
*
* Say you have a 16-byte plaintext $plaintext. Using the default behavior, the two following code snippets
* will yield different outputs:
*
* <code>
* echo $des->encrypt(substr($plaintext, 0, 8));
* echo $des->encrypt(substr($plaintext, 8, 8));
* </code>
* <code>
* echo $des->encrypt($plaintext);
* </code>
*
* The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates
* another, as demonstrated with the following:
*
* <code>
* $des->encrypt(substr($plaintext, 0, 8));
* echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
* </code>
* <code>
* echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
* </code>
*
* With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
* outputs. The reason is due to the fact that the initialization vector's change after every encryption /
* decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
*
* Put another way, when the continuous buffer is enabled, the state of the Crypt_DES() object changes after each
* encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
* continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
* however, they are also less intuitive and more likely to cause you problems.
*
* @see Crypt_DES::disableContinuousBuffer()
* @access public
*/
function enableContinuousBuffer()
{
$this->continuousBuffer = true;
}
/**
* Treat consecutive packets as if they are a discontinuous buffer.
*
* The default behavior.
*
* @see Crypt_DES::enableContinuousBuffer()
* @access public
*/
function disableContinuousBuffer()
{
$this->continuousBuffer = false;
$this->encryptIV = $this->iv;
$this->decryptIV = $this->iv;
}
/**
* 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_DES::disablePadding()
* @access public
*/
function enablePadding()
{
$this->padding = true;
}
/**
* Do not pad packets.
*
* @see Crypt_DES::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_DES::_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_DES::_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);
}
/**
* Encrypts or decrypts a 64-bit block
*
* $mode should be either CRYPT_DES_ENCRYPT or CRYPT_DES_DECRYPT. See
* {@link http://en.wikipedia.org/wiki/Image:Feistel.png Feistel.png} to get a general
* idea of what this function does.
*
* @access private
* @param String $block
* @param Integer $mode
* @return String
*/
function _processBlock($block, $mode)
{
// s-boxes. in the official DES docs, they're described as being matrices that
// one accesses by using the first and last bits to determine the row and the
// middle four bits to determine the column. in this implementation, they've
// been converted to vectors
static $sbox = array(
array(
14, 0, 4, 15, 13, 7, 1, 4, 2, 14, 15, 2, 11, 13, 8, 1,
3, 10 ,10, 6, 6, 12, 12, 11, 5, 9, 9, 5, 0, 3, 7, 8,
4, 15, 1, 12, 14, 8, 8, 2, 13, 4, 6, 9, 2, 1, 11, 7,
15, 5, 12, 11, 9, 3, 7, 14, 3, 10, 10, 0, 5, 6, 0, 13
),
array(
15, 3, 1, 13, 8, 4, 14, 7, 6, 15, 11, 2, 3, 8, 4, 14,
9, 12, 7, 0, 2, 1, 13, 10, 12, 6, 0, 9, 5, 11, 10, 5,
0, 13, 14, 8, 7, 10, 11, 1, 10, 3, 4, 15, 13, 4, 1, 2,
5, 11, 8, 6, 12, 7, 6, 12, 9, 0, 3, 5, 2, 14, 15, 9
),
array(
10, 13, 0, 7, 9, 0, 14, 9, 6, 3, 3, 4, 15, 6, 5, 10,
1, 2, 13, 8, 12, 5, 7, 14, 11, 12, 4, 11, 2, 15, 8, 1,
13, 1, 6, 10, 4, 13, 9, 0, 8, 6, 15, 9, 3, 8, 0, 7,
11, 4, 1, 15, 2, 14, 12, 3, 5, 11, 10, 5, 14, 2, 7, 12
),
array(
7, 13, 13, 8, 14, 11, 3, 5, 0, 6, 6, 15, 9, 0, 10, 3,
1, 4, 2, 7, 8, 2, 5, 12, 11, 1, 12, 10, 4, 14, 15, 9,
10, 3, 6, 15, 9, 0, 0, 6, 12, 10, 11, 1, 7, 13, 13, 8,
15, 9, 1, 4, 3, 5, 14, 11, 5, 12, 2, 7, 8, 2, 4, 14
),
array(
2, 14, 12, 11, 4, 2, 1, 12, 7, 4, 10, 7, 11, 13, 6, 1,
8, 5, 5, 0, 3, 15, 15, 10, 13, 3, 0, 9, 14, 8, 9, 6,
4, 11, 2, 8, 1, 12, 11, 7, 10, 1, 13, 14, 7, 2, 8, 13,
15, 6, 9, 15, 12, 0, 5, 9, 6, 10, 3, 4, 0, 5, 14, 3
),
array(
12, 10, 1, 15, 10, 4, 15, 2, 9, 7, 2, 12, 6, 9, 8, 5,
0, 6, 13, 1, 3, 13, 4, 14, 14, 0, 7, 11, 5, 3, 11, 8,
9, 4, 14, 3, 15, 2, 5, 12, 2, 9, 8, 5, 12, 15, 3, 10,
7, 11, 0, 14, 4, 1, 10, 7, 1, 6, 13, 0, 11, 8, 6, 13
),
array(
4, 13, 11, 0, 2, 11, 14, 7, 15, 4, 0, 9, 8, 1, 13, 10,
3, 14, 12, 3, 9, 5, 7, 12, 5, 2, 10, 15, 6, 8, 1, 6,
1, 6, 4, 11, 11, 13, 13, 8, 12, 1, 3, 4, 7, 10, 14, 7,
10, 9, 15, 5, 6, 0, 8, 15, 0, 14, 5, 2, 9, 3, 2, 12
),
array(
13, 1, 2, 15, 8, 13, 4, 8, 6, 10, 15, 3, 11, 7, 1, 4,
10, 12, 9, 5, 3, 6, 14, 11, 5, 0, 0, 14, 12, 9, 7, 2,
7, 2, 11, 1, 4, 14, 1, 7, 9, 4, 12, 10, 14, 8, 2, 13,
0, 15, 6, 12, 10, 9, 13, 0, 15, 3, 3, 5, 5, 6, 8, 11
)
);
$keys = $this->keys;
$temp = unpack('Na/Nb', $block);
$block = array($temp['a'], $temp['b']);
// because php does arithmetic right shifts, if the most significant bits are set, right
// shifting those into the correct position will add 1's - not 0's. this will intefere
// with the | operation unless a second & is done. so we isolate these bits and left shift
// them into place. we then & each block with 0x7FFFFFFF to prevennt 1's from being added
// for any other shifts.
$msb = array(
($block[0] >> 31) & 1,
($block[1] >> 31) & 1
);
$block[0] &= 0x7FFFFFFF;
$block[1] &= 0x7FFFFFFF;
// we isolate the appropriate bit in the appropriate integer and shift as appropriate. in
// some cases, there are going to be multiple bits in the same integer that need to be shifted
// in the same way. we combine those into one shift operation.
$block = array(
(($block[1] & 0x00000040) << 25) | (($block[1] & 0x00004000) << 16) |
(($block[1] & 0x00400001) << 7) | (($block[1] & 0x40000100) >> 2) |
(($block[0] & 0x00000040) << 21) | (($block[0] & 0x00004000) << 12) |
(($block[0] & 0x00400001) << 3) | (($block[0] & 0x40000100) >> 6) |
(($block[1] & 0x00000010) << 19) | (($block[1] & 0x00001000) << 10) |
(($block[1] & 0x00100000) << 1) | (($block[1] & 0x10000000) >> 8) |
(($block[0] & 0x00000010) << 15) | (($block[0] & 0x00001000) << 6) |
(($block[0] & 0x00100000) >> 3) | (($block[0] & 0x10000000) >> 12) |
(($block[1] & 0x00000004) << 13) | (($block[1] & 0x00000400) << 4) |
(($block[1] & 0x00040000) >> 5) | (($block[1] & 0x04000000) >> 14) |
(($block[0] & 0x00000004) << 9) | ( $block[0] & 0x00000400 ) |
(($block[0] & 0x00040000) >> 9) | (($block[0] & 0x04000000) >> 18) |
(($block[1] & 0x00010000) >> 11) | (($block[1] & 0x01000000) >> 20) |
(($block[0] & 0x00010000) >> 15) | (($block[0] & 0x01000000) >> 24)
,
(($block[1] & 0x00000080) << 24) | (($block[1] & 0x00008000) << 15) |
(($block[1] & 0x00800002) << 6) | (($block[0] & 0x00000080) << 20) |
(($block[0] & 0x00008000) << 11) | (($block[0] & 0x00800002) << 2) |
(($block[1] & 0x00000020) << 18) | (($block[1] & 0x00002000) << 9) |
( $block[1] & 0x00200000 ) | (($block[1] & 0x20000000) >> 9) |
(($block[0] & 0x00000020) << 14) | (($block[0] & 0x00002000) << 5) |
(($block[0] & 0x00200000) >> 4) | (($block[0] & 0x20000000) >> 13) |
(($block[1] & 0x00000008) << 12) | (($block[1] & 0x00000800) << 3) |
(($block[1] & 0x00080000) >> 6) | (($block[1] & 0x08000000) >> 15) |
(($block[0] & 0x00000008) << 8) | (($block[0] & 0x00000800) >> 1) |
(($block[0] & 0x00080000) >> 10) | (($block[0] & 0x08000000) >> 19) |
(($block[1] & 0x00000200) >> 3) | (($block[0] & 0x00000200) >> 7) |
(($block[1] & 0x00020000) >> 12) | (($block[1] & 0x02000000) >> 21) |
(($block[0] & 0x00020000) >> 16) | (($block[0] & 0x02000000) >> 25) |
($msb[1] << 28) | ($msb[0] << 24)
);
for ($i = 0; $i < 16; $i++) {
// start of "the Feistel (F) function" - see the following URL:
// http://en.wikipedia.org/wiki/Image:Data_Encryption_Standard_InfoBox_Diagram.png
$temp = (($sbox[0][((($block[1] >> 27) & 0x1F) | (($block[1] & 1) << 5)) ^ $keys[$mode][$i][0]]) << 28)
| (($sbox[1][(($block[1] & 0x1F800000) >> 23) ^ $keys[$mode][$i][1]]) << 24)
| (($sbox[2][(($block[1] & 0x01F80000) >> 19) ^ $keys[$mode][$i][2]]) << 20)
| (($sbox[3][(($block[1] & 0x001F8000) >> 15) ^ $keys[$mode][$i][3]]) << 16)
| (($sbox[4][(($block[1] & 0x0001F800) >> 11) ^ $keys[$mode][$i][4]]) << 12)
| (($sbox[5][(($block[1] & 0x00001F80) >> 7) ^ $keys[$mode][$i][5]]) << 8)
| (($sbox[6][(($block[1] & 0x000001F8) >> 3) ^ $keys[$mode][$i][6]]) << 4)
| ( $sbox[7][((($block[1] & 0x1F) << 1) | (($block[1] >> 31) & 1)) ^ $keys[$mode][$i][7]]);
$msb = ($temp >> 31) & 1;
$temp &= 0x7FFFFFFF;
$newBlock = (($temp & 0x00010000) << 15) | (($temp & 0x02020120) << 5)
| (($temp & 0x00001800) << 17) | (($temp & 0x01000000) >> 10)
| (($temp & 0x00000008) << 24) | (($temp & 0x00100000) << 6)
| (($temp & 0x00000010) << 21) | (($temp & 0x00008000) << 9)
| (($temp & 0x00000200) << 12) | (($temp & 0x10000000) >> 27)
| (($temp & 0x00000040) << 14) | (($temp & 0x08000000) >> 8)
| (($temp & 0x00004000) << 4) | (($temp & 0x00000002) << 16)
| (($temp & 0x00442000) >> 6) | (($temp & 0x40800000) >> 15)
| (($temp & 0x00000001) << 11) | (($temp & 0x20000000) >> 20)
| (($temp & 0x00080000) >> 13) | (($temp & 0x00000004) << 3)
| (($temp & 0x04000000) >> 22) | (($temp & 0x00000480) >> 7)
| (($temp & 0x00200000) >> 19) | ($msb << 23);
// end of "the Feistel (F) function" - $newBlock is F's output
$temp = $block[1];
$block[1] = $block[0] ^ $newBlock;
$block[0] = $temp;
}
$msb = array(
($block[0] >> 31) & 1,
($block[1] >> 31) & 1
);
$block[0] &= 0x7FFFFFFF;
$block[1] &= 0x7FFFFFFF;
$block = array(
(($block[0] & 0x01000004) << 7) | (($block[1] & 0x01000004) << 6) |
(($block[0] & 0x00010000) << 13) | (($block[1] & 0x00010000) << 12) |
(($block[0] & 0x00000100) << 19) | (($block[1] & 0x00000100) << 18) |
(($block[0] & 0x00000001) << 25) | (($block[1] & 0x00000001) << 24) |
(($block[0] & 0x02000008) >> 2) | (($block[1] & 0x02000008) >> 3) |
(($block[0] & 0x00020000) << 4) | (($block[1] & 0x00020000) << 3) |
(($block[0] & 0x00000200) << 10) | (($block[1] & 0x00000200) << 9) |
(($block[0] & 0x00000002) << 16) | (($block[1] & 0x00000002) << 15) |
(($block[0] & 0x04000000) >> 11) | (($block[1] & 0x04000000) >> 12) |
(($block[0] & 0x00040000) >> 5) | (($block[1] & 0x00040000) >> 6) |
(($block[0] & 0x00000400) << 1) | ( $block[1] & 0x00000400 ) |
(($block[0] & 0x08000000) >> 20) | (($block[1] & 0x08000000) >> 21) |
(($block[0] & 0x00080000) >> 14) | (($block[1] & 0x00080000) >> 15) |
(($block[0] & 0x00000800) >> 8) | (($block[1] & 0x00000800) >> 9)
,
(($block[0] & 0x10000040) << 3) | (($block[1] & 0x10000040) << 2) |
(($block[0] & 0x00100000) << 9) | (($block[1] & 0x00100000) << 8) |
(($block[0] & 0x00001000) << 15) | (($block[1] & 0x00001000) << 14) |
(($block[0] & 0x00000010) << 21) | (($block[1] & 0x00000010) << 20) |
(($block[0] & 0x20000080) >> 6) | (($block[1] & 0x20000080) >> 7) |
( $block[0] & 0x00200000 ) | (($block[1] & 0x00200000) >> 1) |
(($block[0] & 0x00002000) << 6) | (($block[1] & 0x00002000) << 5) |
(($block[0] & 0x00000020) << 12) | (($block[1] & 0x00000020) << 11) |
(($block[0] & 0x40000000) >> 15) | (($block[1] & 0x40000000) >> 16) |
(($block[0] & 0x00400000) >> 9) | (($block[1] & 0x00400000) >> 10) |
(($block[0] & 0x00004000) >> 3) | (($block[1] & 0x00004000) >> 4) |
(($block[0] & 0x00800000) >> 18) | (($block[1] & 0x00800000) >> 19) |
(($block[0] & 0x00008000) >> 12) | (($block[1] & 0x00008000) >> 13) |
($msb[0] << 7) | ($msb[1] << 6)
);
return pack('NN', $block[0], $block[1]);
}
/**
* Creates the key schedule.
*
* @access private
* @param String $key
* @return Array
*/
function _prepareKey($key)
{
static $shifts = array( // number of key bits shifted per round
1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
);
// pad the key and remove extra characters as appropriate.
$key = str_pad(substr($key, 0, 8), 8, chr(0));
$temp = unpack('Na/Nb', $key);
$key = array($temp['a'], $temp['b']);
$msb = array(
($key[0] >> 31) & 1,
($key[1] >> 31) & 1
);
$key[0] &= 0x7FFFFFFF;
$key[1] &= 0x7FFFFFFF;
$key = array(
(($key[1] & 0x00000002) << 26) | (($key[1] & 0x00000204) << 17) |
(($key[1] & 0x00020408) << 8) | (($key[1] & 0x02040800) >> 1) |
(($key[0] & 0x00000002) << 22) | (($key[0] & 0x00000204) << 13) |
(($key[0] & 0x00020408) << 4) | (($key[0] & 0x02040800) >> 5) |
(($key[1] & 0x04080000) >> 10) | (($key[0] & 0x04080000) >> 14) |
(($key[1] & 0x08000000) >> 19) | (($key[0] & 0x08000000) >> 23) |
(($key[0] & 0x00000010) >> 1) | (($key[0] & 0x00001000) >> 10) |
(($key[0] & 0x00100000) >> 19) | (($key[0] & 0x10000000) >> 28)
,
(($key[1] & 0x00000080) << 20) | (($key[1] & 0x00008000) << 11) |
(($key[1] & 0x00800000) << 2) | (($key[0] & 0x00000080) << 16) |
(($key[0] & 0x00008000) << 7) | (($key[0] & 0x00800000) >> 2) |
(($key[1] & 0x00000040) << 13) | (($key[1] & 0x00004000) << 4) |
(($key[1] & 0x00400000) >> 5) | (($key[1] & 0x40000000) >> 14) |
(($key[0] & 0x00000040) << 9) | ( $key[0] & 0x00004000 ) |
(($key[0] & 0x00400000) >> 9) | (($key[0] & 0x40000000) >> 18) |
(($key[1] & 0x00000020) << 6) | (($key[1] & 0x00002000) >> 3) |
(($key[1] & 0x00200000) >> 12) | (($key[1] & 0x20000000) >> 21) |
(($key[0] & 0x00000020) << 2) | (($key[0] & 0x00002000) >> 7) |
(($key[0] & 0x00200000) >> 16) | (($key[0] & 0x20000000) >> 25) |
(($key[1] & 0x00000010) >> 1) | (($key[1] & 0x00001000) >> 10) |
(($key[1] & 0x00100000) >> 19) | (($key[1] & 0x10000000) >> 28) |
($msb[1] << 24) | ($msb[0] << 20)
);
$keys = array();
for ($i = 0; $i < 16; $i++) {
$key[0] <<= $shifts[$i];
$temp = ($key[0] & 0xF0000000) >> 28;
$key[0] = ($key[0] | $temp) & 0x0FFFFFFF;
$key[1] <<= $shifts[$i];
$temp = ($key[1] & 0xF0000000) >> 28;
$key[1] = ($key[1] | $temp) & 0x0FFFFFFF;
$temp = array(
(($key[1] & 0x00004000) >> 9) | (($key[1] & 0x00000800) >> 7) |
(($key[1] & 0x00020000) >> 14) | (($key[1] & 0x00000010) >> 2) |
(($key[1] & 0x08000000) >> 26) | (($key[1] & 0x00800000) >> 23)
,
(($key[1] & 0x02400000) >> 20) | (($key[1] & 0x00000001) << 4) |
(($key[1] & 0x00002000) >> 10) | (($key[1] & 0x00040000) >> 18) |
(($key[1] & 0x00000080) >> 6)
,
( $key[1] & 0x00000020 ) | (($key[1] & 0x00000200) >> 5) |
(($key[1] & 0x00010000) >> 13) | (($key[1] & 0x01000000) >> 22) |
(($key[1] & 0x00000004) >> 1) | (($key[1] & 0x00100000) >> 20)
,
(($key[1] & 0x00001000) >> 7) | (($key[1] & 0x00200000) >> 17) |
(($key[1] & 0x00000002) << 2) | (($key[1] & 0x00000100) >> 6) |
(($key[1] & 0x00008000) >> 14) | (($key[1] & 0x04000000) >> 26)
,
(($key[0] & 0x00008000) >> 10) | ( $key[0] & 0x00000010 ) |
(($key[0] & 0x02000000) >> 22) | (($key[0] & 0x00080000) >> 17) |
(($key[0] & 0x00000200) >> 8) | (($key[0] & 0x00000002) >> 1)
,
(($key[0] & 0x04000000) >> 21) | (($key[0] & 0x00010000) >> 12) |
(($key[0] & 0x00000020) >> 2) | (($key[0] & 0x00000800) >> 9) |
(($key[0] & 0x00800000) >> 22) | (($key[0] & 0x00000100) >> 8)
,
(($key[0] & 0x00001000) >> 7) | (($key[0] & 0x00000088) >> 3) |
(($key[0] & 0x00020000) >> 14) | (($key[0] & 0x00000001) << 2) |
(($key[0] & 0x00400000) >> 21)
,
(($key[0] & 0x00000400) >> 5) | (($key[0] & 0x00004000) >> 10) |
(($key[0] & 0x00000040) >> 3) | (($key[0] & 0x00100000) >> 18) |
(($key[0] & 0x08000000) >> 26) | (($key[0] & 0x01000000) >> 24)
);
$keys[] = $temp;
}
$temp = array(
CRYPT_DES_ENCRYPT => $keys,
CRYPT_DES_DECRYPT => array_reverse($keys)
);
return $temp;
}
}
// vim: ts=4:sw=4:et:
// vim6: fdl=1:

View File

@ -0,0 +1,816 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions.
*
* Uses hash() or mhash() if available and an internal implementation, otherwise. Currently supports the following:
*
* md2, md5, md5-96, sha1, sha1-96, sha256, sha384, and sha512
*
* If {@link Crypt_Hash::setKey() setKey()} is called, {@link Crypt_Hash::hash() hash()} will return the HMAC as opposed to
* the hash. If no valid algorithm is provided, sha1 will be used.
*
* PHP versions 4 and 5
*
* {@internal The variable names are the same as those in
* {@link http://tools.ietf.org/html/rfc2104#section-2 RFC2104}.}}
*
* Here's a short example of how to use this library:
* <code>
* <?php
* include('Crypt/Hash.php');
*
* $hash = new Crypt_Hash('sha1');
*
* $hash->setKey('abcdefg');
*
* echo base64_encode($hash->hash('abcdefg'));
* ?>
* </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.
*
* 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.
*
* 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
*
* @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$
* @link http://phpseclib.sourceforge.net
*/
/**#@+
* @access private
* @see Crypt_Hash::Crypt_Hash()
*/
/**
* Toggles the internal implementation
*/
define('CRYPT_HASH_MODE_INTERNAL', 1);
/**
* Toggles the mhash() implementation, which has been deprecated on PHP 5.3.0+.
*/
define('CRYPT_HASH_MODE_MHASH', 2);
/**
* Toggles the hash() implementation, which works on PHP 5.1.2+.
*/
define('CRYPT_HASH_MODE_HASH', 3);
/**#@-*/
/**
* Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions.
*
* @author Jim Wigginton <terrafrost@php.net>
* @version 0.1.0
* @access public
* @package Crypt_Hash
*/
class Crypt_Hash {
/**
* Byte-length of compression blocks / key (Internal HMAC)
*
* @see Crypt_Hash::setAlgorithm()
* @var Integer
* @access private
*/
var $b;
/**
* Byte-length of hash output (Internal HMAC)
*
* @see Crypt_Hash::setHash()
* @var Integer
* @access private
*/
var $l = false;
/**
* Hash Algorithm
*
* @see Crypt_Hash::setHash()
* @var String
* @access private
*/
var $hash;
/**
* Key
*
* @see Crypt_Hash::setKey()
* @var String
* @access private
*/
var $key = '';
/**
* Outer XOR (Internal HMAC)
*
* @see Crypt_Hash::setKey()
* @var String
* @access private
*/
var $opad;
/**
* Inner XOR (Internal HMAC)
*
* @see Crypt_Hash::setKey()
* @var String
* @access private
*/
var $ipad;
/**
* Default Constructor.
*
* @param optional String $hash
* @return Crypt_Hash
* @access public
*/
function Crypt_Hash($hash = 'sha1')
{
if ( !defined('CRYPT_HASH_MODE') ) {
switch (true) {
case extension_loaded('hash'):
define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_HASH);
break;
case extension_loaded('mhash'):
define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_MHASH);
break;
default:
define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_INTERNAL);
}
}
$this->setHash($hash);
}
/**
* Sets the key for HMACs
*
* Keys can be of any length.
*
* @access public
* @param String $key
*/
function setKey($key)
{
$this->key = $key;
}
/**
* Sets the hash function.
*
* @access public
* @param String $hash
*/
function setHash($hash)
{
switch ($hash) {
case 'md5-96':
case 'sha1-96':
$this->l = 12; // 96 / 8 = 12
break;
case 'md2':
case 'md5':
$this->l = 16;
break;
case 'sha1':
$this->l = 20;
break;
case 'sha256':
$this->l = 32;
break;
case 'sha384':
$this->l = 48;
break;
case 'sha512':
$this->l = 64;
}
switch ($hash) {
case 'md2':
$mode = CRYPT_HASH_MODE_INTERNAL;
break;
case 'sha384':
case 'sha512':
$mode = CRYPT_HASH_MODE == CRYPT_HASH_MODE_MHASH ? CRYPT_HASH_MODE_INTERNAL : CRYPT_HASH_MODE;
break;
default:
$mode = CRYPT_HASH_MODE;
}
switch ( $mode ) {
case CRYPT_HASH_MODE_MHASH:
switch ($hash) {
case 'md5':
case 'md5-96':
$this->hash = MHASH_MD5;
break;
case 'sha256':
$this->hash = MHASH_SHA256;
break;
case 'sha1':
case 'sha1-96':
default:
$this->hash = MHASH_SHA1;
}
return;
case CRYPT_HASH_MODE_HASH:
switch ($hash) {
case 'md5':
case 'md5-96':
$this->hash = 'md5';
return;
case 'sha256':
case 'sha384':
case 'sha512':
$this->hash = $hash;
return;
case 'sha1':
case 'sha1-96':
default:
$this->hash = 'sha1';
}
return;
}
switch ($hash) {
case 'md2':
$this->b = 16;
$this->hash = array($this, '_md2');
break;
case 'md5':
case 'md5-96':
$this->b = 64;
$this->hash = array($this, '_md5');
break;
case 'sha256':
$this->b = 64;
$this->hash = array($this, '_sha256');
break;
case 'sha384':
case 'sha512':
$this->b = 128;
$this->hash = array($this, '_sha512');
break;
case 'sha1':
case 'sha1-96':
default:
$this->b = 64;
$this->hash = array($this, '_sha1');
}
$this->ipad = str_repeat(chr(0x36), $this->b);
$this->opad = str_repeat(chr(0x5C), $this->b);
}
/**
* Compute the HMAC.
*
* @access public
* @param String $text
* @return String
*/
function hash($text)
{
$mode = is_array($this->hash) ? CRYPT_HASH_MODE_INTERNAL : CRYPT_HASH_MODE;
if (!empty($this->key)) {
switch ( $mode ) {
case CRYPT_HASH_MODE_MHASH:
$output = mhash($this->hash, $text, $this->key);
break;
case CRYPT_HASH_MODE_HASH:
$output = hash_hmac($this->hash, $text, $this->key, true);
break;
case CRYPT_HASH_MODE_INTERNAL:
/* "Applications that use keys longer than B bytes will first hash the key using H and then use the
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 = str_pad($key, $this->b, chr(0)); // step 1
$temp = $this->ipad ^ $key; // step 2
$temp .= $text; // step 3
$temp = call_user_func($this->hash, $temp); // step 4
$output = $this->opad ^ $key; // step 5
$output.= $temp; // step 6
$output = call_user_func($this->hash, $output); // step 7
}
} else {
switch ( $mode ) {
case CRYPT_HASH_MODE_MHASH:
$output = mhash($this->hash, $text);
break;
case CRYPT_HASH_MODE_HASH:
$output = hash($this->hash, $text, true);
break;
case CRYPT_HASH_MODE_INTERNAL:
$output = call_user_func($this->hash, $text);
}
}
return substr($output, 0, $this->l);
}
/**
* Returns the hash length (in bytes)
*
* @access private
* @return Integer
*/
function getLength()
{
return $this->l;
}
/**
* Wrapper for MD5
*
* @access private
* @param String $text
*/
function _md5($m)
{
return pack('H*', md5($m));
}
/**
* Wrapper for SHA1
*
* @access private
* @param String $text
*/
function _sha1($m)
{
return pack('H*', sha1($m));
}
/**
* Pure-PHP implementation of MD2
*
* See {@link http://tools.ietf.org/html/rfc1319 RFC1319}.
*
* @access private
* @param String $text
*/
function _md2($m)
{
static $s = array(
41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
31, 26, 219, 153, 141, 51, 159, 17, 131, 20
);
// Step 1. Append Padding Bytes
$pad = 16 - (strlen($m) & 0xF);
$m.= str_repeat(chr($pad), $pad);
$length = strlen($m);
// Step 2. Append Checksum
$c = str_repeat(chr(0), 16);
$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)]);
$l = $c[$j];
}
}
$m.= $c;
$length+= 16;
// Step 3. Initialize MD Buffer
$x = str_repeat(chr(0), 48);
// Step 4. Process Message in 16-Byte Blocks
for ($i = 0; $i < $length; $i+= 16) {
for ($j = 0; $j < 16; $j++) {
$x[$j + 16] = $m[$i + $j];
$x[$j + 32] = $x[$j + 16] ^ $x[$j];
}
$t = chr(0);
for ($j = 0; $j < 18; $j++) {
for ($k = 0; $k < 48; $k++) {
$x[$k] = $t = $x[$k] ^ chr($s[ord($t)]);
//$t = $x[$k] = $x[$k] ^ chr($s[ord($t)]);
}
$t = chr(ord($t) + $j);
}
}
// Step 5. Output
return substr($x, 0, 16);
}
/**
* Pure-PHP implementation of SHA256
*
* 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
*/
function _sha256($m)
{
if (extension_loaded('suhosin')) {
return pack('H*', sha256($m));
}
// Initialize variables
$hash = array(
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
);
// Initialize table of round constants
// (first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311)
static $k = array(
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
);
// Pre-processing
$length = strlen($m);
// to round to nearest 56 mod 64, we'll add 64 - (length + (64 - 56)) % 64
$m.= str_repeat(chr(0), 64 - (($length + 8) & 0x3F));
$m[$length] = chr(0x80);
// we don't support hashing strings 512MB long
$m.= pack('N2', 0, $length << 3);
// Process the message in successive 512-bit chunks
$chunks = str_split($m, 64);
foreach ($chunks as $chunk) {
$w = array();
for ($i = 0; $i < 16; $i++) {
extract(unpack('Ntemp', $this->_string_shift($chunk, 4)));
$w[] = $temp;
}
// Extend the sixteen 32-bit words into sixty-four 32-bit words
for ($i = 16; $i < 64; $i++) {
$s0 = $this->_rightRotate($w[$i - 15], 7) ^
$this->_rightRotate($w[$i - 15], 18) ^
$this->_rightShift( $w[$i - 15], 3);
$s1 = $this->_rightRotate($w[$i - 2], 17) ^
$this->_rightRotate($w[$i - 2], 19) ^
$this->_rightShift( $w[$i - 2], 10);
$w[$i] = $this->_add($w[$i - 16], $s0, $w[$i - 7], $s1);
}
// Initialize hash value for this chunk
list($a, $b, $c, $d, $e, $f, $g, $h) = $hash;
// Main loop
for ($i = 0; $i < 64; $i++) {
$s0 = $this->_rightRotate($a, 2) ^
$this->_rightRotate($a, 13) ^
$this->_rightRotate($a, 22);
$maj = ($a & $b) ^
($a & $c) ^
($b & $c);
$t2 = $this->_add($s0, $maj);
$s1 = $this->_rightRotate($e, 6) ^
$this->_rightRotate($e, 11) ^
$this->_rightRotate($e, 25);
$ch = ($e & $f) ^
($this->_not($e) & $g);
$t1 = $this->_add($h, $s1, $ch, $k[$i], $w[$i]);
$h = $g;
$g = $f;
$f = $e;
$e = $this->_add($d, $t1);
$d = $c;
$c = $b;
$b = $a;
$a = $this->_add($t1, $t2);
}
// Add this chunk's hash to result so far
$hash = array(
$this->_add($hash[0], $a),
$this->_add($hash[1], $b),
$this->_add($hash[2], $c),
$this->_add($hash[3], $d),
$this->_add($hash[4], $e),
$this->_add($hash[5], $f),
$this->_add($hash[6], $g),
$this->_add($hash[7], $h)
);
}
// Produce the final hash value (big-endian)
return pack('N8', $hash[0], $hash[1], $hash[2], $hash[3], $hash[4], $hash[5], $hash[6], $hash[7]);
}
/**
* Pure-PHP implementation of SHA384 and SHA512
*
* @access private
* @param String $text
*/
function _sha512($m)
{
if (!class_exists('Math_BigInteger')) {
require_once('Math/BigInteger.php');
}
static $init384, $init512, $k;
if (!isset($k)) {
// Initialize variables
$init384 = array( // initial values for SHA384
'cbbb9d5dc1059ed8', '629a292a367cd507', '9159015a3070dd17', '152fecd8f70e5939',
'67332667ffc00b31', '8eb44a8768581511', 'db0c2e0d64f98fa7', '47b5481dbefa4fa4'
);
$init512 = array( // initial values for SHA512
'6a09e667f3bcc908', 'bb67ae8584caa73b', '3c6ef372fe94f82b', 'a54ff53a5f1d36f1',
'510e527fade682d1', '9b05688c2b3e6c1f', '1f83d9abfb41bd6b', '5be0cd19137e2179'
);
for ($i = 0; $i < 8; $i++) {
$init384[$i] = new Math_BigInteger($init384[$i], 16);
$init384[$i]->setPrecision(64);
$init512[$i] = new Math_BigInteger($init512[$i], 16);
$init512[$i]->setPrecision(64);
}
// Initialize table of round constants
// (first 64 bits of the fractional parts of the cube roots of the first 80 primes 2..409)
$k = array(
'428a2f98d728ae22', '7137449123ef65cd', 'b5c0fbcfec4d3b2f', 'e9b5dba58189dbbc',
'3956c25bf348b538', '59f111f1b605d019', '923f82a4af194f9b', 'ab1c5ed5da6d8118',
'd807aa98a3030242', '12835b0145706fbe', '243185be4ee4b28c', '550c7dc3d5ffb4e2',
'72be5d74f27b896f', '80deb1fe3b1696b1', '9bdc06a725c71235', 'c19bf174cf692694',
'e49b69c19ef14ad2', 'efbe4786384f25e3', '0fc19dc68b8cd5b5', '240ca1cc77ac9c65',
'2de92c6f592b0275', '4a7484aa6ea6e483', '5cb0a9dcbd41fbd4', '76f988da831153b5',
'983e5152ee66dfab', 'a831c66d2db43210', 'b00327c898fb213f', 'bf597fc7beef0ee4',
'c6e00bf33da88fc2', 'd5a79147930aa725', '06ca6351e003826f', '142929670a0e6e70',
'27b70a8546d22ffc', '2e1b21385c26c926', '4d2c6dfc5ac42aed', '53380d139d95b3df',
'650a73548baf63de', '766a0abb3c77b2a8', '81c2c92e47edaee6', '92722c851482353b',
'a2bfe8a14cf10364', 'a81a664bbc423001', 'c24b8b70d0f89791', 'c76c51a30654be30',
'd192e819d6ef5218', 'd69906245565a910', 'f40e35855771202a', '106aa07032bbd1b8',
'19a4c116b8d2d0c8', '1e376c085141ab53', '2748774cdf8eeb99', '34b0bcb5e19b48a8',
'391c0cb3c5c95a63', '4ed8aa4ae3418acb', '5b9cca4f7763e373', '682e6ff3d6b2b8a3',
'748f82ee5defb2fc', '78a5636f43172f60', '84c87814a1f0ab72', '8cc702081a6439ec',
'90befffa23631e28', 'a4506cebde82bde9', 'bef9a3f7b2c67915', 'c67178f2e372532b',
'ca273eceea26619c', 'd186b8c721c0c207', 'eada7dd6cde0eb1e', 'f57d4f7fee6ed178',
'06f067aa72176fba', '0a637dc5a2c898a6', '113f9804bef90dae', '1b710b35131c471b',
'28db77f523047d84', '32caab7b40c72493', '3c9ebe0a15c9bebc', '431d67c49c100d4c',
'4cc5d4becb3e42b6', '597f299cfc657e2a', '5fcb6fab3ad6faec', '6c44198c4a475817'
);
for ($i = 0; $i < 80; $i++) {
$k[$i] = new Math_BigInteger($k[$i], 16);
}
}
$hash = $this->l == 48 ? $init384 : $init512;
// Pre-processing
$length = strlen($m);
// to round to nearest 112 mod 128, we'll add 128 - (length + (128 - 112)) % 128
$m.= str_repeat(chr(0), 128 - (($length + 16) & 0x7F));
$m[$length] = chr(0x80);
// we don't support hashing strings 512MB long
$m.= pack('N4', 0, 0, 0, $length << 3);
// Process the message in successive 1024-bit chunks
$chunks = str_split($m, 128);
foreach ($chunks as $chunk) {
$w = array();
for ($i = 0; $i < 16; $i++) {
$temp = new Math_BigInteger($this->_string_shift($chunk, 8), 256);
$temp->setPrecision(64);
$w[] = $temp;
}
// Extend the sixteen 32-bit words into eighty 32-bit words
for ($i = 16; $i < 80; $i++) {
$temp = array(
$w[$i - 15]->bitwise_rightRotate(1),
$w[$i - 15]->bitwise_rightRotate(8),
$w[$i - 15]->bitwise_rightShift(7)
);
$s0 = $temp[0]->bitwise_xor($temp[1]);
$s0 = $s0->bitwise_xor($temp[2]);
$temp = array(
$w[$i - 2]->bitwise_rightRotate(19),
$w[$i - 2]->bitwise_rightRotate(61),
$w[$i - 2]->bitwise_rightShift(6)
);
$s1 = $temp[0]->bitwise_xor($temp[1]);
$s1 = $s1->bitwise_xor($temp[2]);
$w[$i] = $w[$i - 16]->copy();
$w[$i] = $w[$i]->add($s0);
$w[$i] = $w[$i]->add($w[$i - 7]);
$w[$i] = $w[$i]->add($s1);
}
// Initialize hash value for this chunk
$a = $hash[0]->copy();
$b = $hash[1]->copy();
$c = $hash[2]->copy();
$d = $hash[3]->copy();
$e = $hash[4]->copy();
$f = $hash[5]->copy();
$g = $hash[6]->copy();
$h = $hash[7]->copy();
// Main loop
for ($i = 0; $i < 80; $i++) {
$temp = array(
$a->bitwise_rightRotate(28),
$a->bitwise_rightRotate(34),
$a->bitwise_rightRotate(39)
);
$s0 = $temp[0]->bitwise_xor($temp[1]);
$s0 = $s0->bitwise_xor($temp[2]);
$temp = array(
$a->bitwise_and($b),
$a->bitwise_and($c),
$b->bitwise_and($c)
);
$maj = $temp[0]->bitwise_xor($temp[1]);
$maj = $maj->bitwise_xor($temp[2]);
$t2 = $s0->add($maj);
$temp = array(
$e->bitwise_rightRotate(14),
$e->bitwise_rightRotate(18),
$e->bitwise_rightRotate(41)
);
$s1 = $temp[0]->bitwise_xor($temp[1]);
$s1 = $s1->bitwise_xor($temp[2]);
$temp = array(
$e->bitwise_and($f),
$g->bitwise_and($e->bitwise_not())
);
$ch = $temp[0]->bitwise_xor($temp[1]);
$t1 = $h->add($s1);
$t1 = $t1->add($ch);
$t1 = $t1->add($k[$i]);
$t1 = $t1->add($w[$i]);
$h = $g->copy();
$g = $f->copy();
$f = $e->copy();
$e = $d->add($t1);
$d = $c->copy();
$c = $b->copy();
$b = $a->copy();
$a = $t1->add($t2);
}
// Add this chunk's hash to result so far
$hash = array(
$hash[0]->add($a),
$hash[1]->add($b),
$hash[2]->add($c),
$hash[3]->add($d),
$hash[4]->add($e),
$hash[5]->add($f),
$hash[6]->add($g),
$hash[7]->add($h)
);
}
// Produce the final hash value (big-endian)
// (Crypt_Hash::hash() trims the output for hashes but not for HMACs. as such, we trim the output here)
$temp = $hash[0]->toBytes() . $hash[1]->toBytes() . $hash[2]->toBytes() . $hash[3]->toBytes() .
$hash[4]->toBytes() . $hash[5]->toBytes();
if ($this->l != 48) {
$temp.= $hash[6]->toBytes() . $hash[7]->toBytes();
}
return $temp;
}
/**
* Right Rotate
*
* @access private
* @param Integer $int
* @param Integer $amt
* @see _sha256()
* @return Integer
*/
function _rightRotate($int, $amt)
{
$invamt = 32 - $amt;
$mask = (1 << $invamt) - 1;
return (($int << $invamt) & 0xFFFFFFFF) | (($int >> $amt) & $mask);
}
/**
* Right Shift
*
* @access private
* @param Integer $int
* @param Integer $amt
* @see _sha256()
* @return Integer
*/
function _rightShift($int, $amt)
{
$mask = (1 << (32 - $amt)) - 1;
return ($int >> $amt) & $mask;
}
/**
* Not
*
* @access private
* @param Integer $int
* @see _sha256()
* @return Integer
*/
function _not($int)
{
return ~$int & 0xFFFFFFFF;
}
/**
* Add
*
* _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
* @see _sha256()
* @access private
*/
function _add()
{
static $mod;
if (!isset($mod)) {
$mod = pow(2, 32);
}
$result = 0;
$arguments = func_get_args();
foreach ($arguments as $argument) {
$result+= $argument < 0 ? ($argument & 0x7FFFFFFF) + 0x80000000 : $argument;
}
return fmod($result, $mod);
}
/**
* String Shift
*
* Inspired by array_shift
*
* @param String $string
* @param optional Integer $index
* @return String
* @access private
*/
function _string_shift(&$string, $index = 1)
{
$substr = substr($string, 0, $index);
$string = substr($string, $index);
return $substr;
}
}

493
lam/lib/3rdParty/phpseclib/Crypt/RC4.php vendored Normal file
View File

@ -0,0 +1,493 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* Pure-PHP implementation of RC4.
*
* Uses mcrypt, if available, and an internal implementation, otherwise.
*
* PHP versions 4 and 5
*
* Useful resources are as follows:
*
* - {@link http://www.mozilla.org/projects/security/pki/nss/draft-kaukonen-cipher-arcfour-03.txt ARCFOUR Algorithm}
* - {@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.
*
* Here's a short example of how to use this library:
* <code>
* <?php
* include('Crypt/RC4.php');
*
* $rc4 = new Crypt_RC4();
*
* $rc4->setKey('abcdefgh');
*
* $size = 10 * 1024;
* $plaintext = '';
* for ($i = 0; $i < $size; $i++) {
* $plaintext.= 'a';
* }
*
* echo $rc4->decrypt($rc4->encrypt($plaintext));
* ?>
* </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.
*
* 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.
*
* 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
*
* @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$
* @link http://phpseclib.sourceforge.net
*/
/**#@+
* @access private
* @see Crypt_RC4::Crypt_RC4()
*/
/**
* Toggles the internal implementation
*/
define('CRYPT_RC4_MODE_INTERNAL', 1);
/**
* Toggles the mcrypt implementation
*/
define('CRYPT_RC4_MODE_MCRYPT', 2);
/**#@-*/
/**#@+
* @access private
* @see Crypt_RC4::_crypt()
*/
define('CRYPT_RC4_ENCRYPT', 0);
define('CRYPT_RC4_DECRYPT', 1);
/**#@-*/
/**
* Pure-PHP implementation of RC4.
*
* @author Jim Wigginton <terrafrost@php.net>
* @version 0.1.0
* @access public
* @package Crypt_RC4
*/
class Crypt_RC4 {
/**
* The Key
*
* @see Crypt_RC4::setKey()
* @var String
* @access private
*/
var $key = "\0";
/**
* The Key Stream for encryption
*
* If CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT, this will be equal to the mcrypt object
*
* @see Crypt_RC4::setKey()
* @var Array
* @access private
*/
var $encryptStream = false;
/**
* The Key Stream for decryption
*
* If CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT, this will be equal to the mcrypt object
*
* @see Crypt_RC4::setKey()
* @var Array
* @access private
*/
var $decryptStream = false;
/**
* The $i and $j indexes for encryption
*
* @see Crypt_RC4::_crypt()
* @var Integer
* @access private
*/
var $encryptIndex = 0;
/**
* The $i and $j indexes for decryption
*
* @see Crypt_RC4::_crypt()
* @var Integer
* @access private
*/
var $decryptIndex = 0;
/**
* MCrypt parameters
*
* @see Crypt_RC4::setMCrypt()
* @var Array
* @access private
*/
var $mcrypt = array('', '');
/**
* The Encryption Algorithm
*
* Only used if CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT. Only possible values are MCRYPT_RC4 or MCRYPT_ARCFOUR.
*
* @see Crypt_RC4::Crypt_RC4()
* @var Integer
* @access private
*/
var $mode;
/**
* Default Constructor.
*
* Determines whether or not the mcrypt extension should be used.
*
* @param optional Integer $mode
* @return Crypt_RC4
* @access public
*/
function 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...
define('CRYPT_RC4_MODE', CRYPT_RC4_MODE_MCRYPT);
break;
default:
define('CRYPT_RC4_MODE', CRYPT_RC4_MODE_INTERNAL);
}
}
switch ( CRYPT_RC4_MODE ) {
case CRYPT_RC4_MODE_MCRYPT:
switch (true) {
case defined('MCRYPT_ARCFOUR'):
$this->mode = MCRYPT_ARCFOUR;
break;
case defined('MCRYPT_RC4');
$this->mode = MCRYPT_RC4;
}
}
}
/**
* Sets the key.
*
* Keys can be between 1 and 256 bytes long. If they are longer then 256 bytes, the first 256 bytes will
* be used. If no key is explicitly set, it'll be assumed to be a single null byte.
*
* @access public
* @param String $key
*/
function setKey($key)
{
$this->key = $key;
if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT ) {
return;
}
$keyLength = strlen($key);
$keyStream = array();
for ($i = 0; $i < 256; $i++) {
$keyStream[$i] = $i;
}
$j = 0;
for ($i = 0; $i < 256; $i++) {
$j = ($j + $keyStream[$i] + ord($key[$i % $keyLength])) & 255;
$temp = $keyStream[$i];
$keyStream[$i] = $keyStream[$j];
$keyStream[$j] = $temp;
}
$this->encryptIndex = $this->decryptIndex = array(0, 0);
$this->encryptStream = $this->decryptStream = $keyStream;
}
/**
* Dummy function.
*
* Some protocols, such as WEP, prepend an "initialization vector" to the key, effectively creating a new key [1].
* If you need to use an initialization vector in this manner, feel free to prepend it to the key, yourself, before
* calling setKey().
*
* [1] WEP's initialization vectors (IV's) are used in a somewhat insecure way. Since, in that protocol,
* the IV's are relatively easy to predict, an attack described by
* {@link http://www.drizzle.com/~aboba/IEEE/rc4_ksaproc.pdf Scott Fluhrer, Itsik Mantin, and Adi Shamir}
* can be used to quickly guess at the rest of the key. The following links elaborate:
*
* {@link http://www.rsa.com/rsalabs/node.asp?id=2009 http://www.rsa.com/rsalabs/node.asp?id=2009}
* {@link http://en.wikipedia.org/wiki/Related_key_attack http://en.wikipedia.org/wiki/Related_key_attack}
*
* @param String $iv
* @see Crypt_RC4::setKey()
* @access public
*/
function setIV($iv)
{
}
/**
* 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.
*
* @see Crypt_RC4::_crypt()
* @access public
* @param String $plaintext
*/
function encrypt($plaintext)
{
return $this->_crypt($plaintext, CRYPT_RC4_ENCRYPT);
}
/**
* Decrypts a message.
*
* $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)).
* Atleast if the continuous buffer is disabled.
*
* @see Crypt_RC4::_crypt()
* @access public
* @param String $ciphertext
*/
function decrypt($ciphertext)
{
return $this->_crypt($ciphertext, CRYPT_RC4_DECRYPT);
}
/**
* Encrypts or decrypts a message.
*
* @see Crypt_RC4::encrypt()
* @see Crypt_RC4::decrypt()
* @access private
* @param String $text
* @param Integer $mode
*/
function _crypt($text, $mode)
{
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);
}
return $newText;
}
if ($this->encryptStream === false) {
$this->setKey($this->key);
}
switch ($mode) {
case CRYPT_RC4_ENCRYPT:
$keyStream = $this->encryptStream;
list($i, $j) = $this->encryptIndex;
break;
case CRYPT_RC4_DECRYPT:
$keyStream = $this->decryptStream;
list($i, $j) = $this->decryptIndex;
}
$newText = '';
for ($k = 0; $k < strlen($text); $k++) {
$i = ($i + 1) & 255;
$j = ($j + $keyStream[$i]) & 255;
$temp = $keyStream[$i];
$keyStream[$i] = $keyStream[$j];
$keyStream[$j] = $temp;
$temp = $keyStream[($keyStream[$i] + $keyStream[$j]) & 255];
$newText.= chr(ord($text[$k]) ^ $temp);
}
if ($this->continuousBuffer) {
switch ($mode) {
case CRYPT_RC4_ENCRYPT:
$this->encryptStream = $keyStream;
$this->encryptIndex = array($i, $j);
break;
case CRYPT_RC4_DECRYPT:
$this->decryptStream = $keyStream;
$this->decryptIndex = array($i, $j);
}
}
return $newText;
}
/**
* Treat consecutive "packets" as if they are a continuous buffer.
*
* Say you have a 16-byte plaintext $plaintext. Using the default behavior, the two following code snippets
* will yield different outputs:
*
* <code>
* echo $rc4->encrypt(substr($plaintext, 0, 8));
* echo $rc4->encrypt(substr($plaintext, 8, 8));
* </code>
* <code>
* echo $rc4->encrypt($plaintext);
* </code>
*
* The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates
* another, as demonstrated with the following:
*
* <code>
* $rc4->encrypt(substr($plaintext, 0, 8));
* echo $rc4->decrypt($des->encrypt(substr($plaintext, 8, 8)));
* </code>
* <code>
* echo $rc4->decrypt($des->encrypt(substr($plaintext, 8, 8)));
* </code>
*
* With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
* outputs. The reason is due to the fact that the initialization vector's change after every encryption /
* decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
*
* Put another way, when the continuous buffer is enabled, the state of the Crypt_DES() object changes after each
* encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
* continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
* however, they are also less intuitive and more likely to cause you problems.
*
* @see Crypt_RC4::disableContinuousBuffer()
* @access public
*/
function enableContinuousBuffer()
{
$this->continuousBuffer = true;
}
/**
* Treat consecutive packets as if they are a discontinuous buffer.
*
* The default behavior.
*
* @see Crypt_RC4::enableContinuousBuffer()
* @access public
*/
function disableContinuousBuffer()
{
if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_INTERNAL ) {
$this->encryptIndex = $this->decryptIndex = array(0, 0);
$this->setKey($this->key);
}
$this->continuousBuffer = false;
}
/**
* Dummy function.
*
* Since RC4 is a stream cipher and not a block cipher, no padding is necessary. The only reason this function is
* included is so that you can switch between a block cipher and a stream cipher transparently.
*
* @see Crypt_RC4::disablePadding()
* @access public
*/
function enablePadding()
{
}
/**
* Dummy function.
*
* @see Crypt_RC4::enablePadding()
* @access public
*/
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;
}
}
}

2119
lam/lib/3rdParty/phpseclib/Crypt/RSA.php vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,130 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* Random Number Generator
*
* PHP versions 4 and 5
*
* Here's a short example of how to use this library:
* <code>
* <?php
* include('Crypt/Random.php');
*
* echo crypt_random();
* ?>
* </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.
*
* 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.
*
* 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
*
* @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$
* @link http://phpseclib.sourceforge.net
*/
/**
* Generate a random value.
*
* 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.
*
* 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.
*
* @param optional Integer $min
* @param optional Integer $max
* @return Integer
* @access public
*/
function crypt_random($min = 0, $max = 0x7FFFFFFF)
{
if ($min == $max) {
return $min;
}
// see http://en.wikipedia.org/wiki//dev/random
// if open_basedir is enabled file_exists() will ouput an "open_basedir restriction in effect" warning,
// so we suppress it.
if (@file_exists('/dev/urandom')) {
static $fp;
if (!$fp) {
$fp = fopen('/dev/urandom', 'rb');
}
extract(unpack('Nrandom', fread($fp, 4)));
// 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));
}
}
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));
}
switch (true) {
case class_exists('Crypt_AES'):
$crypto = new Crypt_AES(CRYPT_AES_MODE_CTR);
break;
case class_exists('Crypt_TripleDES'):
$crypto = new Crypt_TripleDES(CRYPT_DES_MODE_CTR);
break;
case class_exists('Crypt_DES'):
$crypto = new Crypt_DES(CRYPT_DES_MODE_CTR);
break;
case class_exists('Crypt_RC4'):
$crypto = new Crypt_RC4();
break;
default:
extract(unpack('Nrandom', pack('H*', sha1(mt_rand(0, 0x7FFFFFFF)))));
return abs($random) % ($max - $min) + $min;
}
$crypto->setKey($key);
$crypto->setIV($iv);
$crypto->enableContinuousBuffer();
}
extract(unpack('Nrandom', $crypto->encrypt("\0\0\0\0")));
return abs($random) % ($max - $min) + $min;
}
?>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,690 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* Pure-PHP implementation of Triple DES.
*
* Uses mcrypt, if available, and an internal implementation, otherwise. Operates in the EDE3 mode (encrypt-decrypt-encrypt).
*
* PHP versions 4 and 5
*
* Here's a short example of how to use this library:
* <code>
* <?php
* include('Crypt/TripleDES.php');
*
* $des = new Crypt_TripleDES();
*
* $des->setKey('abcdefghijklmnopqrstuvwx');
*
* $size = 10 * 1024;
* $plaintext = '';
* for ($i = 0; $i < $size; $i++) {
* $plaintext.= 'a';
* }
*
* echo $des->decrypt($des->encrypt($plaintext));
* ?>
* </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.
*
* 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.
*
* 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
*
* @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$
* @link http://phpseclib.sourceforge.net
*/
/**
* Include 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);
/**
* Encrypt / decrypt using outer chaining
*
* Outer chaining is used by SSH-2 and when the mode is set to CRYPT_DES_MODE_CBC.
*/
define('CRYPT_DES_MODE_CBC3', CRYPT_DES_MODE_CBC);
/**
* Pure-PHP implementation of Triple DES.
*
* @author Jim Wigginton <terrafrost@php.net>
* @version 0.1.0
* @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";
/**
* The Crypt_DES objects
*
* @var Array
* @access private
*/
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.
*
* Determines whether or not the mcrypt extension should be used. $mode should only, at present, be
* CRYPT_DES_MODE_ECB or CRYPT_DES_MODE_CBC. If not explictly set, CRYPT_DES_MODE_CBC will be used.
*
* @param optional Integer $mode
* @return Crypt_TripleDES
* @access public
*/
function Crypt_TripleDES($mode = CRYPT_DES_MODE_CBC)
{
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...
define('CRYPT_DES_MODE', CRYPT_DES_MODE_MCRYPT);
break;
default:
define('CRYPT_DES_MODE', CRYPT_DES_MODE_INTERNAL);
}
}
if ( $mode == CRYPT_DES_MODE_3CBC ) {
$this->mode = CRYPT_DES_MODE_3CBC;
$this->des = array(
new Crypt_DES(CRYPT_DES_MODE_CBC),
new Crypt_DES(CRYPT_DES_MODE_CBC),
new Crypt_DES(CRYPT_DES_MODE_CBC)
);
// we're going to be doing the padding, ourselves, so disable it in the Crypt_DES objects
$this->des[0]->disablePadding();
$this->des[1]->disablePadding();
$this->des[2]->disablePadding();
return;
}
switch ( CRYPT_DES_MODE ) {
case CRYPT_DES_MODE_MCRYPT:
switch ($mode) {
case CRYPT_DES_MODE_ECB:
$this->mode = MCRYPT_MODE_ECB;
break;
case CRYPT_DES_MODE_CTR:
$this->mode = 'ctr';
break;
case CRYPT_DES_MODE_CBC:
default:
$this->mode = MCRYPT_MODE_CBC;
}
break;
default:
$this->des = array(
new Crypt_DES(CRYPT_DES_MODE_ECB),
new Crypt_DES(CRYPT_DES_MODE_ECB),
new Crypt_DES(CRYPT_DES_MODE_ECB)
);
// we're going to be doing the padding, ourselves, so disable it in the Crypt_DES objects
$this->des[0]->disablePadding();
$this->des[1]->disablePadding();
$this->des[2]->disablePadding();
switch ($mode) {
case CRYPT_DES_MODE_ECB:
case CRYPT_DES_MODE_CTR:
case CRYPT_DES_MODE_CBC:
$this->mode = $mode;
break;
default:
$this->mode = CRYPT_DES_MODE_CBC;
}
}
}
/**
* Sets the key.
*
* Keys can be of any length. Triple DES, itself, can use 128-bit (eg. strlen($key) == 16) or
* 192-bit (eg. strlen($key) == 24) keys. This function pads and truncates $key as appropriate.
*
* DES also requires that every eighth bit be a parity bit, however, we'll ignore that.
*
* If the key is not explicitly set, it'll be assumed to be all zero's.
*
* @access public
* @param String $key
*/
function setKey($key)
{
$length = strlen($key);
if ($length > 8) {
$key = str_pad($key, 24, chr(0));
// 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);
}
$this->key = $key;
switch (true) {
case CRYPT_DES_MODE == CRYPT_DES_MODE_INTERNAL:
case $this->mode == CRYPT_DES_MODE_3CBC:
$this->des[0]->setKey(substr($key, 0, 8));
$this->des[1]->setKey(substr($key, 8, 8));
$this->des[2]->setKey(substr($key, 16, 8));
}
$this->changed = true;
}
/**
* Sets the initialization vector. (optional)
*
* SetIV is not required when CRYPT_DES_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)
{
$this->encryptIV = $this->decryptIV = $this->iv = str_pad(substr($iv, 0, 8), 8, chr(0));
if ($this->mode == CRYPT_DES_MODE_3CBC) {
$this->des[0]->setIV($iv);
$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;
}
/**
* Encrypts a message.
*
* @access public
* @param String $plaintext
*/
function encrypt($plaintext)
{
if ($this->mode != CRYPT_DES_MODE_CTR && $this->mode != 'ctr') {
$plaintext = $this->_pad($plaintext);
}
// if the key is smaller then 8, do what we'd normally do
if ($this->mode == CRYPT_DES_MODE_3CBC && strlen($this->key) > 8) {
$ciphertext = $this->des[2]->encrypt($this->des[1]->decrypt($this->des[0]->encrypt($plaintext)));
return $ciphertext;
}
if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) {
if ($this->changed) {
if (!isset($this->enmcrypt)) {
$this->enmcrypt = mcrypt_module_open(MCRYPT_3DES, '', $this->mode, '');
}
mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
$this->changed = false;
}
$ciphertext = mcrypt_generic($this->enmcrypt, $plaintext);
if (!$this->continuousBuffer) {
mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
}
return $ciphertext;
}
if (strlen($this->key) <= 8) {
$this->des[0]->mode = $this->mode;
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));
$des = $this->des;
$ciphertext = '';
switch ($this->mode) {
case CRYPT_DES_MODE_ECB:
for ($i = 0; $i < strlen($plaintext); $i+=8) {
$block = substr($plaintext, $i, 8);
$block = $des[0]->_processBlock($block, CRYPT_DES_ENCRYPT);
$block = $des[1]->_processBlock($block, CRYPT_DES_DECRYPT);
$block = $des[2]->_processBlock($block, CRYPT_DES_ENCRYPT);
$ciphertext.= $block;
}
break;
case CRYPT_DES_MODE_CBC:
$xor = $this->encryptIV;
for ($i = 0; $i < strlen($plaintext); $i+=8) {
$block = substr($plaintext, $i, 8) ^ $xor;
$block = $des[0]->_processBlock($block, CRYPT_DES_ENCRYPT);
$block = $des[1]->_processBlock($block, CRYPT_DES_DECRYPT);
$block = $des[2]->_processBlock($block, CRYPT_DES_ENCRYPT);
$xor = $block;
$ciphertext.= $block;
}
if ($this->continuousBuffer) {
$this->encryptIV = $xor;
}
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 ($this->continuousBuffer) {
$this->encryptIV = $xor;
}
}
return $ciphertext;
}
/**
* Decrypts a message.
*
* @access public
* @param String $ciphertext
*/
function decrypt($ciphertext)
{
if ($this->mode == CRYPT_DES_MODE_3CBC && strlen($this->key) > 8) {
$plaintext = $this->des[0]->decrypt($this->des[1]->encrypt($this->des[2]->decrypt($ciphertext)));
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 ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) {
if ($this->changed) {
if (!isset($this->demcrypt)) {
$this->demcrypt = mcrypt_module_open(MCRYPT_3DES, '', $this->mode, '');
}
mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
$this->changed = false;
}
$plaintext = mdecrypt_generic($this->demcrypt, $ciphertext);
if (!$this->continuousBuffer) {
mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
}
return $this->mode != 'ctr' ? $this->_unpad($plaintext) : $plaintext;
}
if (strlen($this->key) <= 8) {
$this->des[0]->mode = $this->mode;
return $this->_unpad($this->des[0]->decrypt($plaintext));
}
$des = $this->des;
$plaintext = '';
switch ($this->mode) {
case CRYPT_DES_MODE_ECB:
for ($i = 0; $i < strlen($ciphertext); $i+=8) {
$block = substr($ciphertext, $i, 8);
$block = $des[2]->_processBlock($block, CRYPT_DES_DECRYPT);
$block = $des[1]->_processBlock($block, CRYPT_DES_ENCRYPT);
$block = $des[0]->_processBlock($block, CRYPT_DES_DECRYPT);
$plaintext.= $block;
}
break;
case CRYPT_DES_MODE_CBC:
$xor = $this->decryptIV;
for ($i = 0; $i < strlen($ciphertext); $i+=8) {
$orig = $block = substr($ciphertext, $i, 8);
$block = $des[2]->_processBlock($block, CRYPT_DES_DECRYPT);
$block = $des[1]->_processBlock($block, CRYPT_DES_ENCRYPT);
$block = $des[0]->_processBlock($block, CRYPT_DES_DECRYPT);
$plaintext.= $block ^ $xor;
$xor = $orig;
}
if ($this->continuousBuffer) {
$this->decryptIV = $xor;
}
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 ($this->continuousBuffer) {
$this->decryptIV = $xor;
}
}
return $this->mode != CRYPT_DES_MODE_CTR ? $this->_unpad($plaintext) : $plaintext;
}
/**
* Treat consecutive "packets" as if they are a continuous buffer.
*
* Say you have a 16-byte plaintext $plaintext. Using the default behavior, the two following code snippets
* will yield different outputs:
*
* <code>
* echo $des->encrypt(substr($plaintext, 0, 8));
* echo $des->encrypt(substr($plaintext, 8, 8));
* </code>
* <code>
* echo $des->encrypt($plaintext);
* </code>
*
* The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates
* another, as demonstrated with the following:
*
* <code>
* $des->encrypt(substr($plaintext, 0, 8));
* echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
* </code>
* <code>
* echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
* </code>
*
* With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
* outputs. The reason is due to the fact that the initialization vector's change after every encryption /
* decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
*
* Put another way, when the continuous buffer is enabled, the state of the Crypt_DES() object changes after each
* encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
* continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
* however, they are also less intuitive and more likely to cause you problems.
*
* @see Crypt_TripleDES::disableContinuousBuffer()
* @access public
*/
function enableContinuousBuffer()
{
$this->continuousBuffer = true;
if ($this->mode == CRYPT_DES_MODE_3CBC) {
$this->des[0]->enableContinuousBuffer();
$this->des[1]->enableContinuousBuffer();
$this->des[2]->enableContinuousBuffer();
}
}
/**
* Treat consecutive packets as if they are a discontinuous buffer.
*
* The default behavior.
*
* @see Crypt_TripleDES::enableContinuousBuffer()
* @access public
*/
function disableContinuousBuffer()
{
$this->continuousBuffer = false;
$this->encryptIV = $this->iv;
$this->decryptIV = $this->iv;
if ($this->mode == CRYPT_DES_MODE_3CBC) {
$this->des[0]->disableContinuousBuffer();
$this->des[1]->disableContinuousBuffer();
$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:
// vim6: fdl=1:

File diff suppressed because it is too large Load Diff

1461
lam/lib/3rdParty/phpseclib/Net/SFTP.php vendored Normal file

File diff suppressed because it is too large Load Diff

1160
lam/lib/3rdParty/phpseclib/Net/SSH1.php vendored Normal file

File diff suppressed because it is too large Load Diff

2302
lam/lib/3rdParty/phpseclib/Net/SSH2.php vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,43 @@
<?php
// $Id$
/**
* Replace array_fill()
*
* @category PHP
* @package PHP_Compat
* @license LGPL - http://www.gnu.org/licenses/lgpl.html
* @copyright 2004-2007 Aidan Lister <aidan@php.net>, Arpad Ray <arpad@php.net>
* @link http://php.net/function.array_fill
* @author Jim Wigginton <terrafrost@php.net>
* @version $Revision$
* @since PHP 4.2.0
*/
function php_compat_array_fill($start_index, $num, $value)
{
if ($num <= 0) {
user_error('array_fill(): Number of elements must be positive', E_USER_WARNING);
return false;
}
$temp = array();
$end_index = $start_index + $num;
for ($i = (int) $start_index; $i < $end_index; $i++) {
$temp[$i] = $value;
}
return $temp;
}
// Define
if (!function_exists('array_fill')) {
function array_fill($start_index, $num, $value)
{
return php_compat_array_fill($start_index, $num, $value);
}
}
?>

View File

@ -0,0 +1,67 @@
<?php
// $Id$
/**
* Replace bcpowmod()
*
* @category PHP
* @package PHP_Compat
* @license LGPL - http://www.gnu.org/licenses/lgpl.html
* @copyright 2004-2007 Aidan Lister <aidan@php.net>, Arpad Ray <arpad@php.net>
* @link http://php.net/function.bcpowmod
* @author Sara Golemon <pollita@php.net>
* @version $Revision$
* @since PHP 5.0.0
* @require PHP 4.0.0 (user_error)
*/
function php_compat_bcpowmod($x, $y, $modulus, $scale = 0)
{
// Sanity check
if (!is_scalar($x)) {
user_error('bcpowmod() expects parameter 1 to be string, ' .
gettype($x) . ' given', E_USER_WARNING);
return false;
}
if (!is_scalar($y)) {
user_error('bcpowmod() expects parameter 2 to be string, ' .
gettype($y) . ' given', E_USER_WARNING);
return false;
}
if (!is_scalar($modulus)) {
user_error('bcpowmod() expects parameter 3 to be string, ' .
gettype($modulus) . ' given', E_USER_WARNING);
return false;
}
if (!is_scalar($scale)) {
user_error('bcpowmod() expects parameter 4 to be integer, ' .
gettype($scale) . ' given', E_USER_WARNING);
return false;
}
$t = '1';
while (bccomp($y, '0')) {
if (bccomp(bcmod($y, '2'), '0')) {
$t = bcmod(bcmul($t, $x), $modulus);
$y = bcsub($y, '1');
}
$x = bcmod(bcmul($x, $x), $modulus);
$y = bcdiv($y, '2');
}
return $t;
}
// Define
if (!function_exists('bcpowmod')) {
function bcpowmod($x, $y, $modulus, $scale = 0)
{
return php_compat_bcpowmod($x, $y, $modulus, $scale);
}
}
?>

View File

@ -0,0 +1,59 @@
<?php
/**
* Replace str_split()
*
* @category PHP
* @package PHP_Compat
* @license LGPL - http://www.gnu.org/licenses/lgpl.html
* @copyright 2004-2007 Aidan Lister <aidan@php.net>, Arpad Ray <arpad@php.net>
* @link http://php.net/function.str_split
* @author Aidan Lister <aidan@php.net>
* @version $Revision$
* @since PHP 5
* @require PHP 4.0.0 (user_error)
*/
function php_compat_str_split($string, $split_length = 1)
{
if (!is_scalar($split_length)) {
user_error('str_split() expects parameter 2 to be long, ' .
gettype($split_length) . ' given', E_USER_WARNING);
return false;
}
$split_length = (int) $split_length;
if ($split_length < 1) {
user_error('str_split() The length of each segment must be greater than zero', E_USER_WARNING);
return false;
}
// Select split method
if ($split_length < 65536) {
// Faster, but only works for less than 2^16
preg_match_all('/.{1,' . $split_length . '}/s', $string, $matches);
return $matches[0];
} else {
// Required due to preg limitations
$arr = array();
$idx = 0;
$pos = 0;
$len = strlen($string);
while ($len > 0) {
$blk = ($len < $split_length) ? $len : $split_length;
$arr[$idx++] = substr($string, $pos, $blk);
$pos += $blk;
$len -= $blk;
}
return $arr;
}
}
// Define
if (!function_exists('str_split')) {
function str_split($string, $split_length = 1)
{
return php_compat_str_split($string, $split_length);
}
}