--- /dev/null
+<?php
+/**
+ * An abstract class for simplifing creation of ciphers
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Cipher
+ * @subpackage Block
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Cipher\Block;
+
+/**
+ * An abstract class for simplifing creation of ciphers
+ *
+ * @category PHPCryptLib
+ * @package Cipher
+ * @subpackage Block
+ */
+abstract class AbstractCipher implements \CryptLib\Cipher\Block\Cipher {
+
+ /**
+ * @var int The block size for the cipher
+ */
+ protected $blockSize = 0;
+
+ /**
+ * @var string The cipher name for the current instance
+ */
+ protected $cipher = '';
+
+ /**
+ * @var boolean Is the cipher ready to encrypt/decrypt
+ */
+ protected $initialized = false;
+
+ /**
+ * @var string The key to use for encryption/decryption
+ */
+ protected $key = '';
+
+ /**
+ * @var int The size of the key to use
+ */
+ protected $keySize = 0;
+
+ /**
+ * Decrypt a block of data
+ *
+ * @param string $data The ciphertext to decrypt
+ *
+ * @return string The decrypted data
+ */
+ abstract protected function decryptBlockData($data);
+
+ /**
+ * Encrypt a block of data
+ *
+ * @param string $data The plaintext to encrypt
+ *
+ * @return string The encrypted cipher text
+ */
+ abstract protected function encryptBlockData($data);
+
+ /**
+ * Construct the instance for the supplied cipher name
+ *
+ * @param string $cipher The cipher to implement
+ *
+ * @return void
+ * @throws InvalidArgumentException if the cipher is not supported
+ */
+ public function __construct($cipher) {
+ $ciphers = static::getSupportedCiphers();
+ if (in_array($cipher, $ciphers)) {
+ $this->cipher = $cipher;
+ } else {
+ throw new \InvalidArgumentException('Unsupported Cipher Supplied');
+ }
+ }
+
+ /**
+ * Decrypt a block of data using the supplied string key.
+ *
+ * Note that the supplied data should be the same size as the block size of
+ * the cipher being used.
+ *
+ * @param string $data The data to decrypt
+ *
+ * @return string The result decrypted data
+ * @throws InvalidArgumentException If the data size is not the block size
+ * @throws RuntimeException If the cipher is not initialized
+ */
+ public function decryptBlock($data) {
+ $this->enforceInitializedCipher();
+ $this->enforceProperBlockSize($data);
+ return $this->decryptBlockData($data);
+ }
+
+ /**
+ * Encrypt a block of data using the supplied string key.
+ *
+ * Note that the supplied data should be the same size as the block size of
+ * the cipher being used.
+ *
+ * @param string $data The data to encrypt
+ *
+ * @return string The result encrypted data
+ * @throws InvalidArgumentException If the data size is not the block size
+ * @throws RuntimeException If the cipher is not initialized
+ */
+ public function encryptBlock($data) {
+ $this->enforceInitializedCipher();
+ $this->enforceProperBlockSize($data);
+ return $this->encryptBlockData($data);
+ }
+
+ /**
+ * Get the block size for the current initialized cipher
+ *
+ * @param string $key The key the data will be encrypted with
+ *
+ * @return int The block size for the current cipher
+ */
+ public function getBlockSize() {
+ return $this->blockSize;
+ }
+
+ /**
+ * Get the string name of the current cipher instance
+ *
+ * @return string The current instantiated cipher
+ */
+ public function getCipher() {
+ return $this->cipher;
+ }
+
+ /**
+ * Get the key size for the current initialized cipher
+ *
+ * @return int The key size for the current cipher
+ */
+ public function getKeySize() {
+ return $this->keySize;
+ }
+
+ /**
+ * Set the key to use for the cipher
+ *
+ * @param string $key The key to use
+ *
+ * @throws InvalidArgumentException If the key is not the correct size
+ * @return void
+ */
+ public function setKey($key) {
+ if (strlen($key) != $this->getKeySize()) {
+ throw new \InvalidArgumentException(
+ sprintf(
+ 'The supplied key block is not the correct size [%d:%d]',
+ strlen($key),
+ $this->getKeySize()
+ )
+ );
+ }
+ $this->key = $key;
+ $this->initialized = $this->initialize();
+ }
+
+ /**
+ * Check to see if the cipher is initialized
+ *
+ * @return void
+ * @throws RuntimeException If the cipher is not initialized
+ */
+ protected function enforceInitializedCipher() {
+ if (!$this->initialized) {
+ throw new \RuntimeException(
+ 'The cipher has not been properly initialized'
+ );
+ }
+ }
+
+ /**
+ * Check to see if the data is of the correct block size
+ *
+ * @param string $data The data block to check
+ *
+ * @return void
+ * @throws InvalidArgumentException if the data is not the correct size
+ */
+ protected function enforceProperBlockSize($data) {
+ if (strlen($data) != $this->getBlockSize()) {
+ throw new \InvalidArgumentException(
+ sprintf(
+ 'The supplied data block is not the correct size [%d:%d]',
+ strlen($data),
+ $this->getBlockSize()
+ )
+ );
+ }
+ }
+
+ /**
+ * Initialize the function after the key is set
+ *
+ * @return boolean The status of the initialization
+ */
+ protected function initialize() {
+ return true;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * An abstract class for simplifing creation of cipher modes
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Cipher
+ * @subpackage Block
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Cipher\Block;
+
+/**
+ * An abstract class for simplifing creation of cipher modes
+ *
+ * @category PHPCryptLib
+ * @package Cipher
+ * @subpackage Block
+ */
+abstract class AbstractMode implements \CryptLib\Cipher\Block\Mode {
+
+ /**
+ * @var string Additional data to authenticate with
+ */
+ protected $adata = '';
+
+ /**
+ * @var Cipher The cipher to use for this mode instance
+ */
+ protected $cipher = null;
+
+ /**
+ * @var string The initialization Vector to use for this mode
+ */
+ protected $initv = '';
+
+ /**
+ * @var string The mode name for the current instance
+ */
+ protected $mode = '';
+
+ /**
+ * @var array Mode specific options
+ */
+ protected $options = array();
+
+ /**
+ * @var string The internal state of the mode
+ */
+ protected $state = '';
+
+ /**
+ * Perform the decryption of the current block
+ *
+ * @param string $data The data to decrypt
+ *
+ * @return string The decrypted data
+ */
+ abstract protected function decryptBlock($data);
+
+ /**
+ * Perform the encryption of the current block
+ *
+ * @param string $data The data to encrypt
+ *
+ * @return string The encrypted data
+ */
+ abstract protected function encryptBlock($data);
+
+ /**
+ * Build the instance of the cipher mode
+ *
+ * @param Cipher $cipher The cipher to use for encryption/decryption
+ * @param string $initv The initialization vector (empty if not needed)
+ * @param array $options An array of mode-specific options
+ */
+ public function __construct(
+ \CryptLib\Cipher\Block\Cipher $cipher,
+ $initv,
+ array $options = array()
+ ) {
+ $class = strtolower(get_class($this));
+ $class = substr($class, strrpos($class, '\\') + 1);
+ $this->mode = $class;
+ $this->options = $options + $this->options;
+ $this->cipher = $cipher;
+ $this->initv = $initv;
+ $this->reset();
+ }
+
+ /**
+ * Decrypt the data using the supplied key, cipher and initialization vector
+ *
+ * @param string $data The data to decrypt
+ *
+ * @return string The decrypted data
+ */
+ public function decrypt($data) {
+ $this->enforceBlockSize($data);
+ return $this->decryptBlock($data);
+ }
+
+ /**
+ * Encrypt the data using the supplied key, cipher and initialization vector
+ *
+ * @param string $data The data to encrypt
+ *
+ * @return string The encrypted data
+ */
+ public function encrypt($data) {
+ $this->enforceBlockSize($data);
+ return $this->encryptBlock($data);
+ }
+
+ /**
+ * Finish the mode and append any additional data necessary
+ *
+ * @return string Any additional data
+ */
+ public function finish() {
+ return '';
+ }
+
+ /**
+ * Get the name of the current mode implementation
+ *
+ * @return string The current mode name
+ */
+ public function getMode() {
+ return $this->mode;
+ }
+
+ /**
+ * Reset the mode to start over (destroying any intermediate state)
+ *
+ * @return void
+ */
+ public function reset() {
+ $this->state = $this->initv;
+ }
+
+ /**
+ * Enforce the data block is the correct size for the cipher
+ *
+ * @param string $data The data to check
+ *
+ * @return void
+ * @throws InvalidArgumentException if the block size is not correct
+ */
+ protected function enforceBlockSize($data) {
+ if (strlen($data) != $this->cipher->getBlockSize()) {
+ throw new \InvalidArgumentException(
+ sprintf(
+ 'The data block must match the block size [%d:%d]',
+ strlen($data),
+ $this->cipher->getBlockSize()
+ )
+ );
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * The interface that all block ciphers must implement
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Cipher
+ * @subpackage Block
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Cipher\Block;
+
+/**
+ * The interface that all block ciphers must implement
+ *
+ * @category PHPCryptLib
+ * @package Cipher
+ * @subpackage Block
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @codeCoverageIgnore
+ */
+interface Cipher {
+
+ /**
+ * Get a list of supported ciphers by this cipher.
+ *
+ * @return array An array of supported cipher names (strings)
+ */
+ public static function getSupportedCiphers();
+
+ /**
+ * Decrypt a block of data using the supplied string key.
+ *
+ * Note that the supplied data should be the same size as the block size of
+ * the cipher being used.
+ *
+ * @param string $data The data to decrypt
+ *
+ * @return string The result decrypted data
+ */
+ public function decryptBlock($data);
+
+ /**
+ * Encrypt a block of data using the supplied string key.
+ *
+ * Note that the supplied data should be the same size as the block size of
+ * the cipher being used.
+ *
+ * @param string $data The data to encrypt
+ *
+ * @return string The result encrypted data
+ */
+ public function encryptBlock($data);
+
+ /**
+ * Get the block size for the current initialized cipher.
+ *
+ * @return int The block size for the current cipher
+ */
+ public function getBlockSize();
+
+ /**
+ * Get the key size for the current initialized cipher
+ *
+ * @return int The key size for the current cipher
+ */
+ public function getKeySize();
+
+ /**
+ * Get the string name of the current cipher instance.
+ *
+ * @return string The current instantiated cipher
+ */
+ public function getCipher();
+
+ /**
+ * Set the key to be used in this instance
+ *
+ * @param string $key The key the data will be encrypted with
+ *
+ * @return void
+ */
+ public function setKey($key);
+
+}
--- /dev/null
+<?php
+/**
+ * An implementation of the AES cipher, using the phpseclib implementation
+ *
+ * This was forked from phpseclib and modified to use CryptLib conventions
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Cipher
+ * @subpackage Block
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Cipher\Block\Cipher;
+
+/**
+ * An implementation of the AES cipher, using the phpseclib implementation
+ *
+ * @category PHPCryptLib
+ * @package Cipher
+ * @subpackage Block
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class AES extends Rijndael {
+
+ /**
+ * Get a list of supported ciphers for this class implementation
+ *
+ * @return array A list of supported ciphers
+ */
+ public static function getSupportedCiphers() {
+ return array(
+ 'aes-128',
+ 'aes-192',
+ 'aes-256',
+ );
+ }
+
+ /**
+ * Construct the instance for the supplied cipher name
+ *
+ * @param string $cipher The cipher to implement
+ *
+ * @return void
+ * @throws InvalidArgumentException if the cipher is not supported
+ */
+ public function __construct($cipher) {
+ parent::__construct($cipher);
+ list (, $bits) = explode('-', $cipher, 2);
+ $this->setBlockSize(128);
+ $this->setKeySize($bits);
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * An implementation of the DES cipher, using the phpseclib implementation
+ *
+ * This was forked from phpseclib and modified to use CryptLib conventions
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Cipher
+ * @subpackage Block
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Cipher\Block\Cipher;
+
+/**
+ * An implementation of the DES cipher, using the phpseclib implementation
+ *
+ * @category PHPCryptLib
+ * @package Cipher
+ * @subpackage Block
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class DES extends \CryptLib\Cipher\Block\AbstractCipher {
+
+ /**
+ * @var int The block size for the cipher
+ */
+ protected $blockSize = 8;
+
+ /**
+ * @var int The key size for the cipher
+ */
+ protected $keySize = 8;
+
+ /**
+ * @var array The prepared key schedule
+ */
+ protected $preparedKeys = array();
+
+ /**
+ * 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
+ *
+ * @var array The S-boxes
+ */
+ protected 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
+ )
+ );
+
+ /**
+ * @var array The key shift sequence for shifts per round of DES block
+ */
+ protected static $keyShifts = array(
+ 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
+ );
+
+ /**
+ * Get a list of supported ciphers for this class implementation
+ *
+ * @return array A list of supported ciphers
+ */
+ public static function getSupportedCiphers() {
+ return array('des');
+ }
+
+ /**
+ * Decrypt a block of data using the supplied string key
+ *
+ * Note that the supplied data should be the same size as the block size of
+ * the cipher being used.
+ *
+ * @param string $data The data to decrypt
+ *
+ * @return string The result decrypted data
+ */
+ protected function decryptBlockData($data) {
+ $keys = array_reverse($this->preparedKeys);
+ return $this->processBlock($data, $keys);
+ }
+
+ /**
+ * Encrypt a block of data using the supplied string key
+ *
+ * Note that the supplied data should be the same size as the block size of
+ * the cipher being used.
+ *
+ * @param string $data The data to encrypt
+ *
+ * @return string The result encrypted data
+ */
+ protected function encryptBlockData($data) {
+ return $this->processBlock($data, $this->preparedKeys);
+ }
+
+ /**
+ * Initialize the cipher by preparing the key
+ *
+ * @return boolean The status of the initialization
+ */
+ protected function initialize() {
+ $this->preparedKeys = $this->prepareKey($this->key);
+ return true;
+ }
+
+ /**
+ * Compute the keys necessary to execute the block cipher
+ *
+ * @param string $key The key to prepare
+ *
+ * @return array The prepared keys
+ */
+ private function prepareKey($key) {
+ // 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] <<= static::$keyShifts[$i];
+ $temp = ($key[0] & 0xF0000000) >> 28;
+ $key[0] = ($key[0] | $temp) & 0x0FFFFFFF;
+
+ $key[1] <<= static::$keyShifts[$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;
+ }
+
+ return $keys;
+ }
+
+ /**
+ * Process a block of data and encrypt (or decrypt depending upon key sequence)
+ *
+ * @param string $block The block of data to process
+ * @param array $keys The array of prepared keys to use
+ *
+ * @return string The processed block data
+ */
+ protected function processBlock($block, array $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"
+ $key = ((($block[1] >> 27) & 0x1F)
+ | (($block[1] & 1) << 5)) ^ $keys[$i][0];
+ $temp = ((static::$sbox[0][$key]) << 28);
+ $key = (($block[1] & 0x1F800000) >> 23) ^ $keys[$i][1];
+ $temp |= ((static::$sbox[1][$key]) << 24);
+ $key = (($block[1] & 0x01F80000) >> 19) ^ $keys[$i][2];
+ $temp |= ((static::$sbox[2][$key]) << 20);
+ $key = (($block[1] & 0x001F8000) >> 15) ^ $keys[$i][3];
+ $temp |= ((static::$sbox[3][$key]) << 16);
+ $key = (($block[1] & 0x0001F800) >> 11) ^ $keys[$i][4];
+ $temp |= ((static::$sbox[4][$key]) << 12);
+ $key = (($block[1] & 0x00001F80) >> 7) ^ $keys[$i][5];
+ $temp |= ((static::$sbox[5][$key]) << 8);
+ $key = (($block[1] & 0x000001F8) >> 3) ^ $keys[$i][6];
+ $temp |= ((static::$sbox[6][$key]) << 4);
+ $key = ((($block[1] & 0x1F) << 1)
+ | (($block[1] >> 31) & 1)) ^ $keys[$i][7];
+ $temp |= ( static::$sbox[7][$key]);
+
+ $msb = ($temp >> 31) & 1;
+ $temp &= 0x7FFFFFFF;
+ $nwB = (($temp & 0x00010000) << 15) | (($temp & 0x02020120) << 5);
+ $nwB |= (($temp & 0x00001800) << 17) | (($temp & 0x01000000) >> 10);
+ $nwB |= (($temp & 0x00000008) << 24) | (($temp & 0x00100000) << 6);
+ $nwB |= (($temp & 0x00000010) << 21) | (($temp & 0x00008000) << 9);
+ $nwB |= (($temp & 0x00000200) << 12) | (($temp & 0x10000000) >> 27);
+ $nwB |= (($temp & 0x00000040) << 14) | (($temp & 0x08000000) >> 8);
+ $nwB |= (($temp & 0x00004000) << 4) | (($temp & 0x00000002) << 16);
+ $nwB |= (($temp & 0x00442000) >> 6) | (($temp & 0x40800000) >> 15);
+ $nwB |= (($temp & 0x00000001) << 11) | (($temp & 0x20000000) >> 20);
+ $nwB |= (($temp & 0x00080000) >> 13) | (($temp & 0x00000004) << 3);
+ $nwB |= (($temp & 0x04000000) >> 22) | (($temp & 0x00000480) >> 7);
+ $nwB |= (($temp & 0x00200000) >> 19) | ($msb << 23);
+ // end of "the Feistel (F) function" - $newBlock is F's output
+
+ $temp = $block[1];
+ $block[1] = $block[0] ^ $nwB;
+ $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]);
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * The mcrypt block cipher implementation
+ *
+ * This class is used above all other implementations since it uses a core PHP
+ * library if it is available.
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Cipher
+ * @subpackage Block
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Cipher\Block\Cipher;
+
+/**
+ * The mcrypt block cipher implementation
+ *
+ * This class is used above all other implementations since it uses a core PHP
+ * library if it is available.
+ *
+ * @category PHPCryptLib
+ * @package Cipher
+ * @subpackage Block
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class MCrypt extends \CryptLib\Cipher\Block\AbstractCipher {
+
+ /**
+ * @var resource The mcrypt resource for cipher operations
+ */
+ protected $mcrypt = null;
+
+ /**
+ * Get a list of supported ciphers for this class implementation
+ *
+ * @return array A list of supported ciphers
+ */
+ public static function getSupportedCiphers() {
+ // @codeCoverageIgnoreStart
+ if (!function_exists('mcrypt_list_algorithms')) {
+ return array();
+ }
+ // @codeCoverageIgnoreEnd
+ return mcrypt_list_algorithms();
+ }
+
+ /**
+ * Construct the instance for the supplied cipher name
+ *
+ * @param string $cipher The cipher to implement
+ *
+ * @return void
+ * @throws InvalidArgumentException if the cipher is not supported
+ */
+ public function __construct($cipher) {
+ parent::__construct($cipher);
+ $this->keySize = mcrypt_get_key_size($cipher, MCRYPT_MODE_ECB);
+ $this->blockSize = mcrypt_get_block_size($cipher, MCRYPT_MODE_ECB);
+ }
+
+ /**
+ * Destroy the mcrypt module if it's open
+ *
+ * @return void
+ */
+ public function __destruct() {
+ if ($this->mcrypt) {
+ mcrypt_module_close($this->mcrypt);
+ }
+ }
+
+ /**
+ * Set the key to use for the cipher
+ *
+ * @param string $key The key to use
+ *
+ * @throws InvalidArgumentException If the key is not the correct size
+ * @return void
+ */
+ public function setKey($key) {
+ switch ($this->cipher) {
+ case 'rijndael-128':
+ case 'rijndael-192':
+ case 'rijndael-256':
+ if (!in_array(strlen($key), array(16, 20, 24, 28, 32))) {
+ throw new \InvalidArgumentException(
+ sprintf(
+ 'The supplied key block is in the valid sizes [%d:%s]',
+ strlen($key),
+ '16, 20, 24, 28, 32'
+ )
+ );
+ }
+ $this->keySize = strlen($key);
+ default:
+ parent::setKey($key);
+ }
+ }
+
+ /**
+ * Decrypt a block of data using the supplied string key
+ *
+ * Note that the supplied data should be the same size as the block size of
+ * the cipher being used.
+ *
+ * @param string $data The data to decrypt
+ *
+ * @return string The result decrypted data
+ */
+ protected function decryptBlockData($data) {
+ return mdecrypt_generic($this->mcrypt, $data);
+ }
+
+ /**
+ * Encrypt a block of data using the supplied string key
+ *
+ * Note that the supplied data should be the same size as the block size of
+ * the cipher being used.
+ *
+ * @param string $data The data to encrypt
+ *
+ * @return string The result encrypted data
+ */
+ protected function encryptBlockData($data) {
+ return mcrypt_generic($this->mcrypt, $data);
+ }
+
+ /**
+ * Initialize the cipher by preparing the key
+ *
+ * @return boolean The status of the initialization
+ * @codeCoverageIgnore
+ */
+ protected function initialize() {
+ if ($this->mcrypt) {
+ mcrypt_module_close($this->mcrypt);
+ }
+ $this->mcrypt = mcrypt_module_open($this->cipher, '', MCRYPT_MODE_ECB, '');
+ if ($this->mcrypt) {
+ $initv = str_repeat(chr(0), $this->getBlockSize());
+ return false !== mcrypt_generic_init($this->mcrypt, $this->key, $initv);
+ }
+ return false;
+ }
+
+}
--- /dev/null
+<?php
+
+/**
+ * An implementation of the Rijndael cipher, using the phpseclib implementation
+ *
+ * This was forked from phpseclib and modified to use CryptLib conventions
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Cipher
+ * @subpackage Block
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Cipher\Block\Cipher;
+
+/**
+ * An implementation of the Rijndael cipher, using the phpseclib implementation
+ *
+ * @category PHPCryptLib
+ * @package Cipher
+ * @subpackage Block
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class Rijndael extends \CryptLib\Cipher\Block\AbstractCipher {
+
+ /**
+ * @var int The number of bytes in each block
+ */
+ protected $blockSize = 16;
+
+ /**
+ * @var array The decryption key schedule
+ */
+ protected $decryptionSchedule = array();
+
+ /**
+ * @var array The encryption key schedule
+ */
+ protected $encryptionSchedule = array();
+
+ /**
+ * @var int The number of bytes in the key
+ */
+ protected $keySize = 16;
+
+ /**
+ * @var array The shift offsets used by the cipher
+ */
+ protected $shiftOffsets = array(0, 1, 2, 3);
+
+ /**
+ * @var array The rcon static array
+ */
+ protected static $rcon = array(0,
+ 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000,
+ 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000,
+ 0x6C000000, 0xD8000000, 0xAB000000, 0x4D000000, 0x9A000000,
+ 0x2F000000, 0x5E000000, 0xBC000000, 0x63000000, 0xC6000000,
+ 0x97000000, 0x35000000, 0x6A000000, 0xD4000000, 0xB3000000,
+ 0x7D000000, 0xFA000000, 0xEF000000, 0xC5000000, 0x91000000
+ );
+
+ /**
+ * @var array The initial t array used by the cipher
+ */
+ protected static $tValues = array(
+ 0 => array(),
+ 1 => array(),
+ 2 => array(),
+ 3 => array(
+ 0x6363A5C6, 0x7C7C84F8, 0x777799EE, 0x7B7B8DF6, 0xF2F20DFF, 0x6B6BBDD6,
+ 0x6F6FB1DE, 0xC5C55491, 0x30305060, 0x01010302, 0x6767A9CE, 0x2B2B7D56,
+ 0xFEFE19E7, 0xD7D762B5, 0xABABE64D, 0x76769AEC, 0xCACA458F, 0x82829D1F,
+ 0xC9C94089, 0x7D7D87FA, 0xFAFA15EF, 0x5959EBB2, 0x4747C98E, 0xF0F00BFB,
+ 0xADADEC41, 0xD4D467B3, 0xA2A2FD5F, 0xAFAFEA45, 0x9C9CBF23, 0xA4A4F753,
+ 0x727296E4, 0xC0C05B9B, 0xB7B7C275, 0xFDFD1CE1, 0x9393AE3D, 0x26266A4C,
+ 0x36365A6C, 0x3F3F417E, 0xF7F702F5, 0xCCCC4F83, 0x34345C68, 0xA5A5F451,
+ 0xE5E534D1, 0xF1F108F9, 0x717193E2, 0xD8D873AB, 0x31315362, 0x15153F2A,
+ 0x04040C08, 0xC7C75295, 0x23236546, 0xC3C35E9D, 0x18182830, 0x9696A137,
+ 0x05050F0A, 0x9A9AB52F, 0x0707090E, 0x12123624, 0x80809B1B, 0xE2E23DDF,
+ 0xEBEB26CD, 0x2727694E, 0xB2B2CD7F, 0x75759FEA, 0x09091B12, 0x83839E1D,
+ 0x2C2C7458, 0x1A1A2E34, 0x1B1B2D36, 0x6E6EB2DC, 0x5A5AEEB4, 0xA0A0FB5B,
+ 0x5252F6A4, 0x3B3B4D76, 0xD6D661B7, 0xB3B3CE7D, 0x29297B52, 0xE3E33EDD,
+ 0x2F2F715E, 0x84849713, 0x5353F5A6, 0xD1D168B9, 0x00000000, 0xEDED2CC1,
+ 0x20206040, 0xFCFC1FE3, 0xB1B1C879, 0x5B5BEDB6, 0x6A6ABED4, 0xCBCB468D,
+ 0xBEBED967, 0x39394B72, 0x4A4ADE94, 0x4C4CD498, 0x5858E8B0, 0xCFCF4A85,
+ 0xD0D06BBB, 0xEFEF2AC5, 0xAAAAE54F, 0xFBFB16ED, 0x4343C586, 0x4D4DD79A,
+ 0x33335566, 0x85859411, 0x4545CF8A, 0xF9F910E9, 0x02020604, 0x7F7F81FE,
+ 0x5050F0A0, 0x3C3C4478, 0x9F9FBA25, 0xA8A8E34B, 0x5151F3A2, 0xA3A3FE5D,
+ 0x4040C080, 0x8F8F8A05, 0x9292AD3F, 0x9D9DBC21, 0x38384870, 0xF5F504F1,
+ 0xBCBCDF63, 0xB6B6C177, 0xDADA75AF, 0x21216342, 0x10103020, 0xFFFF1AE5,
+ 0xF3F30EFD, 0xD2D26DBF, 0xCDCD4C81, 0x0C0C1418, 0x13133526, 0xECEC2FC3,
+ 0x5F5FE1BE, 0x9797A235, 0x4444CC88, 0x1717392E, 0xC4C45793, 0xA7A7F255,
+ 0x7E7E82FC, 0x3D3D477A, 0x6464ACC8, 0x5D5DE7BA, 0x19192B32, 0x737395E6,
+ 0x6060A0C0, 0x81819819, 0x4F4FD19E, 0xDCDC7FA3, 0x22226644, 0x2A2A7E54,
+ 0x9090AB3B, 0x8888830B, 0x4646CA8C, 0xEEEE29C7, 0xB8B8D36B, 0x14143C28,
+ 0xDEDE79A7, 0x5E5EE2BC, 0x0B0B1D16, 0xDBDB76AD, 0xE0E03BDB, 0x32325664,
+ 0x3A3A4E74, 0x0A0A1E14, 0x4949DB92, 0x06060A0C, 0x24246C48, 0x5C5CE4B8,
+ 0xC2C25D9F, 0xD3D36EBD, 0xACACEF43, 0x6262A6C4, 0x9191A839, 0x9595A431,
+ 0xE4E437D3, 0x79798BF2, 0xE7E732D5, 0xC8C8438B, 0x3737596E, 0x6D6DB7DA,
+ 0x8D8D8C01, 0xD5D564B1, 0x4E4ED29C, 0xA9A9E049, 0x6C6CB4D8, 0x5656FAAC,
+ 0xF4F407F3, 0xEAEA25CF, 0x6565AFCA, 0x7A7A8EF4, 0xAEAEE947, 0x08081810,
+ 0xBABAD56F, 0x787888F0, 0x25256F4A, 0x2E2E725C, 0x1C1C2438, 0xA6A6F157,
+ 0xB4B4C773, 0xC6C65197, 0xE8E823CB, 0xDDDD7CA1, 0x74749CE8, 0x1F1F213E,
+ 0x4B4BDD96, 0xBDBDDC61, 0x8B8B860D, 0x8A8A850F, 0x707090E0, 0x3E3E427C,
+ 0xB5B5C471, 0x6666AACC, 0x4848D890, 0x03030506, 0xF6F601F7, 0x0E0E121C,
+ 0x6161A3C2, 0x35355F6A, 0x5757F9AE, 0xB9B9D069, 0x86869117, 0xC1C15899,
+ 0x1D1D273A, 0x9E9EB927, 0xE1E138D9, 0xF8F813EB, 0x9898B32B, 0x11113322,
+ 0x6969BBD2, 0xD9D970A9, 0x8E8E8907, 0x9494A733, 0x9B9BB62D, 0x1E1E223C,
+ 0x87879215, 0xE9E920C9, 0xCECE4987, 0x5555FFAA, 0x28287850, 0xDFDF7AA5,
+ 0x8C8C8F03, 0xA1A1F859, 0x89898009, 0x0D0D171A, 0xBFBFDA65, 0xE6E631D7,
+ 0x4242C684, 0x6868B8D0, 0x4141C382, 0x9999B029, 0x2D2D775A, 0x0F0F111E,
+ 0xB0B0CB7B, 0x5454FCA8, 0xBBBBD66D, 0x16163A2C
+ )
+ );
+
+ /**
+ * @var array The initial Decryption t value array
+ */
+ protected static $dtValues = array(
+ 0 => array(),
+ 1 => array(),
+ 2 => array(),
+ 3 => array(
+ 0xF4A75051, 0x4165537E, 0x17A4C31A, 0x275E963A, 0xAB6BCB3B, 0x9D45F11F,
+ 0xFA58ABAC, 0xE303934B, 0x30FA5520, 0x766DF6AD, 0xCC769188, 0x024C25F5,
+ 0xE5D7FC4F, 0x2ACBD7C5, 0x35448026, 0x62A38FB5, 0xB15A49DE, 0xBA1B6725,
+ 0xEA0E9845, 0xFEC0E15D, 0x2F7502C3, 0x4CF01281, 0x4697A38D, 0xD3F9C66B,
+ 0x8F5FE703, 0x929C9515, 0x6D7AEBBF, 0x5259DA95, 0xBE832DD4, 0x7421D358,
+ 0xE0692949, 0xC9C8448E, 0xC2896A75, 0x8E7978F4, 0x583E6B99, 0xB971DD27,
+ 0xE14FB6BE, 0x88AD17F0, 0x20AC66C9, 0xCE3AB47D, 0xDF4A1863, 0x1A3182E5,
+ 0x51336097, 0x537F4562, 0x6477E0B1, 0x6BAE84BB, 0x81A01CFE, 0x082B94F9,
+ 0x48685870, 0x45FD198F, 0xDE6C8794, 0x7BF8B752, 0x73D323AB, 0x4B02E272,
+ 0x1F8F57E3, 0x55AB2A66, 0xEB2807B2, 0xB5C2032F, 0xC57B9A86, 0x3708A5D3,
+ 0x2887F230, 0xBFA5B223, 0x036ABA02, 0x16825CED, 0xCF1C2B8A, 0x79B492A7,
+ 0x07F2F0F3, 0x69E2A14E, 0xDAF4CD65, 0x05BED506, 0x34621FD1, 0xA6FE8AC4,
+ 0x2E539D34, 0xF355A0A2, 0x8AE13205, 0xF6EB75A4, 0x83EC390B, 0x60EFAA40,
+ 0x719F065E, 0x6E1051BD, 0x218AF93E, 0xDD063D96, 0x3E05AEDD, 0xE6BD464D,
+ 0x548DB591, 0xC45D0571, 0x06D46F04, 0x5015FF60, 0x98FB2419, 0xBDE997D6,
+ 0x4043CC89, 0xD99E7767, 0xE842BDB0, 0x898B8807, 0x195B38E7, 0xC8EEDB79,
+ 0x7C0A47A1, 0x420FE97C, 0x841EC9F8, 0x00000000, 0x80868309, 0x2BED4832,
+ 0x1170AC1E, 0x5A724E6C, 0x0EFFFBFD, 0x8538560F, 0xAED51E3D, 0x2D392736,
+ 0x0FD9640A, 0x5CA62168, 0x5B54D19B, 0x362E3A24, 0x0A67B10C, 0x57E70F93,
+ 0xEE96D2B4, 0x9B919E1B, 0xC0C54F80, 0xDC20A261, 0x774B695A, 0x121A161C,
+ 0x93BA0AE2, 0xA02AE5C0, 0x22E0433C, 0x1B171D12, 0x090D0B0E, 0x8BC7ADF2,
+ 0xB6A8B92D, 0x1EA9C814, 0xF1198557, 0x75074CAF, 0x99DDBBEE, 0x7F60FDA3,
+ 0x01269FF7, 0x72F5BC5C, 0x663BC544, 0xFB7E345B, 0x4329768B, 0x23C6DCCB,
+ 0xEDFC68B6, 0xE4F163B8, 0x31DCCAD7, 0x63851042, 0x97224013, 0xC6112084,
+ 0x4A247D85, 0xBB3DF8D2, 0xF93211AE, 0x29A16DC7, 0x9E2F4B1D, 0xB230F3DC,
+ 0x8652EC0D, 0xC1E3D077, 0xB3166C2B, 0x70B999A9, 0x9448FA11, 0xE9642247,
+ 0xFC8CC4A8, 0xF03F1AA0, 0x7D2CD856, 0x3390EF22, 0x494EC787, 0x38D1C1D9,
+ 0xCAA2FE8C, 0xD40B3698, 0xF581CFA6, 0x7ADE28A5, 0xB78E26DA, 0xADBFA43F,
+ 0x3A9DE42C, 0x78920D50, 0x5FCC9B6A, 0x7E466254, 0x8D13C2F6, 0xD8B8E890,
+ 0x39F75E2E, 0xC3AFF582, 0x5D80BE9F, 0xD0937C69, 0xD52DA96F, 0x2512B3CF,
+ 0xAC993BC8, 0x187DA710, 0x9C636EE8, 0x3BBB7BDB, 0x267809CD, 0x5918F46E,
+ 0x9AB701EC, 0x4F9AA883, 0x956E65E6, 0xFFE67EAA, 0xBCCF0821, 0x15E8E6EF,
+ 0xE79BD9BA, 0x6F36CE4A, 0x9F09D4EA, 0xB07CD629, 0xA4B2AF31, 0x3F23312A,
+ 0xA59430C6, 0xA266C035, 0x4EBC3774, 0x82CAA6FC, 0x90D0B0E0, 0xA7D81533,
+ 0x04984AF1, 0xECDAF741, 0xCD500E7F, 0x91F62F17, 0x4DD68D76, 0xEFB04D43,
+ 0xAA4D54CC, 0x9604DFE4, 0xD1B5E39E, 0x6A881B4C, 0x2C1FB8C1, 0x65517F46,
+ 0x5EEA049D, 0x8C355D01, 0x877473FA, 0x0B412EFB, 0x671D5AB3, 0xDBD25292,
+ 0x105633E9, 0xD647136D, 0xD7618C9A, 0xA10C7A37, 0xF8148E59, 0x133C89EB,
+ 0xA927EECE, 0x61C935B7, 0x1CE5EDE1, 0x47B13C7A, 0xD2DF599C, 0xF2733F55,
+ 0x14CE7918, 0xC737BF73, 0xF7CDEA53, 0xFDAA5B5F, 0x3D6F14DF, 0x44DB8678,
+ 0xAFF381CA, 0x68C43EB9, 0x24342C38, 0xA3405FC2, 0x1DC37216, 0xE2250CBC,
+ 0x3C498B28, 0x0D9541FF, 0xA8017139, 0x0CB3DE08, 0xB4E49CD8, 0x56C19064,
+ 0xCB84617B, 0x32B670D5, 0x6C5C7448, 0xB85742D0
+ )
+ );
+
+ /**
+ * @var array The sboxes used for key expansion
+ */
+ protected static $sboxes = array(
+ 0 => array(
+ 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B,
+ 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,
+ 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26,
+ 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
+ 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2,
+ 0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,
+ 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED,
+ 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
+ 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F,
+ 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,
+ 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC,
+ 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
+ 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14,
+ 0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,
+ 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D,
+ 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
+ 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F,
+ 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,
+ 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11,
+ 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
+ 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F,
+ 0xB0, 0x54, 0xBB, 0x16
+ ),
+ 1 => array(),
+ 2 => array(),
+ 3 => array(),
+ );
+
+ /**
+ * @var array The inverse sboxes used for decryption
+ */
+ protected static $invSBoxes = array(
+ 0 => array(
+ 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E,
+ 0x81, 0xF3, 0xD7, 0xFB, 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87,
+ 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, 0x54, 0x7B, 0x94, 0x32,
+ 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
+ 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49,
+ 0x6D, 0x8B, 0xD1, 0x25, 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16,
+ 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, 0x6C, 0x70, 0x48, 0x50,
+ 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
+ 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05,
+ 0xB8, 0xB3, 0x45, 0x06, 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02,
+ 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, 0x3A, 0x91, 0x11, 0x41,
+ 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
+ 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8,
+ 0x1C, 0x75, 0xDF, 0x6E, 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89,
+ 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, 0xFC, 0x56, 0x3E, 0x4B,
+ 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
+ 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59,
+ 0x27, 0x80, 0xEC, 0x5F, 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D,
+ 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, 0xA0, 0xE0, 0x3B, 0x4D,
+ 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
+ 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63,
+ 0x55, 0x21, 0x0C, 0x7D
+ ),
+ 1 => array(),
+ 2 => array(),
+ 3 => array(),
+ );
+
+ /**
+ * Get a list of supported ciphers for this class implementation
+ *
+ * @return array A list of supported ciphers
+ */
+ public static function getSupportedCiphers() {
+ return array(
+ 'rijndael-128',
+ 'rijndael-160',
+ 'rijndael-192',
+ 'rijndael-224',
+ 'rijndael-256',
+ );
+ }
+
+ /**
+ * Initialize the tValues,dtValues,sboxes and inverseSBoxes arrays
+ * by calculating. Since this only needs to be done once, it's
+ * a static method
+ *
+ * @return void
+ */
+ protected static function init() {
+ if (empty(static::$tValues[0])) {
+ $t_3 = static::$tValues[3];
+ $dt3 = static::$dtValues[3];
+ for ($i = 0; $i < 256; $i++) {
+ static::$tValues[2][$i << 8] = (($t_3[$i] << 8) & 0xFFFFFF00)
+ | (($t_3[$i] >> 24) & 0x000000FF);
+ static::$tValues[1][$i << 16] = (($t_3[$i] << 16) & 0xFFFF0000)
+ | (($t_3[$i] >> 16) & 0x0000FFFF);
+ static::$tValues[0][$i << 24] = (($t_3[$i] << 24) & 0xFF000000)
+ | (($t_3[$i] >> 8) & 0x00FFFFFF);
+
+ static::$dtValues[2][$i << 8] = (($dt3[$i] << 8) & 0xFFFFFF00)
+ | (($dt3[$i] >> 24) & 0x000000FF);
+ static::$dtValues[1][$i << 16] = (($dt3[$i] << 16) & 0xFFFF0000)
+ | (($dt3[$i] >> 16) & 0x0000FFFF);
+ static::$dtValues[0][$i << 24] = (($dt3[$i] << 24) & 0xFF000000)
+ | (($dt3[$i] >> 8) & 0x00FFFFFF);
+
+ static::$sboxes[1][$i << 8] = static::$sboxes[0][$i] << 8;
+ static::$sboxes[2][$i << 16] = static::$sboxes[0][$i] << 16;
+ static::$sboxes[3][$i << 24] = static::$sboxes[0][$i] << 24;
+ static::$invSBoxes[1][$i << 8] = static::$invSBoxes[0][$i] << 8;
+ static::$invSBoxes[2][$i << 16] = static::$invSBoxes[0][$i] << 16;
+ static::$invSBoxes[3][$i << 24] = static::$invSBoxes[0][$i] << 24;
+ }
+ }
+ }
+
+ /**
+ * Construct the instance for the supplied cipher name
+ *
+ * @param string $cipher The cipher to implement
+ *
+ * @return void
+ * @throws InvalidArgumentException if the cipher is not supported
+ */
+ public function __construct($cipher) {
+ parent::__construct($cipher);
+ list (, $bits) = explode('-', $cipher, 2);
+ $this->setBlockSize($bits);
+ $this->setKeySize($bits);
+ static::init();
+ }
+
+ /**
+ * Set the key to use for the cipher
+ *
+ * @param string $key The key to use
+ *
+ * @throws InvalidArgumentException If the key is not the correct size
+ * @return void
+ */
+ public function setKey($key) {
+ $length = strlen($key);
+ if ($length != $this->keySize) {
+ $this->setKeySize($length << 3);
+ if ($length != $this->keySize) {
+ throw new \InvalidArgumentException(
+ 'The key is not of a supported length'
+ );
+ }
+ }
+ $this->key = $key;
+ $this->initialized = $this->initialize();
+ }
+
+ /**
+ * Decrypt a block of data using the supplied string key
+ *
+ * Note that the supplied data should be the same size as the block size of
+ * the cipher being used.
+ *
+ * @param string $data The data to decrypt
+ *
+ * @return string The result decrypted data
+ */
+ protected function decryptBlockData($data) {
+ $schedule = $this->decryptionSchedule;
+ return $this->decryptBlockPart($data, $schedule);
+ }
+
+ /**
+ * Encrypt a block of data using the supplied string key
+ *
+ * Note that the supplied data should be the same size as the block size of
+ * the cipher being used.
+ *
+ * @param string $data The data to encrypt
+ *
+ * @return string The result encrypted data
+ */
+ protected function encryptBlockData($data) {
+ $schedule = $this->encryptionSchedule;
+ return $this->encryptBlockPart($data, $schedule);
+ }
+
+ /**
+ * Initialize the cipher by preparing the key
+ *
+ * @return boolean The status of the initialization
+ */
+ protected function initialize() {
+ $this->encryptionSchedule = $this->getEncryptionSchedule($this->key);
+ $this->decryptionSchedule = $this->getDecryptionSchedule($this->key);
+ return true;
+ }
+
+ /**
+ * Encrypt a piece of the block (a single block sized chunk)
+ *
+ * @param string $part The block part to encrypt
+ * @param array $schedule The key schedule to use for encryption
+ *
+ * @return string The encrypted string
+ */
+ protected function encryptBlockPart($part, array $schedule) {
+ $words = unpack('N*words', $part);
+ $state = array();
+ $ictr = 0;
+ foreach ($words as $word) {
+ $state[] = $word ^ $schedule[0][$ictr++];
+ }
+ $nBlocks = $this->blockSize >> 2;
+ $nKeys = $this->keySize >> 2;
+ $nRounds = max($nBlocks, $nKeys) + 6;
+ $temp = array();
+ for ($round = 1; $round < $nRounds; $round++) {
+ $ictr = $this->shiftOffsets[0];
+ $jctr = $this->shiftOffsets[1];
+ $kctr = $this->shiftOffsets[2];
+ $lctr = $this->shiftOffsets[3];
+ while ($ictr < $nBlocks) {
+ $temp[$ictr] = static::$tValues[0][$state[$ictr] & 0xFF000000]
+ ^ static::$tValues[1][$state[$jctr] & 0x00FF0000]
+ ^ static::$tValues[2][$state[$kctr] & 0x0000FF00]
+ ^ static::$tValues[3][$state[$lctr] & 0x000000FF]
+ ^ $schedule[$round][$ictr];
+ $ictr++;
+ $jctr = ($jctr + 1) % $nBlocks;
+ $kctr = ($kctr + 1) % $nBlocks;
+ $lctr = ($lctr + 1) % $nBlocks;
+ }
+ for ($i = 0; $i < $nBlocks; $i++) {
+ $state[$i] = $temp[$i];
+ }
+ }
+ for ($i = 0; $i < $nBlocks; $i++) {
+ $state[$i] = $this->subWord($state[$i]);
+ }
+ $ictr = $this->shiftOffsets[0];
+ $jctr = $this->shiftOffsets[1];
+ $kctr = $this->shiftOffsets[2];
+ $lctr = $this->shiftOffsets[3];
+ while ($ictr < $nBlocks) {
+ $temp[$ictr] = ($state[$ictr] & 0xFF000000)
+ ^ ($state[$jctr] & 0x00FF0000)
+ ^ ($state[$kctr] & 0x0000FF00)
+ ^ ($state[$lctr] & 0x000000FF)
+ ^ $schedule[$nRounds][$ictr];
+ $ictr++;
+ $jctr = ($jctr + 1) % $nBlocks;
+ $kctr = ($kctr + 1) % $nBlocks;
+ $lctr = ($lctr + 1) % $nBlocks;
+ }
+ $state = $temp;
+ array_unshift($state, 'N*');
+ return call_user_func_array('pack', $state);
+ }
+
+ /**
+ * Decrypt a piece of the block (a single block sized chunk)
+ *
+ * @param string $part The block part to decrypt
+ * @param array $schedule The key schedule to use for decryption
+ *
+ * @return string The decrypted string
+ */
+ protected function decryptBlockPart($part, $schedule) {
+ $state = array();
+ $words = unpack('N*word', $part);
+ $inc = 0;
+ $nBlocks = $this->blockSize >> 2;
+ $nKeys = $this->keySize >> 2;
+ $nRounds = max($nBlocks, $nKeys) + 6;
+ foreach ($words as $word) {
+ $state[] = $word ^ $schedule[$nRounds][$inc++];
+ }
+ $temp = array();
+ for ($round = $nRounds - 1; $round > 0; $round--) {
+ $ictr = $this->shiftOffsets[0];
+ $jctr = $nBlocks - $this->shiftOffsets[1];
+ $kctr = $nBlocks - $this->shiftOffsets[2];
+ $lctr = $nBlocks - $this->shiftOffsets[3];
+
+ while ($ictr < $nBlocks) {
+ $temp[$ictr] = static::$dtValues[0][$state[$ictr] & 0xFF000000]
+ ^ static::$dtValues[1][$state[$jctr] & 0x00FF0000]
+ ^ static::$dtValues[2][$state[$kctr] & 0x0000FF00]
+ ^ static::$dtValues[3][$state[$lctr] & 0x000000FF]
+ ^ $schedule[$round][$ictr];
+ $ictr++;
+ $jctr = ($jctr + 1) % $nBlocks;
+ $kctr = ($kctr + 1) % $nBlocks;
+ $lctr = ($lctr + 1) % $nBlocks;
+ }
+ for ($i = 0; $i < $nBlocks; $i++) {
+ $state[$i] = $temp[$i];
+ }
+ }
+ $ictr = $this->shiftOffsets[0];
+ $jctr = $nBlocks - $this->shiftOffsets[1];
+ $kctr = $nBlocks - $this->shiftOffsets[2];
+ $lctr = $nBlocks - $this->shiftOffsets[3];
+ $temp = array();
+ while ($ictr < $nBlocks) {
+ $temp[$ictr] = $schedule[0][$ictr]
+ ^ $this->invSubWord(
+ ($state[$ictr] & 0xFF000000)
+ | ($state[$jctr] & 0x00FF0000)
+ | ($state[$kctr] & 0x0000FF00)
+ | ($state[$lctr] & 0x000000FF)
+ );
+ $ictr++;
+ $jctr = ($jctr + 1) % $nBlocks;
+ $kctr = ($kctr + 1) % $nBlocks;
+ $lctr = ($lctr + 1) % $nBlocks;
+ }
+ $state = $temp;
+ array_unshift($state, 'N*');
+ return call_user_func_array('pack', $state);
+ }
+
+ /**
+ * Set the block size to use for the cipher
+ *
+ * @param int $num The number of bits in the block size
+ *
+ * @return void
+ */
+ protected function setBlockSize($num) {
+ $num >>= 5;
+ $num = max(min($num, 8), 4);
+ $this->blockSize = $num << 2;
+ }
+
+ /**
+ * Set the key size to use for the cipher
+ *
+ * @param int $num The number of bits in the key size
+ *
+ * @return void
+ */
+ protected function setKeySize($num) {
+ $num >>= 5;
+ $num = max(min($num, 8), 4);
+ $this->keySize = $num << 2;
+ }
+
+ /**
+ * Setup the cipher by determining the shift offsets, the key size and
+ * precomputing part of the key schedule
+ *
+ * @param string $key The key to setup the cipher for
+ *
+ * @return array The precomputed schedule part
+ */
+ protected function setup($key) {
+ $this->setShiftOffsets();
+ $nBlocks = $this->blockSize >> 2;
+ $nKeys = $this->keySize >> 2;
+ $nRounds = max($nBlocks, $nKeys) + 6;
+ $words = array_values(unpack('N*words', $key));
+ $length = $nBlocks * ($nRounds + 1);
+ for ($i = $nKeys; $i < $length; $i++) {
+ $temp = $words[$i - 1];
+ if ($i % $nKeys == 0) {
+ $temp = (($temp << 8) & 0xFFFFFF00) | (($temp >> 24) & 0x000000FF);
+ $temp = $this->subWord($temp) ^ static::$rcon[$i / $nKeys];
+ } elseif ($nKeys > 6 && ($i % $nKeys == 4)) {
+ $temp = $this->subWord($temp);
+ }
+ $words[$i] = $words[$i - $nKeys] ^ $temp;
+ }
+ return $words;
+ }
+
+ /**
+ * Convert the kye into an encryption schedule
+ *
+ * @param string $key The key to use
+ *
+ * @return array The generated key schedule
+ */
+ protected function getEncryptionSchedule($key) {
+ $words = $this->setup($key);
+ $nBlocks = $this->blockSize >> 2;
+ $length = $nBlocks * (max($nBlocks, $this->keySize >> 2) + 7);
+ $schedule = array();
+ for ($i = $row = $col = 0; $i < $length; $i++, $col++) {
+ if ($col == $nBlocks) {
+ $col = 0;
+ $row++;
+ }
+ if (!isset($schedule[$row])) {
+ $schedule[$row] = array();
+ }
+ $schedule[$row][$col] = $words[$i];
+ }
+ return $schedule;
+ }
+
+ /**
+ * Convert the kye into an decryption schedule
+ *
+ * @param string $key The key to use
+ *
+ * @return array The generated key schedule
+ */
+ protected function getDecryptionSchedule($key) {
+ $words = $this->getEncryptionSchedule($key);
+ $schedule = array();
+ $length = count($words) - 1;
+ $schedule[] = $words[0];
+ $nBlocks = $this->blockSize >> 2;
+ for ($i = 1; $i < $length; $i++) {
+ $jctr = 0;
+ $temp = array();
+ while ($jctr < $nBlocks) {
+ $dwblock = $this->subWord($words[$i][$jctr]);
+ $temp[$jctr] = static::$dtValues[0][$dwblock & 0xFF000000]
+ ^ static::$dtValues[1][$dwblock & 0x00FF0000]
+ ^ static::$dtValues[2][$dwblock & 0x0000FF00]
+ ^ static::$dtValues[3][$dwblock & 0x000000FF];
+ $jctr++;
+ }
+ $schedule[$i] = $temp;
+ }
+ $schedule[] = $words[$length];
+ return $schedule;
+ }
+
+ /**
+ * Compute the word by merging it with the sboxes
+ *
+ * @param string $word
+ *
+ * @return string The computed word
+ */
+ protected function subWord($word) {
+ return static::$sboxes[0][$word & 0x000000FF]
+ | static::$sboxes[1][$word & 0x0000FF00]
+ | static::$sboxes[2][$word & 0x00FF0000]
+ | static::$sboxes[3][$word & 0xFF000000];
+ }
+
+ /**
+ * Compute the word by merging it with the inverse sboxes
+ *
+ * @param string $word
+ *
+ * @return string The computed word
+ */
+ protected function invSubWord($word) {
+ return static::$invSBoxes[0][$word & 0x000000FF]
+ | static::$invSBoxes[1][$word & 0x0000FF00]
+ | static::$invSBoxes[2][$word & 0x00FF0000]
+ | static::$invSBoxes[3][$word & 0xFF000000];
+ }
+
+ /**
+ * Setup the shift offsets to use for the cipher
+ *
+ * @return void
+ */
+ protected function setShiftOffsets() {
+ switch ($this->blockSize >> 2) {
+ case 4:
+ case 5:
+ case 6:
+ $this->shiftOffsets = array(0, 1, 2, 3);
+ break;
+ case 7:
+ $this->shiftOffsets = array(0, 1, 2, 4);
+ break;
+ case 8:
+ $this->shiftOffsets = array(0, 1, 3, 4);
+ }
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * An implementation of the TripleDES cipher
+ *
+ * This was forked from phpseclib and modified to use CryptLib conventions
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Cipher
+ * @subpackage Block
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Cipher\Block\Cipher;
+
+/**
+ * An implementation of the TripleDES Cipher
+ *
+ * @category PHPCryptLib
+ * @package Cipher
+ * @subpackage Block
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class TripleDES extends DES {
+
+ /**
+ * @var int The key size for the cipher
+ */
+ protected $keySize = 24;
+
+ /**
+ * Get a list of supported ciphers for this class implementation
+ *
+ * @return array A list of supported ciphers
+ */
+ public static function getSupportedCiphers() {
+ return array('tripledes');
+ }
+
+ /**
+ * Set the key to use for the cipher
+ *
+ * @param string $key The key to use
+ *
+ * @throws InvalidArgumentException If the key is not the correct size
+ * @return void
+ */
+ public function setKey($key) {
+ $len = strlen($key);
+ if ($len == 16) {
+ $key .= substr($key, 0, 8);
+ } elseif ($len != 24) {
+ throw new \InvalidArgumentException(
+ 'The supplied key block is not the correct size'
+ );
+ }
+ $this->key = $key;
+ $this->initialized = true;
+ }
+
+ /**
+ * Decrypt a block of data using the supplied string key
+ *
+ * Note that the supplied data should be the same size as the block size of
+ * the cipher being used.
+ *
+ * @param string $data The data to decrypt
+ *
+ * @return string The result decrypted data
+ */
+ protected function decryptBlockData($data) {
+ $key = $this->key;
+ $this->key = substr($key, 16, 8);
+ $this->initialize();
+ $data = parent::decryptBlockData($data);
+ $this->key = substr($key, 8, 8);
+ $this->initialize();
+ $data = parent::encryptBlockData($data);
+ $this->key = substr($key, 0, 8);
+ $this->initialize();
+ $data = parent::decryptBlockData($data);
+ $this->key = $key;
+ return $data;
+ }
+
+ /**
+ * Encrypt a block of data using the supplied string key
+ *
+ * Note that the supplied data should be the same size as the block size of
+ * the cipher being used.
+ *
+ * @param string $data The data to encrypt
+ *
+ * @return string The result encrypted data
+ */
+ protected function encryptBlockData($data) {
+ $key = $this->key;
+ $this->key = substr($key, 0, 8);
+ $this->initialize();
+ $data = parent::encryptBlockData($data);
+ $this->key = substr($key, 8, 8);
+ $this->initialize();
+ $data = parent::decryptBlockData($data);
+ $this->key = substr($key, 16, 8);
+ $this->initialize();
+ $data = parent::encryptBlockData($data);
+ $this->key = $key;
+ return $data;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * The interface that all block cipher modes must implement
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Cipher
+ * @subpackage Block
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Cipher\Block;
+
+/**
+ * The interface that all block cipher modes must implement
+ *
+ * @category PHPCryptLib
+ * @package Cipher
+ * @subpackage Block
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @codeCoverageIgnore
+ */
+interface Mode {
+
+ /**
+ * Build the instance of the cipher mode
+ *
+ * @param Cipher $cipher The cipher to use for encryption/decryption
+ * @param string $initv The initialization vector (empty if not needed)
+ * @param array $options An array of mode-specific options
+ */
+ public function __construct(
+ \CryptLib\Cipher\Block\Cipher $cipher,
+ $initv,
+ array $options = array()
+ );
+
+ /**
+ * Decrypt the data using the supplied key, cipher and initialization vector
+ *
+ * @param string $data The data to decrypt
+ *
+ * @return string The decrypted data
+ */
+ public function decrypt($data);
+
+ /**
+ * Encrypt the data using the supplied key, cipher and initialization vector
+ *
+ * @param string $data The data to encrypt
+ *
+ * @return string The encrypted data
+ */
+ public function encrypt($data);
+
+ /**
+ * Finish the mode and append any additional data necessary
+ *
+ * @return string Any additional data
+ */
+ public function finish();
+
+ /**
+ * Get the name of the current mode implementation
+ *
+ * @return string The current mode name
+ */
+ public function getMode();
+
+ /**
+ * Reset the mode to start over (destroying any intermediate state)
+ *
+ * @return void
+ */
+ public function reset();
+
+}
--- /dev/null
+<?php
+/**
+ * The CBC (Cipher Block Chaining) mode implementation
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Cipher
+ * @subpackage Block
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Cipher\Block\Mode;
+
+/**
+ * The CBC (Cipher Block Chaining) mode implementation
+ *
+ * @category PHPCryptLib
+ * @package Cipher
+ * @subpackage Block
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+
+class CBC extends \CryptLib\Cipher\Block\AbstractMode {
+
+ /**
+ * Decrypt the data using the supplied key, cipher
+ *
+ * @param string $data The data to decrypt
+ *
+ * @return string The decrypted data
+ */
+ protected function decryptBlock($data) {
+ $stub = $this->cipher->decryptBlock($data);
+ $result = $stub ^ $this->state;
+ $this->state = $data;
+ return $result;
+ }
+
+ /**
+ * Encrypt the data using the supplied key, cipher
+ *
+ * @param string $data The data to encrypt
+ *
+ * @return string The encrypted data
+ */
+ protected function encryptBlock($data) {
+ $stub = $this->cipher->encryptBlock($data ^ $this->state);
+ $this->state = $stub;
+ return $stub;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * The CCM (Counter CBC-MAC) mode implementation
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Cipher
+ * @subpackage Block
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ * @see http://tools.ietf.org/html/rfc3610
+ */
+
+namespace CryptLib\Cipher\Block\Mode;
+
+/**
+ * The CCM (Counter CBC-MAC) mode implementation
+ *
+ * @category PHPCryptLib
+ * @package Cipher
+ * @subpackage Block
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @see http://tools.ietf.org/html/rfc3610
+ */
+class CCM extends \CryptLib\Cipher\Block\AbstractMode {
+
+ /**
+ * Indicates which mode the cipher mode is in (encryption/decryption)
+ */
+ const MODE_DECRYPT = 1;
+
+ /**
+ * Indicates which mode the cipher mode is in (encryption/decryption)
+ */
+ const MODE_ENCRYPT = 2;
+
+ /**
+ * @var int The number of octets in the Authentication field
+ */
+ protected $authFieldSize = 8;
+
+ /**
+ * @var string The data buffer for this encryption instance
+ */
+ protected $data = '';
+
+ /**
+ * @var int The number of octets in the length field
+ */
+ protected $lSize = 4;
+
+ /**
+ * @var string The mode name for the current instance
+ */
+ protected $mode = 'ccm';
+
+ /**
+ * @var int The current encryption mode (enc/dec)
+ */
+ protected $encryptionMode = 0;
+
+ /**
+ * @var array Mode specific options
+ */
+ protected $options = array(
+ 'adata' => '',
+ 'lSize' => 4,
+ 'aSize' => 8,
+ );
+
+ /**
+ * @var string The initialization vector to use for this instance
+ */
+ protected $usedIV = '';
+
+ /**
+ * Build the instance of the cipher mode
+ *
+ * @param Cipher $cipher The cipher to use for encryption/decryption
+ * @param string $initv The initialization vector (empty if not needed)
+ * @param array $options An array of mode-specific options
+ */
+ public function __construct(
+ \CryptLib\Cipher\Block\Cipher $cipher,
+ $initv,
+ array $options = array()
+ ) {
+ $this->options = $options + $this->options;
+ $this->cipher = $cipher;
+ $this->initv = $initv;
+ $this->adata = $this->options['adata'];
+ $this->setLSize($this->options['lSize']);
+ $this->setAuthFieldSize($this->options['aSize']);
+ $this->reset();
+ }
+
+ /**
+ * Finish the mode and append any additional data necessary
+ *
+ * @return string Any additional data
+ */
+ public function finish() {
+ $mask = (static::MODE_DECRYPT | static::MODE_ENCRYPT);
+ if (!($this->encryptionMode ^ $mask)) {
+ throw new \LogicException('Cannot encrypt and decrypt in same state');
+ }
+ if ($this->encryptionMode & static::MODE_DECRYPT) {
+ return $this->decryptBlockFinal();
+ } else {
+ return $this->encryptBlockFinal();
+ }
+ }
+
+ /**
+ * Set the auth field size to a different value.
+ *
+ * Valid values: 4, 6, 8, 10, 12, 14, 16
+ *
+ * Note that increasing this size will make it harder for an attacker to
+ * modify the message payload
+ *
+ * @param int $new The new size of auth field to append
+ *
+ * @return void
+ * @throws InvalidArgumentException If the number is outside of the range
+ */
+ public function setAuthFieldSize($new) {
+ if (!in_array($new, array(4, 6, 8, 10, 12, 14, 16))) {
+ throw new \InvalidArgumentException(
+ 'The Auth Field must be one of: 4, 6, 8, 10, 12, 14, 16'
+ );
+ }
+ $this->authFieldSize = (int) $new;
+ $this->reset();
+ }
+
+ /**
+ * Set the size of the length field. This is a tradeoff between the maximum
+ * message size and the size of the initialization vector
+ *
+ * Valid values are 2, 3, 4, 5, 6, 7, 8
+ *
+ * @param int $new The new LSize to use
+ *
+ * @return void
+ * @throws InvalidArgumentException If the number is outside of the range
+ */
+ public function setLSize($new) {
+ if ($new < 2 || $new > 8) {
+ throw new \InvalidArgumentException(
+ 'The LSize must be between 2 and 8 inclusive'
+ );
+ }
+ $this->lSize = (int) $new;
+ $this->reset();
+ }
+
+ /**
+ * Reset the mode to start over (destroying any intermediate state)
+ *
+ * @return void
+ */
+ public function reset() {
+ $this->usedIV = $this->extractInitv(
+ $this->initv,
+ $this->cipher->getBlockSize()
+ );
+ $this->encryptionMode = 0;
+ $this->data = '';
+ }
+
+ /**
+ * Decrypt the data using the supplied key, cipher
+ *
+ * @param string $data The data to decrypt
+ *
+ * @return string The decrypted data
+ */
+ protected function decryptBlock($data) {
+ $this->data .= $data;
+ $this->encryptionMode |= static::MODE_DECRYPT;
+ }
+
+ /**
+ * Perform the decryption of the block data
+ *
+ * @return string The final data
+ */
+ protected function decryptBlockFinal() {
+ $message = substr($this->data, 0, -1 * $this->authFieldSize);
+ $uValue = substr($this->data, -1 * $this->authFieldSize);
+ $data = $this->encryptMessage($message, $uValue);
+ $computedT = substr($data, -1 * $this->authFieldSize);
+ $data = substr($data, 0, -1 * $this->authFieldSize);
+ $authFieldT = $this->computeAuthField($data);
+ if ($authFieldT != $computedT) {
+ return false;
+ }
+ return rtrim($data, chr(0));
+ }
+
+ /**
+ * Encrypt the data using the supplied key, cipher
+ *
+ * @param string $data The data to encrypt
+ *
+ * @return string The encrypted data
+ */
+ protected function encryptBlock($data) {
+ $this->data .= $data;
+ $this->encryptionMode |= static::MODE_ENCRYPT;
+ }
+
+ /**
+ * Perform the encryption of the block data
+ *
+ * @return string The final data
+ */
+ protected function encryptBlockFinal() {
+ $authFieldT = $this->computeAuthField($this->data);
+ $data = $this->encryptMessage($this->data, $authFieldT);
+ return $data;
+ }
+
+ /**
+ * Compute the authentication field
+ *
+ * @param string $data The data to compute with
+ *
+ * @return string The computed MAC Authentication Code
+ */
+ protected function computeAuthField($data) {
+ $blockSize = $this->cipher->getBlockSize();
+ $flags = pack(
+ 'C',
+ 64 * (empty($this->adata) ? 0 : 1)
+ + 8 * (($this->authFieldSize - 2) / 2)
+ + ($this->lSize - 1)
+ );
+ $blocks = array(
+ $flags . $this->usedIV . pack($this->getLPackString(), strlen($data))
+ );
+ if (strlen($data) % $blockSize != 0) {
+ $data .= str_repeat(chr(0), $blockSize - (strlen($data) % $blockSize));
+ }
+
+ $blocks = array_merge(
+ $blocks,
+ $this->processAData($this->adata, $blockSize)
+ );
+ if (!empty($data)) {
+ $blocks = array_merge($blocks, str_split($data, $blockSize));
+ }
+ $crypted = array(
+ 1 => $this->cipher->encryptBlock($blocks[0])
+ );
+
+ $blockLen = count($blocks);
+ for ($i = 1; $i < $blockLen; $i++) {
+ $crypted[$i + 1] = $this->cipher->encryptBlock(
+ $crypted[$i] ^ $blocks[$i]
+ );
+ }
+ return substr(end($crypted), 0, $this->authFieldSize);
+ }
+
+ /**
+ * Encrypt the data using the supplied method
+ *
+ * @param string $data The data to encrypt
+ * @param string $authValue The auth value field
+ *
+ * @return string The encrypted data with authfield payload
+ */
+ protected function encryptMessage($data, $authValue) {
+ $blockSize = $this->cipher->getBlockSize();
+ $flags = pack('C', ($this->lSize - 1));
+ $blocks = str_split($data, $blockSize);
+ $sblocks = array();
+ $blockLen = count($blocks);
+ for ($i = 0; $i <= $blockLen; $i++) {
+ $sblocks[] = $this->cipher->encryptBlock(
+ $flags . $this->usedIV . pack($this->getLPackString(), $i)
+ );
+ }
+ $encrypted = '';
+ foreach ($blocks as $key => $value) {
+ if (strlen($value) < $blockSize) {
+ $sblocks[$key + 1] = substr($sblocks[$key + 1], 0, strlen($value));
+ }
+ $encrypted .= $sblocks[$key + 1] ^ $value;
+ }
+ $sValue = substr($sblocks[0], 0, $this->authFieldSize);
+ $uValue = $authValue ^ $sValue;
+ return $encrypted . $uValue;
+ }
+
+ /**
+ * Enforce the data block is the correct size for the cipher
+ *
+ * @param string $data The data to check
+ *
+ * @return void
+ * @throws InvalidArgumentException if the block size is not correct
+ */
+ protected function enforceBlockSize($data) {
+ return true;
+ }
+
+ /**
+ * Extract the nonce from the initialization vector
+ *
+ * @param string $initv The initialization Vector to trim
+ * @param int $blockSize The size of the final nonce
+ *
+ * @return string The sized nonce
+ * @throws InvalidArgumentException if the IV is too short
+ */
+ protected function extractInitv($initv, $blockSize) {
+ $initSize = $blockSize - 1 - $this->lSize;
+ if (strlen($initv) < $initSize) {
+ throw new \InvalidArgumentException(sprintf(
+ 'Supplied Initialization Vector is too short, should be %d bytes',
+ $initSize
+ ));
+ }
+ return substr($initv, 0, $initSize);
+ }
+
+ /**
+ * Get a packing string related to the instance lSize variable
+ *
+ * @return string The pack() string to use to pack the length variables
+ * @see pack()
+ */
+ protected function getLPackString() {
+ if ($this->lSize <= 3) {
+ return str_repeat('x', $this->lSize - 2) . 'n';
+ }
+ return str_repeat('x', $this->lSize - 4) . 'N';
+ }
+
+ /**
+ * Process the Authentication data for authenticating
+ *
+ * @param string $adata The data to authenticate with
+ * @param int $blockSize The block size for the cipher
+ *
+ * @return array An array of strings bound by the supplied blocksize
+ */
+ protected function processAData($adata, $blockSize) {
+ if (!empty($this->adata)) {
+ if (strlen($this->adata) < ((1 << 16) - (1 << 8))) {
+ $len = pack('n', strlen($this->adata));
+ } else {
+ $len = chr(0xff) . chr(0xfe) . pack('N', strlen($this->adata));
+ }
+ $temp = $len . $this->adata;
+ if (strlen($temp) % $blockSize != 0) {
+ //Pad the string to exactly mod16
+ $temp .= str_repeat(
+ chr(0),
+ $blockSize - (strlen($temp) % $blockSize)
+ );
+ }
+ return str_split($temp, $blockSize);
+ }
+ return array();
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * The CFB (Cipher FeedBack) mode implementation
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Cipher
+ * @subpackage Block
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Cipher\Block\Mode;
+
+/**
+ * The CFB (Cipher FeedBack) mode implementation
+ *
+ * @category PHPCryptLib
+ * @package Cipher
+ * @subpackage Block
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class CFB extends \CryptLib\Cipher\Block\AbstractMode {
+
+ /**
+ * Decrypt the data using the supplied key, cipher
+ *
+ * @param string $data The data to decrypt
+ *
+ * @return string The decrypted data
+ */
+ protected function decryptBlock($data) {
+ $stub = $this->cipher->encryptBlock($this->state);
+ $rawData = $stub ^ $data;
+ $this->state = $rawData;
+ return $rawData;
+ }
+
+ /**
+ * Encrypt the data using the supplied key, cipher
+ *
+ * @param string $data The data to encrypt
+ *
+ * @return string The encrypted data
+ */
+ protected function encryptBlock($data) {
+ $stub = $this->cipher->encryptBlock($this->state);
+ $this->state = $data;
+ return $stub ^ $data;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * The CTR (Counter) mode implementation
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Cipher
+ * @subpackage Block
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Cipher\Block\Mode;
+
+use CryptLib\Core\BaseConverter;
+use CryptLib\Core\BigMath;
+
+/**
+ * The CTR (Counter) mode implementation
+ *
+ * @category PHPCryptLib
+ * @package Cipher
+ * @subpackage Block
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+
+class CTR extends \CryptLib\Cipher\Block\AbstractMode {
+
+ /**
+ * @var BigMath An instance of the BigMath library
+ */
+ protected $bigMath = null;
+
+ /**
+ * Build the instance of the cipher mode
+ *
+ * @param Cipher $cipher The cipher to use for encryption/decryption
+ * @param string $initv The initialization vector (empty if not needed)
+ * @param array $options An array of mode-specific options
+ */
+ public function __construct(
+ \CryptLib\Cipher\Block\Cipher $cipher,
+ $initv,
+ array $options = array()
+ ) {
+ parent::__construct($cipher, $initv, $options);
+ $this->bigMath = BigMath::createFromServerConfiguration();
+ }
+
+ /**
+ * Reset the mode to start over (destroying any intermediate state)
+ *
+ * @return void
+ */
+ public function reset() {
+ $this->state = BaseConverter::ConvertFromBinary($this->initv, '0123456789');
+ $this->state = ltrim($this->state, '0');
+ }
+
+ /**
+ * Decrypt the data using the supplied key, cipher
+ *
+ * @param string $data The data to decrypt
+ *
+ * @return string The decrypted data
+ */
+ protected function decryptBlock($data) {
+ return $this->encryptBlock($data);
+ }
+
+ /**
+ * Encrypt the data using the supplied key, cipher
+ *
+ * @param string $data The data to encrypt
+ *
+ * @return string The encrypted data
+ */
+ protected function encryptBlock($data) {
+ $size = $this->cipher->getBlockSize();
+ $state = str_pad(
+ BaseConverter::convertToBinary($this->state, '0123456789'),
+ $size,
+ chr(0),
+ STR_PAD_LEFT
+ );
+ $stub = $this->cipher->encryptBlock($state);
+ $this->state = $this->bigMath->add($this->state, 1);
+ return $stub ^ $data;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * The ECB (Electronic CodeBook) mode implementation
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Cipher
+ * @subpackage Block
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Cipher\Block\Mode;
+
+/**
+ * The ECB (Electronic CodeBook) mode implementation
+ *
+ * @category PHPCryptLib
+ * @package Cipher
+ * @subpackage Block
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class ECB extends \CryptLib\Cipher\Block\AbstractMode {
+
+ /**
+ * Decrypt the data using the supplied key, cipher and initialization vector
+ *
+ * @param string $data The data to decrypt
+ *
+ * @return string The decrypted data
+ */
+ protected function decryptBlock($data) {
+ return $this->cipher->decryptBlock($data);
+ }
+
+ /**
+ * Encrypt the data using the supplied key, cipher and initialization vector
+ *
+ * @param string $data The data to encrypt
+ *
+ * @return string The encrypted data
+ */
+ protected function encryptBlock($data) {
+ return $this->cipher->encryptBlock($data);
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * The NOFB (Nbit Output FeedBack) mode implementation
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Cipher
+ * @subpackage Block
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Cipher\Block\Mode;
+
+/**
+ * The NOFB (Nbit Output FeedBack) mode implementation
+ *
+ * @category PHPCryptLib
+ * @package Cipher
+ * @subpackage Block
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class NOFB extends \CryptLib\Cipher\Block\AbstractMode {
+
+ /**
+ * Decrypt the data using the supplied key, cipher and initialization vector
+ *
+ * @param string $data The data to decrypt
+ *
+ * @return string The decrypted data
+ */
+ protected function decryptBlock($data) {
+ return $this->encryptBlock($data);
+ }
+
+ /**
+ * Encrypt the data using the supplied key, cipher and initialization vector
+ *
+ * @param string $data The data to encrypt
+ *
+ * @return string The encrypted data
+ */
+ protected function encryptBlock($data) {
+ $this->state = $this->cipher->encryptBlock($this->state);
+ return $this->state ^ $data;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * The Cipher Factory
+ *
+ * Use this factory to instantiate ciphers and modes based upon their names. You
+ * can register new ciphers and modes by simply calling the appropriate methods.
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Cipher
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Cipher;
+
+/**
+ * Some used classes, aliased appropriately
+ */
+use CryptLib\Cipher\Block\Cipher as Cipher;
+use CryptLib\Cipher\Block\Mode as Mode;
+use CryptLib\Cipher\Block\Cipher\MCrypt;
+
+
+/**
+ * The Cipher Factory
+ *
+ * Use this factory to instantiate ciphers and modes based upon their names. You
+ * can register new ciphers and modes by simply calling the appropriate methods.
+ *
+ * @category PHPCryptLib
+ * @package Cipher
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class Factory extends \CryptLib\Core\AbstractFactory {
+
+ /**
+ * @var array A list of available cipher implementations by name of cipher
+ */
+ protected $ciphers = array();
+
+ /**
+ * @var array A list of available mode implementations by name of mode
+ */
+ protected $modes = array();
+
+ /**
+ * Instantiate the factory
+ *
+ * This automatically loads and registers the default cipher and mode
+ * implementations.
+ *
+ * @return void
+ */
+ public function __construct() {
+ $this->loadModes();
+ $this->loadCiphers();
+ }
+
+ /**
+ * Get an instance of a cipher by name
+ *
+ * Note that this will return the passed argument if it is an instance of
+ * the Block cipher interface.
+ *
+ * @param string|Block $cipher The cipher name or instance to load
+ *
+ * @return Cipher The loaded block cipher
+ * @throws RuntimeException if the cipher is not supported
+ */
+ public function getBlockCipher($cipher) {
+ if (is_object($cipher) && $cipher instanceof Cipher) {
+ return $cipher;
+ }
+ $cipher = strtolower($cipher);
+ if (in_array($cipher, MCrypt::getSupportedCiphers())) {
+ //Use the built in MCrypt library if it's available
+ return new MCrypt($cipher);
+ } elseif (isset($this->ciphers[$cipher])) {
+ $class = $this->ciphers[$cipher];
+ return new $class($cipher);
+ }
+ $message = sprintf('Unsupported Cipher %s', $cipher);
+ throw new \RuntimeException($message);
+ }
+
+ /**
+ * Get an instance of a mode by name
+ *
+ * Note that this will return the passed argument if it is an instance of
+ * the Mode interface.
+ *
+ * @param string|Mode $mode The mode name or instance to load
+ *
+ * @return Mode The loaded mode instance
+ * @throws RuntimeException if the mode is not supported
+ */
+ public function getMode(
+ $mode,
+ \CryptLib\Cipher\Block\Cipher $cipher,
+ $initv,
+ array $options = array()
+ ) {
+ if (is_object($mode) && $mode instanceof Mode) {
+ return $mode;
+ }
+ $mode = strtolower($mode);
+ if (isset($this->modes[$mode])) {
+ $class = $this->modes[$mode];
+ return new $class($cipher, $initv, $options);
+ }
+ $message = sprintf('Unsupported Mode %s', $mode);
+ throw new \RuntimeException($message);
+ }
+
+ /**
+ * Register a new cipher implementation class for this factory
+ *
+ * This will iterate over each supported cipher for the class and load the
+ * cipher into the list of supported ciphers
+ *
+ * @param string $name The name of the cipher (ignored)
+ * @param string $class The full class name of the cipher implementation
+ *
+ * @return Factory $this The current factory instance
+ * @throws InvalidArgumentException If the class is not a block cipher
+ */
+ public function registerCipher($name, $class) {
+ $refl = new \ReflectionClass($class);
+ $interface = '\\'. __NAMESPACE__ . '\\Block\\Cipher';
+ if (!$refl->implementsInterface($interface)) {
+ $message = sprintf('Class must implement %s', $interface);
+ throw new \InvalidArgumentException($message);
+ }
+ foreach ($class::getSupportedCiphers() as $cipher){
+ $this->ciphers[$cipher] = $class;
+ }
+ return $this;
+ }
+
+ /**
+ * Register a new mode implementation class for this factory
+ *
+ * @param string $name The name of the mode (ignored)
+ * @param string $class The full class name of the mode implementation
+ *
+ * @return Factory $this The current factory instance
+ * @throws InvalidArgumentException If the class is not a valid mode
+ */
+ public function registerMode($name, $class) {
+ $refl = new \ReflectionClass($class);
+ $interface = '\\'. __NAMESPACE__ . '\\Block\\Mode';
+ if (!$refl->implementsInterface($interface)) {
+ throw new \InvalidArgumentException('Class must implement Mode');
+ }
+ $this->modes[strtolower($name)] = $class;
+ return $this;
+ }
+
+ /**
+ * Load all core cipher implementations
+ *
+ * @return void
+ */
+ protected function loadCiphers() {
+ $this->loadFiles(
+ __DIR__ . '/Block/Cipher',
+ __NAMESPACE__ . '\\Block\\Cipher\\',
+ array($this, 'registerCipher')
+ );
+ }
+
+ /**
+ * Load all core mode implementations
+ *
+ * @return void
+ */
+ protected function loadModes() {
+ $this->loadFiles(
+ __DIR__ . '/Block/Mode',
+ __NAMESPACE__ . '\\Block\\Mode\\',
+ array($this, 'registerMode')
+ );
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * The base abstract factory used by all CryptLib factories
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Core
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Core;
+
+/**
+ * The base abstract factory used by all CryptLib factories
+ *
+ * @category PHPCryptLib
+ * @package Core
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+abstract class AbstractFactory {
+
+ /**
+ * Register a type with the factory by name
+ *
+ * This is an internal method to check if a provided class name implements
+ * an interface, and if it does to append that class to an internal array
+ * by name.
+ *
+ * @param string $type The name of the variable to store the class
+ * @param string $implements The interface to validate against
+ * @param string $name The name of this particular class
+ * @param string $class The fully qualified class name
+ * @param boolean $instantiate Should the class be stored instantiated
+ *
+ * @return void
+ * @throws InvalidArgumentException If class does not implement interface
+ */
+ protected function registerType(
+ $type,
+ $implements,
+ $name,
+ $class,
+ $instantiate = false
+ ) {
+ $name = strtolower($name);
+ $refl = new \ReflectionClass($class);
+ if (!$refl->implementsInterface($implements)) {
+ $message = sprintf('Class must implement %s', $implements);
+ throw new \InvalidArgumentException($message);
+ }
+ if ($instantiate) {
+ $class = new $class;
+ }
+
+ $this->{$type}[$name] = $class;
+ }
+
+ /**
+ * Load a set of classes from a directory into the factory
+ *
+ * @param string $directory The directory to search for classes in
+ * @param string $namespace The namespace prefix for any found classes
+ * @param string $callback The callback with which to register the class
+ *
+ * @return void
+ */
+ protected function loadFiles($directory, $namespace, $callback) {
+ foreach (new \DirectoryIterator($directory) as $file) {
+ $filename = $file->getBasename();
+ if ($file->isFile() && substr($filename, -4) == '.php') {
+ $name = substr($filename, 0, -4);
+ $class = $namespace . $name;
+ call_user_func($callback, $name, $class);
+ }
+ }
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * An implementation of the PSR-0 Autoloader. This can be replaced at will with
+ * other implementations if necessary.
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Core
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Core;
+
+/**
+ * An implementation of the PSR-0 Autoloader. This can be replaced at will with
+ * other implementations if necessary.
+ *
+ * @category PHPCryptLib
+ * @package Core
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class AutoLoader {
+
+ /**
+ * @var string The namespace prefix for this instance.
+ */
+ protected $namespace = '';
+
+ /**
+ * @var string The filesystem prefix to use for this instance
+ */
+ protected $path = '';
+
+ /**
+ * Build the instance of the autoloader
+ *
+ * @param string $namespace The prefixed namespace this instance will load
+ * @param string $path The filesystem path to the root of the namespace
+ *
+ * @return void
+ */
+ public function __construct($namespace, $path) {
+ $this->namespace = ltrim($namespace, '\\');
+ $this->path = rtrim($path, '/\\') . DIRECTORY_SEPARATOR;
+ }
+
+ /**
+ * Try to load a class
+ *
+ * @param string $class The class name to load
+ *
+ * @return boolean If the loading was successful
+ */
+ public function load($class) {
+ $class = ltrim($class, '\\');
+ if (strpos($class, $this->namespace) === 0) {
+ $nsparts = explode('\\', $class);
+ $class = array_pop($nsparts);
+ $nsparts[] = '';
+ $path = $this->path . implode(DIRECTORY_SEPARATOR, $nsparts);
+ $path .= str_replace('_', DIRECTORY_SEPARATOR, $class) . '.php';
+ if (file_exists($path)) {
+ require $path;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Register the autoloader to PHP
+ *
+ * @return boolean The status of the registration
+ */
+ public function register() {
+ return spl_autoload_register(array($this, 'load'));
+ }
+
+ /**
+ * Unregister the autoloader to PHP
+ *
+ * @return boolean The status of the unregistration
+ */
+ public function unregister() {
+ return spl_autoload_unregister(array($this, 'load'));
+ }
+
+}
\ No newline at end of file
--- /dev/null
+<?php
+
+/**
+ * A Utility class for converting between raw binary strings and a given
+ * list of characters
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Core
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Core;
+
+/**
+ * A Utility class for converting between raw binary strings and a given
+ * list of characters
+ *
+ * @category PHPCryptLib
+ * @package Core
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class BaseConverter {
+
+ /**
+ * Convert from a raw binary string to a string of characters
+ *
+ * @param string $string The string to convert from
+ * @param string $characters The list of characters to convert to
+ *
+ * @return string The converted string
+ */
+ public static function convertFromBinary($string, $characters) {
+ if ($string === '' || empty($characters)) {
+ return '';
+ }
+ $string = str_split($string);
+ $callback = function($str) {
+ return ord($str);
+ };
+ $string = array_map($callback, $string);
+ $converted = static::baseConvert($string, 256, strlen($characters));
+ $callback = function ($num) use ($characters) {
+ return $characters[$num];
+ };
+ $ret = implode('', array_map($callback, $converted));
+ return $ret;
+ }
+
+ /**
+ * Convert to a raw binary string from a string of characters
+ *
+ * @param string $string The string to convert from
+ * @param string $characters The list of characters to convert to
+ *
+ * @return string The converted string
+ */
+ public static function convertToBinary($string, $characters) {
+ if (empty($string) || empty($characters)) {
+ return '';
+ }
+ $string = str_split($string);
+ $callback = function($str) use ($characters) {
+ return strpos($characters, $str);
+ };
+ $string = array_map($callback, $string);
+ $converted = static::baseConvert($string, strlen($characters), 256);
+ $callback = function ($num) {
+ return chr($num);
+ };
+ return implode('', array_map($callback, $converted));
+ }
+
+ /**
+ * Convert an array of input blocks to another numeric base
+ *
+ * This function was modified from an implementation found on StackOverflow.
+ * Special Thanks to @KeithRandall for supplying the implementation.
+ *
+ * @param int[] $source The source number, as an array
+ * @param int $srcBase The source base as an integer
+ * @param int $dstBase The destination base as an integer
+ *
+ * @see http://codegolf.stackexchange.com/questions/1620/arb/1626#1626
+ * @return int[] An array of integers in the encoded base
+ */
+ public static function baseConvert(array $source, $srcBase, $dstBase) {
+ if ($dstBase < 2) {
+ $message = sprintf('Invalid Destination Base: %d', $dstBase);
+ throw new \InvalidArgumentException($message);
+ }
+ $result = array();
+ $count = count($source);
+ while ($count) {
+ $itMax = $count;
+ $remainder = $count = $i = 0;
+ while($i < $itMax) {
+ $dividend = $source[$i++] + $remainder * $srcBase;
+ $remainder = $dividend % $dstBase;
+ $res = ($dividend - $remainder) / $dstBase;
+ if ($count || $res) {
+ $source[$count++] = $res;
+ }
+ }
+ $result[] = $remainder;
+ }
+ return array_reverse($result);
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * A class for arbitrary precision math functions
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Core
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+namespace CryptLib\Core;
+
+/**
+ * A class for arbitrary precision math functions
+ *
+ * @category PHPCryptLib
+ * @package Core
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+abstract class BigMath {
+
+ /**
+ * Get an instance of the big math class
+ *
+ * This is NOT a singleton. It simply loads the proper strategy
+ * given the current server configuration
+ *
+ * @return \CryptLib\Core\BigMath A big math instance
+ */
+ public static function createFromServerConfiguration() {
+ //@codeCoverageIgnoreStart
+ if (extension_loaded('bcmath')) {
+ return new \CryptLib\Core\BigMath\BCMath();
+ } elseif (extension_loaded('gmp')) {
+ return new \CryptLib\Core\BigMath\GMP();
+ } else {
+ return new \CryptLib\Core\BigMath\PHPMath();
+ }
+ //@codeCoverageIgnoreEnd
+ }
+
+ /**
+ * Add two numbers together
+ *
+ * @param string $left The left argument
+ * @param string $right The right argument
+ *
+ * @return A base-10 string of the sum of the two arguments
+ */
+ abstract public function add($left, $right);
+
+ /**
+ * Subtract two numbers
+ *
+ * @param string $left The left argument
+ * @param string $right The right argument
+ *
+ * @return A base-10 string of the difference of the two arguments
+ */
+ abstract public function subtract($left, $right);
+
+}
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * A class for arbitrary precision math functions implemented using bcmath
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Core
+ * @subpackage BigMath
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+namespace CryptLib\Core\BigMath;
+
+/**
+ * A class for arbitrary precision math functions implemented using bcmath
+ *
+ * @category PHPCryptLib
+ * @package Core
+ * @subpackage BigMath
+ */
+class BCMath extends \CryptLib\Core\BigMath {
+
+ /**
+ * Add two numbers together
+ *
+ * @param string $left The left argument
+ * @param string $right The right argument
+ *
+ * @return A base-10 string of the sum of the two arguments
+ */
+ public function add($left, $right) {
+ return bcadd($left, $right, 0);
+ }
+
+ /**
+ * Subtract two numbers
+ *
+ * @param string $left The left argument
+ * @param string $right The right argument
+ *
+ * @return A base-10 string of the difference of the two arguments
+ */
+ public function subtract($left, $right) {
+ return bcsub($left, $right);
+ }
+
+}
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * A class for arbitrary precision math functions implemented using GMP
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Core
+ * @subpackage BigMath
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+namespace CryptLib\Core\BigMath;
+
+/**
+ * A class for arbitrary precision math functions implemented using GMP
+ *
+ * @category PHPCryptLib
+ * @package Core
+ * @subpackage BigMath
+ */
+class GMP extends \CryptLib\Core\BigMath {
+
+ /**
+ * Add two numbers together
+ *
+ * @param string $left The left argument
+ * @param string $right The right argument
+ *
+ * @return A base-10 string of the sum of the two arguments
+ */
+ public function add($left, $right) {
+ return gmp_strval(gmp_add($left, $right));
+ }
+
+ /**
+ * Subtract two numbers
+ *
+ * @param string $left The left argument
+ * @param string $right The right argument
+ *
+ * @return A base-10 string of the difference of the two arguments
+ */
+ public function subtract($left, $right) {
+ return gmp_strval(gmp_sub($left, $right));
+ }
+
+}
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * A class for arbitrary precision math functions implemented in PHP
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Core
+ * @subpackage BigMath
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+namespace CryptLib\Core\BigMath;
+
+use CryptLib\Core\BaseConverter;
+
+/**
+ * A class for arbitrary precision math functions implemented in PHP
+ *
+ * @category PHPCryptLib
+ * @package Core
+ * @subpackage BigMath
+ */
+class PHPMath extends \CryptLib\Core\BigMath {
+
+ /**
+ * Add two numbers together
+ *
+ * @param string $left The left argument
+ * @param string $right The right argument
+ *
+ * @return A base-10 string of the sum of the two arguments
+ */
+ public function add($left, $right) {
+ if (empty($left)) {
+ return $right;
+ } elseif (empty($right)) {
+ return $left;
+ }
+ $negative = '';
+ if ($left[0] == '-' && $right[0] == '-') {
+ $negative = '-';
+ $left = substr($left, 1);
+ $right = substr($right, 1);
+ } elseif ($left[0] == '-') {
+ return $this->subtract($right, substr($left, 1));
+ } elseif ($right[0] == '-') {
+ return $this->subtract($left, substr($right, 1));
+ }
+ $left = $this->normalize($left);
+ $right = $this->normalize($right);
+ $result = BaseConverter::convertFromBinary(
+ $this->addBinary($left, $right),
+ '0123456789'
+ );
+ return $negative . $result;
+ }
+
+ /**
+ * Subtract two numbers
+ *
+ * @param string $left The left argument
+ * @param string $right The right argument
+ *
+ * @return A base-10 string of the difference of the two arguments
+ */
+ public function subtract($left, $right) {
+ if (empty($left)) {
+ return $right;
+ } elseif (empty($right)) {
+ return $left;
+ } elseif ($right[0] == '-') {
+ return $this->add($left, substr($right, 1));
+ } elseif ($left[0] == '-') {
+ return '-' . $this->add(ltrim($left, '-'), $right);
+ }
+ $left = $this->normalize($left);
+ $right = $this->normalize($right);
+ $results = $this->subtractBinary($left, $right);
+ $result = BaseConverter::convertFromBinary($results[1], '0123456789');
+ return $results[0] . $result;
+ }
+
+ /**
+ * Add two binary strings together
+ *
+ * @param string $left The left argument
+ * @param string $right The right argument
+ *
+ * @return string The binary result
+ */
+ protected function addBinary($left, $right) {
+ $len = max(strlen($left), strlen($right));
+ $left = str_pad($left, $len, chr(0), STR_PAD_LEFT);
+ $right = str_pad($right, $len, chr(0), STR_PAD_LEFT);
+ $result = '';
+ $carry = 0;
+ for ($i = 0; $i < $len; $i++) {
+ $sum = ord($left[$len - $i - 1])
+ + ord($right[$len - $i - 1])
+ + $carry;
+ $result .= chr($sum % 256);
+ $carry = $sum >> 8;
+ }
+ while ($carry) {
+ $result .= chr($carry % 256);
+ $carry >>= 8;
+ }
+ return strrev($result);
+ }
+
+ /**
+ * Subtract two binary strings using 256's compliment
+ *
+ * @param string $left The left argument
+ * @param string $right The right argument
+ *
+ * @return string The binary result
+ */
+ protected function subtractBinary($left, $right) {
+ $len = max(strlen($left), strlen($right));
+ $left = str_pad($left, $len, chr(0), STR_PAD_LEFT);
+ $right = str_pad($right, $len, chr(0), STR_PAD_LEFT);
+ $right = $this->compliment($right);
+ $result = $this->addBinary($left, $right);
+ if (strlen($result) > $len) {
+ // Positive Result
+ $carry = substr($result, 0, -1 * $len);
+ $result = substr($result, strlen($carry));
+ return array(
+ '',
+ $this->addBinary($result, $carry)
+ );
+ }
+ return array('-', $this->compliment($result));
+ }
+
+ /**
+ * Take the 256 base compliment
+ *
+ * @param string $string The binary string to compliment
+ *
+ * @return string The complimented string
+ */
+ protected function compliment($string) {
+ $result = '';
+ $len = strlen($string);
+ for ($i = 0; $i < $len; $i++) {
+ $result .= chr(255 - ord($string[$i]));
+ }
+ return $result;
+ }
+
+ /**
+ * Transform a string number into a binary string using base autodetection
+ *
+ * @param string $string The string to transform
+ *
+ * @return string The binary transformed number
+ */
+ protected function normalize($string) {
+ return BaseConverter::convertToBinary(
+ $string,
+ '0123456789'
+ );
+ }
+
+}
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * The Enum base class for Enum functionality
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Core
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+namespace CryptLib\Core;
+
+use \ReflectionObject;
+
+/**
+ * The Enum base class for Enum functionality
+ *
+ * This is based off of the SplEnum class implementation (which is only available
+ * as a PECL extension in 5.3)
+ *
+ * @see http://www.php.net/manual/en/class.splenum.php
+ * @category PHPCryptLib
+ * @package Core
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+abstract class Enum {
+
+ /**
+ * A default value of null is provided. Override this to set your own default
+ */
+ const __DEFAULT = null;
+
+ /**
+ * @var string The name of the constant this instance is using
+ */
+ protected $name = '';
+
+ /**
+ * @var scalar The value of the constant this instance is using.
+ */
+ protected $value = '';
+
+ /**
+ * Creates a new value of the Enum type
+ *
+ * @param mixed $value The value this instance represents
+ * @param boolean $strict Not Implemented at this time
+ *
+ * @return void
+ * @throws UnexpectedValueException If the value is not a constant
+ */
+ public function __construct($value = null, $strict = false) {
+ if (is_null($value)) {
+ $value = static::__DEFAULT;
+ }
+ $validValues = $this->getConstList();
+ $this->name = array_search($value, $validValues);
+ if (!$this->name) {
+ throw new \UnexpectedValueException(
+ 'Value not a const in enum ' . get_class($this)
+ );
+ }
+ $this->value = $value;
+ }
+
+ /**
+ * Cast the current object to a string and return its value
+ *
+ * @return mixed the current value of the instance
+ */
+ public function __toString() {
+ return (string) $this->value;
+ }
+
+ /**
+ * Compare two enums using numeric comparison
+ *
+ * @param Enum $arg The enum to compare this instance to
+ *
+ * @return int 0 if same, 1 if the argument is greater, -1 else
+ */
+ public function compare(Enum $arg) {
+ if ($this->value == $arg->value) {
+ return 0;
+ } elseif ($this->value > $arg->value) {
+ return -1;
+ } else {
+ return 1;
+ }
+ }
+
+ /**
+ * Returns all constants (including values) as an associative array
+ *
+ * @param boolean $include_default Include the __default magic value?
+ *
+ * @return array All of the constants found against this instance
+ */
+ public function getConstList($include_default = false) {
+ static $constCache = array();
+ $class = get_class($this);
+ if (!isset($constCache[$class])) {
+ $reflector = new ReflectionObject($this);
+ $constCache[$class] = $reflector->getConstants();
+ }
+ if (!$include_default) {
+ $constants = $constCache[$class];
+ unset($constants['__DEFAULT']);
+ return $constants;
+ }
+ return $constCache[$class];
+ }
+
+}
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * The strength FlyweightEnum class
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Core
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Core;
+
+/**
+ * The strength FlyweightEnum class
+ *
+ * All mixing strategies must extend this class
+ *
+ * @category PHPCryptLib
+ * @package Core
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class Strength extends Enum {
+
+ /**
+ * We provide a default value of VeryLow so that we don't accidentally over
+ * state the strength if we forget to pass in a value...
+ */
+ const __DEFAULT = self::VERYLOW;
+
+ /**
+ * This represents Non-Cryptographic strengths. It should not be used any time
+ * that security or confidentiality is at stake
+ */
+ const VERYLOW = 1;
+
+ /**
+ * This represents the bottom line of Cryptographic strengths. It may be used
+ * for low security uses where some strength is required.
+ */
+ const LOW = 3;
+
+ /**
+ * This is the general purpose Cryptographical strength. It should be suitable
+ * for all uses except the most sensitive.
+ */
+ const MEDIUM = 5;
+
+ /**
+ * This is the highest strength available. It should not be used unless the
+ * high strength is needed, due to hardware constraints (and entropy
+ * limitations).
+ */
+ const HIGH = 7;
+
+}
--- /dev/null
+<?php
+/**
+ * A core wrapper class to provide easy access to all of the cryptographic functions
+ * contained within the library
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Core
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib;
+
+/**
+ * The autoloader class will be autoloaded at this point even if another autoloader
+ * is in use. So if it does not exist at this point, we know we must bootstrap
+ * the libraries.
+ */
+if (!class_exists('\\CryptLib\Core\AutoLoader', true)) {
+ require_once 'bootstrap.php';
+}
+
+use CryptLib\Password\Factory as PasswordFactory;
+use CryptLib\Random\Factory as RandomFactory;
+
+/**
+ * A core wrapper class to provide easy access to some of the cryptographic
+ * functions contained within the library
+ *
+ * @category PHPCryptLib
+ * @package Core
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class CryptLib {
+
+ /**
+ * Create a password hash from the supplied password and generator prefix
+ *
+ * @param string $password The password to hash
+ * @param string $prefix The prefix of the hashing function
+ *
+ * @return string The generated password hash
+ */
+ public function createPasswordHash($password, $prefix = '$2a$') {
+ $factory = new PasswordFactory();
+ return $factory->createHash($password, $prefix);
+ }
+
+ /**
+ * Verify a password against a supplied password hash
+ *
+ * @param string $password The supplied password to attempt to verify
+ * @param string $hash The valid hash to verify against
+ *
+ * @return boolean Is the password valid
+ */
+ public function verifyPasswordHash($password, $hash) {
+ $factory = new PasswordFactory();
+ return $factory->verifyHash($password, $hash);
+ }
+
+ /**
+ * Get a random element from the array
+ *
+ * @param array $sourceArray The source array to fetch from
+ *
+ * @return mixed A random element from the source array
+ */
+ public function getRandomArrayElement(array $sourceArray) {
+ $keys = array_keys($sourceArray);
+ $upperBound = count($keys);
+ $factory = new RandomFactory;
+ $generator = $factory->getMediumStrengthGenerator();
+ $key = $generator->generateInt(0, $upperBound - 1);
+ return $sourceArray[$keys[$key]];
+ }
+
+ /**
+ * Generate a random full-byte string (characters 0 - 255)
+ *
+ * @param int $size The length of the generated string
+ *
+ * @return string The generated string
+ */
+ public function getRandomBytes($size) {
+ $factory = new RandomFactory;
+ $generator = $factory->getMediumStrengthGenerator();
+ return $generator->generate($size);
+ }
+
+ /**
+ * Get a random number between the supplied boundaries
+ *
+ * @param int $min The smallest bound the generated number can be
+ * @param int $max The upper bound on the generated number
+ *
+ * @return int The generated random number
+ */
+ public function getRandomNumber($min = 0, $max = PHP_INT_MAX) {
+ $factory = new RandomFactory;
+ $generator = $factory->getMediumStrengthGenerator();
+ return $generator->generateInt($min, $max);
+ }
+
+ /**
+ * Generate a random token using base64 characters (a-zA-Z0-9./)
+ *
+ * @param int $size The number of characters in the generated output
+ *
+ * @return string The generated token string
+ */
+ public function getRandomToken($size) {
+ $factory = new RandomFactory;
+ $generator = $factory->getMediumStrengthGenerator();
+ return $generator->generateString($size);
+ }
+
+ /**
+ * Shuffle an array. This will preserve key => value relationships, and return
+ * a new array that has been randomized in order.
+ *
+ * To get keys randomized, simply pass the result through array_values()...
+ *
+ * @param array $array The input array to randomize
+ *
+ * @return array The suffled array
+ */
+ public function shuffleArray(array $array) {
+ $factory = new RandomFactory;
+ $generator = $factory->getMediumStrengthGenerator();
+ $result = array();
+ $values = array_values($array);
+ $keys = array_keys($array);
+ $max = count($array);
+ for ($i = $max - 1; $i >= 0; $i--) {
+ $int = $generator->generateInt(0, $i);
+ $result[$keys[$int]] = $values[$int];
+ unset($keys[$int], $values[$int]);
+ $keys = array_values($keys);
+ $values = array_values($values);
+ }
+ return $result;
+ }
+
+ /**
+ * Shuffle a string and return the randomized string
+ *
+ * @param string $string The string to randomize
+ *
+ * @return string The shuffled string
+ */
+ public function shuffleString($string) {
+ $factory = new RandomFactory;
+ $generator = $factory->getMediumStrengthGenerator();
+ $array = str_split($string);
+ $result = $this->shuffleArray($array);
+ return implode('', $result);
+ }
+
+}
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * The core Encryption Factory
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Encryption
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Encryption;
+
+use CryptLib\Cipher\Factory as CipherFactory;
+
+/**
+ * The core Encryption Factory
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Encryption
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class Factory extends \CryptLib\Core\AbstractFactory {
+
+ /**
+ * @var Factory The Cipher Factory to use for this instance
+ */
+ protected $cipherFactory = null;
+
+ /**
+ * @var array An array of PackingModes available for use
+ */
+ protected $packingModes = array();
+
+ /**
+ * Build the instance
+ *
+ * @param Factory $factory The Cipher Factory to use for this instance
+ *
+ * @return void
+ */
+ public function __construct(CryptoLib\Cipher\Factory $factory = null) {
+ if (is_null($factory)) {
+ $factory = new CipherFactory();
+ }
+ $this->cipherFactory = $factory;
+ $this->loadPackingModes();
+ }
+
+ /**
+ * Get a packing mode by name
+ *
+ * @param string|PackingMode $name The name of the packing mode or instance
+ *
+ * @return PackingMode The instantiated PackingMode class
+ * @throws RuntimeException If the mode does not exist
+ */
+ public function getPackingMode($name) {
+ if (is_object($name) && $name instanceof PackingMode) {
+ return $name;
+ }
+ $name = strtolower($name);
+ if (isset($this->packingModes[$name])) {
+ $class = $this->packingModes[$name];
+ return new $class;
+ }
+ $message = sprintf('Invalid Mode Supplied: %s', $name);
+ throw new \RuntimeException($message);
+ }
+
+ /**
+ * Register a new packing mode by name
+ *
+ * @param string $name The name of the packing mode
+ * @param string $class The class to instantiate for the mode
+ *
+ * @return Factory $this The current factory instance
+ */
+ public function registerPackingMode($name, $class) {
+ $this->registerType(
+ 'packingModes',
+ __NAMESPACE__ . '\\PackingMode',
+ $name,
+ $class
+ );
+ return $this;
+ }
+
+ /**
+ * Load the core packing modes for this instance
+ *
+ * @return void
+ */
+ protected function loadPackingModes() {
+ $this->loadFiles(
+ __DIR__ . '/PackingMode',
+ __NAMESPACE__ . '\\PackingMode\\',
+ array($this, 'registerPackingMode')
+ );
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * The core PackingMode interface. All packingmodes must implement this
+ * interface
+ *
+ * A packing mode is a method for padding a string to a specified size using
+ * various methods
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Encryption
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Encryption;
+
+/**
+ * The core PackingMode interface. All packingmodes must implement this
+ * interface
+ *
+ * A packing mode is a method for padding a string to a specified size using
+ * various methods
+ *
+ * @category PHPCryptLib
+ * @package Encryption
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @codeCoverageIgnore
+ */
+interface PackingMode {
+
+ /**
+ * Pad the string to the specified size
+ *
+ * @param string $string The string to pad
+ * @param int $blockSize The size to pad to
+ *
+ * @return string The padded string
+ */
+ public function pad($string, $blockSize = 32);
+
+ /**
+ * Strip the padding from the supplied string
+ *
+ * @param string $string The string to trim
+ *
+ * @return string The unpadded string
+ */
+ public function strip($string);
+
+}
+
--- /dev/null
+<?php
+/**
+ * A packing mode implementation for ASNIx923 padding
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Encryption
+ * @subpackage PackingMode
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Encryption\PackingMode;
+
+/**
+ * A packing mode implementation for ASNIx923 padding
+ *
+ * @category PHPCryptLib
+ * @package Encryption
+ * @subpackage PackingMode
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class ANSIx923 implements \CryptLib\Encryption\PackingMode {
+
+ /**
+ * Pad the string to the specified size
+ *
+ * @param string $string The string to pad
+ * @param int $blockSize The size to pad to
+ *
+ * @return string The padded string
+ */
+ public function pad($string, $blockSize = 32) {
+ $pad = $blockSize - (strlen($string) % $blockSize);
+ return $string . str_repeat(chr(0), $pad - 1) . chr($pad);
+ }
+
+ /**
+ * Strip the padding from the supplied string
+ *
+ * @param string $string The string to trim
+ *
+ * @return string The unpadded string
+ */
+ public function strip($string) {
+ $end = ord(substr($string, -1));
+ $len = strlen($string) - $end;
+ $tmp = str_repeat(chr(0), $end - 1) . chr($end);
+ if (substr($string, $len) == $tmp) {
+ return substr($string, 0, $len);
+ }
+ return false;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * A Packing Mode implementation of the ISO 10126 standard
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Encryption
+ * @subpackage PackingMode
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Encryption\PackingMode;
+
+/**
+ * A Packing Mode implementation of the ISO 10126 standard
+ *
+ * @category PHPCryptLib
+ * @package Encryption
+ * @subpackage PackingMode
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class ISO10126 implements \CryptLib\Encryption\PackingMode {
+
+ /**
+ * Pad the string to the specified size
+ *
+ * @param string $string The string to pad
+ * @param int $blockSize The size to pad to
+ *
+ * @return string The padded string
+ */
+ public function pad($string, $blockSize = 32) {
+ $pad = $blockSize - (strlen($string) % $blockSize);
+ $padstr = '';
+ for ($i = 1; $i < $pad; $i++) {
+ $padstr .= chr(mt_rand(0, 255));
+ }
+ return $string . $padstr . chr($pad);
+ }
+
+ /**
+ * Strip the padding from the supplied string
+ *
+ * @param string $string The string to trim
+ *
+ * @return string The unpadded string
+ */
+ public function strip($string) {
+ $end = ord(substr($string, -1));
+ $len = strlen($string) - $end;
+ return substr($string, 0, $len);
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * A packing mode implementation for no padding
+ *
+ * This is provided for completeness only. Do not use this with actual ciphers
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Encryption
+ * @subpackage PackingMode
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Encryption\PackingMode;
+
+/**
+ * A packing mode implementation for no padding
+ *
+ * This is provided for completeness only. Do not use this with actual ciphers
+ *
+ * @category PHPCryptLib
+ * @package Encryption
+ * @subpackage PackingMode
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class None implements \CryptLib\Encryption\PackingMode {
+
+ /**
+ * Pad the string to the specified size
+ *
+ * @param string $string The string to pad
+ * @param int $blockSize The size to pad to
+ *
+ * @return string The padded string
+ */
+ public function pad($string, $blockSize = 32) {
+ return $string;
+ }
+
+ /**
+ * Strip the padding from the supplied string
+ *
+ * @param string $string The string to trim
+ *
+ * @return string The unpadded string
+ */
+ public function strip($string) {
+ return $string;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * A packing mode implementation for PKCS7 padding
+ *
+ * PHP version 5.3
+ *
+ * @see http://tools.ietf.org/html/rfc2315
+ * @category PHPCryptLib
+ * @package Encryption
+ * @subpackage PackingMode
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Encryption\PackingMode;
+
+/**
+ * A packing mode implementation for PKCS7 padding
+ *
+ * PHP version 5.3
+ *
+ * @see http://tools.ietf.org/html/rfc2315
+ * @category PHPCryptLib
+ * @package Encryption
+ * @subpackage PackingMode
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class PKCS7 implements \CryptLib\Encryption\PackingMode {
+
+ /**
+ * Pad the string to the specified size
+ *
+ * @param string $string The string to pad
+ * @param int $blockSize The size to pad to
+ *
+ * @return string The padded string
+ */
+ public function pad($string, $blockSize = 32) {
+ $pad = $blockSize - (strlen($string) % $blockSize);
+ return $string . str_repeat(chr($pad), $pad);
+ }
+
+ /**
+ * Strip the padding from the supplied string
+ *
+ * @param string $string The string to trim
+ *
+ * @return string The unpadded string
+ */
+ public function strip($string) {
+ $end = substr($string, -1);
+ $last = ord($end);
+ $len = strlen($string) - $last;
+ if (substr($string, $len) == str_repeat($end, $last)) {
+ return substr($string, 0, $len);
+ }
+ return false;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * A packing mode implementation for null-byte padding
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Encryption
+ * @subpackage PackingMode
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Encryption\PackingMode;
+
+/**
+ * A packing mode implementation for null-byte padding
+ *
+ * @category PHPCryptLib
+ * @package Encryption
+ * @subpackage PackingMode
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class Zeros implements \CryptLib\Encryption\PackingMode {
+
+ /**
+ * Pad the string to the specified size
+ *
+ * @param string $string The string to pad
+ * @param int $blockSize The size to pad to
+ *
+ * @return string The padded string
+ */
+ public function pad($string, $blockSize = 32) {
+ $pad = $blockSize - (strlen($string) % $blockSize);
+ if ($pad == $blockSize) {
+ return $string;
+ }
+ return $string . str_repeat(chr(0), $pad);
+ }
+
+ /**
+ * Strip the padding from the supplied string
+ *
+ * @param string $string The string to trim
+ *
+ * @return string The unpadded string
+ */
+ public function strip($string) {
+ return rtrim($string, chr(0));
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * An implementation of a streamable CRC32
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Hash
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+namespace CryptLib\Hash;
+
+/**
+ * An implementation of a streamable CRC32
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Hash
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class CRC32 {
+
+ /**
+ * @var int The initialal value for the CRC32
+ */
+ protected static $initValue = 0xFFFFFFFF;
+
+ /**
+ * @var array The table of permutations for substituting CRC32 data with
+ */
+ protected static $table = array(
+ 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
+ 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
+ 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
+ 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
+ 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
+ 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
+ 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
+ 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
+ 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
+ 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
+ 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
+ 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
+ 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
+ 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
+ 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
+ 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
+ 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
+ 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
+ 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
+ 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
+ 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
+ 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
+ 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
+ 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
+ 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
+ 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
+ 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
+ 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
+ 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
+ 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
+ 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
+ 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
+ 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
+ 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
+ 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
+ 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
+ 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
+ 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
+ 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
+ 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
+ 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
+ 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
+ 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D,
+ );
+
+ /**
+ * Compute a CRC32 value of a string
+ *
+ * @param string $data The data to calculate the crc32 for
+ *
+ * @return int The computed CRC32 value
+ */
+ public static function calculate($data) {
+ return static::update(static::$initValue ^ 0xFFFFFFFF, $data);
+ }
+
+ /**
+ * Updates an existing CRC32 value with a new byte (for a stream)
+ *
+ * @param int $crc32 The previous CRC32 value
+ * @param string $data The new byte to end (string length 1)
+ *
+ * @return int The updated CRC32 value
+ */
+ public static function update($crc32, $data) {
+ $result = $crc32 ^ 0xFFFFFFFF;
+ $length = strlen($data);
+ for ($i = 0; $i < $length; $i++) {
+ $lowPart = $result & 0xFF;
+ $shifted = ($result >> 8) & 0xFFFFFF;
+ $result = static::$table[($lowPart ^ ord($data[$i])) & 0xFF] ^ $shifted;
+ }
+ return $result ^ 0xFFFFFFFF;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * A hash utility data mapper class
+ *
+ * This class's purpose is to store information about hash algorithms that is
+ * otherwise unavailable during runtime. Some information is available (such
+ * as the output size), but is included anyway for performance and completeness
+ * reasons.
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Hash
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+namespace CryptLib\Hash;
+
+/**
+ * A hash utility data mapper class
+ *
+ * This class's purpose is to store information about hash algorithms that is
+ * otherwise unavailable during runtime. Some information is available (such
+ * as the output size), but is included anyway for performance and completeness
+ * reasons.
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Hash
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class Hash {
+
+ /**
+ * This array contains information about each hash function available to PHP
+ * at the present time. Block sizes are not available from functions, so they
+ * must be hard coded.
+ *
+ * The "secure" indicates the strength of the hash and whether or not any known
+ * cryptographic attacks exist for the hash function. This will only apply when
+ * using the hash functions for situations that require cryptographic strength
+ * such as message signing. For other uses the insecure ones can have valid
+ * uses.
+ *
+ * @var array An array of information about each supported hash function
+ */
+ protected static $hashInfo = array(
+ 'md2' => array(
+ 'HashSize' => 128,
+ 'BlockSize' => 128,
+ 'secure' => false,
+ ),
+ 'md4' => array(
+ 'HashSize' => 128,
+ 'BlockSize' => 512,
+ 'secure' => false,
+ ),
+ 'md5' => array(
+ 'HashSize' => 128,
+ 'BlockSize' => 512,
+ 'secure' => false,
+ ),
+ 'sha1' => array(
+ 'HashSize' => 160,
+ 'BlockSize' => 512,
+ 'secure' => false,
+ ),
+ 'sha224' => array(
+ 'HashSize' => 224,
+ 'BlockSize' => 512,
+ 'secure' => true,
+ ),
+ 'sha256' => array(
+ 'HashSize' => 256,
+ 'BlockSize' => 512,
+ 'secure' => true,
+ ),
+ 'sha384' => array(
+ 'HashSize' => 384,
+ 'BlockSize' => 1024,
+ 'secure' => true,
+ ),
+ 'sha512' => array(
+ 'HashSize' => 512,
+ 'BlockSize' => 1024,
+ 'secure' => true,
+ ),
+ 'ripemd128' => array(
+ 'HashSize' => 128,
+ 'BlockSize' => 512,
+ 'secure' => true,
+ ),
+ 'ripemd160' => array(
+ 'HashSize' => 160,
+ 'BlockSize' => 512,
+ 'secure' => true,
+ ),
+ 'ripemd256' => array(
+ 'HashSize' => 256,
+ 'BlockSize' => 512,
+ 'secure' => true,
+ ),
+ 'ripemd320' => array(
+ 'HashSize' => 320,
+ 'BlockSize' => 512,
+ 'secure' => true,
+ ),
+ 'whirlpool' => array(
+ 'HashSize' => 512,
+ 'BlockSize' => 512,
+ 'secure' => true,
+ ),
+ 'tiger128,3' => array(
+ 'HashSize' => 128,
+ 'BlockSize' => 512,
+ 'secure' => true,
+ ),
+ 'tiger160,3' => array(
+ 'HashSize' => 160,
+ 'BlockSize' => 512,
+ 'secure' => true,
+ ),
+ 'tiger192,3' => array(
+ 'HashSize' => 192,
+ 'BlockSize' => 512,
+ 'secure' => true,
+ ),
+ 'tiger128,4' => array(
+ 'HashSize' => 128,
+ 'BlockSize' => 512,
+ 'secure' => true,
+ ),
+ 'tiger160,4' => array(
+ 'HashSize' => 160,
+ 'BlockSize' => 512,
+ 'secure' => true,
+ ),
+ 'tiger192,4' => array(
+ 'HashSize' => 192,
+ 'BlockSize' => 512,
+ 'secure' => true,
+ ),
+ 'snefru' => array(
+ 'HashSize' => 256,
+ 'BlockSize' => 512,
+ 'secure' => false,
+ ),
+ 'snefru256' => array(
+ 'HashSize' => 256,
+ 'BlockSize' => 512,
+ 'secure' => false,
+ ),
+ 'gost' => array(
+ 'HashSize' => 256,
+ 'BlockSize' => 256,
+ 'secure' => false,
+ ),
+ 'adler32' => array(
+ 'HashSize' => 32,
+ 'BlockSize' => 16,
+ 'secure' => false,
+ ),
+ 'crc32' => array(
+ 'HashSize' => 32,
+ 'BlockSize' => 32,
+ 'secure' => false,
+ ),
+ 'crc32b' => array(
+ 'HashSize' => 32,
+ 'BlockSize' => 32,
+ 'secure' => false,
+ ),
+ 'salsa10' => array(
+ 'HashSize' => 512,
+ 'BlockSize' => 512,
+ 'secure' => true,
+ ),
+ 'salsa20' => array(
+ 'HashSize' => 512,
+ 'BlockSize' => 512,
+ 'secure' => true,
+ ),
+ 'haval128,3' => array(
+ 'HashSize' => 128,
+ 'BlockSize' => 1024,
+ 'secure' => false,
+ ),
+ 'haval160,3' => array(
+ 'HashSize' => 160,
+ 'BlockSize' => 1024,
+ 'secure' => false,
+ ),
+ 'haval192,3' => array(
+ 'HashSize' => 192,
+ 'BlockSize' => 1024,
+ 'secure' => false,
+ ),
+ 'haval224,3' => array(
+ 'HashSize' => 224,
+ 'BlockSize' => 1024,
+ 'secure' => false,
+ ),
+ 'haval256,3' => array(
+ 'HashSize' => 256,
+ 'BlockSize' => 1024,
+ 'secure' => false,
+ ),
+ 'haval128,4' => array(
+ 'HashSize' => 128,
+ 'BlockSize' => 1024,
+ 'secure' => false,
+ ),
+ 'haval160,4' => array(
+ 'HashSize' => 160,
+ 'BlockSize' => 1024,
+ 'secure' => false,
+ ),
+ 'haval192,4' => array(
+ 'HashSize' => 192,
+ 'BlockSize' => 1024,
+ 'secure' => false,
+ ),
+ 'haval224,4' => array(
+ 'HashSize' => 224,
+ 'BlockSize' => 1024,
+ 'secure' => false,
+ ),
+ 'haval256,4' => array(
+ 'HashSize' => 256,
+ 'BlockSize' => 1024,
+ 'secure' => false,
+ ),
+ 'haval128,5' => array(
+ 'HashSize' => 128,
+ 'BlockSize' => 1024,
+ 'secure' => false,
+ ),
+ 'haval160,5' => array(
+ 'HashSize' => 160,
+ 'BlockSize' => 1024,
+ 'secure' => false,
+ ),
+ 'haval192,5' => array(
+ 'HashSize' => 192,
+ 'BlockSize' => 1024,
+ 'secure' => false,
+ ),
+ 'haval224,5' => array(
+ 'HashSize' => 224,
+ 'BlockSize' => 1024,
+ 'secure' => false,
+ ),
+ 'haval256,5' => array(
+ 'HashSize' => 256,
+ 'BlockSize' => 1024,
+ 'secure' => false,
+ ),
+ 'joaat' => array(
+ 'HashSize' => 32,
+ 'BlockSize' => 64,
+ 'secure' => false,
+ ),
+ 'fnv132' => array(
+ 'HashSize' => 32,
+ 'BlockSize' => 32,
+ 'secure' => false,
+ ),
+ 'fnv164' => array(
+ 'HashSize' => 64,
+ 'BlockSize' => 64,
+ 'secure' => false,
+ ),
+ );
+
+ /**
+ * Get the block size of the specified function in bytes
+ *
+ * @param string $hash The hash function to look up
+ *
+ * @return int The number of bytes in the block function
+ */
+ public static function getBlockSize($hash) {
+ return static::getBlockSizeInBits($hash) / 8;
+ }
+
+ /**
+ * Get the block size of the specified function in bits
+ *
+ * @param string $hash The hash function to look up
+ *
+ * @return int The number of bits in the block function
+ */
+ public static function getBlockSizeInBits($hash) {
+ if (isset(static::$hashInfo[$hash]['BlockSize'])) {
+ return static::$hashInfo[$hash]['BlockSize'];
+ }
+ return 0;
+ }
+
+ /**
+ * Get the output size of the specified function in bytes
+ *
+ * @param string $hash The hash function to look up
+ *
+ * @return int The number of bytes outputted by the hash function
+ */
+ public static function getHashSize($hash) {
+ return static::getHashSizeInBits($hash) / 8;
+ }
+
+ /**
+ * Get the output size of the specified function in bits
+ *
+ * @param string $hash The hash function to look up
+ *
+ * @return int The number of bits outputted by the hash function
+ */
+ public static function getHashSizeInBits($hash) {
+ if (isset(static::$hashInfo[$hash]['HashSize'])) {
+ return static::$hashInfo[$hash]['HashSize'];
+ }
+ return 0;
+ }
+
+ /**
+ * Check to see if the hash function specified is available
+ *
+ * @param string $hash The hash function to look up
+ *
+ * @return boolean If the hash function is available in this version of PHP
+ */
+ public static function isAvailable($hash) {
+ return in_array($hash, hash_algos());
+ }
+
+ /**
+ * Check to see if the specified hash function is secure enough for
+ * cryptographic uses
+ *
+ * The "secure" indicates the strength of the hash and whether or not any known
+ * cryptographic attacks exist for the hash function. This will only apply when
+ * using the hash functions for situations that require cryptographic strength
+ * such as message signing. For other uses the insecure ones can have valid
+ * uses.
+ *
+ * @param string $hash The hash function to look up
+ *
+ * @return bolean If the function is secure
+ */
+ public static function isSecure($hash) {
+ if (isset(static::$hashInfo[$hash])) {
+ return static::$hashInfo[$hash]['secure'];
+ }
+ return false;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * An abstract implementation of some standard key derivation needs
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Key
+ * @subpackage Derivation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Key\Derivation;
+
+/**
+ * An abstract implementation of some standard key derivation needs
+ *
+ * @category PHPCryptLib
+ * @package Key
+ * @subpackage Derivation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+abstract class AbstractDerivation {
+
+ /**
+ * @var Hash A hashing algorithm to use for the derivation
+ */
+ protected $hash = null;
+
+ /**
+ * @var array An array of options for the key derivation function
+ */
+ protected $options = array(
+ 'hash' => 'sha512',
+ );
+
+ /**
+ * Construct the derivation instance
+ *
+ * @param array $options An array of options to set for this instance
+ *
+ * @return void
+ */
+ public function __construct(array $options = array()) {
+ $this->options = $options + $this->options;
+ $this->hash = $this->options['hash'];
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * The standard Key Derivation Function interface
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Key
+ * @subpackage Derivation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT Licenses
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Key\Derivation;
+
+/**
+ * The standard Key Derivation Function interface
+ *
+ * @category PHPCryptLib
+ * @package Key
+ * @subpackage Derivation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @codeCoverageIgnore
+ */
+interface KDF {
+
+ /**
+ * Derive a key of the specified length based on the inputted secret
+ *
+ * @param string $secret The secret to base the key on
+ * @param int $length The length of the key to derive
+ * @param string $other Additional data to append to the key
+ *
+ * @return string The generated key
+ */
+ public function derive($secret, $length, $other = '');
+
+}
--- /dev/null
+<?php
+/**
+ * An implementation of the RFC 10833-2 KDF1 Standard key derivation function
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Key
+ * @subpackage Derivation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Key\Derivation\KDF;
+
+use CryptLib\Hash\Hash;
+
+/**
+ * An implementation of the RFC 10833-2 KDF1 Standard key derivation function
+ *
+ * @category PHPCryptLib
+ * @package Key
+ * @subpackage Derivation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class KDF1
+ extends \CryptLib\Key\Derivation\AbstractDerivation
+ implements \CryptLib\Key\Derivation\KDF
+{
+
+ /**
+ * Derive a key of the specified length based on the inputted secret
+ *
+ * @param string $secret The secret to base the key on
+ * @param int $length The length of the key to derive
+ * @param string $other Additional data to append to the key
+ *
+ * @return string The generated key
+ */
+ public function derive($secret, $length, $other = '') {
+ $size = Hash::getHashSize($this->hash);
+ $len = ceil($length / $size);
+ $res = '';
+ for ($i = 0; $i < $len; $i++) {
+ $tmp = pack('N', $i);
+ $res .= hash($this->hash, $secret . $tmp . $other, true);
+ }
+ return substr($res, 0, $length);
+ }
+
+}
+
--- /dev/null
+<?php
+/**
+ * An implementation of the RFC 10833-2 KDF2 Standard key derivation function
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Key
+ * @subpackage Derivation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Key\Derivation\KDF;
+
+use CryptLib\Hash\Hash;
+
+/**
+ * An implementation of the RFC 10833-2 KDF2 Standard key derivation function
+ *
+ * @category PHPCryptLib
+ * @package Key
+ * @subpackage Derivation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class KDF2
+ extends \CryptLib\Key\Derivation\AbstractDerivation
+ implements \CryptLib\Key\Derivation\KDF
+{
+
+ /**
+ * Derive a key of the specified length based on the inputted secret
+ *
+ * @param string $secret The secret to base the key on
+ * @param int $length The length of the key to derive
+ * @param string $other Additional data to append to the key
+ *
+ * @return string The generated key
+ */
+ public function derive($secret, $length, $other = '') {
+ $size = Hash::getHashSize($this->hash);
+ $len = ceil($length / $size);
+ $res = '';
+ for ($i = 1; $i <= $len; $i++) {
+ $tmp = pack('N', $i);
+ $res .= hash($this->hash, $secret . $tmp . $other, true);
+ }
+ return substr($res, 0, $length);
+ }
+
+}
+
--- /dev/null
+<?php
+/**
+ * An implementation of the RFC 10833-2 KDF3 Standard key derivation function
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Key
+ * @subpackage Derivation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Key\Derivation\KDF;
+
+use CryptLib\Hash\Hash;
+
+/**
+ * An implementation of the RFC 10833-2 KDF3 Standard key derivation function
+ *
+ * @category PHPCryptLib
+ * @package Key
+ * @subpackage Derivation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class KDF3
+ extends \CryptLib\Key\Derivation\AbstractDerivation
+ implements \CryptLib\Key\Derivation\KDF
+{
+
+ /**
+ * @var array An array of options for the key derivation function
+ */
+ protected $options = array(
+ 'hash' => 'sha512',
+ 'pAmt' => 4,
+ );
+
+ /**
+ * Derive a key of the specified length based on the inputted secret
+ *
+ * @param string $secret The secret to base the key on
+ * @param int $length The length of the key to derive
+ * @param string $other Additional data to append to the key
+ *
+ * @return string The generated key
+ */
+ public function derive($secret, $length, $other = '') {
+ $size = Hash::getHashSize($this->hash);
+ $len = ceil($length / $size);
+ $res = '';
+ $stub = str_repeat(chr(0), max($this->options['pAmt'], 0));
+ for ($i = 0; $i < $len; $i++) {
+ $tmp = $stub . pack('N', $i);
+ $res .= hash($this->hash, $tmp . $secret . $other, true);
+ }
+ return substr($res, 0, $length);
+ }
+
+}
+
--- /dev/null
+<?php
+/**
+ * The core PBKDF interface (Password Based Key Derivation Function)
+ *
+ * This interface must be used to describe all derivation functions that take a
+ * password as input and produce a key or hash as output
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Key
+ * @subpackage Derivation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Key\Derivation;
+
+/**
+ * The core PBKDF interface (Password Based Key Derivation Function)
+ *
+ * This interface must be used to describe all derivation functions that take a
+ * password as input and produce a key or hash as output
+ *
+ * @category PHPCryptLib
+ * @package Key
+ * @subpackage Derivation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @codeCoverageIgnore
+ */
+interface PBKDF {
+
+ /**
+ * Derive a key from the supplied arguments
+ *
+ * @param string $password The password to derive from
+ * @param string $salt The salt string to use
+ * @param int $iterations The number of iterations to use
+ * @param int $length The size of the string to generate
+ *
+ * @return string The derived key
+ */
+ public function derive($passkey, $salt, $iterations, $klen);
+
+ /**
+ * Get the signature for this implementation
+ *
+ * This should include all information needed to build the same isntance
+ * later.
+ *
+ * @return string The signature for this instance
+ */
+ public function getSignature();
+
+}
--- /dev/null
+<?php
+/**
+ * An implementation of the crypt library's Blowfish hash method
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Key
+ * @subpackage Derivation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Key\Derivation\PBKDF;
+
+/**
+ * An implementation of the crypt library's Blowfish hash method
+ *
+ * @category PHPCryptLib
+ * @package Key
+ * @subpackage Derivation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class BCrypt
+ extends \CryptLib\Key\Derivation\AbstractDerivation
+ implements \CryptLib\Key\Derivation\PBKDF
+{
+
+ /**
+ * Derive a key from the supplied arguments
+ *
+ * @param string $password The password to derive from
+ * @param string $salt The salt string to use
+ * @param int $iterations The number of iterations to use
+ * @param int $length The size of the string to generate
+ *
+ * @return string The derived key
+ */
+ public function derive($password, $salt, $iterations, $length) {
+ $salt = $this->encode64($salt);
+ if (strlen($salt) > 22) {
+ $salt = substr($salt, 0, 22);
+ } elseif (strlen($salt) < 22) {
+ $salt = str_pad($salt, '0');
+ }
+ $expense = ceil(log($iterations, 2));
+ $expense = $expense < 4 ? 4 : $expense;
+ $expense = $expense > 31 ? 31 : $expense;
+ $salt = '$2a$'.str_pad($expense, 2, '0', STR_PAD_LEFT).'$'.$salt;
+ return crypt($password, $salt);
+ }
+
+ /**
+ * Get the signature for this implementation
+ *
+ * This should include all information needed to build the same isntance
+ * later.
+ *
+ * @return string The signature for this instance
+ */
+ public function getSignature() {
+ return 'bcrypt';
+ }
+
+ /**
+ * Encode a string for a blowfish salt
+ *
+ * @param string $string The string to encode
+ *
+ * @return The encoded string
+ */
+ protected function encode64($string) {
+ return str_replace(
+ array('+', '='),
+ array('.', '/'),
+ base64_encode($string)
+ );
+ }
+}
+
--- /dev/null
+<?php
+/**
+ * An implementation of the RFC 2898 PBKDF1 Standard key derivation function
+ *
+ * PHP version 5.3
+ *
+ * @see http://www.ietf.org/rfc/rfc2898.txt
+ * @category PHPCryptLib
+ * @package Key
+ * @subpackage Derivation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Key\Derivation\PBKDF;
+
+use CryptLib\Hash\Hash;
+
+/**
+ * An implementation of the RFC 2989 PBKDF1 Standard key derivation function
+ *
+ * @see http://www.ietf.org/rfc/rfc2898.txt
+ * @category PHPCryptLib
+ * @package Key
+ * @subpackage Derivation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class PBKDF1
+ extends \CryptLib\Key\Derivation\AbstractDerivation
+ implements \CryptLib\Key\Derivation\PBKDF
+{
+
+ /**
+ * Derive a key from the supplied arguments
+ *
+ * @param string $password The password to derive from
+ * @param string $salt The salt string to use
+ * @param int $iterations The number of iterations to use
+ * @param int $length The size of the string to generate
+ *
+ * @return string The derived key
+ */
+ public function derive($password, $salt, $iterations, $length) {
+ $size = Hash::getHashSize($this->hash);
+ if ($length > $size) {
+ $message = 'Length is too long for hash';
+ throw new \InvalidArgumentException($message);
+ }
+ $tmp = hash($this->hash, $password . $salt, true);
+ for ($i = 2; $i <= $iterations; $i++) {
+ $tmp = hash($this->hash, $tmp, true);
+ }
+ return substr($tmp, 0, $length);
+ }
+
+ /**
+ * Get the signature for this implementation
+ *
+ * This should include all information needed to build the same isntance
+ * later.
+ *
+ * @return string The signature for this instance
+ */
+ public function getSignature() {
+ return 'pbkdf1-' . $this->hash;
+ }
+
+}
+
--- /dev/null
+<?php
+/**
+ * An implementation of the RFC 2898 PBKDF2 Standard key derivation function
+ *
+ * PHP version 5.3
+ *
+ * @see http://www.ietf.org/rfc/rfc2898.txt
+ * @category PHPCryptLib
+ * @package Key
+ * @subpackage Derivation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Key\Derivation\PBKDF;
+
+use CryptLib\Hash\Hash;
+
+/**
+ * An implementation of the RFC 2898 PBKDF2 Standard key derivation function
+ *
+ * @see http://www.ietf.org/rfc/rfc2898.txt
+ * @category PHPCryptLib
+ * @package Key
+ * @subpackage Derivation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class PBKDF2
+ extends \CryptLib\Key\Derivation\AbstractDerivation
+ implements \CryptLib\Key\Derivation\PBKDF
+{
+
+ /**
+ * Derive a key from the supplied arguments
+ *
+ * @param string $password The password to derive from
+ * @param string $salt The salt string to use
+ * @param int $iterations The number of iterations to use
+ * @param int $length The size of the string to generate
+ *
+ * @return string The derived key
+ */
+ public function derive($password, $salt, $iterations, $length) {
+ $size = Hash::getHashSize($this->hash);
+ $len = ceil($length / $size);
+ $result = '';
+ for ($i = 1; $i <= $len; $i++) {
+ $tmp = hash_hmac(
+ $this->hash,
+ $salt . pack('N', $i),
+ $password,
+ true
+ );
+ $res = $tmp;
+ for ($j = 1; $j < $iterations; $j++) {
+ $tmp = hash_hmac($this->hash, $tmp, $password, true);
+ $res ^= $tmp;
+ }
+ $result .= $res;
+ }
+ return substr($result, 0, $length);
+ }
+
+ /**
+ * Get the signature for this implementation
+ *
+ * This should include all information needed to build the same isntance
+ * later.
+ *
+ * @return string The signature for this instance
+ */
+ public function getSignature() {
+ return 'pbkdf2-' . $this->hash;
+ }
+
+}
+
--- /dev/null
+<?php
+/**
+ * An implementation of the crypt library's SHA512 hash method
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Key
+ * @subpackage Derivation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Key\Derivation\PBKDF;
+
+/**
+ * An implementation of the crypt library's SHA512 hash method
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Key
+ * @subpackage Derivation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class SHA256
+ extends \CryptLib\Key\Derivation\AbstractDerivation
+ implements \CryptLib\Key\Derivation\PBKDF
+{
+
+ /**
+ * Derive a key from the supplied arguments
+ *
+ * @param string $password The password to derive from
+ * @param string $salt The salt string to use
+ * @param int $iterations The number of iterations to use
+ * @param int $length The size of the string to generate
+ *
+ * @return string The derived key
+ */
+ public function derive($password, $salt, $iterations, $length) {
+ $salt = substr(str_pad($salt, 16, chr(0)), 0, 16);
+ $salt = '$5$rounds='.$iterations.'$'.$salt;
+ return crypt($password, $salt);
+ }
+
+ /**
+ * Get the signature for this implementation
+ *
+ * This should include all information needed to build the same isntance
+ * later.
+ *
+ * @return string The signature for this instance
+ */
+ public function getSignature() {
+ return 'sha256';
+ }
+
+}
+
--- /dev/null
+<?php
+/**
+ * An implementation of the crypt library's SHA512 hash method
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Key
+ * @subpackage Derivation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Key\Derivation\PBKDF;
+
+/**
+ * An implementation of the crypt library's SHA512 hash method
+ *
+ * @category PHPCryptLib
+ * @package Key
+ * @subpackage Derivation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class SHA512
+ extends \CryptLib\Key\Derivation\AbstractDerivation
+ implements \CryptLib\Key\Derivation\PBKDF
+{
+
+ /**
+ * Derive a key from the supplied arguments
+ *
+ * @param string $password The password to derive from
+ * @param string $salt The salt string to use
+ * @param int $iterations The number of iterations to use
+ * @param int $length The size of the string to generate
+ *
+ * @return string The derived key
+ */
+ public function derive($password, $salt, $iterations, $length) {
+ $salt = substr(str_pad($salt, 16, chr(0)), 0, 16);
+ $salt = '$6$rounds='.$iterations.'$'.$salt;
+ return crypt($password, $salt);
+ }
+
+ /**
+ * Get the signature for this implementation
+ *
+ * This should include all information needed to build the same isntance
+ * later.
+ *
+ * @return string The signature for this instance
+ */
+ public function getSignature() {
+ return 'sha512';
+ }
+
+}
+
--- /dev/null
+<?php
+/**
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Key\Derivation\PBKDF;
+
+use CryptLib\Hash\Hash;
+
+/**
+ * Description of pbkdf2
+ *
+ * @author ircmaxell
+ */
+class Schneier
+ extends \CryptLib\Key\Derivation\AbstractDerivation
+ implements \CryptLib\Key\Derivation\PBKDF
+{
+
+ public function derive($password, $salt, $iterations, $length) {
+ $size = Hash::getHashSize($this->hash);
+ if ($length > $size) {
+ throw new \InvalidArgumentException('Length is too long for hash');
+ }
+ $tmp = hash($this->hash, $password . $salt, true);
+ for ($i = 2; $i <= $iterations; $i++) {
+ $tmp = hash($this->hash, $tmp . $password . $salt, true);
+ }
+ return substr($tmp, 0, $length);
+ }
+
+ /**
+ * Get the signature for this implementation
+ *
+ * This should include all information needed to build the same instance
+ * later.
+ *
+ * @return string The signature for this instance
+ */
+ public function getSignature() {
+ return 'schneier-'.$this->hash;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * The core Key Factory
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Key
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Key;
+
+/**
+ * The core Key Factory
+ *
+ * @category PHPCryptLib
+ * @package Key
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class Factory extends \CryptLib\Core\AbstractFactory {
+
+ /**
+ * @var array An array of KDF class implementations
+ */
+ protected $kdf = array();
+
+ /**
+ * @var array An array of PBKDF class implementations
+ */
+ protected $pbkdf = array();
+
+ /**
+ * @var array An array of symmetric key generator implementations
+ */
+ protected $symmetricGenerators = array();
+
+ /**
+ * Construct the instance, loading the core implementations
+ *
+ * @return void
+ */
+ public function __construct() {
+ $this->loadPBKDF();
+ $this->loadKDF();
+ //$this->loadSymmetricGenerators();
+ }
+
+ public function getKDF($name = 'kdf3', array $options = array()) {
+ if (isset($this->kdf[$name])) {
+ $class = $this->kdf[$name];
+ return new $class($options);
+ }
+ throw new \InvalidArgumentException('Unsupported KDF');
+ }
+
+ public function getPBKDF($name = 'pbkdf2', array $options = array()) {
+ if (isset($this->pbkdf[$name])) {
+ $class = $this->pbkdf[$name];
+ return new $class($options);
+ }
+ throw new \InvalidArgumentException('Unsupported PBKDF');
+ }
+
+ public function getPBKDFFromSignature($signature) {
+ list ($name, $hash) = explode('-', $signature, 2);
+ return $this->getPBKDF($name, array('hash' => $hash));
+ }
+
+ public function getSymmetricKeyGenerator() {
+ }
+
+ public function registerKDF($name, $class) {
+ $this->registerType(
+ 'kdf',
+ __NAMESPACE__ . '\\Derivation\\KDF',
+ $name,
+ $class
+ );
+ }
+
+ public function registerPBKDF($name, $class) {
+ $this->registerType(
+ 'pbkdf',
+ __NAMESPACE__ . '\\Derivation\\PBKDF',
+ $name,
+ $class
+ );
+ }
+
+ protected function loadKDF() {
+ $this->loadFiles(
+ __DIR__ . '/Derivation/KDF',
+ __NAMESPACE__ . '\\Derivation\\KDF\\',
+ array($this, 'registerKDF')
+ );
+ }
+
+ protected function loadPBKDF() {
+ $this->loadFiles(
+ __DIR__ . '/Derivation/PBKDF',
+ __NAMESPACE__ . '\\Derivation\\PBKDF\\',
+ array($this, 'registerPBKDF')
+ );
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Key;
+
+/**
+ * Description of generator
+ *
+ * @author ircmaxell
+ * @codeCoverageIgnore
+ */
+interface Generator extends Key {
+
+ public static function test();
+
+ public function __construct(array $options = array());
+
+ /**
+ * Generate a key of the supplied size
+ *
+ * @param Strength $strength The strength of the generated key
+ * @param int $size The size of the generated key (in bytes)
+ * @param string $passPhrase The passphrase to encrypt the key with
+ *
+ * @return void
+ */
+ public function generate(
+ \CryptLib\Core\Strength $strength,
+ $size,
+ $passPhrase = ''
+ );
+
+}
--- /dev/null
+<?php
+/**
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Key;
+
+/**
+ *
+ * @author ircmaxell
+ * @codeCoverageIgnore
+ */
+interface Key {
+
+ const SYMMETRIC = 'symmetric';
+
+ const PUBLICKEY = 'publickey';
+
+ public function __toString();
+
+ public function getType();
+
+}
--- /dev/null
+<?php
+/**
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Key;
+
+/**
+ *
+ * @author ircmaxell
+ * @codeCoverageIgnore
+ */
+interface Symmetric extends Key {
+
+ public function getKey();
+
+ public function saveKey($filename);
+
+}
--- /dev/null
+<?php
+/**
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Key\Symmetric;
+
+/**
+ * Description of abstractsymetric
+ *
+ * @author ircmaxell
+ */
+abstract class AbstractSymmetric implements \CryptLib\Key\Symmetric {
+
+ protected $key = '';
+
+ public function __toString() {
+ return $this->getKey();
+ }
+
+ public function getKey() {
+ return $this->key;
+ }
+
+ public function getType() {
+ return self::SYMMETRIC;
+ }
+
+ public function saveKey($filename) {
+ file_put_contents($filename, $this->getKey());
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Key\Symmetric\Generator;
+
+use CryptLib\Random\Factory as RandomFactory;
+use CryptLib\Key\Factory as KeyFactory;
+use CryptLib\Key\Symmetric\Raw as Raw;
+
+/**
+ * Description of mtrand
+ *
+ * @author ircmaxell
+ */
+class Internal implements \CryptLib\Key\Generator {
+
+ protected $kdf = null;
+
+ protected $random = null;
+
+ public static function test() {
+ return true;
+ }
+
+ public function __construct(array $options = array()) {
+ $options += array('kdf' => null, 'random' => null);
+ if (is_null($options['kdf'])) {
+ $factory = new KeyFactory();
+ $options['kdf'] = $factory->getKdf('kdf3');
+ }
+ $this->kdf = $options['kdf'];
+ if (is_null($options['random'])) {
+ $options['random'] = new RandomFactory();
+ }
+ $this->random = $options['random'];
+ }
+
+ public function __toString() {
+ }
+
+ public function generate(
+ \CryptLib\Core\Strength $strength,
+ $size,
+ $passphrase = ''
+ ) {
+ $generator = $this->random->getGenerator($strength);
+ $seed = $generator->generate($size);
+ $key = $this->kdf->derive($seed, $size, $passphrase);
+ return new Raw(substr($key, 0, $size));
+ }
+
+ public function getType() {
+ return static::TYPE_SYMMETRIC;
+ }
+}
--- /dev/null
+<?php
+/**
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Key\Symmetric;
+
+/**
+ * Description of raw
+ *
+ * @author ircmaxell
+ */
+class Raw extends AbstractSymmetric {
+
+ public function __construct($key) {
+ $this->key = $key;
+ }
+
+}
+
--- /dev/null
+<?php
+/**
+ * An abstract class for MessageAuthenticationCode generation
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package MAC
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+namespace CryptLib\MAC;
+
+/**
+ * An abstract class for MessageAuthenticationCode generation
+ *
+ * @category PHPCryptLib
+ * @package MAC
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+abstract class AbstractMAC implements MAC {
+
+ /**
+ * @var array The stored options for this instance
+ */
+ protected $options = array();
+
+ /**
+ * Build the instance of the MAC generator
+ *
+ * @param array $options The options for the instance
+ *
+ * @return void
+ */
+ public function __construct(array $options = array()) {
+ $this->options = $options + $this->options;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * A Cipher based MAC generator (Based upon the CMAC specification)
+ *
+ * PHP version 5.3
+ *
+ * @see http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf
+ * @category PHPCryptLib
+ * @package MAC
+ * @subpackage Implementation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+namespace CryptLib\MAC\Implementation;
+
+use \CryptLib\Cipher\Factory;
+
+/**
+ * A Cipher based MAC generator (Based upon the CMAC specification)
+ *
+ * @see http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf
+ * @category PHPCryptLib
+ * @package MAC
+ * @subpackage Implementation
+ */
+class CMAC extends \CryptLib\MAC\AbstractMAC {
+
+ protected $cipher = null;
+
+ /**
+ * @var array The stored options for this instance
+ */
+ protected $options = array(
+ 'cipher' => 'aes-128',
+ 'cipherFactory' => null,
+ );
+
+ /**
+ * Build the instance of the MAC generator
+ *
+ * @param array $options The options for the instance
+ *
+ * @return void
+ */
+ public function __construct(array $options = array()) {
+ parent::__construct($options);
+ if (is_null($this->options['cipherFactory'])) {
+ $this->options['cipherFactory'] = new Factory;
+ }
+ $this->cipher = $this->options['cipherFactory']->getBlockCipher(
+ $this->options['cipher']
+ );
+ }
+
+ /**
+ * Generate the MAC using the supplied data
+ *
+ * @param string $data The data to use to generate the MAC with
+ * @param string $key The key to generate the MAC
+ * @param int $size The size of the output to return
+ *
+ * @return string The generated MAC of the appropriate size
+ */
+ public function generate($data, $key, $size = 0) {
+ $blockSize = $this->cipher->getBlockSize();
+ if ($size == 0) {
+ $size = $blockSize;
+ }
+ if ($size > $blockSize) {
+ throw new \OutOfRangeException(
+ sprintf(
+ 'The size is too big for the cipher primitive [%d:%d]',
+ $size,
+ $blockSize
+ )
+ );
+ }
+ $this->cipher->setKey($key);
+ $keys = $this->generateKeys();
+ $mBlocks = $this->splitDataIntoMBlocks($data, $keys);
+ $cBlock = str_repeat(chr(0), $blockSize);
+ foreach ($mBlocks as $key => $block) {
+ $cBlock = $this->cipher->encryptBlock($cBlock ^ $block);
+ }
+ return substr($cBlock, 0, $size);
+ }
+
+ /**
+ * Generate a pair of keys by encrypting a block of all 0's, and then
+ * maniuplating the result
+ *
+ * @return array The generated keys
+ */
+ protected function generateKeys() {
+ $keys = array();
+ $blockSize = $this->cipher->getBlockSize();
+ $rVal = $this->getRValue($blockSize);
+ $text = str_repeat(chr(0), $blockSize);
+ $lVal = $this->cipher->encryptBlock($text);
+ $keys[0] = $this->leftShift($lVal, 1);
+ if (ord(substr($lVal, 0, 1)) > 127) {
+ $keys[0] = $keys[0] ^ $rVal;
+ }
+ $keys[1] = $this->leftShift($keys[0], 1);
+ if (ord(substr($keys[0], 0, 1)) > 127) {
+ $keys[1] = $keys[1] ^ $rVal;
+ }
+ return $keys;
+ }
+
+ /**
+ * Get an RValue based upon the block size
+ *
+ * @param int $size The size of the block in bytes
+ *
+ * @see http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf
+ * @return string A RValue of the appropriate block size
+ */
+ protected function getRValue($size) {
+ switch ($size * 8) {
+ case 64:
+ return str_repeat(chr(0), 7) . chr(0x1B);
+ case 128:
+ return str_repeat(chr(0), 15) . chr(0x87);
+ default:
+ }
+ throw new \RuntimeException('Unsupported Block Size For The Cipher');
+ }
+
+ protected function leftShift($data, $bits) {
+ $mask = (0xff << (8 - $bits)) & 0xff;
+ $state = 0;
+ $result = '';
+ $length = strlen($data);
+ for ($i = $length - 1; $i >= 0; $i--) {
+ $tmp = ord($data[$i]);
+ $result .= chr(($tmp << $bits) | $state);
+ $state = ($tmp & $mask) >> (8 - $bits);
+ }
+ return strrev($result);
+ }
+
+ /**
+ * Split the data into appropriate block chunks, encoding with the kyes
+ *
+ * @param string $data The data to split
+ * @param array $keys The keys to use for encoding
+ *
+ * @return array The array of chunked and encoded data
+ */
+ protected function splitDataIntoMBlocks($data, array $keys) {
+ $blockSize = $this->cipher->getBlockSize();
+ $data = str_split($data, $blockSize);
+ $last = end($data);
+ if (strlen($last) != $blockSize) {
+ //Pad the last element
+ $last .= chr(0x80) . str_repeat(chr(0), $blockSize - 1 - strlen($last));
+ $last = $last ^ $keys[1];
+ } else {
+ $last = $last ^ $keys[0];
+ }
+ $data[count($data) - 1] = $last;
+ return $data;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * A Hash-Base MAC generator
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package MAC
+ * @subpackage Implementation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+namespace CryptLib\MAC\Implementation;
+
+use \CryptLib\Hash\Hash;
+
+/**
+ * A Hash-Base MAC generator
+ *
+ * @category PHPCryptLib
+ * @package MAC
+ * @subpackage Implementation
+ */
+class HMAC extends \CryptLib\MAC\AbstractMAC {
+
+ /**
+ * @var array The stored options for this instance
+ */
+ protected $options = array(
+ 'hash' => 'sha256',
+ );
+
+ /**
+ * Generate the MAC using the supplied data
+ *
+ * @param string $data The data to use to generate the MAC with
+ * @param string $key The key to generate the MAC
+ * @param int $size The size of the output to return
+ *
+ * @return string The generated MAC of the appropriate size
+ */
+ public function generate($data, $key, $size = 0) {
+ $hash = $this->options['hash'];
+ $outputSize = Hash::getHashSize($hash);
+ if ($size == 0) {
+ $size = $outputSize;
+ }
+ if ($size > $outputSize) {
+ throw new \OutOfRangeException(
+ sprintf(
+ 'The size is too big for the hash primitive [%d:%d]',
+ $size,
+ $outputSize
+ )
+ );
+ }
+ $return = hash_hmac($hash, $data, $key, true);
+ return substr($return, 0, $size);
+ }
+
+}
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * The basic interface for MAC (Message Authentication Code) generation
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package MAC
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+namespace CryptLib\MAC;
+
+/**
+ * The basic interface for MAC (Message Authentication Code) generation
+ *
+ * @category PHPCryptLib
+ * @package MAC
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+interface MAC {
+
+ /**
+ * Build the instance of the MAC generator
+ *
+ * @param array $options The options for the instance
+ *
+ * @return void
+ */
+ public function __construct(array $options = array());
+
+ /**
+ * Generate the MAC using the supplied data
+ *
+ * @param string $data The data to use to generate the MAC with
+ * @param string $key The key to generate the MAC
+ * @param int $size The size of the output to return
+ *
+ * @return string The generated MAC of the appropriate size
+ */
+ public function generate($data, $key, $size = 0);
+
+}
--- /dev/null
+<?php
+/**
+ * The Password Factory
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Password
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Password;
+
+use CryptLib\Password\Implementation\Blowfish;
+
+/**
+ * The Password Factory
+ *
+ * @category PHPCryptLib
+ * @package Password
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class Factory extends \CryptLib\Core\AbstractFactory {
+
+ /**
+ * @var array An array of implementation classes
+ */
+ protected $implementations = array();
+
+ /**
+ * Build a new instance of the factory, loading core implementations
+ *
+ * @return void
+ */
+ public function __construct() {
+ $this->loadImplementations();
+ }
+
+ /**
+ * Create a new password hash from the supplied password
+ *
+ * This defaults to using Blowfish if $prefix is not supplied
+ *
+ * @param string $password The password to hash
+ * @param string $prefix The prefix for the implementation
+ *
+ * @return string The hashed password
+ * @throws DomainException if the supplied prefix is not supported
+ */
+ public function createHash($password, $prefix = '$2a$') {
+ if ($prefix === false) {
+ throw new \DomainException('Unsupported Prefix Supplied');
+ }
+ foreach ($this->implementations as $impl) {
+ if ($impl::getPrefix() == $prefix) {
+ $instance = new $impl;
+ return $instance->create($password);
+ }
+ }
+ throw new \DomainException('Unsupported Prefix Supplied');
+ }
+
+ /**
+ * Verify a hash with a supplied password
+ *
+ * @param string $password The password to check against
+ * @param string $hash The hash to verify
+ *
+ * @return boolean True if valid, false if not
+ * @throws DomainException if the supplied prefix is not supported
+ */
+ public function verifyHash($password, $hash) {
+ foreach ($this->implementations as $impl) {
+ if ($impl::detect($hash)) {
+ $instance = $impl::loadFromHash($hash);
+ return $instance->verify($password, $hash);
+ }
+ }
+ throw new \DomainException('Unsupported Password Hash Supplied');
+ }
+
+ /**
+ * Register a password implementation for this factory instance
+ *
+ * @param string $name The name of the stategy
+ * @param string $class The class name of the implementation
+ *
+ * @return Factory $this The current factory instance
+ */
+ public function registerImplementation($name, $class) {
+ $this->registerType(
+ 'implementations',
+ __NAMESPACE__ . '\\Password',
+ $name,
+ $class
+ );
+ return $this;
+ }
+
+ /**
+ * Load all core password hashing implementations
+ *
+ * @return void
+ */
+ protected function loadImplementations() {
+ $this->loadFiles(
+ __DIR__ . '/Implementation',
+ __NAMESPACE__ . '\\Implementation\\',
+ array($this, 'registerImplementation')
+ );
+ }
+
+}
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * The APR1 password hashing implementation
+ *
+ * Use this class to generate and validate APR1 password hashes. APR1 hashes
+ * are used primarrily by Apache for .htaccess password storage.
+ *
+ * PHP version 5.3
+ *
+ * @see http://httpd.apache.org/docs/2.2/misc/password_encryptions.html
+ * @category PHPCryptLib
+ * @package Password
+ * @subpackage Implementation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Password\Implementation;
+
+use CryptLib\Random\Factory as RandomFactory;
+
+/**
+ * The APR1 password hashing implementation
+ *
+ * Use this class to generate and validate APR1 password hashes. APR1 hashes
+ * are used primarrily by Apache for .htaccess password storage.
+ *
+ * @see http://httpd.apache.org/docs/2.2/misc/password_encryptions.html
+ * @category PHPCryptLib
+ * @package Password
+ * @subpackage Implementation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class APR1 implements \CryptLib\Password\Password {
+
+ /**
+ * @var Generator The random generator to use for seeds
+ */
+ protected $generator = null;
+
+ /**
+ * @var Hash The hash function to use (MD5)
+ */
+ protected $hash = null;
+
+ /**
+ * @var int The number of iterations to perform (1000 for APR1)
+ */
+ protected $iterations = 1000;
+
+ /**
+ * Determine if the hash was made with this method
+ *
+ * @param string $hash The hashed data to check
+ *
+ * @return boolean Was the hash created by this method
+ */
+ public static function detect($hash) {
+ return strncmp($hash, '$apr1$', 6) === 0;
+ }
+
+ /**
+ * Return the prefix used by this hashing method
+ *
+ * @return string The prefix used
+ */
+ public static function getPrefix() {
+ return '$apr1$';
+ }
+
+ /**
+ * Load an instance of the class based upon the supplied hash
+ *
+ * @param string $hash The hash to load from
+ *
+ * @return Password the created instance
+ * @throws InvalidArgumentException if the hash wasn't created here
+ */
+ public static function loadFromHash($hash) {
+ if (!static::detect($hash)) {
+ throw new \InvalidArgumentException('Hash Not Created Here');
+ }
+ return new static;
+ }
+
+ /**
+ * Build a new instance
+ *
+ * @param Generator $generator The random generator to use for seeds
+ *
+ * @return void
+ */
+ public function __construct(
+ \CryptLib\Random\Generator $generator = null
+ ) {
+ if (is_null($generator)) {
+ $random = new RandomFactory();
+ $generator = $random->getMediumStrengthGenerator();
+ }
+ $this->generator = $generator;
+ }
+
+ /**
+ * Create a password hash for a given plain text password
+ *
+ * @param string $password The password to hash
+ *
+ * @return string The formatted password hash
+ */
+ public function create($password) {
+ $salt = $this->to64($this->generator->generateInt(0, PHP_INT_MAX), 8);
+ return $this->hash($password, $salt, $this->iterations);
+ }
+
+ /**
+ * Verify a password hash against a given plain text password
+ *
+ * @param string $password The password to hash
+ * @param string $hash The supplied ahsh to validate
+ *
+ * @return boolean Does the password validate against the hash
+ */
+ public function verify($password, $hash) {
+ $bits = explode('$', $hash);
+ if (!isset($bits[3]) || $bits[1] != 'apr1') {
+ return false;
+ }
+ $test = $this->hash($password, $bits[2], $this->iterations);
+ return $test == $hash;
+ }
+
+ /**
+ * Perform the hashing of the password
+ *
+ * @param string $password The plain text password to hash
+ * @param string $salt The 8 byte salt to use
+ * @param int $iterations The number of iterations to use
+ *
+ * @return string The hashed password
+ */
+ protected function hash($password, $salt, $iterations) {
+ $len = strlen($password);
+ $text = $password . '$apr1$' . $salt;
+ $bin = md5($password.$salt.$password, true);
+ for ($i = $len; $i > 0; $i -= 16) {
+ $text .= substr($bin, 0, min(16, $i));
+ }
+ for ($i = $len; $i > 0; $i >>= 1) {
+ $text .= ($i & 1) ? chr(0) : $password[0];
+ }
+ $bin = $this->iterate($text, $iterations, $salt, $password);
+ return $this->convertToHash($bin, $salt);
+ }
+
+ protected function iterate($text, $iterations, $salt, $password) {
+ $bin = md5($text, true);
+ for ($i = 0; $i < $iterations; $i++) {
+ $new = ($i & 1) ? $password : $bin;
+ if ($i % 3) {
+ $new .= $salt;
+ }
+ if ($i % 7) {
+ $new .= $password;
+ }
+ $new .= ($i & 1) ? $bin : $password;
+ $bin = md5($new, true);
+ }
+ return $bin;
+ }
+
+ protected function convertToHash($bin, $salt) {
+ $tmp = '$apr1$'.$salt.'$';
+ $tmp .= $this->to64(
+ (ord($bin[0])<<16) | (ord($bin[6])<<8) | ord($bin[12]),
+ 4
+ );
+ $tmp .= $this->to64(
+ (ord($bin[1])<<16) | (ord($bin[7])<<8) | ord($bin[13]),
+ 4
+ );
+ $tmp .= $this->to64(
+ (ord($bin[2])<<16) | (ord($bin[8])<<8) | ord($bin[14]),
+ 4
+ );
+ $tmp .= $this->to64(
+ (ord($bin[3])<<16) | (ord($bin[9])<<8) | ord($bin[15]),
+ 4
+ );
+ $tmp .= $this->to64(
+ (ord($bin[4])<<16) | (ord($bin[10])<<8) | ord($bin[5]),
+ 4
+ );
+ $tmp .= $this->to64(
+ ord($bin[11]),
+ 2
+ );
+ return $tmp;
+ }
+
+ /**
+ * Convert the input number to a base64 number of the specified size
+ *
+ * @param int $num The number to convert
+ * @param int $size The size of the result string
+ *
+ * @return string The converted representation
+ */
+ protected function to64($num, $size) {
+ static $seed = '';
+ if (empty($seed)) {
+ $seed = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'.
+ 'abcdefghijklmnopqrstuvwxyz';
+ }
+ $result = '';
+ while (--$size >= 0) {
+ $result .= $seed[$num & 0x3f];
+ $num >>= 6;
+ }
+ return $result;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * The Blowfish password hashing implementation
+ *
+ * Use this class to generate and validate Blowfish password hashes.
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Password
+ * @subpackage Implementation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Password\Implementation;
+
+use CryptLib\Random\Factory as RandomFactory;
+
+/**
+ * The Blowfish password hashing implementation
+ *
+ * Use this class to generate and validate Blowfish password hashes.
+ *
+ * @category PHPCryptLib
+ * @package Password
+ * @subpackage Implementation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class Blowfish implements \CryptLib\Password\Password {
+
+ /**
+ * @var Generator The random generator to use for seeds
+ */
+ protected $generator = null;
+
+ /**
+ * @var int The number of iterations to perform (base 2)
+ */
+ protected $iterations = 10;
+
+ /**
+ * Determine if the hash was made with this method
+ *
+ * @param string $hash The hashed data to check
+ *
+ * @return boolean Was the hash created by this method
+ */
+ public static function detect($hash) {
+ static $regex = '/^\$2[ay]\$(0[4-9]|[1-2][0-9]|3[0-1])\$[a-zA-Z0-9.\/]{53}/';
+ return 1 == preg_match($regex, $hash);
+ }
+
+ /**
+ * Return the prefix used by this hashing method
+ *
+ * @return string The prefix used
+ */
+ public static function getPrefix() {
+ if (version_compare(PHP_VERSION, '5.3.7') >= 0) {
+ return '$2y$';
+ } else {
+ return '$2a$';
+ }
+ }
+
+ /**
+ * Load an instance of the class based upon the supplied hash
+ *
+ * @param string $hash The hash to load from
+ *
+ * @return Password the created instance
+ * @throws InvalidArgumentException if the hash wasn't created here
+ */
+ public static function loadFromHash($hash) {
+ if (!static::detect($hash)) {
+ throw new \InvalidArgumentException('Hash Not Created Here');
+ }
+ list(, , $iterations) = explode('$', $hash, 4);
+ return new static((int) $iterations);
+ }
+
+ /**
+ * Build a new instance
+ *
+ * @param int $iterations The number of times to iterate the hash
+ * @param Generator $generator The random generator to use for seeds
+ *
+ * @return void
+ */
+ public function __construct(
+ $iterations = 8,
+ \CryptLib\Random\Generator $generator = null
+ ) {
+ if ($iterations > 31 || $iterations < 4) {
+ throw new \InvalidArgumentException('Invalid Iteration Count Supplied');
+ }
+ $this->iterations = $iterations;
+ if (is_null($generator)) {
+ $random = new RandomFactory();
+ $generator = $random->getMediumStrengthGenerator();
+ }
+ $this->generator = $generator;
+ }
+
+ /**
+ * Create a password hash for a given plain text password
+ *
+ * @param string $password The password to hash
+ *
+ * @return string The formatted password hash
+ */
+ public function create($password) {
+ /**
+ * Check for security flaw in the bcrypt implementation used by crypt()
+ * @see http://php.net/security/crypt_blowfish.php
+ */
+ $match = preg_match('/[\x80-\xFF]/', $password);
+ if (version_compare(PHP_VERSION, '5.3.7', '<') && $match) {
+ throw new \RuntimeException(
+ 'The bcrypt implementation used by PHP contains a security flaw ' .
+ 'for password with 8-bit character. We suggest to upgrade to ' .
+ 'PHP 5.3.7+ or use passwords with only 7-bit characters'
+ );
+ }
+ $salt = $this->to64($this->generator->generate(16));
+ $prefix = static::getPrefix();
+ $prefix .= str_pad($this->iterations, 2, '0', STR_PAD_LEFT);
+ $saltstring = $prefix . '$' . $salt;
+ $result = crypt($password, $saltstring);
+ if ($result[0] == '*') {
+ //@codeCoverageIgnoreStart
+ throw new \RuntimeException('Password Could Not Be Created');
+ //@codeCoverageIgnoreEnd
+ }
+ return $result;
+ }
+
+ /**
+ * Verify a password hash against a given plain text password
+ *
+ * @param string $password The password to hash
+ * @param string $hash The supplied ahsh to validate
+ *
+ * @return boolean Does the password validate against the hash
+ */
+ public function verify($password, $hash) {
+ if (!static::detect($hash)) {
+ throw new \InvalidArgumentException(
+ 'The hash was not created here, we cannot verify it'
+ );
+ }
+ $test = crypt($password, $hash);
+ return $test == $hash;
+ }
+
+ /**
+ * Convert the input number to a base64 number of the specified size
+ *
+ * @param int $input The number to convert
+ *
+ * @return string The converted representation
+ */
+ protected function to64($input) {
+ static $itoa = null;
+ if (empty($itoa)) {
+ $itoa = './ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+ . 'abcdefghijklmnopqrstuvwxyz0123456789';
+ }
+ $output = '';
+ $size = strlen($input);
+ $ictr = 0;
+ do {
+ $cval1 = ord($input[$ictr++]);
+ $output .= $itoa[$cval1 >> 2];
+ $cval1 = ($cval1 & 0x03) << 4;
+ if ($ictr >= $size) {
+ $output .= $itoa[$cval1];
+ break;
+ }
+ $cval2 = ord($input[$ictr++]);
+ $cval1 |= $cval2 >> 4;
+ $output .= $itoa[$cval1];
+ $cval1 = ($cval2 & 0x0f) << 2;
+ $cval2 = ord($input[$ictr++]);
+ $cval1 |= $cval2 >> 6;
+ $output .= $itoa[$cval1];
+ $output .= $itoa[$cval2 & 0x3f];
+ } while (true);
+ return $output;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * The Drupal password hashing implementation
+ *
+ * Use this class to generate and validate Drupal password hashes.
+ *
+ * PHP version 5.3
+ *
+ * @see http://www.openwall.com/phpass/
+ * @category PHPCryptLib
+ * @package Password
+ * @subpackage Implementation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Password\Implementation;
+
+use CryptLib\Random\Factory as RandomFactory;
+
+/**
+ * The PHPASS password hashing implementation
+ *
+ * Use this class to generate and validate PHPASS password hashes.
+ *
+ * @see http://www.openwall.com/phpass/
+ * @category PHPCryptLib
+ * @package Password
+ * @subpackage Implementation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class Drupal extends PHPASS {
+
+ /**
+ * @var string The prefix for the generated hash
+ */
+ protected static $prefix = '$S$';
+
+ /**
+ * @var string The hash function to use for this instance
+ */
+ protected $hashFunction = 'sha512';
+
+ /**
+ * Determine if the hash was made with this method
+ *
+ * @param string $hash The hashed data to check
+ *
+ * @return boolean Was the hash created by this method
+ */
+ public static function detect($hash) {
+ $prefix = preg_quote(static::$prefix, '/');
+ return 1 == preg_match('/^'.$prefix.'[a-zA-Z0-9.\/]{95}$/', $hash);
+ }
+
+}
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * The basic Hash implementation.
+ *
+ * It's worth noting, since there's no prefix, you cannot create a hash using
+ * the factory method.
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Password
+ * @subpackage Implementation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Password\Implementation;
+
+use CryptLib\Random\Factory as RandomFactory;
+
+/**
+ * The basic Hash implementation.
+ *
+ * It's worth noting, since there's no prefix, you cannot create a hash using
+ * the factory method.
+ *
+ * @category PHPCryptLib
+ * @package Password
+ * @subpackage Implementation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class Hash implements \CryptLib\Password\Password {
+
+ /**
+ * @var Generator The random generator to use for seeds
+ */
+ protected $generator = null;
+
+ /**
+ * @var Hash The hash function to use (MD5)
+ */
+ protected $hash = null;
+
+ /**
+ * Determine if the hash was made with this method
+ *
+ * @param string $hash The hashed data to check
+ *
+ * @return boolean Was the hash created by this method
+ */
+ public static function detect($hash) {
+ $res = preg_match('/^[a-fA-F0-9]+$/', $hash);
+ $res &= (int) in_array(strlen($hash), array(32, 40, 64, 128));
+ return (boolean) $res;
+ }
+
+ /**
+ * Return the prefix used by this hashing method
+ *
+ * @return string The prefix used
+ */
+ public static function getPrefix() {
+ return false;
+ }
+
+ /**
+ * Load an instance of the class based upon the supplied hash
+ *
+ * @param string $hash The hash to load from
+ *
+ * @return Password the created instance
+ * @throws InvalidArgumentException if the hash wasn't created here
+ */
+ public static function loadFromHash($hash) {
+ if (!static::detect($hash)) {
+ throw new \InvalidArgumentException('Hash Not Created Here');
+ }
+ $hashMethod = '';
+ switch (strlen($hash)) {
+ case 32:
+ $hashMethod = 'md5';
+ break;
+ case 40:
+ $hashMethod = 'sha1';
+ break;
+ case 64:
+ $hashMethod = 'sha256';
+ break;
+ case 128:
+ $hashMethod = 'sha512';
+ break;
+ }
+ return new static($hashMethod);
+ }
+
+ /**
+ * Build a new instance
+ *
+ * @param string $hashMethod The hash function to use for hashing
+ * @param Generator $generator The random generator to use for seeds
+ * @param Factory $factory The hash factory to use for this instance
+ *
+ * @return void
+ */
+ public function __construct(
+ $hashMethod,
+ \CryptLib\Random\Generator $generator = null
+ ) {
+ $this->hash = $hashMethod;
+ if (is_null($generator)) {
+ $random = new RandomFactory();
+ $generator = $random->getMediumStrengthGenerator();
+ }
+ $this->generator = $generator;
+ }
+
+ /**
+ * Create a password hash for a given plain text password
+ *
+ * @param string $password The password to hash
+ *
+ * @return string The formatted password hash
+ */
+ public function create($password) {
+ throw new \BadMethodCallException(
+ 'Unsalted Passwords are only implemented for verification'
+ );
+ }
+
+ /**
+ * Verify a password hash against a given plain text password
+ *
+ * @param string $password The password to hash
+ * @param string $hash The supplied ahsh to validate
+ *
+ * @return boolean Does the password validate against the hash
+ */
+ public function verify($password, $hash) {
+ $test = hash($this->hash, $password);
+ return $test == $hash;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * The Joomla based hash implementation based off of the md5-hex hash method
+ *
+ * It's worth noting, since there's no prefix, you cannot create a hash using
+ * the factory method.
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Password
+ * @subpackage Implementation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Password\Implementation;
+
+use CryptLib\Random\Factory as RandomFactory;
+
+/**
+ * The Joomla based hash implementation based off of the md5-hex hash method
+ *
+ * It's worth noting, since there's no prefix, you cannot create a hash using
+ * the factory method.
+ *
+ * @category PHPCryptLib
+ * @package Password
+ * @subpackage Implementation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class Joomla implements \CryptLib\Password\Password {
+
+ /**
+ * @var Generator The random generator to use for seeds
+ */
+ protected $generator = null;
+
+ /**
+ * Determine if the hash was made with this method
+ *
+ * @param string $hash The hashed data to check
+ *
+ * @return boolean Was the hash created by this method
+ */
+ public static function detect($hash) {
+ return (boolean) preg_match('/^[a-fA-F0-9]{32}:[a-zA-z0-9]{32}$/', $hash);
+ }
+
+ /**
+ * Return the prefix used by this hashing method
+ *
+ * @return string The prefix used
+ */
+ public static function getPrefix() {
+ return false;
+ }
+
+ /**
+ * Load an instance of the class based upon the supplied hash
+ *
+ * @param string $hash The hash to load from
+ *
+ * @return Password the created instance
+ * @throws InvalidArgumentException if the hash wasn't created here
+ */
+ public static function loadFromHash($hash) {
+ if (!static::detect($hash)) {
+ throw new \InvalidArgumentException('Hash Not Created Here');
+ }
+ return new static();
+ }
+
+ /**
+ * Build a new instance
+ *
+ * @param Generator $generator The random generator to use for seeds
+ * @param Factory $factory The hash factory to use for this instance
+ *
+ * @return void
+ */
+ public function __construct(
+ \CryptLib\Random\Generator $generator = null
+ ) {
+ if (is_null($generator)) {
+ $random = new RandomFactory();
+ $generator = $random->getMediumStrengthGenerator();
+ }
+ $this->generator = $generator;
+ }
+
+ /**
+ * Create a password hash for a given plain text password
+ *
+ * @param string $password The password to hash
+ *
+ * @return string The formatted password hash
+ */
+ public function create($password) {
+ $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
+ $salt = $this->generator->generateString(32, $chars);
+ $hash = md5($password . $salt);
+ return $hash . ':' . $salt;
+ }
+
+ /**
+ * Verify a password hash against a given plain text password
+ *
+ * @param string $password The password to hash
+ * @param string $hash The supplied ahsh to validate
+ *
+ * @return boolean Does the password validate against the hash
+ */
+ public function verify($password, $hash) {
+ if (!static::detect($hash)) {
+ throw new \InvalidArgumentException(
+ 'The hash was not created here, we cannot verify it'
+ );
+ }
+ list ($hash, $salt) = explode(':', $hash, 2);
+ $test = md5($password . $salt);
+ return $test == $hash;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * The PBKDF based password hashing implementation
+ *
+ * Use this class to generate and validate PBKDF hashed passwords.
+ *
+ * PHP version 5.3
+ *
+ * @see http://httpd.apache.org/docs/2.2/misc/password_encryptions.html
+ * @category PHPCryptLib
+ * @package Password
+ * @subpackage Implementation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Password\Implementation;
+
+use CryptLib\Key\Factory as KeyFactory;
+use CryptLib\Random\Factory as RandomFactory;
+use CryptLib\Key\Derivation\PBKDF\PBKDF2 as PBKDF2;
+
+/**
+ * The PBKDF based password hashing implementation
+ *
+ * Use this class to generate and validate PBKDF hashed passwords.
+ *
+ * PHP version 5.3
+ *
+ * @see http://httpd.apache.org/docs/2.2/misc/password_encryptions.html
+ * @category PHPCryptLib
+ * @package Password
+ * @subpackage Implementation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class PBKDF implements \CryptLib\Password\Password {
+
+ /**
+ * @var PBKDF The PBKDF derivation implementation to use for this instance
+ */
+ protected $derivation = null;
+
+ /**
+ * @var Generator The Random Number Generator to use for making salts
+ */
+ protected $generator = null;
+
+ /**
+ * @var int The number of iterations to perform on the password
+ */
+ protected $iterations = 5000;
+
+ /**
+ * @var int The length in bytes of the generated password hash
+ */
+ protected $size = 40;
+
+ /**
+ * Determine if the hash was made with this method
+ *
+ * @param string $hash The hashed data to check
+ *
+ * @return boolean Was the hash created by this method
+ */
+ public static function detect($hash) {
+ return strncmp($hash, '$pbkdf$', 7) === 0;
+ }
+
+ /**
+ * Return the prefix used by this hashing method
+ *
+ * @return string The prefix used
+ */
+ public static function getPrefix() {
+ return '$pbkdf$';
+ }
+
+ /**
+ * Load an instance of the class based upon the supplied hash
+ *
+ * @param string $hash The hash to load from
+ *
+ * @return Password the created instance
+ * @throws InvalidArgumentException if the hash wasn't created here
+ */
+ public static function loadFromHash($hash) {
+ if (!static::detect($hash)) {
+ throw new \InvalidArgumentException('Hash Not Created Here');
+ }
+ $parts = explode('$', $hash);
+ if (count($parts) != 7) {
+ throw new \InvalidArgumentException('Hash Not Created Here');
+ }
+ $signature = $parts[2];
+ $factory = new KeyFactory();
+ $hash = $factory->getPBKDFFromSignature($signature);
+ $iterations = $parts[3];
+ $size = $parts[4];
+ return new static($hash, $size, $iterations);
+ }
+
+ /**
+ * Build a new instance of the PBKDF password class
+ *
+ * @param PBKDF $derivation The derivation class to use
+ * @param int $size The size of hash to generate
+ * @param int $iterations The number of iterations to perform
+ * @param Generator $generator The Random Generator to use
+ *
+ * @return void;
+ */
+ public function __construct(
+ \CryptLib\Key\Derivation\PBKDF $derivation = null,
+ $size = 40,
+ $iterations = 5000,
+ \CryptLib\Random\Generator $generator = null
+ ) {
+ if (is_null($derivation)) {
+ $derivation = new PBKDF2();
+ }
+ $this->derivation = $derivation;
+ $this->size = $size < 40 ? 40 : (int) $size;
+ $this->iterations = $iterations > 0 ? (int) $iterations : 1;
+ if (is_null($generator)) {
+ $factory = new RandomFactory;
+ $generator = $factory->getMediumStrengthGenerator();
+ }
+ $this->generator = $generator;
+ }
+
+ /**
+ * Create a password hash for a given plain text password
+ *
+ * @param string $password The password to hash
+ *
+ * @return string The formatted password hash
+ */
+ public function create($password) {
+ $size = $this->size - 8; // remove size of stored bits
+ $saltSize = floor($size / 5); //Use 20% of the size for the salt
+ $hashSize = $size - $saltSize;
+ $salt = $this->generator->generate($saltSize);
+ return $this->hash($password, $salt, $this->iterations, $hashSize);
+ }
+
+ /**
+ * Verify a password hash against a given plain text password
+ *
+ * @param string $password The password to hash
+ * @param string $hash The supplied ahsh to validate
+ *
+ * @return boolean Does the password validate against the hash
+ */
+ public function verify($password, $hash) {
+ if (strlen($hash) <= 16 || strpos($hash, '$') === false) {
+ return false;
+ }
+ $parts = explode('$', $hash);
+ if (count($parts) != 7) {
+ return false;
+ } elseif ($parts[2] != $this->derivation->getSignature()) {
+ return false;
+ }
+ $iterations = $parts[3];
+ $size = $parts[4];
+ $salt = base64_decode($parts[5]);
+ return $this->hash($password, $salt, $iterations, $size) == $hash;
+ }
+
+ /**
+ * Perform the hashing of the password
+ *
+ * @param string $password The plain text password to hash
+ * @param string $salt The 8 byte salt to use
+ * @param int $iterations The number of iterations to use
+ *
+ * @return string The hashed password
+ */
+ protected function hash($password, $salt, $iterations, $size) {
+ $bit = $this->derivation->derive($password, $salt, $iterations, $size);
+ $sig = $this->derivation->getSignature();
+ $sig = '$pbkdf$' . $sig . '$' . $iterations . '$' . $size;
+ return $sig . '$' . base64_encode($salt) . '$' . base64_encode($bit);
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * The PHPASS password hashing implementation
+ *
+ * Use this class to generate and validate PHPASS password hashes.
+ *
+ * PHP version 5.3
+ *
+ * @see http://www.openwall.com/phpass/
+ * @category PHPCryptLib
+ * @package Password
+ * @subpackage Implementation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Password\Implementation;
+
+use CryptLib\Random\Factory as RandomFactory;
+
+/**
+ * The PHPASS password hashing implementation
+ *
+ * Use this class to generate and validate PHPASS password hashes.
+ *
+ * @see http://www.openwall.com/phpass/
+ * @category PHPCryptLib
+ * @package Password
+ * @subpackage Implementation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class PHPASS implements \CryptLib\Password\Password {
+
+ /**
+ * @var string The ITOA string to be used for base64 conversion
+ */
+ protected static $itoa = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ
+ abcdefghijklmnopqrstuvwxyz';
+
+ /**
+ * @var Generator The random generator to use for seeds
+ */
+ protected $generator = null;
+
+ /**
+ * This is the hash function to use. To be overriden by child classes
+ *
+ * @var string The hash function to use for this instance
+ */
+ protected $hashFunction = 'md5';
+
+ /**
+ * @var int The number of iterations to perform (base 2)
+ */
+ protected $iterations = 10;
+
+ /**
+ * @var string The prefix for the generated hash
+ */
+ protected static $prefix = '$P$';
+
+ /**
+ * Determine if the hash was made with this method
+ *
+ * @param string $hash The hashed data to check
+ *
+ * @return boolean Was the hash created by this method
+ */
+ public static function detect($hash) {
+ $prefix = preg_quote(static::$prefix, '/');
+ return 1 == preg_match('/^'.$prefix.'[a-zA-Z0-9.\/]{31}$/', $hash);
+ }
+
+ /**
+ * Return the prefix used by this hashing method
+ *
+ * @return string The prefix used
+ */
+ public static function getPrefix() {
+ return static::$prefix;
+ }
+
+ /**
+ * Initialize the password hasher by replacing away spaces in the itoa var
+ *
+ * @return void
+ */
+ public static function init() {
+ static::$itoa = preg_replace('/\s/', '', static::$itoa);
+ }
+
+ /**
+ * Load an instance of the class based upon the supplied hash
+ *
+ * @param string $hash The hash to load from
+ *
+ * @return Password the created instance
+ * @throws InvalidArgumentException if the hash wasn't created here
+ */
+ public static function loadFromHash($hash) {
+ if (!static::detect($hash)) {
+ throw new \InvalidArgumentException('Hash Not Created Here');
+ }
+ $iterations = static::decodeIterations($hash[3]);
+ return new static($iterations);
+ }
+
+ /**
+ * Decode an ITOA encoded iteration count
+ *
+ * @param string $byte The character to decode
+ *
+ * @return int The decoded iteration count (base2)
+ */
+ protected static function decodeIterations($byte) {
+ return strpos(static::$itoa, $byte);
+ }
+
+ /**
+ * Encode a base2 iteration count to a base64 character
+ *
+ * @param int $number
+ *
+ * @return string The encoded character
+ */
+ protected static function encodeIterations($number) {
+ return static::$itoa[$number];
+ }
+
+ /**
+ * Build a new instance
+ *
+ * @param int $iterations The number of times to iterate the hash
+ * @param Generator $generator The random generator to use for seeds
+ * @param Factory $factory The hash factory to use for this instance
+ *
+ * @return void
+ */
+ public function __construct(
+ $iterations = 8,
+ \CryptLib\Random\Generator $generator = null
+ ) {
+ if ($iterations > 30 || $iterations < 7) {
+ throw new \InvalidArgumentException('Invalid Iteration Count Supplied');
+ }
+ $this->iterations = $iterations;
+ if (is_null($generator)) {
+ $random = new RandomFactory();
+ $generator = $random->getMediumStrengthGenerator();
+ }
+ $this->generator = $generator;
+ }
+
+ /**
+ * Create a password hash for a given plain text password
+ *
+ * @param string $password The password to hash
+ *
+ * @return string The formatted password hash
+ */
+ public function create($password) {
+ $salt = $this->to64($this->generator->generate(6));
+ $prefix = static::encodeIterations($this->iterations) . $salt;
+ return static::$prefix . $prefix . $this->hash($password, $salt);
+ }
+
+ /**
+ * Verify a password hash against a given plain text password
+ *
+ * @param string $password The password to hash
+ * @param string $hash The supplied ahsh to validate
+ *
+ * @return boolean Does the password validate against the hash
+ */
+ public function verify($password, $hash) {
+ if (!static::detect($hash)) {
+ throw new \InvalidArgumentException(
+ 'The hash was not created here, we cannot verify it'
+ );
+ }
+ $iterations = static::decodeIterations($hash[3]);
+ if ($iterations != $this->iterations) {
+ throw new \InvalidArgumentException(
+ 'Iteration Count Mismatch, Bailing'
+ );
+ }
+ $salt = substr($hash, 4, 8);
+ $hash = substr($hash, 12);
+ $test = $this->hash($password, $salt);
+ return $test == $hash;
+ }
+
+ /**
+ * Execute the hash function with proper iterations
+ *
+ * @param string $password The password to hash
+ * @param string $salt The salt to use to hash
+ *
+ * @return string The base64 encoded generated hash
+ */
+ protected function hash($password, $salt) {
+ $count = 1 << $this->iterations;
+ $hash = hash($this->hashFunction, $salt . $password, true);
+ do {
+ $hash = hash($this->hashFunction, $hash . $password, true);
+ } while (--$count);
+ return $this->to64($hash);
+ }
+
+ /**
+ * Convert the input number to a base64 number of the specified size
+ *
+ * @param int $input The number to convert
+ *
+ * @return string The converted representation
+ */
+ protected function to64($input) {
+ $output = '';
+ $count = strlen($input);
+ $ictr = 0;
+ do {
+ $value = ord($input[$ictr++]);
+ $output .= static::$itoa[$value & 0x3f];
+ if ($ictr < $count) {
+ $value |= ord($input[$ictr]) << 8;
+ }
+ $output .= static::$itoa[($value >> 6) & 0x3f];
+ if ($ictr++ >= $count) {
+ break;
+ }
+ if ($ictr < $count) {
+ $value |= ord($input[$ictr]) << 16;
+ }
+ $output .= static::$itoa[($value >> 12) & 0x3f];
+ if ($ictr++ < $count) {
+ $output .= static::$itoa[($value >> 18) & 0x3f];
+ }
+ } while ($ictr < $count);
+ return $output;
+ }
+
+}
+
+PHPASS::init();
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * The PHPBB password hashing implementation
+ *
+ * Use this class to generate and validate PHPBB password hashes.
+ *
+ * PHP version 5.3
+ *
+ * @see http://www.openwall.com/phpass/
+ * @category PHPCryptLib
+ * @package Password
+ * @subpackage Implementation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Password\Implementation;
+
+use CryptLib\Random\Factory as RandomFactory;
+
+/**
+ * The PHPBB password hashing implementation
+ *
+ * Use this class to generate and validate PHPBB password hashes.
+ *
+ * @see http://www.openwall.com/phpass/
+ * @category PHPCryptLib
+ * @package Password
+ * @subpackage Implementation
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class PHPBB extends PHPASS {
+
+ /**
+ * @var string The prefix for the generated hash
+ */
+ protected static $prefix = '$H$';
+
+}
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * The core password hash interface
+ *
+ * All pasword implementations must implement this interface
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Password
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Password;
+
+/**
+ * The core password key interface
+ *
+ * All pasword implementations must implement this interface
+ *
+ * @category PHPCryptLib
+ * @package Password
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @codeCoverageIgnore
+ */
+interface Password {
+
+ /**
+ * Determine if the hash was made with this method
+ *
+ * @param string $hash The hashed data to check
+ *
+ * @return boolean Was the hash created by this method
+ */
+ public static function detect($hash);
+
+ /**
+ * Return the prefix used by this hashing method
+ *
+ * @return string The prefix used
+ */
+ public static function getPrefix();
+
+ /**
+ * Load an instance of the class based upon the supplied hash
+ *
+ * @param string $hash The hash to load from
+ *
+ * @return Password the created instance
+ */
+ public static function loadFromHash($hash);
+
+ /**
+ * Create a password hash for a given plain text password
+ *
+ * @param string $password The password to hash
+ *
+ * @return string The formatted password hash
+ */
+ public function create($password);
+
+ /**
+ * Verify a password hash against a given plain text password
+ *
+ * @param string $password The password to hash
+ * @param string $hash The supplied ahsh to validate
+ *
+ * @return boolean Does the password validate against the hash
+ */
+ public function verify($password, $hash);
+
+}
--- /dev/null
+<?php
+/**
+ * An abstract mixer to implement a common mixing strategy
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Random
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Random;
+
+/**
+ * An abstract mixer to implement a common mixing strategy
+ *
+ * @see http://tools.ietf.org/html/rfc4086#section-5.2
+ * @category PHPCryptLib
+ * @package Random
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+abstract class AbstractMixer implements \CryptLib\Random\Mixer {
+
+ /**
+ * Get the block size (the size of the individual blocks used for the mixing)
+ *
+ * @return int The block size
+ */
+ abstract protected function getPartSize();
+
+ /**
+ * Mix 2 parts together using one method
+ *
+ * @param string $part1 The first part to mix
+ * @param string $part2 The second part to mix
+ *
+ * @return string The mixed data
+ */
+ abstract protected function mixParts1($part1, $part2);
+
+ /**
+ * Mix 2 parts together using another different method
+ *
+ * @param string $part1 The first part to mix
+ * @param string $part2 The second part to mix
+ *
+ * @return string The mixed data
+ */
+ abstract protected function mixParts2($part1, $part2);
+
+ /**
+ * Mix the provided array of strings into a single output of the same size
+ *
+ * All elements of the array should be the same size.
+ *
+ * @param array $parts The parts to be mixed
+ *
+ * @return string The mixed result
+ */
+ public function mix(array $parts) {
+ if (empty($parts)) {
+ return '';
+ }
+ $len = strlen($parts[0]);
+ $parts = $this->normalizeParts($parts);
+ $stringSize = count($parts[0]);
+ $partsSize = count($parts);
+ $result = '';
+ $offset = 0;
+ for ($i = 0; $i < $stringSize; $i++) {
+ $stub = $parts[$offset][$i];
+ for ($j = 1; $j < $partsSize; $j++) {
+ $newKey = $parts[($j + $offset) % $partsSize][$i];
+ //Alternately mix the output for each source
+ if ($j % 2 == 1) {
+ $stub ^= $this->mixParts1($stub, $newKey);
+ } else {
+ $stub ^= $this->mixParts2($stub, $newKey);
+ }
+ }
+ $result .= $stub;
+ $offset = ($offset + 1) % $partsSize;
+ }
+ return substr($result, 0, $len);
+ }
+
+ /**
+ * Normalize the part array and split it block part size.
+ *
+ * This will make all parts the same length and a multiple
+ * of the part size
+ *
+ * @param array $parts The parts to normalize
+ *
+ * @return array The normalized and split parts
+ */
+ protected function normalizeParts(array $parts) {
+ $blockSize = $this->getPartSize();
+ $callback = function($value) {
+ return strlen($value);
+ };
+ $maxSize = max(array_map($callback, $parts));
+ if ($maxSize % $blockSize != 0) {
+ $maxSize += $blockSize - ($maxSize % $blockSize);
+ }
+ foreach ($parts as &$part) {
+ $part = str_pad($part, $maxSize, chr(0));
+ $part = str_split($part, $blockSize);
+ }
+ return $parts;
+ }
+}
--- /dev/null
+<?php
+/**
+ * The Random Factory
+ *
+ * Use this factory to instantiate random number generators, sources and mixers.
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Random
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Random;
+
+use CryptLib\Core\Strength;
+
+/**
+ * The Random Factory
+ *
+ * Use this factory to instantiate random number generators, sources and mixers.
+ *
+ * @category PHPCryptLib
+ * @package Random
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class Factory extends \CryptLib\Core\AbstractFactory {
+
+ /**
+ * @var array A list of available random number mixing strategies
+ */
+ protected $mixers = array();
+
+ /**
+ * @var array A list of available random number sources
+ */
+ protected $sources = array();
+
+ /**
+ * Build a new instance of the factory, loading core mixers and sources
+ *
+ * @return void
+ */
+ public function __construct() {
+ $this->loadMixers();
+ $this->loadSources();
+ }
+
+ /**
+ * Get a generator for the requested strength
+ *
+ * @param Strength $strength The requested strength of the random number
+ *
+ * @return Generator The instantiated generator
+ * @throws RuntimeException If an appropriate mixing strategy isn't found
+ */
+ public function getGenerator(\CryptLib\Core\Strength $strength) {
+ $sources = $this->getSources();
+ $newSources = array();
+ foreach ($sources as $source) {
+ if ($strength->compare($source::getStrength()) <= 0) {
+ $newSources[] = new $source;
+ }
+ }
+ $mixer = $this->findMixer($strength);
+ return new Generator($newSources, $mixer);
+ }
+
+ /**
+ * Get a high strength random number generator
+ *
+ * High Strength keys should ONLY be used for generating extremely strong
+ * cryptographic keys. Generating them is very resource intensive and may
+ * take several minutes or more depending on the requested size.
+ *
+ * @return Generator The instantiated generator
+ */
+ public function getHighStrengthGenerator() {
+ return $this->getGenerator(new Strength(Strength::HIGH));
+ }
+
+ /**
+ * Get a low strength random number generator
+ *
+ * Low Strength should be used anywhere that random strings are needed in a
+ * non-cryptographical setting. They are not strong enough to be used as
+ * keys or salts. They are however useful for one-time use tokens.
+ *
+ * @return Generator The instantiated generator
+ */
+ public function getLowStrengthGenerator() {
+ return $this->getGenerator(new Strength(Strength::LOW));
+ }
+
+ /**
+ * Get a medium strength random number generator
+ *
+ * Medium Strength should be used for most needs of a cryptographic nature.
+ * They are strong enough to be used as keys and salts. However, they do
+ * take some time and resources to generate, so they should not be over-used
+ *
+ * @return Generator The instantiated generator
+ */
+ public function getMediumStrengthGenerator() {
+ return $this->getGenerator(new Strength(Strength::MEDIUM));
+ }
+
+ /**
+ * Get all loaded mixing strategies
+ *
+ * @return array An array of mixers
+ */
+ public function getMixers() {
+ return $this->mixers;
+ }
+
+ /**
+ * Get all loaded random number sources
+ *
+ * @return array An array of sources
+ */
+ public function getSources() {
+ return $this->sources;
+ }
+
+ /**
+ * Register a mixing strategy for this factory instance
+ *
+ * @param string $name The name of the stategy
+ * @param string $class The class name of the implementation
+ *
+ * @return Factory $this The current factory instance
+ */
+ public function registerMixer($name, $class) {
+ $this->registerType(
+ 'mixers',
+ __NAMESPACE__ . '\\Mixer',
+ $name,
+ $class
+ );
+ return $this;
+ }
+
+ /**
+ * Register a random number source for this factory instance
+ *
+ * Note that this class must implement the Source interface
+ *
+ * @param string $name The name of the stategy
+ * @param string $class The class name of the implementation
+ *
+ * @return Factory $this The current factory instance
+ */
+ public function registerSource($name, $class) {
+ $this->registerType(
+ 'sources',
+ __NAMESPACE__ . '\\Source',
+ $name,
+ $class
+ );
+ return $this;
+ }
+
+ /**
+ * Find a mixer based upon the requested strength
+ *
+ * @param Strength $strength The strength mixer to find
+ *
+ * @return Mixer The found mixer
+ * @throws RuntimeException if a valid mixer cannot be found
+ */
+ protected function findMixer(\CryptLib\Core\Strength $strength) {
+ $newMixer = null;
+ $fallback = null;
+ foreach ($this->getMixers() as $mixer) {
+ if ($strength->compare($mixer::getStrength()) == 0) {
+ $newMixer = new $mixer;
+ } elseif ($strength->compare($mixer::getStrength()) == 1) {
+ $fallback = new $mixer;
+ }
+ }
+ if (is_null($newMixer)) {
+ if (is_null($fallback)) {
+ throw new \RuntimeException('Could not find mixer');
+ }
+ return $fallback;
+ }
+ return $newMixer;
+ }
+
+ /**
+ * Load all core mixing strategies
+ *
+ * @return void
+ */
+ protected function loadMixers() {
+ $this->loadFiles(
+ __DIR__ . '/Mixer',
+ __NAMESPACE__ . '\\Mixer\\',
+ array($this, 'registerMixer')
+ );
+ }
+
+ /**
+ * Load all core random number sources
+ *
+ * @return void
+ */
+ protected function loadSources() {
+ $this->loadFiles(
+ __DIR__ . '/Source',
+ __NAMESPACE__ . '\\Source\\',
+ array($this, 'registerSource')
+ );
+ }
+
+}
+
--- /dev/null
+<?php
+/**
+ * The Random Number Generator Class
+ *
+ * Use this factory to generate cryptographic quality random numbers (strings)
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Random
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @author Timo Hamina
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Random;
+
+use CryptLib\Core\BaseConverter;
+
+/**
+ * The Random Number Generator Class
+ *
+ * Use this factory to generate cryptographic quality random numbers (strings)
+ *
+ * @category PHPCryptLib
+ * @package Random
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @author Timo Hamina
+ */
+class Generator {
+
+ /**
+ * @var Mixer The mixing strategy to use for this generator instance
+ */
+ protected $mixer = null;
+
+ /**
+ * @var array An array of random number sources to use for this generator
+ */
+ protected $sources = array();
+
+ /**
+ * Build a new instance of the generator
+ *
+ * @param array $sources An array of random data sources to use
+ * @param Mixer $mixer The mixing strategy to use for this generator
+ */
+ public function __construct(array $sources, Mixer $mixer) {
+ foreach ($sources as $source) {
+ $this->addSource($source);
+ }
+ $this->mixer = $mixer;
+ }
+
+ /**
+ * Add a random number source to the generator
+ *
+ * @param Source $source The random number source to add
+ *
+ * @return Generator $this The current generator instance
+ */
+ public function addSource(Source $source) {
+ $this->sources[] = $source;
+ return $this;
+ }
+
+ /**
+ * Generate a random number (string) of the requested size
+ *
+ * @param int $size The size of the requested random number
+ *
+ * @return string The generated random number (string)
+ */
+ public function generate($size) {
+ $seeds = array();
+ foreach ($this->sources as $source) {
+ $seeds[] = $source->generate($size);
+ }
+ return $this->mixer->mix($seeds);
+ }
+
+ /**
+ * Generate a random integer with the given range
+ *
+ * @param int $min The lower bound of the range to generate
+ * @param int $max The upper bound of the range to generate
+ *
+ * @return int The generated random number within the range
+ */
+ public function generateInt($min = 0, $max = PHP_INT_MAX) {
+ $tmp = (int) max($max, $min);
+ $min = (int) min($max, $min);
+ $max = $tmp;
+ $range = $max - $min;
+ if ($range == 0) {
+ return $max;
+ } elseif ($range > PHP_INT_MAX || is_float($range)) {
+ /**
+ * This works, because PHP will auto-convert it to a float at this point,
+ * But on 64 bit systems, the float won't have enough precision to
+ * actually store the difference, so we need to check if it's a float
+ * and hence auto-converted...
+ */
+ throw new \RangeException(
+ 'The supplied range is too great to generate'
+ );
+ }
+
+ $bits = (int) floor(log($range, 2) + 1);
+ $bytes = (int) max(ceil($bits / 8), 1);
+ $mask = (int) (pow(2, $bits) - 1);
+ /**
+ * The mask is a better way of dropping unused bits. Basically what it does
+ * is to set all the bits in the mask to 1 that we may need. Since the max
+ * range is PHP_INT_MAX, we will never need negative numbers (which would
+ * have the MSB set on the max int possible to generate). Therefore we
+ * can just mask that away. Since pow returns a float, we need to cast
+ * it back to an int so the mask will work.
+ *
+ * On a 64 bit platform, that means that PHP_INT_MAX is 2^63 - 1. Which
+ * is also the mask if 63 bits are needed (by the log(range, 2) call).
+ * So if the computed result is negative (meaning the 64th bit is set), the
+ * mask will correct that.
+ *
+ * This turns out to be slightly better than the shift as we don't need to
+ * worry about "fixing" negative values.
+ */
+ do {
+ $test = $this->generate($bytes);
+ $result = hexdec(bin2hex($test)) & $mask;
+ } while ($result > $range);
+ return $result + $min;
+ }
+
+ /**
+ * Generate a random string of specified length.
+ *
+ * This uses the supplied character list for generating the new result
+ * string.
+ *
+ * @param int $length The length of the generated string
+ * @param string $characters An optional list of characters to use
+ *
+ * @return string The generated random string
+ */
+ public function generateString($length, $characters = '') {
+ if ($length == 0 || strlen($characters) == 1) {
+ return '';
+ } elseif (empty($characters)) {
+ // Default to base 64
+ $characters = '0123456789abcdefghijklmnopqrstuvwxyz' .
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZ./';
+ }
+ //determine how many bytes to generate
+ $bytes = ceil($length * floor(log(strlen($characters), 2) + 1.01) / 8);
+ $rand = $this->generate($bytes);
+ $result = BaseConverter::convertFromBinary($rand, $characters);
+ if (strlen($result) < $length) {
+ $result = str_pad($result, $length, $characters[0], STR_PAD_LEFT);
+ } else {
+ $result = substr($result, 0, $length);
+ }
+ return $result;
+ }
+
+ /**
+ * Get the Mixer used for this instance
+ *
+ * @return Mixer the current mixer
+ */
+ public function getMixer() {
+ return $this->mixer;
+ }
+
+ /**
+ * Get the Sources used for this instance
+ *
+ * @return Source[] the current mixer
+ */
+ public function getSources() {
+ return $this->sources;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * The Mixer strategy interface.
+ *
+ * All mixing strategies must implement this interface
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Random
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Random;
+
+/**
+ * The Mixer strategy interface.
+ *
+ * All mixing strategies must implement this interface
+ *
+ * @category PHPCryptLib
+ * @package Random
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @codeCoverageIgnore
+ */
+interface Mixer {
+
+ /**
+ * Return an instance of Strength indicating the strength of the mixer
+ *
+ * @return Strength An instance of one of the strength classes
+ */
+ public static function getStrength();
+
+ /**
+ * Test to see if the mixer is available
+ *
+ * @return boolean If the mixer is available on the system
+ */
+ public static function test();
+
+ /**
+ * Mix the provided array of strings into a single output of the same size
+ *
+ * All elements of the array should be the same size.
+ *
+ * @param array $parts The parts to be mixed
+ *
+ * @return string The mixed result
+ */
+ public function mix(array $parts);
+
+}
--- /dev/null
+<?php
+/**
+ * The DES medium strength mixer class
+ *
+ * This class implements a mixer based upon the recommendations in RFC 4086
+ * section 5.2
+ *
+ * PHP version 5.3
+ *
+ * @see http://tools.ietf.org/html/rfc4086#section-5.2
+ * @category PHPCryptLib
+ * @package Random
+ * @subpackage Mixer
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Random\Mixer;
+
+use \CryptLib\Cipher\Factory as CipherFactory;
+use \CryptLib\Core\Strength;
+
+/**
+ * The DES medium strength mixer class
+ *
+ * This class implements a mixer based upon the recommendations in RFC 4086
+ * section 5.2
+ *
+ * @see http://tools.ietf.org/html/rfc4086#section-5.2
+ * @category PHPCryptLib
+ * @package Random
+ * @subpackage Mixer
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class DES extends \CryptLib\Random\AbstractMixer {
+
+ /**
+ * An instance of a DES symmetric encryption cipher
+ *
+ * @var Cipher The DES cipher instance
+ */
+ protected $cipher = 'des';
+
+ /**
+ * Return an instance of Strength indicating the strength of the source
+ *
+ * @return Strength An instance of one of the strength classes
+ */
+ public static function getStrength() {
+ return new Strength(Strength::MEDIUM);
+ }
+
+ /**
+ * Test to see if the mixer is available
+ *
+ * @return boolean If the mixer is available on the system
+ */
+ public static function test() {
+ return true;
+ }
+
+ /**
+ * Build a new instance of the DES mixing function
+ *
+ * @param Factory $factory The optional encryption factory to use
+ *
+ * @return void
+ */
+ public function __construct(\CryptLib\Cipher\Factory $factory = null) {
+ if (is_null($factory)) {
+ $factory = new CipherFactory();
+ }
+ $this->cipher = $factory->getBlockCipher($this->cipher);
+ }
+
+ /**
+ * Get the block size (the size of the individual blocks used for the mixing)
+ *
+ * @return int The block size
+ */
+ protected function getPartSize() {
+ return $this->cipher->getBlockSize();
+ }
+
+ /**
+ * Mix 2 parts together using one method
+ *
+ * @param string $part1 The first part to mix
+ * @param string $part2 The second part to mix
+ *
+ * @return string The mixed data
+ */
+ protected function mixParts1($part1, $part2) {
+ $this->cipher->setKey($part2);
+ return $this->cipher->encryptBlock($part1);
+ }
+
+ /**
+ * Mix 2 parts together using another different method
+ *
+ * @param string $part1 The first part to mix
+ * @param string $part2 The second part to mix
+ *
+ * @return string The mixed data
+ */
+ protected function mixParts2($part1, $part2) {
+ $this->cipher->setKey($part1);
+ return $this->cipher->decryptBlock($part2);
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * The Hash medium strength mixer class
+ *
+ * This class implements a mixer based upon the recommendations in RFC 4086
+ * section 5.2
+ *
+ * PHP version 5.3
+ *
+ * @see http://tools.ietf.org/html/rfc4086#section-5.2
+ * @category PHPCryptLib
+ * @package Random
+ * @subpackage Mixer
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Random\Mixer;
+
+use \CryptLib\Core\Strength;
+
+/**
+ * The Hash medium strength mixer class
+ *
+ * This class implements a mixer based upon the recommendations in RFC 4086
+ * section 5.2
+ *
+ * @see http://tools.ietf.org/html/rfc4086#section-5.2
+ * @category PHPCryptLib
+ * @package Random
+ * @subpackage Mixer
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class Hash extends \CryptLib\Random\AbstractMixer {
+
+ /**
+ * @var string The hash instance to use
+ */
+ protected $hash = null;
+
+ /**
+ * Build the hash mixer
+ *
+ * @param string $hash The hash instance to use (defaults to sha512)
+ *
+ * @return void
+ */
+ public function __construct($hash = 'sha512') {
+ $this->hash = $hash;
+ }
+
+ /**
+ * Return an instance of Strength indicating the strength of the source
+ *
+ * @return Strength An instance of one of the strength classes
+ */
+ public static function getStrength() {
+ return new Strength(Strength::LOW);
+ }
+
+ /**
+ * Test to see if the mixer is available
+ *
+ * @return boolean If the mixer is available on the system
+ */
+ public static function test() {
+ return true;
+ }
+
+ /**
+ * Get the block size (the size of the individual blocks used for the mixing)
+ *
+ * @return int The block size
+ */
+ protected function getPartSize() {
+ return strlen(hash($this->hash, '', true));
+ }
+
+ /**
+ * Mix 2 parts together using one method
+ *
+ * @param string $part1 The first part to mix
+ * @param string $part2 The second part to mix
+ *
+ * @return string The mixed data
+ */
+ protected function mixParts1($part1, $part2) {
+ return hash_hmac($this->hash, $part1, $part2, true);
+ }
+
+ /**
+ * Mix 2 parts together using another different method
+ *
+ * @param string $part1 The first part to mix
+ * @param string $part2 The second part to mix
+ *
+ * @return string The mixed data
+ */
+ protected function mixParts2($part1, $part2) {
+ return hash_hmac($this->hash, $part2, $part1, true);
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * The Rijndael-128 based high strength mixer class
+ *
+ * This class implements a mixer based upon the recommendations in RFC 4086
+ * section 5.2
+ *
+ * PHP version 5.3
+ *
+ * @see http://tools.ietf.org/html/rfc4086#section-5.2
+ * @category PHPCryptLib
+ * @package Random
+ * @subpackage Mixer
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Random\Mixer;
+
+use \CryptLib\Cipher\Factory as CipherFactory;
+use \CryptLib\Core\Strength;
+
+/**
+ * The Rijndael-128 based high strength mixer class
+ *
+ * This class implements a mixer based upon the recommendations in RFC 4086
+ * section 5.2
+ *
+ * @see http://tools.ietf.org/html/rfc4086#section-5.2
+ * @category PHPCryptLib
+ * @package Random
+ * @subpackage Mixer
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class Rijndael extends DES {
+
+ /**
+ * An instance of a Rijndael symmetric encryption cipher
+ *
+ * @var Cipher The Rijndael cipher instance
+ */
+ protected $cipher = 'rijndael-128';
+
+ /**
+ * Return an instance of Strength indicating the strength of the source
+ *
+ * @return Strength An instance of one of the strength classes
+ */
+ public static function getStrength() {
+ return new Strength(Strength::HIGH);
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * The Random Number Source interface.
+ *
+ * All random number sources must implement this interface
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Random
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Random;
+
+/**
+ * The Random Number Source interface.
+ *
+ * All random number sources must implement this interface
+ *
+ * @category PHPCryptLib
+ * @package Random
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @codeCoverageIgnore
+ */
+interface Source {
+
+ /**
+ * Return an instance of Strength indicating the strength of the source
+ *
+ * @return Strength An instance of one of the strength classes
+ */
+ public static function getStrength();
+
+ /**
+ * Generate a random string of the specified size
+ *
+ * Note: If the source fails to generate enough data, the result must be
+ * padded to the requested length.
+ *
+ * @param int $size The size of the requested random string
+ *
+ * @return string A string of the requested size
+ */
+ public function generate($size);
+
+}
--- /dev/null
+<?php
+/**
+ * The Capicom Random Number Source
+ *
+ * This uses the Windows CapiCom Com object to generate random numbers
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Random
+ * @subpackage Source
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Random\Source;
+
+use CryptLib\Core\Strength;
+
+/**
+ * The Capicom Random Number Source
+ *
+ * This uses the Windows CapiCom Com object to generate random numbers
+ *
+ * @category PHPCryptLib
+ * @package Random
+ * @subpackage Source
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @codeCoverageIgnore
+ */
+class CAPICOM implements \CryptLib\Random\Source {
+
+ /**
+ * Return an instance of Strength indicating the strength of the source
+ *
+ * @return Strength An instance of one of the strength classes
+ */
+ public static function getStrength() {
+ return new Strength(Strength::MEDIUM);
+ }
+
+ /**
+ * Generate a random string of the specified size
+ *
+ * @param int $size The size of the requested random string
+ *
+ * @return string A string of the requested size
+ */
+ public function generate($size) {
+ if (!class_exists('\\COM', false)) {
+ return str_repeat(chr(0), $size);
+ }
+ try {
+ $util = new \COM('CAPICOM.Utilities.1');
+ $data = base64_decode($util->GetRandom($size, 0));
+ return str_pad($data, $size, chr(0));
+ } catch (\Exception $e) {
+ unset($e);
+ return str_repeat(chr(0), $size);
+ }
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * The MTRand Random Number Source
+ *
+ * This source generates low strength random numbers by using the internal
+ * mt_rand() function. By itself it is quite weak. However when combined with
+ * other sources it does provide significant benefit.
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Random
+ * @subpackage Source
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Random\Source;
+
+use CryptLib\Core\Strength;
+
+/**
+ * The MTRand Random Number Source
+ *
+ * This source generates low strength random numbers by using the internal
+ * mt_rand() function. By itself it is quite weak. However when combined with
+ * other sources it does provide significant benefit.
+ *
+ * @category PHPCryptLib
+ * @package Random
+ * @subpackage Source
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @codeCoverageIgnore
+ */
+class MTRand implements \CryptLib\Random\Source {
+
+ /**
+ * Return an instance of Strength indicating the strength of the source
+ *
+ * @return Strength An instance of one of the strength classes
+ */
+ public static function getStrength() {
+ // Detect if Suhosin Hardened PHP patch is applied
+ if (defined('S_ALL')) {
+ return new Strength(Strength::MEDIUM);
+ } else {
+ return new Strength(Strength::LOW);
+ }
+ }
+
+ /**
+ * Generate a random string of the specified size
+ *
+ * @param int $size The size of the requested random string
+ *
+ * @return string A string of the requested size
+ */
+ public function generate($size) {
+ $result = '';
+ for ($i = 0; $i < $size; $i++) {
+ $result .= chr((mt_rand() ^ mt_rand()) % 256);
+ }
+ return $result;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * The Microtime Random Number Source
+ *
+ * This uses the current micro-second (looped several times) for a **very** weak
+ * random number source. This is only useful when combined with several other
+ * stronger sources
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Random
+ * @subpackage Source
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Random\Source;
+
+use CryptLib\Core\Strength;
+
+/**
+ * The Microtime Random Number Source
+ *
+ * This uses the current micro-second (looped several times) for a **very** weak
+ * random number source. This is only useful when combined with several other
+ * stronger sources
+ *
+ * @category PHPCryptLib
+ * @package Random
+ * @subpackage Source
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @codeCoverageIgnore
+ */
+class MicroTime implements \CryptLib\Random\Source {
+
+ private $state = null;
+
+ /**
+ * Return an instance of Strength indicating the strength of the source
+ *
+ * @return Strength An instance of one of the strength classes
+ */
+ public static function getStrength() {
+ return new Strength(Strength::VERYLOW);
+ }
+
+ public function __construct() {
+ $state = '';
+ if (function_exists('posix_times')) {
+ $state .= serialize(posix_times());
+ }
+ $state .= getmypid() . memory_get_usage();
+ $state .= serialize($_ENV);
+ $this->state = hash('sha512', $state, true);
+ }
+
+ /**
+ * Generate a random string of the specified size
+ *
+ * @param int $size The size of the requested random string
+ *
+ * @return string A string of the requested size
+ */
+ public function generate($size) {
+ $result = '';
+ $seed = microtime() . memory_get_usage();
+ $this->state = hash('sha512', $this->state . $seed, true);
+ /**
+ * Make the generated randomness a bit better by forcing a GC run which
+ * should complete in a indeterminate amount of time, hence improving
+ * the strength of the randomness a bit. It's still not crypto-safe,
+ * but at least it's more difficult to predict.
+ */
+ gc_collect_cycles();
+ for ($i = 0; $i < $size; $i += 8) {
+ $seed = $this->state . microtime() . pack('N', $i);
+ $this->state = hash('sha512', $seed, true);
+ /**
+ * We only use the first 8 bytes here to prevent exposing the state
+ * in its entirety, which could potentially expose other random
+ * generations in the future (in the same process)...
+ */
+ $result .= substr($this->state, 0, 8);
+ }
+ return substr($result, 0, $size);
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * The OpenSSL Random Number Source
+ *
+ * This uses the OS's secure generator to generate high strength numbers
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Random
+ * @subpackage Source
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Random\Source;
+
+use CryptLib\Core\Strength;
+
+/**
+ * The OpenSSL Random Number Source
+ *
+ * This uses the OS's secure generator to generate high strength numbers
+ *
+ * @category PHPCryptLib
+ * @package Random
+ * @subpackage Source
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @codeCoverageIgnore
+ */
+class OpenSSL implements \CryptLib\Random\Source {
+
+ /**
+ * Return an instance of Strength indicating the strength of the source
+ *
+ * @return Strength An instance of one of the strength classes
+ */
+ public static function getStrength() {
+ return new Strength(Strength::HIGH);
+ }
+
+ /**
+ * Generate a random string of the specified size
+ *
+ * @param int $size The size of the requested random string
+ *
+ * @return string A string of the requested size
+ */
+ public function generate($size) {
+ if (!function_exists('openssl_random_pseudo_bytes') || $size < 1) {
+ return str_repeat(chr(0), $size);
+ }
+ /**
+ * Note, normally we would check the return of of $crypto_strong to
+ * ensure that we generated a good random string. However, since we're
+ * using this as one part of many sources a low strength random number
+ * shouldn't be much of an issue.
+ */
+ return openssl_random_pseudo_bytes($size);
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * The Rand Random Number Source
+ *
+ * This source generates low strength random numbers by using the internal
+ * rand() function. By itself it is quite weak. However when combined with
+ * other sources it does provide significant benefit.
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Random
+ * @subpackage Source
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Random\Source;
+
+use CryptLib\Core\Strength;
+
+/**
+ * The Rand Random Number Source
+ *
+ * This source generates low strength random numbers by using the internal
+ * rand() function. By itself it is quite weak. However when combined with
+ * other sources it does provide significant benefit.
+ *
+ * @category PHPCryptLib
+ * @package Random
+ * @subpackage Source
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @codeCoverageIgnore
+ */
+class Rand implements \CryptLib\Random\Source {
+
+ /**
+ * Return an instance of Strength indicating the strength of the source
+ *
+ * @return Strength An instance of one of the strength classes
+ */
+ public static function getStrength() {
+ // Detect if Suhosin Hardened PHP patch is applied
+ if (defined('S_ALL')) {
+ return new Strength(Strength::LOW);
+ } else {
+ return new Strength(Strength::VERYLOW);
+ }
+ }
+
+ /**
+ * Generate a random string of the specified size
+ *
+ * @param int $size The size of the requested random string
+ *
+ * @return string A string of the requested size
+ */
+ public function generate($size) {
+ $result = '';
+ for ($i = 0; $i < $size; $i++) {
+ $result .= chr((rand() ^ rand()) % 256);
+ }
+ return $result;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * The Random Random Number Source
+ *
+ * This uses the *nix /dev/random device to generate high strength numbers
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Random
+ * @subpackage Source
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Random\Source;
+
+use CryptLib\Core\Strength;
+
+/**
+ * The Random Random Number Source
+ *
+ * This uses the *nix /dev/random device to generate high strength numbers
+ *
+ * @category PHPCryptLib
+ * @package Random
+ * @subpackage Source
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @codeCoverageIgnore
+ */
+class Random extends URandom {
+
+ /**
+ * @var string The file to read from
+ */
+ protected $file = '/dev/random';
+
+ /**
+ * Return an instance of Strength indicating the strength of the source
+ *
+ * @return Strength An instance of one of the strength classes
+ */
+ public static function getStrength() {
+ return new Strength(Strength::HIGH);
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * The URandom Random Number Source
+ *
+ * This uses the *nix /dev/urandom device to generate medium strength numbers
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Random
+ * @subpackage Source
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Random\Source;
+
+use CryptLib\Core\Strength;
+
+/**
+ * The URandom Random Number Source
+ *
+ * This uses the *nix /dev/urandom device to generate medium strength numbers
+ *
+ * @category PHPCryptLib
+ * @package Random
+ * @subpackage Source
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @codeCoverageIgnore
+ */
+class URandom implements \CryptLib\Random\Source {
+
+ /**
+ * @var string The file to read from
+ */
+ protected $file = '/dev/urandom';
+
+ /**
+ * Return an instance of Strength indicating the strength of the source
+ *
+ * @return Strength An instance of one of the strength classes
+ */
+ public static function getStrength() {
+ return new Strength(Strength::MEDIUM);
+ }
+
+ /**
+ * Generate a random string of the specified size
+ *
+ * @param int $size The size of the requested random string
+ *
+ * @return string A string of the requested size
+ */
+ public function generate($size) {
+ if ($size == 0 || !file_exists($this->file)) {
+ return str_repeat(chr(0), $size);
+ }
+ $file = fopen($this->file, 'rb');
+ if (!$file) {
+ return str_repeat(chr(0), $size);
+ }
+ if (function_exists('stream_set_read_buffer')) {
+ stream_set_read_buffer($file, 0);
+ }
+ $result = fread($file, $size);
+ fclose($file);
+ return $result;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * The UniqID Random Number Source
+ *
+ * This uses the internal `uniqid()` function to generate low strength random
+ * numbers.
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Random
+ * @subpackage Source
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib\Random\Source;
+
+use CryptLib\Core\Strength;
+
+/**
+ * The UniqID Random Number Source
+ *
+ * This uses the internal `uniqid()` function to generate low strength random
+ * numbers.
+ *
+ * @category PHPCryptLib
+ * @package Random
+ * @subpackage Source
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @codeCoverageIgnore
+ */
+class UniqID implements \CryptLib\Random\Source {
+
+ /**
+ * Return an instance of Strength indicating the strength of the source
+ *
+ * @return Strength An instance of one of the strength classes
+ */
+ public static function getStrength() {
+ return new Strength(Strength::LOW);
+ }
+
+ /**
+ * Generate a random string of the specified size
+ *
+ * @param int $size The size of the requested random string
+ *
+ * @return string A string of the requested size
+ */
+ public function generate($size) {
+ $result = '';
+ while (strlen($result) < $size) {
+ $result = uniqid($result, true);
+ }
+ return substr($result, 0, $size);
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * Bootstrap the library. This registers a simple autoloader for autoloading
+ * classes
+ *
+ * If you are using this library inside of another that uses a similar
+ * autoloading system, you can use that autoloader instead of this file.
+ *
+ * PHP version 5.3
+ *
+ * @category PHPCryptLib
+ * @package Core
+ * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright 2011 The Authors
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @version Build @@version@@
+ */
+
+namespace CryptLib;
+
+require_once __DIR__ . '/Core/AutoLoader.php';
+
+$autoloader = new Core\AutoLoader(__NAMESPACE__, dirname(__DIR__));
+
+$autoloader->register();
\ No newline at end of file
$fields = array('csrf_token' => 'nulltoken', 'showpw' => 0, 'password' => $this->hash, 'reboot_device' => 'true');
$cookie = 'challengev='.$this->challenge.'; '.$this->session;
$data = $this->sentRequest($path, $fields, $cookie);
+
$json = json_decode($data['body'], true);
return $json;
return $json;
}
+ /**
+ * decrypt data from router
+ *
+ * @param string $data
+ * @return array
+ */
+ public function decrypt ($data) {
+ require_once 'CryptLib/CryptLib.php';
+ $factory = new CryptLib\Cipher\Factory();
+ $aes = $factory->getBlockCipher('rijndael-128');
+
+ $iv = hex2bin(substr($this->challenge, 16, 16));
+ $adata = hex2bin(substr($this->challenge, 32, 16));
+ $dkey = hex2bin($this->derivedk);
+ $enc = hex2bin($data);
+
+ $aes->setKey($dkey);
+ $mode = $factory->getMode('ccm', $aes, $iv, [ 'adata' => $adata, 'lSize' => 7]);
+
+ $mode->decrypt($enc);
+
+ return $mode->finish();
+ }
+
+ /**
+ * decrypt data for the router
+ *
+ * @param array $data
+ * @return string
+ */
+ public function encrypt ($data) {
+ require_once 'CryptLib/CryptLib.php';
+ $factory = new CryptLib\Cipher\Factory();
+ $aes = $factory->getBlockCipher('rijndael-128');
+
+ $iv = hex2bin(substr($this->challenge, 16, 16));
+ $adata = hex2bin(substr($this->challenge, 32, 16));
+ $dkey = hex2bin($this->derivedk);
+
+ $aes->setKey($dkey);
+ $mode = $factory->getMode('ccm', $aes, $iv, [ 'adata' => $adata, 'lSize' => 7]);
+ $mode->encrypt(http_build_query($data));
+
+ return $mode->finish();
+ }
+
/**
* sends the request to router
*
curl_close($ch);
// fix invalid json
+
$body = preg_replace("/(\r\n)|(\r)/", "\n", $body);
$body = preg_replace('/\'/i', '"', $body);
$body = preg_replace("/\[\s+\]/i", '[ {} ]', $body);