Import Horde_Cipher:: from CVS.
authorMichael M Slusarz <slusarz@curecanti.org>
Sun, 5 Jul 2009 20:29:25 +0000 (14:29 -0600)
committerMichael M Slusarz <slusarz@curecanti.org>
Sun, 5 Jul 2009 20:29:25 +0000 (14:29 -0600)
Am dubious about the state of this package, especially since neither
blowfish nor Cast128 pass the unit tests (they don't work in CVS either
going back for many years).  It might be best to dump them or else use
PEAR's Crypt_Blowfish module instead.

19 files changed:
framework/Cipher/lib/Horde/Cipher.php [new file with mode: 0644]
framework/Cipher/lib/Horde/Cipher/BlockMode.php [new file with mode: 0644]
framework/Cipher/lib/Horde/Cipher/BlockMode/Cbc.php [new file with mode: 0644]
framework/Cipher/lib/Horde/Cipher/BlockMode/Cfb64.php [new file with mode: 0644]
framework/Cipher/lib/Horde/Cipher/BlockMode/Ecb.php [new file with mode: 0644]
framework/Cipher/lib/Horde/Cipher/BlockMode/Ofb64.php [new file with mode: 0644]
framework/Cipher/lib/Horde/Cipher/Blowfish.php [new file with mode: 0644]
framework/Cipher/lib/Horde/Cipher/Cast128.php [new file with mode: 0644]
framework/Cipher/lib/Horde/Cipher/Des.php [new file with mode: 0644]
framework/Cipher/lib/Horde/Cipher/Rc2.php [new file with mode: 0644]
framework/Cipher/lib/Horde/Cipher/Rc4.php [new file with mode: 0644]
framework/Cipher/package.xml [new file with mode: 0644]
framework/Cipher/test/Horde/Cipher/Cipher1.phpt [new file with mode: 0644]
framework/Cipher/test/Horde/Cipher/Cipher2.phpt [new file with mode: 0644]
framework/Cipher/test/Horde/Cipher/Cipher3.phpt [new file with mode: 0644]
framework/Cipher/test/Horde/Cipher/Cipher4.phpt [new file with mode: 0644]
framework/Cipher/test/Horde/Cipher/Cipher5.phpt [new file with mode: 0644]
framework/Cipher/test/Horde/Cipher/Cipher6.phpt [new file with mode: 0644]
framework/Cipher/test/Horde/Cipher/cipher_functions.php [new file with mode: 0644]

diff --git a/framework/Cipher/lib/Horde/Cipher.php b/framework/Cipher/lib/Horde/Cipher.php
new file mode 100644 (file)
index 0000000..83beb32
--- /dev/null
@@ -0,0 +1,123 @@
+<?php
+/**
+ * The Horde_Cipher:: class provides a common abstracted interface to
+ * various Ciphers for encryption of arbitrary length pieces of data.
+ *
+ * Copyright 2002-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Mike Cochrane <mike@graftonhall.co.nz>
+ * @package Horde_Cipher
+ */
+class Horde_Cipher
+{
+    /**
+     * The block mode for the cipher chaining
+     *
+     * @var string
+     */
+    protected $_blockMode = 'cbc';
+
+    /**
+     * The block size.
+     *
+     * @var integer
+     */
+    protected $_blockSize = 8;
+
+    /**
+     * The initialization vector
+     *
+     * @var string
+     */
+    protected $_iv = null;
+
+    /**
+     * Attempts to return a concrete Horde_Cipher instance.
+     *
+     * @param string $cipher  The type of concrete Horde_Cipher subclass to
+     *                        return.
+     * @param array $params   A hash containing any additional parameters a
+     *                        subclass might need.
+     *
+     * @return Horde_Cipher  The newly created concrete Horde_Cipher instance.
+     * @throws Horde_Exception
+     */
+    static public function factory($driver, $params = null)
+    {
+        $class = 'Horde_Cipher_' . Horde_String::ucfirst(basename($driver));
+        if (!class_exists($class)) {
+            throw new Horde_Exception('Driver ' . $driver . ' not found');
+        }
+        return new $class($params);
+    }
+
+    /**
+     * Set the block mode for cipher chaining.
+     *
+     * @param string $blockMode  The new blockmode.
+     */
+    public function setBlockMode($blockMode)
+    {
+        $this->_blockMode = $blockMode;
+    }
+
+    /**
+     * Return the size of the blocks that this cipher needs.
+     *
+     * @return integer  The number of characters per block.
+     */
+    public function getBlockSize()
+    {
+        return $this->_blockSize;
+    }
+
+    /**
+     * Set the IV.
+     *
+     * @param string $iv  The new IV.
+     */
+    public function setIV($iv)
+    {
+        $this->_iv = $iv;
+    }
+
+    /**
+     * Encrypt a string.
+     *
+     * @param string $plaintext  The data to encrypt.
+     *
+     * @return string  The encrypted data.
+     */
+    public function encrypt($plaintext)
+    {
+        $blockMode = Horde_Cipher_BlockMode::factory($this->_blockMode);
+
+        if (!is_null($this->_iv)) {
+            $blockMode->setIV($this->_iv);
+        }
+
+        return $blockMode->encrypt($this, $plaintext);
+    }
+
+    /**
+     * Decrypt a string.
+     *
+     * @param string $ciphertext  The data to decrypt.
+     *
+     * @return string  The decrypted data.
+     */
+    public function decrypt($ciphertext)
+    {
+        $blockMode = Horde_Cipher_BlockMode::factory($this->_blockMode);
+
+        if (!is_null($this->_iv)) {
+            $blockMode->setIV($this->_iv);
+        }
+
+        return $blockMode->decrypt($this, $ciphertext);
+    }
+
+}
diff --git a/framework/Cipher/lib/Horde/Cipher/BlockMode.php b/framework/Cipher/lib/Horde/Cipher/BlockMode.php
new file mode 100644 (file)
index 0000000..1859d77
--- /dev/null
@@ -0,0 +1,79 @@
+<?php
+/**
+ * The Horde_Cipher_BlockMode:: class provides a common abstracted
+ * interface to various block mode handlers for ciphers.
+ *
+ * Copyright 2002-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Mike Cochrane <mike@graftonhall.co.nz>
+ * @package Horde_Cipher
+ */
+class Horde_Cipher_BlockMode
+{
+    /**
+     * The initialization vector.
+     *
+     * @var string
+     */
+    protected $_iv = "\0\0\0\0\0\0\0\0";
+
+    /**
+     * Attempts to return a concrete instance based on $mode.
+     *
+     * @param string $mode   The type of concrete subclass to return.
+     *                       subclass to return.
+     * @param array $params  A hash containing any additional parameters a
+     *                       subclass might need.
+     *
+     * @return Horde_Cipher_BlockMode  The newly created concrete instance.
+     * @throws Horde_Exception
+     */
+    static public function factory($driver, $params = null)
+    {
+        $class = 'Horde_Cipher_BlockMode_' . Horde_String::ucfirst(basename($driver));
+        if (!class_exists($class)) {
+            throw new Horde_Exception('Driver ' . $driver . ' not found');
+        }
+        return new $class($params);
+    }
+
+    /**
+     * Set the IV.
+     *
+     * @param string $iv  The new IV.
+     */
+    public function setIV($iv)
+    {
+        $this->_iv = $iv;
+    }
+
+    /**
+     * Encrypt a string.
+     *
+     * @param Horde_Cipher $cipher  Cipher algorithm to use for encryption.
+     * @param string $plaintext     The data to encrypt.
+     *
+     * @return string  The encrypted data.
+     */
+    public function encrypt($cipher, $plaintext)
+    {
+        return $plaintext;
+    }
+
+    /**
+     * Decrypt a string.
+     *
+     * @param Horde_Cipher $cipher  Cipher algorithm to use for decryption.
+     * @param string $ciphertext    The data to decrypt.
+     *
+     * @return string  The decrypted data.
+     */
+    public function decrypt($cipher, $ciphertext)
+    {
+        return $ciphertext;
+    }
+
+}
diff --git a/framework/Cipher/lib/Horde/Cipher/BlockMode/Cbc.php b/framework/Cipher/lib/Horde/Cipher/BlockMode/Cbc.php
new file mode 100644 (file)
index 0000000..3f3453a
--- /dev/null
@@ -0,0 +1,78 @@
+<?php
+/**
+ * The Horde_Cipher_BlockMode_Cbc:: class implements Horde_Cipher_BlockMode
+ * using the Cipher Block Chaining method of encrypting blocks of data.
+ *
+ * Copyright 2002-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Mike Cochrane <mike@graftonhall.co.nz>
+ * @package Horde_Cipher
+ */
+class Horde_Cipher_BlockMode_Cbc extends Horde_Cipher_BlockMode
+{
+    /**
+     * Encrypt a string.
+     *
+     * @param Horde_Cipher $cipher  Cipher algorithm to use for encryption.
+     * @param string $plaintext     The data to encrypt.
+     *
+     * @return string  The encrypted data.
+     */
+    public function encrypt($cipher, $plaintext)
+    {
+        $encrypted = '';
+
+        $blocksize = $cipher->getBlockSize();
+        $previousCipher = $this->_iv;
+
+        $jMax = strlen($plaintext);
+        for ($j = 0; $j < $jMax; $j += $blocksize) {
+            $plain = substr($plaintext, $j, $blocksize);
+
+            if (strlen($plain) < $blocksize) {
+                // pad the block with \0's if it's not long enough
+                $plain = str_pad($plain, 8, "\0");
+            }
+
+            $plain = $plain ^ $previousCipher;
+            $previousCipher = $cipher->encryptBlock($plain);
+            $encrypted .= $previousCipher;
+        }
+
+        return $encrypted;
+    }
+
+    /**
+     * Decrypt a string.
+     *
+     * @param Horde_Cipher $cipher  Cipher algorithm to use for decryption.
+     * @param string $ciphertext    The data to decrypt.
+     *
+     * @return string  The decrypted data.
+     */
+    public function decrypt($cipher, $ciphertext)
+    {
+        $decrypted = '';
+
+        $blocksize = $cipher->getBlockSize();
+        $previousCipher = $this->_iv;
+
+        $jMax = strlen($ciphertext);
+        for ($j = 0; $j < $jMax; $j += $blocksize) {
+            $plain = substr($ciphertext, $j, $blocksize);
+            $decrypted .= $cipher->decryptBlock($plain) ^ $previousCipher;
+            $previousCipher = $plain;
+        }
+
+        // Remove trailing \0's used to pad the last block.
+        while (substr($decrypted, -1, 1) == "\0") {
+            $decrypted = substr($decrypted, 0, -1);
+        }
+
+        return $decrypted;
+    }
+
+}
diff --git a/framework/Cipher/lib/Horde/Cipher/BlockMode/Cfb64.php b/framework/Cipher/lib/Horde/Cipher/BlockMode/Cfb64.php
new file mode 100644 (file)
index 0000000..96a7fe7
--- /dev/null
@@ -0,0 +1,82 @@
+<?php
+/**
+ * The Horde_Cipher_BlockMode_Cfb64:: class implements Horde_Cipher_BlockMode
+ * using a 64 bit cipher feedback.
+ *
+ * This can be used to encrypt any length string and the encrypted
+ * version will be the same length.
+ *
+ * Copyright 2002-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Mike Cochrane <mike@graftonhall.co.nz>
+ * @package Horde_Cipher
+ */
+class Horde_Cipher_BlockMode_Cfb64 extends Horde_Cipher_BlockMode
+{
+    /**
+     * Encrypt a string.
+     *
+     * @param Horde_Cipher $cipher  Cipher algorithm to use for encryption.
+     * @param string $plaintext     The data to encrypt.
+     *
+     * @return string  The encrypted data.
+     */
+    function encrypt($cipher, $plaintext)
+    {
+        $encrypted = '';
+
+        $n = 0;
+        $jMax = strlen($plaintext);
+        for ($j = 0; $j < $jMax; ++$j) {
+            if ($n == 0) {
+                $this->_iv = $cipher->encryptBlock($this->_iv);
+            }
+
+            $c = $plaintext[$j] ^ $this->_iv[$n];
+            $this->_iv = substr($this->_iv, 0, $n) . $c . substr($this->_iv, $n + 1);
+            $encrypted .= $c;
+
+            $n = (++$n) & 0x07;
+        }
+
+        return $encrypted;
+    }
+
+    /**
+     * Decrypt a string.
+     *
+     * @param Horde_Cipher $cipher  Cipher algorithm to use for decryption.
+     * @param string $ciphertext    The data to decrypt.
+     *
+     * @return string  The decrypted data.
+     */
+    function decrypt($cipher, $ciphertext)
+    {
+        $decrypted = '';
+
+        $n = 0;
+        $jMax = strlen($ciphertext);
+        for ($j = 0; $j < $jMax; ++$j) {
+            if ($n == 0) {
+                $this->_iv = $cipher->encryptBlock($this->_iv);
+            }
+
+            $c = $ciphertext[$j] ^ $this->_iv[$n];
+            $this->_iv = substr($this->_iv, 0, $n) . substr($ciphertext, $j, 1) . substr($this->_iv, $n + 1);
+            $decrypted .= $c;
+
+            $n = (++$n) & 0x07;
+        }
+
+        // Remove trailing \0's used to pad the last block.
+        while (substr($decrypted, -1, 1) == "\0") {
+            $decrypted = substr($decrypted, 0, -1);
+        }
+
+        return $decrypted;
+    }
+
+}
diff --git a/framework/Cipher/lib/Horde/Cipher/BlockMode/Ecb.php b/framework/Cipher/lib/Horde/Cipher/BlockMode/Ecb.php
new file mode 100644 (file)
index 0000000..4cd350d
--- /dev/null
@@ -0,0 +1,71 @@
+<?php
+/**
+ * The Horde_Cipher_BlockMode_Ecb:: class implements Horde_Cipher_BlockMode
+ * using the Electronic Code Book method of encrypting blocks of data.
+ *
+ * Copyright 2002-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Mike Cochrane <mike@graftonhall.co.nz>
+ * @package Horde_Cipher
+ */
+class Horde_Cipher_BlockMode_Ecb extends Horde_Cipher_BlockMode
+{
+    /**
+     * Encrypt a string.
+     *
+     * @param Horde_Cipher $cipher  Cipher algorithm to use for encryption.
+     * @param string $plaintext     The data to encrypt.
+     *
+     * @return string  The encrypted data.
+     */
+    public function encrypt($cipher, $plaintext)
+    {
+        $encrypted = '';
+        $blocksize = $cipher->getBlockSize();
+
+        $jMax = strlen($plaintext);
+        for ($j = 0; $j < $jMax; $j += $blocksize) {
+            $plain = substr($plaintext, $j, $blocksize);
+
+            if (strlen($plain) < $blocksize) {
+                // pad the block with \0's if it's not long enough
+                $plain = str_pad($plain, 8, "\0");
+            }
+
+            $encrypted .= $cipher->encryptBlock($plain);
+        }
+
+        return $encrypted;
+    }
+
+    /**
+     * Decrypt a string.
+     *
+     * @param Horde_Cipher $cipher  Cipher algorithm to use for decryption.
+     * @param string $ciphertext    The data to decrypt.
+     *
+     * @return string  The decrypted data.
+     */
+    public function decrypt($cipher, $ciphertext)
+    {
+        $decrypted = '';
+        $blocksize = $cipher->getBlockSize();
+
+        $jMax = strlen($ciphertext);
+        for ($j = 0; $j < $jMax; $j += $blocksize) {
+            $plain = substr($ciphertext, $j, $blocksize);
+            $decrypted .= $cipher->decryptBlock($plain);
+        }
+
+        // Remove trailing \0's used to pad the last block.
+        while (substr($decrypted, -1, 1) == "\0") {
+            $decrypted = substr($decrypted, 0, -1);
+        }
+
+        return $decrypted;
+    }
+
+}
diff --git a/framework/Cipher/lib/Horde/Cipher/BlockMode/Ofb64.php b/framework/Cipher/lib/Horde/Cipher/BlockMode/Ofb64.php
new file mode 100644 (file)
index 0000000..6eade81
--- /dev/null
@@ -0,0 +1,75 @@
+<?php
+/**
+ * The Horde_Cipher_BlockMode_Ofb64:: class implements Horde_Cipher_BlockMode
+ * using a 64 bit output feedback.
+ *
+ * This can used to encrypt any length string and the encrypted version
+ * will be the same length.
+ *
+ * Copyright 2002-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Mike Cochrane <mike@graftonhall.co.nz>
+ * @package Horde_Cipher
+ */
+class Horde_Cipher_BlockMode_Ofb64 extends Horde_Cipher_BlockMode
+{
+    /**
+     * Encrypt a string.
+     *
+     * @param Horde_Cipher $cipher  Cipher algorithm to use for encryption.
+     * @param string $plaintext     The data to encrypt.
+     *
+     * @return string  The encrypted data.
+     */
+    public function encrypt($cipher, $plaintext)
+    {
+        $encrypted = '';
+
+        $n = 0;
+        $jMax = strlen($plaintext);
+        for ($j = 0; $j < $jMax; ++$j) {
+            if ($n == 0) {
+                $this->_iv = $cipher->encryptBlock($this->_iv);
+            }
+
+            $c = $plaintext[$j] ^ $this->_iv[$n];
+            $encrypted .= $c;
+
+            $n = (++$n) & 0x07;
+        }
+
+        return $encrypted;
+    }
+
+    /**
+     * Decrypt a string.
+     *
+     * @param Horde_Cipher $cipher  Cipher algorithm to use for decryption.
+     * @param string $ciphertext    The data to decrypt.
+     *
+     * @return string  The decrypted data.
+     */
+    public function decrypt($cipher, $ciphertext)
+    {
+        $decrypted = '';
+
+        $n = 0;
+        $jMax = strlen($ciphertext);
+        for ($j = 0; $j < $jMax; ++$j) {
+            if ($n == 0) {
+                $this->_iv = $cipher->encryptBlock($this->_iv);
+            }
+
+            $c = $ciphertext[$j] ^ $this->_iv[$n];
+            $decrypted .= $c;
+
+            $n = (++$n) & 0x07;
+        }
+
+        return $decrypted;
+    }
+
+}
diff --git a/framework/Cipher/lib/Horde/Cipher/Blowfish.php b/framework/Cipher/lib/Horde/Cipher/Blowfish.php
new file mode 100644 (file)
index 0000000..f9a8402
--- /dev/null
@@ -0,0 +1,468 @@
+<?php
+/**
+ * The Horde_Cipher_Blowfish:: class implements the Horde_Cipher interface
+ * encryption data using the Blowfish algorithm.
+ *
+ * Copyright 2002-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Mike Cochrane <mike@graftonhall.co.nz>
+ * @package Horde_Cipher
+ */
+class Horde_Cipher_Blowfish extends Horde_Cipher
+{
+    /**
+     * Pi Array
+     *
+     * @var array
+     */
+    protected $p = array(
+        0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344,
+        0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89,
+        0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C,
+        0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917,
+        0x9216D5D9, 0x8979FB1B);
+
+    /**
+     * S Box (s1)
+     *
+     * @var array
+     */
+    protected $s1 = array(
+        0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7,
+        0xB8E1AFED, 0x6A267E96, 0xBA7C9045, 0xF12C7F99,
+        0x24A19947, 0xB3916CF7, 0x0801F2E2, 0x858EFC16,
+        0x636920D8, 0x71574E69, 0xA458FEA3, 0xF4933D7E,
+        0x0D95748F, 0x728EB658, 0x718BCD58, 0x82154AEE,
+        0x7B54A41D, 0xC25A59B5, 0x9C30D539, 0x2AF26013,
+        0xC5D1B023, 0x286085F0, 0xCA417918, 0xB8DB38EF,
+        0x8E79DCB0, 0x603A180E, 0x6C9E0E8B, 0xB01E8A3E,
+        0xD71577C1, 0xBD314B27, 0x78AF2FDA, 0x55605C60,
+        0xE65525F3, 0xAA55AB94, 0x57489862, 0x63E81440,
+        0x55CA396A, 0x2AAB10B6, 0xB4CC5C34, 0x1141E8CE,
+        0xA15486AF, 0x7C72E993, 0xB3EE1411, 0x636FBC2A,
+        0x2BA9C55D, 0x741831F6, 0xCE5C3E16, 0x9B87931E,
+        0xAFD6BA33, 0x6C24CF5C, 0x7A325381, 0x28958677,
+        0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193,
+        0x61D809CC, 0xFB21A991, 0x487CAC60, 0x5DEC8032,
+        0xEF845D5D, 0xE98575B1, 0xDC262302, 0xEB651B88,
+        0x23893E81, 0xD396ACC5, 0x0F6D6FF3, 0x83F44239,
+        0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E,
+        0x21C66842, 0xF6E96C9A, 0x670C9C61, 0xABD388F0,
+        0x6A51A0D2, 0xD8542F68, 0x960FA728, 0xAB5133A3,
+        0x6EEF0B6C, 0x137A3BE4, 0xBA3BF050, 0x7EFB2A98,
+        0xA1F1651D, 0x39AF0176, 0x66CA593E, 0x82430E88,
+        0x8CEE8619, 0x456F9FB4, 0x7D84A5C3, 0x3B8B5EBE,
+        0xE06F75D8, 0x85C12073, 0x401A449F, 0x56C16AA6,
+        0x4ED3AA62, 0x363F7706, 0x1BFEDF72, 0x429B023D,
+        0x37D0D724, 0xD00A1248, 0xDB0FEAD3, 0x49F1C09B,
+        0x075372C9, 0x80991B7B, 0x25D479D8, 0xF6E8DEF7,
+        0xE3FE501A, 0xB6794C3B, 0x976CE0BD, 0x04C006BA,
+        0xC1A94FB6, 0x409F60C4, 0x5E5C9EC2, 0x196A2463,
+        0x68FB6FAF, 0x3E6C53B5, 0x1339B2EB, 0x3B52EC6F,
+        0x6DFC511F, 0x9B30952C, 0xCC814544, 0xAF5EBD09,
+        0xBEE3D004, 0xDE334AFD, 0x660F2807, 0x192E4BB3,
+        0xC0CBA857, 0x45C8740F, 0xD20B5F39, 0xB9D3FBDB,
+        0x5579C0BD, 0x1A60320A, 0xD6A100C6, 0x402C7279,
+        0x679F25FE, 0xFB1FA3CC, 0x8EA5E9F8, 0xDB3222F8,
+        0x3C7516DF, 0xFD616B15, 0x2F501EC8, 0xAD0552AB,
+        0x323DB5FA, 0xFD238760, 0x53317B48, 0x3E00DF82,
+        0x9E5C57BB, 0xCA6F8CA0, 0x1A87562E, 0xDF1769DB,
+        0xD542A8F6, 0x287EFFC3, 0xAC6732C6, 0x8C4F5573,
+        0x695B27B0, 0xBBCA58C8, 0xE1FFA35D, 0xB8F011A0,
+        0x10FA3D98, 0xFD2183B8, 0x4AFCB56C, 0x2DD1D35B,
+        0x9A53E479, 0xB6F84565, 0xD28E49BC, 0x4BFB9790,
+        0xE1DDF2DA, 0xA4CB7E33, 0x62FB1341, 0xCEE4C6E8,
+        0xEF20CADA, 0x36774C01, 0xD07E9EFE, 0x2BF11FB4,
+        0x95DBDA4D, 0xAE909198, 0xEAAD8E71, 0x6B93D5A0,
+        0xD08ED1D0, 0xAFC725E0, 0x8E3C5B2F, 0x8E7594B7,
+        0x8FF6E2FB, 0xF2122B64, 0x8888B812, 0x900DF01C,
+        0x4FAD5EA0, 0x688FC31C, 0xD1CFF191, 0xB3A8C1AD,
+        0x2F2F2218, 0xBE0E1777, 0xEA752DFE, 0x8B021FA1,
+        0xE5A0CC0F, 0xB56F74E8, 0x18ACF3D6, 0xCE89E299,
+        0xB4A84FE0, 0xFD13E0B7, 0x7CC43B81, 0xD2ADA8D9,
+        0x165FA266, 0x80957705, 0x93CC7314, 0x211A1477,
+        0xE6AD2065, 0x77B5FA86, 0xC75442F5, 0xFB9D35CF,
+        0xEBCDAF0C, 0x7B3E89A0, 0xD6411BD3, 0xAE1E7E49,
+        0x00250E2D, 0x2071B35E, 0x226800BB, 0x57B8E0AF,
+        0x2464369B, 0xF009B91E, 0x5563911D, 0x59DFA6AA,
+        0x78C14389, 0xD95A537F, 0x207D5BA2, 0x02E5B9C5,
+        0x83260376, 0x6295CFA9, 0x11C81968, 0x4E734A41,
+        0xB3472DCA, 0x7B14A94A, 0x1B510052, 0x9A532915,
+        0xD60F573F, 0xBC9BC6E4, 0x2B60A476, 0x81E67400,
+        0x08BA6FB5, 0x571BE91F, 0xF296EC6B, 0x2A0DD915,
+        0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664,
+        0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A);
+
+    /**
+     * S Box (s2)
+     *
+     * @var array
+     */
+    protected $s2 = array(
+        0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623,
+        0xAD6EA6B0, 0x49A7DF7D, 0x9CEE60B8, 0x8FEDB266,
+        0xECAA8C71, 0x699A17FF, 0x5664526C, 0xC2B19EE1,
+        0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E,
+        0x3F54989A, 0x5B429D65, 0x6B8FE4D6, 0x99F73FD6,
+        0xA1D29C07, 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1,
+        0x4CDD2086, 0x8470EB26, 0x6382E9C6, 0x021ECC5E,
+        0x09686B3F, 0x3EBAEFC9, 0x3C971814, 0x6B6A70A1,
+        0x687F3584, 0x52A0E286, 0xB79C5305, 0xAA500737,
+        0x3E07841C, 0x7FDEAE5C, 0x8E7D44EC, 0x5716F2B8,
+        0xB03ADA37, 0xF0500C0D, 0xF01C1F04, 0x0200B3FF,
+        0xAE0CF51A, 0x3CB574B2, 0x25837A58, 0xDC0921BD,
+        0xD19113F9, 0x7CA92FF6, 0x94324773, 0x22F54701,
+        0x3AE5E581, 0x37C2DADC, 0xC8B57634, 0x9AF3DDA7,
+        0xA9446146, 0x0FD0030E, 0xECC8C73E, 0xA4751E41,
+        0xE238CD99, 0x3BEA0E2F, 0x3280BBA1, 0x183EB331,
+        0x4E548B38, 0x4F6DB908, 0x6F420D03, 0xF60A04BF,
+        0x2CB81290, 0x24977C79, 0x5679B072, 0xBCAF89AF,
+        0xDE9A771F, 0xD9930810, 0xB38BAE12, 0xDCCF3F2E,
+        0x5512721F, 0x2E6B7124, 0x501ADDE6, 0x9F84CD87,
+        0x7A584718, 0x7408DA17, 0xBC9F9ABC, 0xE94B7D8C,
+        0xEC7AEC3A, 0xDB851DFA, 0x63094366, 0xC464C3D2,
+        0xEF1C1847, 0x3215D908, 0xDD433B37, 0x24C2BA16,
+        0x12A14D43, 0x2A65C451, 0x50940002, 0x133AE4DD,
+        0x71DFF89E, 0x10314E55, 0x81AC77D6, 0x5F11199B,
+        0x043556F1, 0xD7A3C76B, 0x3C11183B, 0x5924A509,
+        0xF28FE6ED, 0x97F1FBFA, 0x9EBABF2C, 0x1E153C6E,
+        0x86E34570, 0xEAE96FB1, 0x860E5E0A, 0x5A3E2AB3,
+        0x771FE71C, 0x4E3D06FA, 0x2965DCB9, 0x99E71D0F,
+        0x803E89D6, 0x5266C825, 0x2E4CC978, 0x9C10B36A,
+        0xC6150EBA, 0x94E2EA78, 0xA5FC3C53, 0x1E0A2DF4,
+        0xF2F74EA7, 0x361D2B3D, 0x1939260F, 0x19C27960,
+        0x5223A708, 0xF71312B6, 0xEBADFE6E, 0xEAC31F66,
+        0xE3BC4595, 0xA67BC883, 0xB17F37D1, 0x018CFF28,
+        0xC332DDEF, 0xBE6C5AA5, 0x65582185, 0x68AB9802,
+        0xEECEA50F, 0xDB2F953B, 0x2AEF7DAD, 0x5B6E2F84,
+        0x1521B628, 0x29076170, 0xECDD4775, 0x619F1510,
+        0x13CCA830, 0xEB61BD96, 0x0334FE1E, 0xAA0363CF,
+        0xB5735C90, 0x4C70A239, 0xD59E9E0B, 0xCBAADE14,
+        0xEECC86BC, 0x60622CA7, 0x9CAB5CAB, 0xB2F3846E,
+        0x648B1EAF, 0x19BDF0CA, 0xA02369B9, 0x655ABB50,
+        0x40685A32, 0x3C2AB4B3, 0x319EE9D5, 0xC021B8F7,
+        0x9B540B19, 0x875FA099, 0x95F7997E, 0x623D7DA8,
+        0xF837889A, 0x97E32D77, 0x11ED935F, 0x16681281,
+        0x0E358829, 0xC7E61FD6, 0x96DEDFA1, 0x7858BA99,
+        0x57F584A5, 0x1B227263, 0x9B83C3FF, 0x1AC24696,
+        0xCDB30AEB, 0x532E3054, 0x8FD948E4, 0x6DBC3128,
+        0x58EBF2EF, 0x34C6FFEA, 0xFE28ED61, 0xEE7C3C73,
+        0x5D4A14D9, 0xE864B7E3, 0x42105D14, 0x203E13E0,
+        0x45EEE2B6, 0xA3AAABEA, 0xDB6C4F15, 0xFACB4FD0,
+        0xC742F442, 0xEF6ABBB5, 0x654F3B1D, 0x41CD2105,
+        0xD81E799E, 0x86854DC7, 0xE44B476A, 0x3D816250,
+        0xCF62A1F2, 0x5B8D2646, 0xFC8883A0, 0xC1C7B6A3,
+        0x7F1524C3, 0x69CB7492, 0x47848A0B, 0x5692B285,
+        0x095BBF00, 0xAD19489D, 0x1462B174, 0x23820E00,
+        0x58428D2A, 0x0C55F5EA, 0x1DADF43E, 0x233F7061,
+        0x3372F092, 0x8D937E41, 0xD65FECF1, 0x6C223BDB,
+        0x7CDE3759, 0xCBEE7460, 0x4085F2A7, 0xCE77326E,
+        0xA6078084, 0x19F8509E, 0xE8EFD855, 0x61D99735,
+        0xA969A7AA, 0xC50C06C2, 0x5A04ABFC, 0x800BCADC,
+        0x9E447A2E, 0xC3453484, 0xFDD56705, 0x0E1E9EC9,
+        0xDB73DBD3, 0x105588CD, 0x675FDA79, 0xE3674340,
+        0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20,
+        0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, 0xDB83ADF7);
+
+    /**
+     * S Box (s3)
+     *
+     * @var array
+     */
+    protected $s3 = array(
+        0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934,
+        0x411520F7, 0x7602D4F7, 0xBCF46B2E, 0xD4A20068,
+        0xD4082471, 0x3320F46A, 0x43B7D4B7, 0x500061AF,
+        0x1E39F62E, 0x97244546, 0x14214F74, 0xBF8B8840,
+        0x4D95FC1D, 0x96B591AF, 0x70F4DDD3, 0x66A02F45,
+        0xBFBC09EC, 0x03BD9785, 0x7FAC6DD0, 0x31CB8504,
+        0x96EB27B3, 0x55FD3941, 0xDA2547E6, 0xABCA0A9A,
+        0x28507825, 0x530429F4, 0x0A2C86DA, 0xE9B66DFB,
+        0x68DC1462, 0xD7486900, 0x680EC0A4, 0x27A18DEE,
+        0x4F3FFEA2, 0xE887AD8C, 0xB58CE006, 0x7AF4D6B6,
+        0xAACE1E7C, 0xD3375FEC, 0xCE78A399, 0x406B2A42,
+        0x20FE9E35, 0xD9F385B9, 0xEE39D7AB, 0x3B124E8B,
+        0x1DC9FAF7, 0x4B6D1856, 0x26A36631, 0xEAE397B2,
+        0x3A6EFA74, 0xDD5B4332, 0x6841E7F7, 0xCA7820FB,
+        0xFB0AF54E, 0xD8FEB397, 0x454056AC, 0xBA489527,
+        0x55533A3A, 0x20838D87, 0xFE6BA9B7, 0xD096954B,
+        0x55A867BC, 0xA1159A58, 0xCCA92963, 0x99E1DB33,
+        0xA62A4A56, 0x3F3125F9, 0x5EF47E1C, 0x9029317C,
+        0xFDF8E802, 0x04272F70, 0x80BB155C, 0x05282CE3,
+        0x95C11548, 0xE4C66D22, 0x48C1133F, 0xC70F86DC,
+        0x07F9C9EE, 0x41041F0F, 0x404779A4, 0x5D886E17,
+        0x325F51EB, 0xD59BC0D1, 0xF2BCC18F, 0x41113564,
+        0x257B7834, 0x602A9C60, 0xDFF8E8A3, 0x1F636C1B,
+        0x0E12B4C2, 0x02E1329E, 0xAF664FD1, 0xCAD18115,
+        0x6B2395E0, 0x333E92E1, 0x3B240B62, 0xEEBEB922,
+        0x85B2A20E, 0xE6BA0D99, 0xDE720C8C, 0x2DA2F728,
+        0xD0127845, 0x95B794FD, 0x647D0862, 0xE7CCF5F0,
+        0x5449A36F, 0x877D48FA, 0xC39DFD27, 0xF33E8D1E,
+        0x0A476341, 0x992EFF74, 0x3A6F6EAB, 0xF4F8FD37,
+        0xA812DC60, 0xA1EBDDF8, 0x991BE14C, 0xDB6E6B0D,
+        0xC67B5510, 0x6D672C37, 0x2765D43B, 0xDCD0E804,
+        0xF1290DC7, 0xCC00FFA3, 0xB5390F92, 0x690FED0B,
+        0x667B9FFB, 0xCEDB7D9C, 0xA091CF0B, 0xD9155EA3,
+        0xBB132F88, 0x515BAD24, 0x7B9479BF, 0x763BD6EB,
+        0x37392EB3, 0xCC115979, 0x8026E297, 0xF42E312D,
+        0x6842ADA7, 0xC66A2B3B, 0x12754CCC, 0x782EF11C,
+        0x6A124237, 0xB79251E7, 0x06A1BBE6, 0x4BFB6350,
+        0x1A6B1018, 0x11CAEDFA, 0x3D25BDD8, 0xE2E1C3C9,
+        0x44421659, 0x0A121386, 0xD90CEC6E, 0xD5ABEA2A,
+        0x64AF674E, 0xDA86A85F, 0xBEBFE988, 0x64E4C3FE,
+        0x9DBC8057, 0xF0F7C086, 0x60787BF8, 0x6003604D,
+        0xD1FD8346, 0xF6381FB0, 0x7745AE04, 0xD736FCCC,
+        0x83426B33, 0xF01EAB71, 0xB0804187, 0x3C005E5F,
+        0x77A057BE, 0xBDE8AE24, 0x55464299, 0xBF582E61,
+        0x4E58F48F, 0xF2DDFDA2, 0xF474EF38, 0x8789BDC2,
+        0x5366F9C3, 0xC8B38E74, 0xB475F255, 0x46FCD9B9,
+        0x7AEB2661, 0x8B1DDF84, 0x846A0E79, 0x915F95E2,
+        0x466E598E, 0x20B45770, 0x8CD55591, 0xC902DE4C,
+        0xB90BACE1, 0xBB8205D0, 0x11A86248, 0x7574A99E,
+        0xB77F19B6, 0xE0A9DC09, 0x662D09A1, 0xC4324633,
+        0xE85A1F02, 0x09F0BE8C, 0x4A99A025, 0x1D6EFE10,
+        0x1AB93D1D, 0x0BA5A4DF, 0xA186F20F, 0x2868F169,
+        0xDCB7DA83, 0x573906FE, 0xA1E2CE9B, 0x4FCD7F52,
+        0x50115E01, 0xA70683FA, 0xA002B5C4, 0x0DE6D027,
+        0x9AF88C27, 0x773F8641, 0xC3604C06, 0x61A806B5,
+        0xF0177A28, 0xC0F586E0, 0x006058AA, 0x30DC7D62,
+        0x11E69ED7, 0x2338EA63, 0x53C2DD94, 0xC2C21634,
+        0xBBCBEE56, 0x90BCB6DE, 0xEBFC7DA1, 0xCE591D76,
+        0x6F05E409, 0x4B7C0188, 0x39720A3D, 0x7C927C24,
+        0x86E3725F, 0x724D9DB9, 0x1AC15BB4, 0xD39EB8FC,
+        0xED545578, 0x08FCA5B5, 0xD83D7CD3, 0x4DAD0FC4,
+        0x1E50EF5E, 0xB161E6F8, 0xA28514D9, 0x6C51133C,
+        0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, 0xDDC6C837,
+        0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0);
+
+    /**
+     * S Box (s4)
+     *
+     * @var array
+     */
+    protected $s4 = array(
+        0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B,
+        0x5CB0679E, 0x4FA33742, 0xD3822740, 0x99BC9BBE,
+        0xD5118E9D, 0xBF0F7315, 0xD62D1C7E, 0xC700C47B,
+        0xB78C1B6B, 0x21A19045, 0xB26EB1BE, 0x6A366EB4,
+        0x5748AB2F, 0xBC946E79, 0xC6A376D2, 0x6549C2C8,
+        0x530FF8EE, 0x468DDE7D, 0xD5730A1D, 0x4CD04DC6,
+        0x2939BBDB, 0xA9BA4650, 0xAC9526E8, 0xBE5EE304,
+        0xA1FAD5F0, 0x6A2D519A, 0x63EF8CE2, 0x9A86EE22,
+        0xC089C2B8, 0x43242EF6, 0xA51E03AA, 0x9CF2D0A4,
+        0x83C061BA, 0x9BE96A4D, 0x8FE51550, 0xBA645BD6,
+        0x2826A2F9, 0xA73A3AE1, 0x4BA99586, 0xEF5562E9,
+        0xC72FEFD3, 0xF752F7DA, 0x3F046F69, 0x77FA0A59,
+        0x80E4A915, 0x87B08601, 0x9B09E6AD, 0x3B3EE593,
+        0xE990FD5A, 0x9E34D797, 0x2CF0B7D9, 0x022B8B51,
+        0x96D5AC3A, 0x017DA67D, 0xD1CF3ED6, 0x7C7D2D28,
+        0x1F9F25CF, 0xADF2B89B, 0x5AD6B472, 0x5A88F54C,
+        0xE029AC71, 0xE019A5E6, 0x47B0ACFD, 0xED93FA9B,
+        0xE8D3C48D, 0x283B57CC, 0xF8D56629, 0x79132E28,
+        0x785F0191, 0xED756055, 0xF7960E44, 0xE3D35E8C,
+        0x15056DD4, 0x88F46DBA, 0x03A16125, 0x0564F0BD,
+        0xC3EB9E15, 0x3C9057A2, 0x97271AEC, 0xA93A072A,
+        0x1B3F6D9B, 0x1E6321F5, 0xF59C66FB, 0x26DCF319,
+        0x7533D928, 0xB155FDF5, 0x03563482, 0x8ABA3CBB,
+        0x28517711, 0xC20AD9F8, 0xABCC5167, 0xCCAD925F,
+        0x4DE81751, 0x3830DC8E, 0x379D5862, 0x9320F991,
+        0xEA7A90C2, 0xFB3E7BCE, 0x5121CE64, 0x774FBE32,
+        0xA8B6E37E, 0xC3293D46, 0x48DE5369, 0x6413E680,
+        0xA2AE0810, 0xDD6DB224, 0x69852DFD, 0x09072166,
+        0xB39A460A, 0x6445C0DD, 0x586CDECF, 0x1C20C8AE,
+        0x5BBEF7DD, 0x1B588D40, 0xCCD2017F, 0x6BB4E3BB,
+        0xDDA26A7E, 0x3A59FF45, 0x3E350A44, 0xBCB4CDD5,
+        0x72EACEA8, 0xFA6484BB, 0x8D6612AE, 0xBF3C6F47,
+        0xD29BE463, 0x542F5D9E, 0xAEC2771B, 0xF64E6370,
+        0x740E0D8D, 0xE75B1357, 0xF8721671, 0xAF537D5D,
+        0x4040CB08, 0x4EB4E2CC, 0x34D2466A, 0x0115AF84,
+        0xE1B00428, 0x95983A1D, 0x06B89FB4, 0xCE6EA048,
+        0x6F3F3B82, 0x3520AB82, 0x011A1D4B, 0x277227F8,
+        0x611560B1, 0xE7933FDC, 0xBB3A792B, 0x344525BD,
+        0xA08839E1, 0x51CE794B, 0x2F32C9B7, 0xA01FBAC9,
+        0xE01CC87E, 0xBCC7D1F6, 0xCF0111C3, 0xA1E8AAC7,
+        0x1A908749, 0xD44FBD9A, 0xD0DADECB, 0xD50ADA38,
+        0x0339C32A, 0xC6913667, 0x8DF9317C, 0xE0B12B4F,
+        0xF79E59B7, 0x43F5BB3A, 0xF2D519FF, 0x27D9459C,
+        0xBF97222C, 0x15E6FC2A, 0x0F91FC71, 0x9B941525,
+        0xFAE59361, 0xCEB69CEB, 0xC2A86459, 0x12BAA8D1,
+        0xB6C1075E, 0xE3056A0C, 0x10D25065, 0xCB03A442,
+        0xE0EC6E0E, 0x1698DB3B, 0x4C98A0BE, 0x3278E964,
+        0x9F1F9532, 0xE0D392DF, 0xD3A0342B, 0x8971F21E,
+        0x1B0A7441, 0x4BA3348C, 0xC5BE7120, 0xC37632D8,
+        0xDF359F8D, 0x9B992F2E, 0xE60B6F47, 0x0FE3F11D,
+        0xE54CDA54, 0x1EDAD891, 0xCE6279CF, 0xCD3E7E6F,
+        0x1618B166, 0xFD2C1D05, 0x848FD2C5, 0xF6FB2299,
+        0xF523F357, 0xA6327623, 0x93A83531, 0x56CCCD02,
+        0xACF08162, 0x5A75EBB5, 0x6E163697, 0x88D273CC,
+        0xDE966292, 0x81B949D0, 0x4C50901B, 0x71C65614,
+        0xE6C6C7BD, 0x327A140A, 0x45E1D006, 0xC3F27B9A,
+        0xC9AA53FD, 0x62A80F00, 0xBB25BFE2, 0x35BDD2F6,
+        0x71126905, 0xB2040222, 0xB6CBCF7C, 0xCD769C2B,
+        0x53113EC0, 0x1640E3D3, 0x38ABBD60, 0x2547ADF0,
+        0xBA38209C, 0xF746CE76, 0x77AFA1C5, 0x20756060,
+        0x85CBFE4E, 0x8AE88DD8, 0x7AAAF9B0, 0x4CF9AA7E,
+        0x1948C25C, 0x02FB8A8C, 0x01C36AE4, 0xD6EBE1F9,
+        0x90D4F869, 0xA65CDEA0, 0x3F09252D, 0xC208E69F,
+        0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6);
+
+    /**
+     * The number of rounds to do
+     *
+     * @var integer
+     */
+    protected $_rounds = 16;
+
+    /**
+     * Set the key to be used for en/decryption.
+     *
+     * @param string $key  The key to use.
+     */
+    public function setKey($key)
+    {
+        $key = array_values(unpack('C*', $key));
+        $keyLen = count($key);
+        if ($keyLen == 0) {
+            return false;
+        }
+
+        $keyPos = $keyXor = 0;
+        for ($i = 0, $iMax = count($this->p); $i < $iMax; ++$i) {
+            for ($t = 0; $t < 4; $t++) {
+                $keyXor = ($keyXor << 8) | (($key[$keyPos]) & 0x0ff);
+                if (++$keyPos == $keyLen) {
+                    $keyPos = 0;
+                }
+            }
+            $this->p[$i] = $this->p[$i] ^ $keyXor;
+        }
+
+        $encZero = array('L' => 0, 'R' => 0);
+        for ($i = 0; $i + 1 < $iMax; $i += 2) {
+            $encZero = $this->_encryptBlock($encZero['L'], $encZero['R']);
+            $this->p[$i] = $encZero['L'];
+            $this->p[$i + 1] = $encZero['R'];
+        }
+
+        $iMax = count($this->s1);
+        for ($i = 0; $i < $iMax; $i += 2) {
+            $encZero = $this->_encryptBlock($encZero['L'], $encZero['R']);
+            $this->s1[$i] = $encZero['L'];
+            $this->s1[$i + 1] = $encZero['R'];
+        }
+
+        $iMax = count($this->s2);
+        for ($i = 0; $i < $iMax; $i += 2) {
+            $encZero = $this->_encryptBlock($encZero['L'], $encZero['R']);
+            $this->s2[$i] = $encZero['L'];
+            $this->s2[$i + 1] = $encZero['R'];
+        }
+
+        $iMax = count($this->s3);
+        for ($i = 0; $i < $iMax; $i += 2) {
+            $encZero = $this->_encryptBlock($encZero['L'], $encZero['R']);
+            $this->s3[$i] = $encZero['L'];
+            $this->s3[$i + 1] = $encZero['R'];
+        }
+
+        $iMax = count($this->s4);
+        for ($i = 0; $i < $iMax; $i += 2) {
+            $encZero = $this->_encryptBlock($encZero['L'], $encZero['R']);
+            $this->s4[$i] = $encZero['L'];
+            $this->s4[$i + 1] = $encZero['R'];
+        }
+    }
+
+    /**
+     * Encrypt a block of data.
+     *
+     * @param string $block      The data to encrypt.
+     * @param string $key        The key to use.
+     *
+     * @return string  The encrypted output.
+     */
+    public function encryptBlock($block, $key = null)
+    {
+        if (!is_null($key)) {
+            $this->setKey($key);
+        }
+
+        list($L, $R) = array_values(unpack('N*', $block));
+        $parts = $this->_encryptBlock($L, $R);
+        return pack('NN', $parts['L'], $parts['R']);
+    }
+
+    /**
+     * Encrypt left and right halves of a block of data.
+     *
+     * @param integer $L  Left half of the data.
+     * @param integer $R  Right half of the data.
+     *
+     * @return array  A hash, with keys 'L' and 'R', and the encrypted data as
+     *                the values.
+     */
+    protected function _encryptBlock($L, $R)
+    {
+        $L ^= $this->p[0];
+        $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[1];
+        $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[2];
+        $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[3];
+        $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[4];
+        $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[5];
+        $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[6];
+        $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[7];
+        $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[8];
+        $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[9];
+        $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[10];
+        $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[11];
+        $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[12];
+        $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[13];
+        $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[14];
+        $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[15];
+        $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[16];
+        $R ^= $this->p[17];
+
+        return array('L' => $R, 'R' => $L);
+    }
+
+    /**
+     * Decrypt a block of data.
+     *
+     * @param string $block  The data to decrypt.
+     * @param string $key    The key to use.
+     *
+     * @return string  The decrypted output.
+     */
+    public function decryptBlock($block, $key = null)
+    {
+        if (!is_null($key)) {
+            $this->setKey($key);
+        }
+
+        list($L, $R) = array_values(unpack('N*', $block));
+
+        $L ^= $this->p[17];
+        $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[16];
+        $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[15];
+        $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[14];
+        $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[13];
+        $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[12];
+        $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[11];
+        $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[10];
+        $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[9];
+        $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[8];
+        $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[7];
+        $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[6];
+        $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[5];
+        $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[4];
+        $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[3];
+        $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[2];
+        $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[1];
+
+        return pack("NN", $R ^ $this->p[0], $L);
+    }
+
+}
diff --git a/framework/Cipher/lib/Horde/Cipher/Cast128.php b/framework/Cipher/lib/Horde/Cipher/Cast128.php
new file mode 100644 (file)
index 0000000..3ce14ce
--- /dev/null
@@ -0,0 +1,693 @@
+<?php
+/**
+ * The Horde_Cipher_Cast128:: class implements the Cipher interface encryption
+ * data using the CAST128 (aka Cast5) algorithm as defined in RFC2144.
+ *
+ * Copyright 2002-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Mike Cochrane <mike@graftonhall.co.nz>
+ * @package Horde_Cipher
+ */
+class Horde_Cipher_Cast128 extends Horde_Cipher
+{
+    /**
+     * S box (s1).
+     *
+     * @var array
+     */
+    protected $_s1 = array(
+        0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949,
+        0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e,
+        0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d,
+        0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0,
+        0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7,
+        0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935,
+        0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d,
+        0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50,
+        0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe,
+        0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3,
+        0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167,
+        0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291,
+        0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779,
+        0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2,
+        0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511,
+        0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d,
+        0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5,
+        0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324,
+        0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c,
+        0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc,
+        0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d,
+        0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96,
+        0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a,
+        0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d,
+        0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd,
+        0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6,
+        0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9,
+        0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872,
+        0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c,
+        0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e,
+        0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9,
+        0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf);
+
+    /**
+     * S box (s2).
+     *
+     * @var array
+     */
+    protected $_s2 = array(
+        0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651,
+        0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3,
+        0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb,
+        0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806,
+        0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b,
+        0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359,
+        0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b,
+        0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c,
+        0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34,
+        0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb,
+        0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd,
+        0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860,
+        0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b,
+        0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304,
+        0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b,
+        0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf,
+        0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c,
+        0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13,
+        0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f,
+        0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6,
+        0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6,
+        0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58,
+        0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906,
+        0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d,
+        0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6,
+        0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4,
+        0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6,
+        0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f,
+        0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249,
+        0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa,
+        0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9,
+        0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1);
+
+    /**
+     * S box (s3).
+     *
+     * @var array
+     */
+    protected $_s3 = array(
+        0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90,
+        0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5,
+        0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e,
+        0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240,
+        0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5,
+        0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b,
+        0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71,
+        0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04,
+        0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82,
+        0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15,
+        0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2,
+        0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176,
+        0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148,
+        0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc,
+        0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341,
+        0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e,
+        0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51,
+        0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f,
+        0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a,
+        0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b,
+        0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b,
+        0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5,
+        0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45,
+        0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536,
+        0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc,
+        0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0,
+        0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69,
+        0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2,
+        0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49,
+        0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d,
+        0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a,
+        0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783);
+
+    /**
+     * S box (s4).
+     *
+     * @var array
+     */
+    protected $_s4 = array(
+        0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1,
+        0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf,
+        0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15,
+        0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121,
+        0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25,
+        0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5,
+        0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb,
+        0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5,
+        0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d,
+        0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6,
+        0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23,
+        0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003,
+        0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6,
+        0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119,
+        0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24,
+        0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a,
+        0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79,
+        0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df,
+        0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26,
+        0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab,
+        0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7,
+        0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417,
+        0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2,
+        0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2,
+        0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a,
+        0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919,
+        0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef,
+        0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876,
+        0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab,
+        0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04,
+        0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282,
+        0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2);
+
+    /**
+     * S box (s5).
+     *
+     * @var array
+     */
+    protected $_s5 = array(
+        0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f,
+        0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a,
+        0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff,
+        0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02,
+        0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a,
+        0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7,
+        0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9,
+        0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981,
+        0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774,
+        0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655,
+        0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2,
+        0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910,
+        0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1,
+        0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da,
+        0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049,
+        0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f,
+        0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba,
+        0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be,
+        0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3,
+        0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840,
+        0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4,
+        0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2,
+        0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7,
+        0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5,
+        0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e,
+        0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e,
+        0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801,
+        0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad,
+        0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0,
+        0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20,
+        0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8,
+        0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4);
+
+    /**
+     * S box (s6).
+     *
+     * @var array
+     */
+    protected $_s6 = array(
+        0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac,
+        0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138,
+        0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367,
+        0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98,
+        0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072,
+        0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3,
+        0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd,
+        0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8,
+        0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9,
+        0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54,
+        0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387,
+        0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc,
+        0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf,
+        0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf,
+        0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f,
+        0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289,
+        0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950,
+        0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f,
+        0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b,
+        0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be,
+        0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13,
+        0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976,
+        0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0,
+        0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891,
+        0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da,
+        0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc,
+        0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084,
+        0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25,
+        0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121,
+        0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5,
+        0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd,
+        0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f);
+
+    /**
+     * S box (s7).
+     *
+     * @var array
+     */
+    protected $_s7 = array(
+        0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f,
+        0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de,
+        0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43,
+        0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19,
+        0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2,
+        0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516,
+        0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88,
+        0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816,
+        0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756,
+        0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a,
+        0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264,
+        0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688,
+        0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28,
+        0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3,
+        0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7,
+        0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06,
+        0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033,
+        0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a,
+        0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566,
+        0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509,
+        0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962,
+        0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e,
+        0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c,
+        0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c,
+        0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285,
+        0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301,
+        0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be,
+        0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767,
+        0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647,
+        0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914,
+        0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c,
+        0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3);
+
+    /**
+     * S box (s8).
+     *
+     * @var array
+     */
+    protected $_s8 = array(
+        0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5,
+        0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc,
+        0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd,
+        0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d,
+        0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2,
+        0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862,
+        0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc,
+        0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c,
+        0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e,
+        0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039,
+        0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8,
+        0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42,
+        0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5,
+        0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472,
+        0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225,
+        0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c,
+        0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb,
+        0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054,
+        0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70,
+        0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc,
+        0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c,
+        0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3,
+        0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4,
+        0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101,
+        0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f,
+        0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e,
+        0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a,
+        0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c,
+        0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384,
+        0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c,
+        0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82,
+        0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e);
+
+    /**
+     * Masking Keys.
+     *
+     * @var array
+     */
+    protected $_km = array();
+
+    /**
+     * Rotate Keys.
+     *
+     * @var array
+     */
+    protected $_kr = array();
+
+    /**
+     * The number of rounds to do.
+     *
+     * @var integer
+     */
+    protected $_rounds = 16;
+
+    /**
+     * Set the key to be used for en/decryption.
+     *
+     * @param string $key  The key to use.
+     */
+    public function setKey($key)
+    {
+        if (!is_null($key)) {
+            $this->_rounds = (strlen($key) < 11) ? 12 : 16;
+            $this->_keySchedule($this->_formatKey($key));
+        }
+    }
+
+    /**
+     * Encrypt a block of data.
+     *
+     * @param string $block  The data to encrypt.
+     * @param string $key    The key to use.
+     *
+     * @return string  The encrypted output.
+     */
+    public function encryptBlock($block, $key = null)
+    {
+        $this->setKey($key);
+
+        $L = $this->_formatData(substr($block, 0, 4));
+        $R = $this->_formatData(substr($block, 4, 4));
+
+        $L ^= $this->_f1($R, $this->_km[1], $this->_kr[1]);
+        $R ^= $this->_f2($L, $this->_km[2], $this->_kr[2]);
+        $L ^= $this->_f3($R, $this->_km[3], $this->_kr[3]);
+        $R ^= $this->_f1($L, $this->_km[4], $this->_kr[4]);
+        $L ^= $this->_f2($R, $this->_km[5], $this->_kr[5]);
+        $R ^= $this->_f3($L, $this->_km[6], $this->_kr[6]);
+        $L ^= $this->_f1($R, $this->_km[7], $this->_kr[7]);
+        $R ^= $this->_f2($L, $this->_km[8], $this->_kr[8]);
+        $L ^= $this->_f3($R, $this->_km[9], $this->_kr[9]);
+        $R ^= $this->_f1($L, $this->_km[10], $this->_kr[10]);
+        $L ^= $this->_f2($R, $this->_km[11], $this->_kr[11]);
+        $R ^= $this->_f3($L, $this->_km[12], $this->_kr[12]);
+        if ($this->_rounds > 12) {
+            $L ^= $this->_f1($R, $this->_km[13], $this->_kr[13]);
+            $R ^= $this->_f2($L, $this->_km[14], $this->_kr[14]);
+            $L ^= $this->_f3($R, $this->_km[15], $this->_kr[15]);
+            $R ^= $this->_f1($L, $this->_km[16], $this->_kr[16]);
+        }
+
+        return pack('N', $R) . pack('N', $L);
+    }
+
+    /**
+     * Decrypt a block of data.
+     *
+     * @param string $block  The data to decrypt.
+     * @param string $key    The key to use.
+     *
+     * @return string  The decrypted output.
+     */
+    public function decryptBlock($block, $key = null)
+    {
+        $this->setKey($key);
+
+        $R = $this->_formatData(substr($block, 0, 4));
+        $L = $this->_formatData(substr($block, 4, 4));
+
+        if ($this->_rounds > 12) {
+            $R ^= $this->_f1($L, $this->_km[16], $this->_kr[16]);
+            $L ^= $this->_f3($R, $this->_km[15], $this->_kr[15]);
+            $R ^= $this->_f2($L, $this->_km[14], $this->_kr[14]);
+            $L ^= $this->_f1($R, $this->_km[13], $this->_kr[13]);
+        }
+
+        $R ^= $this->_f3($L, $this->_km[12], $this->_kr[12]);
+        $L ^= $this->_f2($R, $this->_km[11], $this->_kr[11]);
+        $R ^= $this->_f1($L, $this->_km[10], $this->_kr[10]);
+        $L ^= $this->_f3($R, $this->_km[9], $this->_kr[9]);
+        $R ^= $this->_f2($L, $this->_km[8], $this->_kr[8]);
+        $L ^= $this->_f1($R, $this->_km[7], $this->_kr[7]);
+        $R ^= $this->_f3($L, $this->_km[6], $this->_kr[6]);
+        $L ^= $this->_f2($R, $this->_km[5], $this->_kr[5]);
+        $R ^= $this->_f1($L, $this->_km[4], $this->_kr[4]);
+        $L ^= $this->_f3($R, $this->_km[3], $this->_kr[3]);
+        $R ^= $this->_f2($L, $this->_km[2], $this->_kr[2]);
+        $L ^= $this->_f1($R, $this->_km[1], $this->_kr[1]);
+
+        return pack('N', $L) . pack('N', $R);
+    }
+
+    /**
+     * f1()
+     */
+    protected function _f1($d, $Km, $Kr)
+    {
+        $I = $Km + $d;
+
+        /* Nasty Fix as
+         * $I << $Kr | $I >> (32 - $Kr)
+         * Doesn't always give the correct answer
+         */
+        $bin = str_pad(decbin($I), 32, '0', STR_PAD_LEFT);
+        $I = bindec(substr($bin, $Kr) . substr($bin, 0, $Kr));
+
+        $f = $this->_s1[($I >> 24) & 0xFF] ^ $this->_s2[($I >> 16) & 0xFF];
+        $f = $f - $this->_s3[($I >> 8) & 0xFF];
+        return $f + $this->_s4[$I & 0xFF];
+    }
+
+    /**
+     * f2()
+     */
+    protected function _f2($d, $Km, $Kr)
+    {
+        $I = $Km ^ $d;
+
+        /* Nasty Fix as
+         * $I << $Kr | $I >> (32 - $Kr)
+         * Doesn't always give the correct answer
+         */
+        $bin = str_pad(decbin($I), 32, '0', STR_PAD_LEFT);
+        $I = bindec(substr($bin, $Kr) . substr($bin, 0, $Kr));
+
+        $f = $this->_s1[($I >> 24) & 0xFF] - $this->_s2[($I >> 16) & 0xFF];
+        $f = $f + $this->_s3[($I >> 8) & 0xFF];
+        return $f ^ $this->_s4[$I & 0xFF];
+    }
+
+    /**
+     * f3()
+     */
+    protected function _f3($d, $Km, $Kr)
+    {
+        $I = 0xFFFFFFFF & ($Km - $d);
+
+        /* Nasty Fix as
+         * $I << $Kr | $I >> (32 - $Kr)
+         * Doesn't always give the correct answer
+         */
+        $bin = str_pad(decbin($I), 32, '0', STR_PAD_LEFT);
+        $I = bindec(substr($bin, $Kr) . substr($bin, 0, $Kr));
+
+        $f = ($this->_s1[($I >> 24) & 0xFF] + $this->_s2[($I >> 16) & 0xFF]);
+        $f = $f ^ $this->_s3[($I >> 8) & 0xFF];
+        return 0xFFFFFFFF & ($f - $this->_s4[$I & 0xFF]);
+    }
+
+    /**
+     * Convert a string into a array of the ordinates of its characters.
+     *
+     * @param string $data  Data to convert.
+     *
+     * @return array  The converted data.
+     */
+    protected function _formatData($data)
+    {
+        return $this->_combine4(unpack('C*', $data), 0x1);
+    }
+
+    /**
+     * Converts a text key into an array padded with \0's to a length of 128
+     * bits.
+     *
+     * @param string $key  The key to format.
+     *
+     * @return array  The padded key.
+     */
+    protected function _formatKey($key)
+    {
+        $res = array_values(unpack('C*', $key));
+        for ($i = count($res); $i < 16; ++$i) {
+            $res[$i] = 0;
+        }
+        return $res;
+    }
+
+    /**
+     * Create the complete key shedule.
+     *
+     * @param array $key  The key to use.
+     */
+    protected function _keySchedule($key)
+    {
+        $x0x1x2x3 = $this->_combine4($key, 0x0);
+        $x4x5x6x7 = $this->_combine4($key, 0x4);
+        $x8x9xAxB = $this->_combine4($key, 0x8);
+        $xCxDxExF = $this->_combine4($key, 0xC);
+
+        $b = $this->_split($x0x1x2x3); $x0 = $b[0]; $x1 = $b[1]; $x2 = $b[2]; $x3 = $b[3];
+        $b = $this->_split($x4x5x6x7); $x4 = $b[0]; $x5 = $b[1]; $x6 = $b[2]; $x7 = $b[3];
+        $b = $this->_split($x8x9xAxB); $x8 = $b[0]; $x9 = $b[1]; $xA = $b[2]; $xB = $b[3];
+        $b = $this->_split($xCxDxExF); $xC = $b[0]; $xD = $b[1]; $xE = $b[2]; $xF = $b[3];
+
+        $z0z1z2z3 = $x0x1x2x3 ^ $this->_s5[$xD] ^ $this->_s6[$xF] ^ $this->_s7[$xC] ^ $this->_s8[$xE] ^ $this->_s7[$x8];
+        $b = $this->_split($z0z1z2z3); $z0 = $b[0]; $z1 = $b[1]; $z2 = $b[2]; $z3 = $b[3];
+        $z4z5z6z7 = $x8x9xAxB ^ $this->_s5[$z0] ^ $this->_s6[$z2] ^ $this->_s7[$z1] ^ $this->_s8[$z3] ^ $this->_s8[$xA];
+        $b = $this->_split($z4z5z6z7); $z4 = $b[0]; $z5 = $b[1]; $z6 = $b[2]; $z7 = $b[3];
+        $z8z9zAzB = $xCxDxExF ^ $this->_s5[$z7] ^ $this->_s6[$z6] ^ $this->_s7[$z5] ^ $this->_s8[$z4] ^ $this->_s5[$x9];
+        $b = $this->_split($z8z9zAzB); $z8 = $b[0]; $z9 = $b[1]; $zA = $b[2]; $zB = $b[3];
+        $zCzDzEzF = $x4x5x6x7 ^ $this->_s5[$zA] ^ $this->_s6[$z9] ^ $this->_s7[$zB] ^ $this->_s8[$z8] ^ $this->_s6[$xB];
+        $b = $this->_split($zCzDzEzF); $zC = $b[0]; $zD = $b[1]; $zE = $b[2]; $zF = $b[3];
+
+        $this->_km[1] = $this->_s5[$z8] ^ $this->_s6[$z9] ^ $this->_s7[$z7] ^ $this->_s8[$z6] ^ $this->_s5[$z2];
+        $this->_km[2] = $this->_s5[$zA] ^ $this->_s6[$zB] ^ $this->_s7[$z5] ^ $this->_s8[$z4] ^ $this->_s6[$z6];
+        $this->_km[3] = $this->_s5[$zC] ^ $this->_s6[$zD] ^ $this->_s7[$z3] ^ $this->_s8[$z2] ^ $this->_s7[$z9];
+        $this->_km[4] = $this->_s5[$zE] ^ $this->_s6[$zF] ^ $this->_s7[$z1] ^ $this->_s8[$z0] ^ $this->_s8[$zC];
+
+        $x0x1x2x3 = $z8z9zAzB ^ $this->_s5[$z5] ^ $this->_s6[$z7] ^ $this->_s7[$z4] ^ $this->_s8[$z6] ^ $this->_s7[$z0];
+        $b = $this->_split($x0x1x2x3); $x0 = $b[0]; $x1 = $b[1]; $x2 = $b[2]; $x3 = $b[3];
+        $x4x5x6x7 = $z0z1z2z3 ^ $this->_s5[$x0] ^ $this->_s6[$x2] ^ $this->_s7[$x1] ^ $this->_s8[$x3] ^ $this->_s8[$z2];
+        $b = $this->_split($x4x5x6x7); $x4 = $b[0]; $x5 = $b[1]; $x6 = $b[2]; $x7 = $b[3];
+        $x8x9xAxB = $z4z5z6z7 ^ $this->_s5[$x7] ^ $this->_s6[$x6] ^ $this->_s7[$x5] ^ $this->_s8[$x4] ^ $this->_s5[$z1];
+        $b = $this->_split($x8x9xAxB); $x8 = $b[0]; $x9 = $b[1]; $xA = $b[2]; $xB = $b[3];
+        $xCxDxExF = $zCzDzEzF ^ $this->_s5[$xA] ^ $this->_s6[$x9] ^ $this->_s7[$xB] ^ $this->_s8[$x8] ^ $this->_s6[$z3];
+        $b = $this->_split($xCxDxExF); $xC = $b[0]; $xD = $b[1]; $xE = $b[2]; $xF = $b[3];
+
+        $this->_km[5]  = $this->_s5[$x3] ^ $this->_s6[$x2] ^ $this->_s7[$xC] ^ $this->_s8[$xD] ^ $this->_s5[$x8];
+        $this->_km[6]  = $this->_s5[$x1] ^ $this->_s6[$x0] ^ $this->_s7[$xE] ^ $this->_s8[$xF] ^ $this->_s6[$xD];
+        $this->_km[7]  = $this->_s5[$x7] ^ $this->_s6[$x6] ^ $this->_s7[$x8] ^ $this->_s8[$x9] ^ $this->_s7[$x3];
+        $this->_km[8]  = $this->_s5[$x5] ^ $this->_s6[$x4] ^ $this->_s7[$xA] ^ $this->_s8[$xB] ^ $this->_s8[$x7];
+
+        $z0z1z2z3 = $x0x1x2x3 ^ $this->_s5[$xD] ^ $this->_s6[$xF] ^ $this->_s7[$xC] ^ $this->_s8[$xE] ^ $this->_s7[$x8];
+        $b = $this->_split($z0z1z2z3); $z0 = $b[0]; $z1 = $b[1]; $z2 = $b[2]; $z3 = $b[3];
+        $z4z5z6z7 = $x8x9xAxB ^ $this->_s5[$z0] ^ $this->_s6[$z2] ^ $this->_s7[$z1] ^ $this->_s8[$z3] ^ $this->_s8[$xA];
+        $b = $this->_split($z4z5z6z7); $z4 = $b[0]; $z5 = $b[1]; $z6 = $b[2]; $z7 = $b[3];
+        $z8z9zAzB = $xCxDxExF ^ $this->_s5[$z7] ^ $this->_s6[$z6] ^ $this->_s7[$z5] ^ $this->_s8[$z4] ^ $this->_s5[$x9];
+        $b = $this->_split($z8z9zAzB); $z8 = $b[0]; $z9 = $b[1]; $zA = $b[2]; $zB = $b[3];
+        $zCzDzEzF = $x4x5x6x7 ^ $this->_s5[$zA] ^ $this->_s6[$z9] ^ $this->_s7[$zB] ^ $this->_s8[$z8] ^ $this->_s6[$xB];
+        $b = $this->_split($zCzDzEzF); $zC = $b[0]; $zD = $b[1]; $zE = $b[2]; $zF = $b[3];
+
+        $this->_km[9]  = $this->_s5[$z3] ^ $this->_s6[$z2] ^ $this->_s7[$zC] ^ $this->_s8[$zD] ^ $this->_s5[$z9];
+        $this->_km[10] = $this->_s5[$z1] ^ $this->_s6[$z0] ^ $this->_s7[$zE] ^ $this->_s8[$zF] ^ $this->_s6[$zC];
+        $this->_km[11] = $this->_s5[$z7] ^ $this->_s6[$z6] ^ $this->_s7[$z8] ^ $this->_s8[$z9] ^ $this->_s7[$z2];
+        $this->_km[12] = $this->_s5[$z5] ^ $this->_s6[$z4] ^ $this->_s7[$zA] ^ $this->_s8[$zB] ^ $this->_s8[$z6];
+
+        $x0x1x2x3 = $z8z9zAzB ^ $this->_s5[$z5] ^ $this->_s6[$z7] ^ $this->_s7[$z4] ^ $this->_s8[$z6] ^ $this->_s7[$z0];
+        $b = $this->_split($x0x1x2x3); $x0 = $b[0]; $x1 = $b[1]; $x2 = $b[2]; $x3 = $b[3];
+        $x4x5x6x7 = $z0z1z2z3 ^ $this->_s5[$x0] ^ $this->_s6[$x2] ^ $this->_s7[$x1] ^ $this->_s8[$x3] ^ $this->_s8[$z2];
+        $b = $this->_split($x4x5x6x7); $x4 = $b[0]; $x5 = $b[1]; $x6 = $b[2]; $x7 = $b[3];
+        $x8x9xAxB = $z4z5z6z7 ^ $this->_s5[$x7] ^ $this->_s6[$x6] ^ $this->_s7[$x5] ^ $this->_s8[$x4] ^ $this->_s5[$z1];
+        $b = $this->_split($x8x9xAxB); $x8 = $b[0]; $x9 = $b[1]; $xA = $b[2]; $xB = $b[3];
+        $xCxDxExF = $zCzDzEzF ^ $this->_s5[$xA] ^ $this->_s6[$x9] ^ $this->_s7[$xB] ^ $this->_s8[$x8] ^ $this->_s6[$z3];
+        $b = $this->_split($xCxDxExF); $xC = $b[0]; $xD = $b[1]; $xE = $b[2]; $xF = $b[3];
+
+        $this->_km[13] = $this->_s5[$x8] ^ $this->_s6[$x9] ^ $this->_s7[$x7] ^ $this->_s8[$x6] ^ $this->_s5[$x3];
+        $this->_km[14] = $this->_s5[$xA] ^ $this->_s6[$xB] ^ $this->_s7[$x5] ^ $this->_s8[$x4] ^ $this->_s6[$x7];
+        $this->_km[15] = $this->_s5[$xC] ^ $this->_s6[$xD] ^ $this->_s7[$x3] ^ $this->_s8[$x2] ^ $this->_s7[$x8];
+        $this->_km[16] = $this->_s5[$xE] ^ $this->_s6[$xF] ^ $this->_s7[$x1] ^ $this->_s8[$x0] ^ $this->_s8[$xD];
+
+        $z0z1z2z3 = $x0x1x2x3 ^ $this->_s5[$xD] ^ $this->_s6[$xF] ^ $this->_s7[$xC] ^ $this->_s8[$xE] ^ $this->_s7[$x8];
+        $b = $this->_split($z0z1z2z3); $z0 = $b[0]; $z1 = $b[1]; $z2 = $b[2]; $z3 = $b[3];
+        $z4z5z6z7 = $x8x9xAxB ^ $this->_s5[$z0] ^ $this->_s6[$z2] ^ $this->_s7[$z1] ^ $this->_s8[$z3] ^ $this->_s8[$xA];
+        $b = $this->_split($z4z5z6z7); $z4 = $b[0]; $z5 = $b[1]; $z6 = $b[2]; $z7 = $b[3];
+        $z8z9zAzB = $xCxDxExF ^ $this->_s5[$z7] ^ $this->_s6[$z6] ^ $this->_s7[$z5] ^ $this->_s8[$z4] ^ $this->_s5[$x9];
+        $b = $this->_split($z8z9zAzB); $z8 = $b[0]; $z9 = $b[1]; $zA = $b[2]; $zB = $b[3];
+        $zCzDzEzF = $x4x5x6x7 ^ $this->_s5[$zA] ^ $this->_s6[$z9] ^ $this->_s7[$zB] ^ $this->_s8[$z8] ^ $this->_s6[$xB];
+        $b = $this->_split($zCzDzEzF); $zC = $b[0]; $zD = $b[1]; $zE = $b[2]; $zF = $b[3];
+
+        $this->_kr[1]  = 0x1F & ($this->_s5[$z8] ^ $this->_s6[$z9] ^ $this->_s7[$z7] ^ $this->_s8[$z6] ^ $this->_s5[$z2]);
+        $this->_kr[2]  = 0x1F & ($this->_s5[$zA] ^ $this->_s6[$zB] ^ $this->_s7[$z5] ^ $this->_s8[$z4] ^ $this->_s6[$z6]);
+        $this->_kr[3]  = 0x1F & ($this->_s5[$zC] ^ $this->_s6[$zD] ^ $this->_s7[$z3] ^ $this->_s8[$z2] ^ $this->_s7[$z9]);
+        $this->_kr[4]  = 0x1F & ($this->_s5[$zE] ^ $this->_s6[$zF] ^ $this->_s7[$z1] ^ $this->_s8[$z0] ^ $this->_s8[$zC]);
+
+        $x0x1x2x3 = $z8z9zAzB ^ $this->_s5[$z5] ^ $this->_s6[$z7] ^ $this->_s7[$z4] ^ $this->_s8[$z6] ^ $this->_s7[$z0];
+        $b = $this->_split($x0x1x2x3); $x0 = $b[0]; $x1 = $b[1]; $x2 = $b[2]; $x3 = $b[3];
+        $x4x5x6x7 = $z0z1z2z3 ^ $this->_s5[$x0] ^ $this->_s6[$x2] ^ $this->_s7[$x1] ^ $this->_s8[$x3] ^ $this->_s8[$z2];
+        $b = $this->_split($x4x5x6x7); $x4 = $b[0]; $x5 = $b[1]; $x6 = $b[2]; $x7 = $b[3];
+        $x8x9xAxB = $z4z5z6z7 ^ $this->_s5[$x7] ^ $this->_s6[$x6] ^ $this->_s7[$x5] ^ $this->_s8[$x4] ^ $this->_s5[$z1];
+        $b = $this->_split($x8x9xAxB); $x8 = $b[0]; $x9 = $b[1]; $xA = $b[2]; $xB = $b[3];
+        $xCxDxExF = $zCzDzEzF ^ $this->_s5[$xA] ^ $this->_s6[$x9] ^ $this->_s7[$xB] ^ $this->_s8[$x8] ^ $this->_s6[$z3];
+        $b = $this->_split($xCxDxExF); $xC = $b[0]; $xD = $b[1]; $xE = $b[2]; $xF = $b[3];
+
+        $this->_kr[5]  = 0x1F & ($this->_s5[$x3] ^ $this->_s6[$x2] ^ $this->_s7[$xC] ^ $this->_s8[$xD] ^ $this->_s5[$x8]);
+        $this->_kr[6]  = 0x1F & ($this->_s5[$x1] ^ $this->_s6[$x0] ^ $this->_s7[$xE] ^ $this->_s8[$xF] ^ $this->_s6[$xD]);
+        $this->_kr[7]  = 0x1F & ($this->_s5[$x7] ^ $this->_s6[$x6] ^ $this->_s7[$x8] ^ $this->_s8[$x9] ^ $this->_s7[$x3]);
+        $this->_kr[8]  = 0x1F & ($this->_s5[$x5] ^ $this->_s6[$x4] ^ $this->_s7[$xA] ^ $this->_s8[$xB] ^ $this->_s8[$x7]);
+
+        $z0z1z2z3 = $x0x1x2x3 ^ $this->_s5[$xD] ^ $this->_s6[$xF] ^ $this->_s7[$xC] ^ $this->_s8[$xE] ^ $this->_s7[$x8];
+        $b = $this->_split($z0z1z2z3); $z0 = $b[0]; $z1 = $b[1]; $z2 = $b[2]; $z3 = $b[3];
+        $z4z5z6z7 = $x8x9xAxB ^ $this->_s5[$z0] ^ $this->_s6[$z2] ^ $this->_s7[$z1] ^ $this->_s8[$z3] ^ $this->_s8[$xA];
+        $b = $this->_split($z4z5z6z7); $z4 = $b[0]; $z5 = $b[1]; $z6 = $b[2]; $z7 = $b[3];
+        $z8z9zAzB = $xCxDxExF ^ $this->_s5[$z7] ^ $this->_s6[$z6] ^ $this->_s7[$z5] ^ $this->_s8[$z4] ^ $this->_s5[$x9];
+        $b = $this->_split($z8z9zAzB); $z8 = $b[0]; $z9 = $b[1]; $zA = $b[2]; $zB = $b[3];
+        $zCzDzEzF = $x4x5x6x7 ^ $this->_s5[$zA] ^ $this->_s6[$z9] ^ $this->_s7[$zB] ^ $this->_s8[$z8] ^ $this->_s6[$xB];
+        $b = $this->_split($zCzDzEzF); $zC = $b[0]; $zD = $b[1]; $zE = $b[2]; $zF = $b[3];
+
+        $this->_kr[9]  = 0x1F & ($this->_s5[$z3] ^ $this->_s6[$z2] ^ $this->_s7[$zC] ^ $this->_s8[$zD] ^ $this->_s5[$z9]);
+        $this->_kr[10] = 0x1F & ($this->_s5[$z1] ^ $this->_s6[$z0] ^ $this->_s7[$zE] ^ $this->_s8[$zF] ^ $this->_s6[$zC]);
+        $this->_kr[11] = 0x1F & ($this->_s5[$z7] ^ $this->_s6[$z6] ^ $this->_s7[$z8] ^ $this->_s8[$z9] ^ $this->_s7[$z2]);
+        $this->_kr[12] = 0x1F & ($this->_s5[$z5] ^ $this->_s6[$z4] ^ $this->_s7[$zA] ^ $this->_s8[$zB] ^ $this->_s8[$z6]);
+
+        $x0x1x2x3 = $z8z9zAzB ^ $this->_s5[$z5] ^ $this->_s6[$z7] ^ $this->_s7[$z4] ^ $this->_s8[$z6] ^ $this->_s7[$z0];
+        $b = $this->_split($x0x1x2x3); $x0 = $b[0]; $x1 = $b[1]; $x2 = $b[2]; $x3 = $b[3];
+        $x4x5x6x7 = $z0z1z2z3 ^ $this->_s5[$x0] ^ $this->_s6[$x2] ^ $this->_s7[$x1] ^ $this->_s8[$x3] ^ $this->_s8[$z2];
+        $b = $this->_split($x4x5x6x7); $x4 = $b[0]; $x5 = $b[1]; $x6 = $b[2]; $x7 = $b[3];
+        $x8x9xAxB = $z4z5z6z7 ^ $this->_s5[$x7] ^ $this->_s6[$x6] ^ $this->_s7[$x5] ^ $this->_s8[$x4] ^ $this->_s5[$z1];
+        $b = $this->_split($x8x9xAxB); $x8 = $b[0]; $x9 = $b[1]; $xA = $b[2]; $xB = $b[3];
+        $xCxDxExF = $zCzDzEzF ^ $this->_s5[$xA] ^ $this->_s6[$x9] ^ $this->_s7[$xB] ^ $this->_s8[$x8] ^ $this->_s6[$z3];
+        $b = $this->_split($xCxDxExF); $xC = $b[0]; $xD = $b[1]; $xE = $b[2]; $xF = $b[3];
+
+        $this->_kr[13] = 0x1F & ($this->_s5[$x8] ^ $this->_s6[$x9] ^ $this->_s7[$x7] ^ $this->_s8[$x6] ^ $this->_s5[$x3]);
+        $this->_kr[14] = 0x1F & ($this->_s5[$xA] ^ $this->_s6[$xB] ^ $this->_s7[$x5] ^ $this->_s8[$x4] ^ $this->_s6[$x7]);
+        $this->_kr[15] = 0x1F & ($this->_s5[$xC] ^ $this->_s6[$xD] ^ $this->_s7[$x3] ^ $this->_s8[$x2] ^ $this->_s7[$x8]);
+        $this->_kr[16] = 0x1F & ($this->_s5[$xE] ^ $this->_s6[$xF] ^ $this->_s7[$x1] ^ $this->_s8[$x0] ^ $this->_s8[$xD]);
+    }
+
+    /**
+     * Unpack the 32 bit value into an array of four 8 bit values.
+     *
+     * @param integer $x  32 bit value.
+     *
+     * @return array  Four 8 bit values MS to LS.
+     */
+    protected function _split($x)
+    {
+        return array(($x >> 24) & 0xFF, ($x >> 16) & 0xFF, ($x >> 8) & 0xFF, $x & 0xFF);
+    }
+
+    /**
+     * Pack four 8 bit values into one 32 bit value.
+     *
+     * @param array $key      Array of 8 bit values.
+     * @param integer $start  Start position in array to get 4 values from.
+     *
+     * @return integer  32 bit value.
+     */
+    protected function _combine4($key, $start = 0)
+    {
+        $res = 0;
+
+        if (isset($key[$start])) {
+            $res |= ($key[$start]) << 24;
+        }
+        if (isset($key[$start + 1])) {
+            $res |= ($key[$start + 1]) << 16;
+        }
+        if (isset($key[$start + 2])) {
+            $res |= ($key[$start + 2]) << 8;
+        }
+        if (isset($key[$start + 3])) {
+            $res |= ($key[$start + 3]);
+        }
+
+        return $res;
+    }
+
+}
diff --git a/framework/Cipher/lib/Horde/Cipher/Des.php b/framework/Cipher/lib/Horde/Cipher/Des.php
new file mode 100644 (file)
index 0000000..8954fda
--- /dev/null
@@ -0,0 +1,419 @@
+<?php
+/**
+ * The Cipher_des:: class implements the Cipher interface encryption data
+ * using the Data Encryption Standard (DES) algorithm as defined in FIPS46-3.
+ *
+ * Copyright 2003-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Mike Cochrane <mike@graftonhall.co.nz>
+ * @package Horde_Cipher
+ */
+class Horde_Cipher_Des extends Horde_Cipher
+{
+    /**
+     * Initial Permutation.
+     *
+     * @var array
+     */
+    protected $_ip = array(
+        58, 50, 42, 34, 26, 18, 10,  2,
+        60, 52, 44, 36, 28, 20, 12,  4,
+        62, 54, 46, 38, 30, 22, 14,  6,
+        64, 56, 48, 40, 32, 24, 16,  8,
+        57, 49, 41, 33, 25, 17,  9,  1,
+        59, 51, 43, 35, 27, 19, 11,  3,
+        61, 53, 45, 37, 29, 21, 13,  5,
+        63, 55, 47, 39, 31, 23, 15,  7
+    );
+
+    /**
+     * Final Permutation IP^-1.
+     *
+     * @var array
+     */
+    protected $_fp = array(
+        40,  8, 48, 16, 56, 24, 64, 32,
+        39,  7, 47, 15, 55, 23, 63, 31,
+        38,  6, 46, 14, 54, 22, 62, 30,
+        37,  5, 45, 13, 53, 21, 61, 29,
+        36,  4, 44, 12, 52, 20, 60, 28,
+        35,  3, 43, 11, 51, 19, 59, 27,
+        34,  2, 42, 10, 50, 18, 58, 26,
+        33,  1, 41,  9, 49, 17, 57, 25
+    );
+
+    /**
+     * E Bit Selection Table.
+     *
+     * @var array
+     */
+    protected $_e = array(
+        32,  1,  2,  3,  4,  5,
+         4,  5,  6,  7,  8,  9,
+         8,  9, 10, 11, 12, 13,
+        12, 13, 14, 15, 16, 17,
+        16, 17, 18, 19, 20, 21,
+        20, 21, 22, 23, 24, 25,
+        24, 25, 26, 27, 28, 29,
+        28, 29, 30, 31, 32,  1
+    );
+
+    /**
+     * S boxes.
+     *
+     * @var array
+     */
+    protected $_s = array(
+        /* S1 */
+        1 => array(
+           14,  4, 13,  1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7,
+            0, 15,  7,  4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5,  3,  8,
+            4,  1, 14,  8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10,  5,  0,
+           15, 12,  8,  2,  4,  9,  1,  7,  5, 11,  3, 14, 10,  0,  6, 13
+        ),
+
+        /* S2 */
+        2 => array(
+           15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10,
+            3, 13,  4,  7, 15,  2,  8, 14, 12,  0,  1, 10,  6,  9, 11,  5,
+            0, 14,  7, 11, 10,  4, 13,  1,  5,  8, 12,  6,  9,  3,  2, 15,
+           13,  8, 10,  1,  3, 15,  4,  2, 11,  6,  7, 12,  0,  5, 14,  9,
+        ),
+
+        /* S3 */
+        3 => array(
+           10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8,
+           13,  7,  0,  9,  3,  4,  6, 10,  2,  8,  5, 14, 12, 11, 15,  1,
+           13,  6,  4,  9,  8, 15,  3,  0, 11,  1,  2, 12,  5, 10, 14,  7,
+            1, 10, 13,  0,  6,  9,  8,  7,  4, 15, 14,  3, 11,  5,  2, 12,
+        ),
+
+        /* S4 */
+        4 => array(
+            7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15,
+           13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14,  9,
+           10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8,  4,
+            3, 15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, 14,
+        ),
+
+        /* S5 */
+        5 => array(
+            2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9,
+           14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3,  9,  8,  6,
+            4,  2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6,  3,  0, 14,
+           11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10,  4,  5,  3,
+        ),
+
+        /* S6 */
+        6 => array(
+           12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11,
+           10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8,
+            9, 14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6,
+            4,  3,  2, 12,  9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, 13,
+        ),
+
+        /* S7 */
+        7 => array(
+            4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1,
+           13,  0, 11,  7,  4,  9,  1, 10, 14,  3,  5, 12,  2, 15,  8,  6,
+            1,  4, 11, 13, 12,  3,  7, 14, 10, 15,  6,  8,  0,  5,  9,  2,
+            6, 11, 13,  8,  1,  4, 10,  7,  9,  5,  0, 15, 14,  2,  3, 12,
+        ),
+
+        /* S8 */
+        8 => array(
+            13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7,
+             1, 15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2,
+             7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8,
+             2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11
+        )
+    );
+
+    /**
+     * Primitive function.
+     *
+     * @var array
+     */
+    protected $_p = array(
+        16,  7, 20, 21,
+        29, 12, 28, 17,
+         1, 15, 23, 26,
+         5, 18, 31, 10,
+         2,  8, 24, 14,
+        32, 27,  3,  9,
+        19, 13, 30,  6,
+        22, 11,  4, 25
+    );
+
+    /**
+     * Permuted Choice Table.
+     *
+     * @var array
+     */
+    protected $_pc1 = array(
+        57, 49, 41, 33, 25, 17,  9,
+         1, 58, 50, 42, 34, 26, 18,
+        10,  2, 59, 51, 43, 35, 27,
+        19, 11,  3, 60, 52, 44, 36,
+
+        63, 55, 47, 39, 31, 23, 15,
+         7, 62, 54, 46, 38, 30, 22,
+        14,  6, 61, 53, 45, 37, 29,
+        21, 13,  5, 28, 20, 12,  4
+    );
+
+    /**
+     * Number left rotations of pc1.
+     *
+     * @var array
+     */
+    protected $_shifts = array(
+        1, 1, 2, 2, 2, 2, 2, 2,
+        1, 2, 2, 2, 2, 2, 2, 1
+    );
+
+    /**
+     * Permuted Choice Table 2.
+     *
+     * @var array
+     */
+    protected $_pc2 = array(
+        14, 17, 11, 24,  1,  5,
+         3, 28, 15,  6, 21, 10,
+        23, 19, 12,  4, 26,  8,
+        16,  7, 27, 20, 13,  2,
+        41, 52, 31, 37, 47, 55,
+        30, 40, 51, 45, 33, 48,
+        44, 49, 39, 56, 34, 53,
+        46, 42, 50, 36, 29, 32
+    );
+
+    /**
+     * Key Schedule.
+     *
+     * @var array
+     */
+    protected $_ks = array();
+
+    /**
+     * Set the key to be used for en/decryption.
+     *
+     * @param string $key  The key to use.
+     */
+    public function setKey($key)
+    {
+        if (!is_null($key)) {
+            $this->_ks = $this->_keySchedule($key);
+        }
+    }
+
+    /**
+     * Encrypt a block of data.
+     *
+     * @param string $block  The data to encrypt.
+     * @param string $key    The key to use.
+     *
+     * @return string  The encrypted output.
+     */
+    public function encryptBlock($block, $key = null)
+    {
+        $this->setKey($key);
+
+        $block = $this->_initialPerm($block);
+
+        $L = substr($block, 0, 4);
+        $R = substr($block, 4, 4);
+
+        for ($i = 1; $i <= 16; ++$i) {
+            $R_prev = $R;
+            $L_prev = $L;
+
+            $L = $R;
+            $R = $L_prev ^ $this->_f($R_prev, $i);
+        }
+
+        $block = $R . $L;
+        $block = $this->_finalPerm($block);
+
+        return $block;
+    }
+
+    /**
+     * Decrypt a block of data.
+     *
+     * @param string $block  The data to decrypt.
+     * @param string $key    The key to use.
+     *
+     * @return string  The decrypted output.
+     */
+    public function decryptBlock($block, $key = null)
+    {
+        $block = $this->_initialPerm($block);
+
+        $this->setKey($key);
+
+        $L = substr($block, 0, 4);
+        $R = substr($block, 4, 4);
+
+        for ($i = 16; $i >= 1; --$i) {
+            $R_prev = $R;
+            $L_prev = $L;
+
+            $L = $R_prev;
+            $R = $L_prev ^ $this->_f($R_prev, $i);
+        }
+
+        $block = $R . $L;
+        $block = $this->_finalPerm($block);
+
+        return $block;
+    }
+
+    /**
+     * Put an input string through an initial permutation
+     *
+     * @param string $input  Input string.
+     *
+     * @return string  Permutated string.
+     */
+    protected function _initialPerm($input)
+    {
+        // TODO: Some stylie bitwise thing instead.
+
+        $input_bin = $output = $output_bin = '';
+
+        for ($i = 0; $i < 8; ++$i) {
+            $input_bin .= str_pad(decbin(ord($input[$i])), 8, '0', STR_PAD_LEFT);
+        }
+
+        foreach ($this->_ip as $offset) {
+            $output_bin .= $input_bin[$offset - 1];
+        }
+
+        for ($i = 0; $i < 8; $i++) {
+            $output .= chr(bindec(substr($output_bin, 8 * $i, 8)));
+        }
+
+        return $output;
+    }
+
+    /**
+     * Put an input string through a final permutation.
+     *
+     * @param string $input  Input string.
+     *
+     * @return string  Permutated string.
+     */
+    protected function _finalPerm($input)
+    {
+        // TODO: Some stylie bitwise thing instead.
+
+        $input_bin = $output = $output_bin = '';
+
+        for ($i = 0; $i < 8; ++$i) {
+            $input_bin .= str_pad(decbin(ord($input[$i])), 8, '0', STR_PAD_LEFT);
+        }
+
+        foreach ($this->_fp as $offset) {
+            $output_bin .= $input_bin[$offset - 1];
+        }
+
+        for ($i = 0; $i < 8; ++$i) {
+            $output .= chr(bindec(substr($output_bin, 8 * $i, 8)));
+        }
+
+        return $output;
+    }
+
+
+    /**
+     * The permutation function.
+     *
+     * @param string $input   Input string.
+     * @param integer $round  The round.
+     *
+     * @return string  The output string.
+     */
+    protected function _f($input, $round)
+    {
+        // TODO: Some stylie bitwise thing instead.
+        $key = $this->_ks[$round];
+
+        $combined_bin = $expanded_bin = $input_bin = $output_bin = $output = '';
+        $expanded = array();
+
+        for ($i = 0; $i < 4; ++$i) {
+            $input_bin .= str_pad(decbin(ord($input[$i])), 8, '0', STR_PAD_LEFT);
+        }
+
+        foreach ($this->_e as $offset) {
+            $expanded_bin .= $input_bin[$offset - 1];
+        }
+
+        for ($i = 0; $i < 8; ++$i) {
+            $expanded[$i] = bindec('00' . substr($expanded_bin, $i * 6, 6)) ^ $key[$i];
+        }
+
+        for ($i = 0; $i < 8; ++$i) {
+            $s_index = (($expanded[$i] & 0x20) >> 4) | ($expanded[$i] & 0x01);
+            $s_index = 16 * $s_index + (($expanded[$i] & 0x1E) >> 1);
+            $val = $this->_s[$i + 1][$s_index];
+            $combined_bin .= str_pad(decbin($val), 4, '0', STR_PAD_LEFT);
+        }
+
+        foreach ($this->_p as $offset) {
+            $output_bin .= $combined_bin[$offset - 1];
+        }
+
+        for ($i = 0; $i < 4; ++$i) {
+            $output .= chr(bindec(substr($output_bin, $i * 8, 8)));
+        }
+
+        return $output;
+    }
+
+    /**
+     * Create the complete key schedule.
+     *
+     * @param string $key  The key to use.
+     *
+     * @return array  Key schedule.
+     */
+    protected function _keySchedule($key)
+    {
+        $key = str_pad($key, 8, "\0");
+        $c = $d = $key_bin = '';
+        $ks = array();
+
+        for ($i = 0; $i < 8; ++$i) {
+            $key_bin .= str_pad(decbin(ord($key[$i])), 8, '0', STR_PAD_LEFT);
+        }
+
+        for ($i = 0; $i < 28; ++$i) {
+            $c .= $key_bin[$this->_pc1[$i] - 1];
+            $d .= $key_bin[$this->_pc1[28 + $i] - 1];
+        }
+
+        for ($i = 0; $i < 16; ++$i) {
+            $c = substr($c, $this->_shifts[$i]) . substr($c, 0, $this->_shifts[$i]);
+            $d = substr($d, $this->_shifts[$i]) . substr($d, 0, $this->_shifts[$i]);
+
+            $cd = $c . $d;
+
+            $permutated_bin = '';
+            foreach ($this->_pc2 as $offset) {
+                $permutated_bin .= $cd[$offset - 1];
+            }
+
+            for ($j = 0; $j < 8; $j++) {
+                $ks[$i + 1][] = bindec('00' . substr($permutated_bin, $j * 6, 6));
+            }
+        }
+
+        return $ks;
+    }
+
+}
diff --git a/framework/Cipher/lib/Horde/Cipher/Rc2.php b/framework/Cipher/lib/Horde/Cipher/Rc2.php
new file mode 100644 (file)
index 0000000..34fc1fe
--- /dev/null
@@ -0,0 +1,181 @@
+<?php
+/**
+ * The Horde_Cipher_Rc2:: class implements the Cipher interface encryption
+ * data using the RC2 algorithm as described in RFC2268.
+ *
+ * Based on the notes by Peter Gutmann <pgut01@cs.auckland.ac.nz>
+ * http://www.mirrors.wiretapped.net/security/cryptography/
+ *   algorithms/rc2/comments/gutman-960211
+ *
+ * Copyright 2002-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Mike Cochrane <mike@graftonhall.co.nz>
+ * @package Horde_Cipher
+ */
+class Horde_Cipher_Rc2 extends Horde_Cipher
+{
+    /**
+     * Permutations array.
+     *
+     * @var array
+     */
+    protected $_perm = array(
+        0xD9, 0x78, 0xF9, 0xC4, 0x19, 0xDD, 0xB5, 0xED, 0x28, 0xE9, 0xFD,
+        0x79, 0x4A, 0xA0, 0xD8, 0x9D, 0xC6, 0x7E, 0x37, 0x83, 0x2B, 0x76,
+        0x53, 0x8E, 0x62, 0x4C, 0x64, 0x88, 0x44, 0x8B, 0xFB, 0xA2, 0x17,
+        0x9A, 0x59, 0xF5, 0x87, 0xB3, 0x4F, 0x13, 0x61, 0x45, 0x6D, 0x8D,
+        0x09, 0x81, 0x7D, 0x32, 0xBD, 0x8F, 0x40, 0xEB, 0x86, 0xB7, 0x7B,
+        0x0B, 0xF0, 0x95, 0x21, 0x22, 0x5C, 0x6B, 0x4E, 0x82, 0x54, 0xD6,
+        0x65, 0x93, 0xCE, 0x60, 0xB2, 0x1C, 0x73, 0x56, 0xC0, 0x14, 0xA7,
+        0x8C, 0xF1, 0xDC, 0x12, 0x75, 0xCA, 0x1F, 0x3B, 0xBE, 0xE4, 0xD1,
+        0x42, 0x3D, 0xD4, 0x30, 0xA3, 0x3C, 0xB6, 0x26, 0x6F, 0xBF, 0x0E,
+        0xDA, 0x46, 0x69, 0x07, 0x57, 0x27, 0xF2, 0x1D, 0x9B, 0xBC, 0x94,
+        0x43, 0x03, 0xF8, 0x11, 0xC7, 0xF6, 0x90, 0xEF, 0x3E, 0xE7, 0x06,
+        0xC3, 0xD5, 0x2F, 0xC8, 0x66, 0x1E, 0xD7, 0x08, 0xE8, 0xEA, 0xDE,
+        0x80, 0x52, 0xEE, 0xF7, 0x84, 0xAA, 0x72, 0xAC, 0x35, 0x4D, 0x6A,
+        0x2A, 0x96, 0x1A, 0xD2, 0x71, 0x5A, 0x15, 0x49, 0x74, 0x4B, 0x9F,
+        0xD0, 0x5E, 0x04, 0x18, 0xA4, 0xEC, 0xC2, 0xE0, 0x41, 0x6E, 0x0F,
+        0x51, 0xCB, 0xCC, 0x24, 0x91, 0xAF, 0x50, 0xA1, 0xF4, 0x70, 0x39,
+        0x99, 0x7C, 0x3A, 0x85, 0x23, 0xB8, 0xB4, 0x7A, 0xFC, 0x02, 0x36,
+        0x5B, 0x25, 0x55, 0x97, 0x31, 0x2D, 0x5D, 0xFA, 0x98, 0xE3, 0x8A,
+        0x92, 0xAE, 0x05, 0xDF, 0x29, 0x10, 0x67, 0x6C, 0xBA, 0xC9, 0xD3,
+        0x00, 0xE6, 0xCF, 0xE1, 0x9E, 0xA8, 0x2C, 0x63, 0x16, 0x01, 0x3F,
+        0x58, 0xE2, 0x89, 0xA9, 0x0D, 0x38, 0x34, 0x1B, 0xAB, 0x33, 0xFF,
+        0xB0, 0xBB, 0x48, 0x0C, 0x5F, 0xB9, 0xB1, 0xCD, 0x2E, 0xC5, 0xF3,
+        0xDB, 0x47, 0xE5, 0xA5, 0x9C, 0x77, 0x0A, 0xA6, 0x20, 0x68, 0xFE,
+        0x7F, 0xC1, 0xAD
+    );
+
+    /**
+     * Array to hold the key schedule.
+     *
+     * @var array
+     */
+    protected $_keySchedule = array();
+
+    /**
+     * Set the key to be used for en/decryption.
+     *
+     * @param string $key  The key to use.
+     */
+    public function setKey($key)
+    {
+        $key = array_values(unpack('C*', $key));
+        $bits = 1024;
+
+        /* Expand input key to 128 bytes */
+        $len = count($key);
+        $last = $key[$len - 1];
+        for ($i = $len; $i < 128; ++$i) {
+            $last = $this->_perm[($key[$i - $len] + $last) & 0xFF];
+            $key[$i] = $last;
+        }
+
+        /* Phase 2 - reduce effective key size to "bits" */
+        if ($len != 8) {
+            $len = $len * 8;
+        }
+        $key[128 - $len] = $this->_perm[$key[128 - $len] & 0xFF];
+        for ($i = 127 - $len; $i >= 0; --$i) {
+            $key[$i] = $this->_perm[$key[$i + $len] ^ $key[$i + 1]];
+        }
+
+        /* Phase 3 - convert to 16 bit values */
+        for ($i = 63; $i >= 0; --$i) {
+            $this->_keySchedule[$i] = ($key[$i * 2 + 1] << 8 | $key[$i * 2]) & 0xFFFF;
+        }
+    }
+
+    /**
+     * Encrypt a block of data.
+     *
+     * @param string $block  The data to encrypt.
+     * @param string $key    The key to use.
+     *
+     * @return string  The encrypted output.
+     */
+    public function encryptBlock($block, $key = null)
+    {
+        if (!is_null($key)) {
+            $this->setKey($key);
+        }
+
+        $plain = unpack('v*', $block);
+
+        for ($i = 0; $i < 16; ++$i) {
+            $plain[1] += ($plain[2] & ~$plain[4]) + ($plain[3] & $plain[4]) + $this->_keySchedule[4 * $i + 0];
+            $bin = str_pad(decbin(0xFFFF & $plain[1]), 32, '0', STR_PAD_LEFT);
+            $plain[1] = bindec($bin . substr($bin, 16, 1));
+
+            $plain[2] += ($plain[3] & ~$plain[1]) + ($plain[4] & $plain[1]) + $this->_keySchedule[4 * $i + 1];
+            $bin = str_pad(decbin(0xFFFF & $plain[2]), 32, '0', STR_PAD_LEFT);
+            $plain[2] = bindec($bin . substr($bin, 16, 2));
+
+            $plain[3] += ($plain[4] & ~$plain[2]) + ($plain[1] & $plain[2]) + $this->_keySchedule[4 * $i + 2];
+            $bin = str_pad(decbin(0xFFFF & $plain[3]), 16, '0', STR_PAD_LEFT);
+            $plain[3] = bindec($bin . substr($bin, 0, 3));
+
+            $plain[4] += ($plain[1] & ~$plain[3]) + ($plain[2] & $plain[3]) + $this->_keySchedule[4 * $i + 3];
+            $bin = str_pad(decbin(0xFFFF & $plain[4]), 16, '0', STR_PAD_LEFT);
+            $plain[4] = bindec($bin . substr($bin, 0, 5));
+
+            if ($i == 4 || $i == 10) {
+                $plain[1] += $this->_keySchedule[$plain[4] & 0x3F];
+                $plain[2] += $this->_keySchedule[$plain[1] & 0x3F];
+                $plain[3] += $this->_keySchedule[$plain[2] & 0x3F];
+                $plain[4] += $this->_keySchedule[$plain[3] & 0x3F];
+            }
+
+        }
+
+        return pack("v*", $plain[1], $plain[2], $plain[3], $plain[4]);
+    }
+
+    /**
+     * Decrypt a block of data.
+     *
+     * @param string $block  The data to decrypt.
+     * @param string $key    The key to use.
+     *
+     * @return string  The decrypted output.
+     */
+    public function decryptBlock($block, $key = null)
+    {
+        if (!is_null($key)) {
+            $this->setKey($key);
+        }
+
+        $cipher = unpack('v*', $block);
+
+        for ($i = 15; $i >= 0; --$i) {
+            $bin = str_pad(decbin(0xFFFF & $cipher[4]), 16, '0', STR_PAD_LEFT);
+            $cipher[4] = bindec(substr($bin, -21, 21) . substr($bin, 0, 11));
+            $cipher[4] -= ($cipher[1] & ~$cipher[3]) + ($cipher[2] & $cipher[3]) + $this->_keySchedule[4 * $i + 3];
+
+            $bin = str_pad(decbin(0xFFFF & $cipher[3]), 16, '0', STR_PAD_LEFT);
+            $cipher[3] = bindec(substr($bin, -19, 19) . substr($bin, 0, 13));
+            $cipher[3] -= ($cipher[4] & ~$cipher[2]) + ($cipher[1] & $cipher[2]) + $this->_keySchedule[4 * $i + 2];
+
+            $bin = str_pad(decbin(0xFFFF & $cipher[2]), 16, '0', STR_PAD_LEFT);
+            $cipher[2] = bindec(substr($bin, -18, 18) . substr($bin, 0, 14));
+            $cipher[2] -= ($cipher[3] & ~$cipher[1]) + ($cipher[4] & $cipher[1]) + $this->_keySchedule[4 * $i + 1];
+
+            $bin = str_pad(decbin(0xFFFF & $cipher[1]), 16, '0', STR_PAD_LEFT);
+            $cipher[1] = bindec(substr($bin, -17, 17) . substr($bin, 0, 15));
+            $cipher[1] -= ($cipher[2] & ~$cipher[4]) + ($cipher[3] & $cipher[4]) + $this->_keySchedule[4 * $i + 0];
+
+            if ($i == 5 || $i == 11) {
+                $cipher[4] -= $this->_keySchedule[$cipher[3] & 0x3F];
+                $cipher[3] -= $this->_keySchedule[$cipher[2] & 0x3F];
+                $cipher[2] -= $this->_keySchedule[$cipher[1] & 0x3F];
+                $cipher[1] -= $this->_keySchedule[$cipher[4] & 0x3F];
+            }
+        }
+
+        return pack("v*", $cipher[1], $cipher[2], $cipher[3], $cipher[4]);
+    }
+
+}
diff --git a/framework/Cipher/lib/Horde/Cipher/Rc4.php b/framework/Cipher/lib/Horde/Cipher/Rc4.php
new file mode 100644 (file)
index 0000000..308895c
--- /dev/null
@@ -0,0 +1,85 @@
+<?php
+/**
+ * The Horde_Cipher_Rc4:: class implements the Horde_Cipher interface
+ * encryption data using the RC4 encryption algorthim. This class uses the
+ * PEAR Crypt_RC4 class to do the encryption.
+ *
+ * Copyright 2002-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Mike Cochrane <mike@graftonhall.co.nz>
+ * @package Horde_Cipher
+ */
+class Horde_Cipher_Rc4 extends Horde_Cipher
+{
+    /**
+     * Pointer to a PEAR Crypt_RC4 object
+     *
+     * @var Crypt_RC4
+     */
+    protected $_cipher;
+
+    /**
+     * Constructor.
+     */
+    public function __construct($params = null)
+    {
+        $this->_cipher = new Crypt_Rc4();
+    }
+
+    /**
+     * Set the key to be used for en/decryption.
+     *
+     * @param string $key  The key to use.
+     */
+    public function setKey($key)
+    {
+        $this->_cipher->setKey($key);
+    }
+
+    /**
+     * Encrypt a block of data.
+     *
+     * @param string $block  The data to encrypt.
+     * @param string $key    The key to use.
+     *
+     * @return string  The encrypted output.
+     */
+    public function encryptBlock($block, $key = null)
+    {
+        if (!is_null($key)) {
+            $this->setKey($key);
+        }
+
+        // Make a copy of the cipher as it destroys itself during a crypt
+        $cipher = $this->_cipher;
+        $cipher->crypt($block);
+
+        return $block;
+    }
+
+    /**
+     * Decrypt a block of data.
+     *
+     * @param string $block  The data to decrypt.
+     * @param string $key    The key to use.
+     *
+     * @return string  The decrypted output.
+     */
+    public function decryptBlock($block, $key = null)
+    {
+        if (!is_null($key)) {
+            $this->setKey($key);
+        }
+
+        // Make a copy of the cipher as it destroys itself during a
+        // crypt.
+        $cipher = $this->_cipher;
+        $cipher->decrypt($block);
+
+        return $block;
+    }
+
+}
diff --git a/framework/Cipher/package.xml b/framework/Cipher/package.xml
new file mode 100644 (file)
index 0000000..ba48475
--- /dev/null
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<package packagerversion="1.4.9" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
+http://pear.php.net/dtd/tasks-1.0.xsd
+http://pear.php.net/dtd/package-2.0
+http://pear.php.net/dtd/package-2.0.xsd">
+ <name>Horde_Cipher</name>
+ <channel>pear.horde.org</channel>
+ <summary>Cipher API</summary>
+ <description>This package provides a Block Mode Cipher API, supporting the following ciphers:
+* Blowfish
+* Cast128
+* DES
+* RC2
+* RC4
+
+And supporting the following block modes:
+* CBC
+* ECB
+* CFB64
+* OFB64
+ </description>
+ <lead>
+  <name>Chuck Hagenbuch</name>
+  <user>chuck</user>
+  <email>chuck@horde.org</email>
+  <active>yes</active>
+ </lead>
+ <lead>
+  <name>Jan Schneider</name>
+  <user>jan</user>
+  <email>jan@horde.org</email>
+  <active>yes</active>
+ </lead>
+ <date>2009-07-05</date>
+ <version>
+  <release>0.1.0</release>
+  <api>0.1.0</api>
+ </version>
+ <stability>
+  <release>beta</release>
+  <api>beta</api>
+ </stability>
+ <license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
+ <notes>* Initial Horde 4 Package.
+ </notes>
+ <contents>
+  <dir name="/">
+   <dir name="lib">
+    <dir name="Horde">
+     <dir name="Cipher">
+      <dir name="BlockMode">
+       <file name="Cbc.php" role="php" />
+       <file name="Cfb64.php" role="php" />
+       <file name="Ecb.php" role="php" />
+       <file name="Ofb64.php" role="php" />
+      </dir> <!-- /lib/Horde/Cipher/BlockMode -->
+      <file name="BlockMode.php" role="php" />
+      <file name="Blowfish.php" role="php" />
+      <file name="Cast128.php" role="php" />
+      <file name="Des.php" role="php" />
+      <file name="Rc2.php" role="php" />
+      <file name="Rc4.php" role="php" />
+     </dir> <!-- /lib/Horde/Cipher -->
+     <file name="Cipher.php" role="php" />
+    </dir> <!-- /lib/Horde -->
+   </dir> <!-- /lib -->
+   <dir name="test">
+    <dir name="Horde">
+     <dir name="Cipher">
+      <file name="Cipher1.phpt" role="test" />
+      <file name="Cipher2.phpt" role="test" />
+      <file name="Cipher3.phpt" role="test" />
+      <file name="Cipher4.phpt" role="test" />
+      <file name="Cipher5.phpt" role="test" />
+      <file name="Cipher6.phpt" role="test" />
+      <file name="cipher_functions.php" role="php" />
+     </dir> <!-- /test/Horde/Cipher -->
+    </dir> <!-- /test/Horde -->
+   </dir> <!-- /test -->
+  </dir> <!-- / -->
+ </contents>
+ <dependencies>
+  <required>
+   <php>
+    <min>5.2.0</min>
+   </php>
+   <pearinstaller>
+    <min>1.5.4</min>
+   </pearinstaller>
+  </required>
+ </dependencies>
+ <phprelease>
+  <filelist>
+   <install name="/lib/Horde/Cipher/BlockMode/Cbc.php" as="Horde/Cipher/BlockMode/Cbc.php" />
+   <install name="/lib/Horde/Cipher/BlockMode/Cfb64.php" as="Horde/Cipher/BlockMode/Cfb64.php" />
+   <install name="/lib/Horde/Cipher/BlockMode/Ecb.php" as="Horde/Cipher/BlockMode/Ecb.php" />
+   <install name="/lib/Horde/Cipher/BlockMode/Ofb64.php" as="Horde/Cipher/BlockMode/Ofb64.php" />
+   <install name="/lib/Horde/Cipher/BlockMode.php" as="Horde/Cipher/BlockMode.php" />
+   <install name="/lib/Horde/Cipher/Blowfish.php" as="Horde/Cipher/Blowfish.php" />
+   <install name="/lib/Horde/Cipher/Cast128.php" as="Horde/Cipher/Cast128.php" />
+   <install name="/lib/Horde/Cipher/Des.php" as="Horde/Cipher/Des.php" />
+   <install name="/lib/Horde/Cipher/Rc2.php" as="Horde/Cipher/Rc2.php" />
+   <install name="/lib/Horde/Cipher/Rc4.php" as="Horde/Cipher/Rc4.php" />
+   <install name="/lib/Horde/Cipher.php" as="Horde/Cipher.php" />
+  </filelist>
+ </phprelease>
+ <changelog>
+  <release>
+   <date>2006-05-08</date>
+   <time>18:16:29</time>
+   <version>
+    <release>0.0.2</release>
+    <api>0.0.2</api>
+   </version>
+   <stability>
+    <release>alpha</release>
+    <api>alpha</api>
+   </stability>
+   <license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
+   <notes>Converted to package.xml 2.0 for pear.horde.org
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>0.0.1</release>
+    <api>0.0.1</api>
+   </version>
+   <stability>
+    <release>alpha</release>
+    <api>alpha</api>
+   </stability>
+   <date>2003-07-03</date>
+   <license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
+   <notes>Initial release as a PEAR package
+   </notes>
+  </release>
+ </changelog>
+</package>
diff --git a/framework/Cipher/test/Horde/Cipher/Cipher1.phpt b/framework/Cipher/test/Horde/Cipher/Cipher1.phpt
new file mode 100644 (file)
index 0000000..9f1588e
--- /dev/null
@@ -0,0 +1,66 @@
+--TEST--
+RC4 Horde_Cipher:: Tests
+--SKIPIF--
+<?php
+    $rc4 = @include_once 'Crypt/Rc4.php';
+    if (!$rc4) echo 'skip Crypt_Rc4 pear module not available';
+?>
+--FILE--
+<?php
+
+require_once dirname(__FILE__) . '/cipher_functions.php';
+require_once dirname(__FILE__) . '/../../../lib/Horde/Cipher.php';
+require_once dirname(__FILE__) . '/../../../lib/Horde/Cipher/Rc4.php';
+
+/* RC4 Cipher */
+echo "RC4:\n";
+echo "----\n\n";
+
+// 64 Bit key test
+echo "64-bit Key\n";
+$key = "\x01\x23\x45\x67\x89\xab\xcd\xef";
+$plaintext = "\x01\x23\x45\x67\x89\xab\xcd\xef";
+$ciphertext = "\x75\xb7\x87\x80\x99\xe0\xc5\x96";
+testCipher('rc4', $key, $plaintext, $ciphertext);
+
+// 64 Bit key test
+echo "64-bit Key\n";
+$key = "\x01\x23\x45\x67\x89\xab\xcd\xef";
+$plaintext = "\x00\x00\x00\x00\x00\x00\x00\x00";
+$ciphertext = "\x74\x94\xc2\xe7\x10\x4b\x08\x79";
+testCipher('rc4', $key, $plaintext, $ciphertext);
+
+// 64 Bit key test
+echo "64-bit Key\n";
+$key = "\x00\x00\x00\x00\x00\x00\x00\x00";
+$plaintext = "\x00\x00\x00\x00\x00\x00\x00\x00";
+$ciphertext = "\xde\x18\x89\x41\xa3\x37\x5d\x3a";
+testCipher('rc4', $key, $plaintext, $ciphertext);
+
+// 32 Bit key test
+echo "32-bit Key\n";
+$key = "\xef\x01\x23\x45";
+$plaintext = "\x00\x00\x00\x00\x00\x00\x00\x00";
+$ciphertext = "\xd6\xa1\x41\xa7\xec\x3c\x38\xdf";
+testCipher('rc4', $key, $plaintext, $ciphertext);
+
+?>
+--EXPECT--
+RC4:
+----
+
+64-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+64-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+64-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+32-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
diff --git a/framework/Cipher/test/Horde/Cipher/Cipher2.phpt b/framework/Cipher/test/Horde/Cipher/Cipher2.phpt
new file mode 100644 (file)
index 0000000..965275d
--- /dev/null
@@ -0,0 +1,87 @@
+--TEST--
+DES Horde_Cipher:: Tests
+--FILE--
+<?php
+
+require_once dirname(__FILE__) . '/cipher_functions.php';
+require_once dirname(__FILE__) . '/../../../lib/Horde/Cipher.php';
+require_once dirname(__FILE__) . '/../../../lib/Horde/Cipher/Des.php';
+
+/* DES Cipher */
+echo "DES:\n";
+echo "----\n\n";
+
+// 64 Bit key test
+$tests = array(
+    "\x00\x00\x00\x00\x00\x00\x00\x00", "\x00\x00\x00\x00\x00\x00\x00\x00", "\x8C\xA6\x4D\xE9\xC1\xB1\x23\xA7",
+    "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", "\x73\x59\xB2\x16\x3E\x4E\xDC\x58",
+    "\x30\x00\x00\x00\x00\x00\x00\x00", "\x10\x00\x00\x00\x00\x00\x00\x01", "\x95\x8E\x6E\x62\x7A\x05\x55\x7B",
+    "\x01\x23\x45\x67\x89\xAB\xCD\xEF", "\x11\x11\x11\x11\x11\x11\x11\x11", "\x17\x66\x8D\xFC\x72\x92\x53\x2D",
+    "\x11\x11\x11\x11\x11\x11\x11\x11", "\x01\x23\x45\x67\x89\xAB\xCD\xEF", "\x8A\x5A\xE1\xF8\x1A\xB8\xF2\xDD",
+
+    // Initial Permutation and Expansion test
+    "\x01\x01\x01\x01\x01\x01\x01\x01", "\x95\xF8\xA5\xE5\xDD\x31\xD9\x00", "\x80\x00\x00\x00\x00\x00\x00\x00",
+
+    // Key Permutation test
+    "\x80\x01\x01\x01\x01\x01\x01\x01", "\x00\x00\x00\x00\x00\x00\x00\x00", "\x95\xA8\xD7\x28\x13\xDA\xA9\x4D",
+
+    // Data Permutation tests
+    "\x10\x46\x91\x34\x89\x98\x01\x31", "\x00\x00\x00\x00\x00\x00\x00\x00", "\x88\xD5\x5E\x54\xF5\x4C\x97\xB4",
+
+    // S-Box test
+    "\x7C\xA1\x10\x45\x4A\x1A\x6E\x57", "\x01\xA1\xD6\xD0\x39\x77\x67\x42", "\x69\x0F\x5B\x0D\x9A\x26\x93\x9B",
+    "\x01\x31\xD9\x61\x9D\xC1\x37\x6E", "\x5C\xD5\x4C\xA8\x3D\xEF\x57\xDA", "\x7A\x38\x9D\x10\x35\x4B\xD2\x71",
+ );
+
+for ($i = 0; $i < count($tests); $i+= 3) {
+    echo "64-bit Key\n";
+    $key = $tests[$i];
+    $plaintext = $tests[$i + 1];
+    $ciphertext = $tests[$i + 2];
+    testCipher('des', $key, $plaintext, $ciphertext);
+}
+
+?>
+--EXPECT--
+DES:
+----
+
+64-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+64-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+64-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+64-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+64-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+64-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+64-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+64-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+64-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+64-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
diff --git a/framework/Cipher/test/Horde/Cipher/Cipher3.phpt b/framework/Cipher/test/Horde/Cipher/Cipher3.phpt
new file mode 100644 (file)
index 0000000..20c9062
--- /dev/null
@@ -0,0 +1,62 @@
+--TEST--
+RC2 Horde_Cipher:: Tests
+--FILE--
+<?php
+
+require_once dirname(__FILE__) . '/cipher_functions.php';
+require_once dirname(__FILE__) . '/../../../lib/Horde/Cipher.php';
+require_once dirname(__FILE__) . '/../../../lib/Horde/Cipher/Rc2.php';
+
+/* RC2 Cipher */
+echo "RC2:\n";
+echo "----\n\n";
+
+// 8 Bit key test
+echo "8-bit Key\n";
+$key = "\x88";
+$plaintext = "\x00\x00\x00\x00\x00\x00\x00\x00";
+$ciphertext = "\x61\xa8\xa2\x44\xad\xac\xcc\xf0";
+testCipher('rc2', $key, $plaintext, $ciphertext);
+
+// 64 Bit key test
+echo "64-bit Key\n";
+$key = "\x00\x00\x00\x00\x00\x00\x00\x00";
+$plaintext = "\x00\x00\x00\x00\x00\x00\x00\x00";
+$ciphertext = "\xeb\xb7\x73\xf9\x93\x27\x8e\xff";
+testCipher('rc2', $key, $plaintext, $ciphertext);
+
+// 128 Bit key test
+echo "128-bit Key\n";
+$key = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F";
+$plaintext = "\x00\x00\x00\x00\x00\x00\x00\x00";
+$ciphertext = "\x50\xDC\x01\x62\xBD\x75\x7F\x31";
+testCipher('rc2', $key, $plaintext, $ciphertext);
+
+// 64 Bit key test
+echo "64-bit Key\n";
+$key = "\xff\xff\xff\xff\xff\xff\xff\xff";
+$plaintext = "\xff\xff\xff\xff\xff\xff\xff\xff";
+$ciphertext = "\x27\x8b\x27\xe4\x2e\x2f\x0d\x49";
+testCipher('rc2', $key, $plaintext, $ciphertext);
+
+?>
+--EXPECT--
+RC2:
+----
+
+8-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+64-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+128-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+64-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
diff --git a/framework/Cipher/test/Horde/Cipher/Cipher4.phpt b/framework/Cipher/test/Horde/Cipher/Cipher4.phpt
new file mode 100644 (file)
index 0000000..5e8f934
--- /dev/null
@@ -0,0 +1,50 @@
+--TEST--
+Cast128 Horde_Cipher:: Tests
+--FILE--
+<?php
+
+require_once dirname(__FILE__) . '/cipher_functions.php';
+require_once dirname(__FILE__) . '/../../../lib/Horde/Cipher.php';
+require_once dirname(__FILE__) . '/../../../lib/Horde/Cipher/Cast128.php';
+
+/* Cast 128 Cipher */
+echo "Cast 128:\n";
+echo "---------\n\n";
+
+// 128 Bit key test
+echo "128-bit Key\n";
+$key = "\x01\x23\x45\x67\x12\x34\x56\x78\x23\x45\x67\x89\x34\x56\x78\x9A";
+$plaintext = "\x01\x23\x45\x67\x89\xAB\xCD\xEF";
+$ciphertext = "\x23\x8B\x4F\xE5\x84\x7E\x44\xB2";
+testCipher('cast128', $key, $plaintext, $ciphertext);
+
+// 80 Bit key text
+echo "80-bit Key\n";
+$key = "\x01\x23\x45\x67\x12\x34\x56\x78\x23\x45";
+$plaintext = "\x01\x23\x45\x67\x89\xAB\xCD\xEF";
+$ciphertext = "\xEB\x6A\x71\x1A\x2C\x02\x27\x1B";
+testCipher('cast128', $key, $plaintext, $ciphertext);
+
+// 40 Bit key text
+echo "40-bit Key\n";
+$key = "\x01\x23\x45\x67\x12";
+$plaintext = "\x01\x23\x45\x67\x89\xAB\xCD\xEF";
+$ciphertext = "\x7A\xC8\x16\xD1\x6E\x9B\x30\x2E";
+testCipher('cast128', $key, $plaintext, $ciphertext);
+
+?>
+--EXPECT--
+Cast 128:
+---------
+
+128-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+80-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+40-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
diff --git a/framework/Cipher/test/Horde/Cipher/Cipher5.phpt b/framework/Cipher/test/Horde/Cipher/Cipher5.phpt
new file mode 100644 (file)
index 0000000..e3a2eb8
--- /dev/null
@@ -0,0 +1,155 @@
+--TEST--
+Blowfish Cipher:: Tests
+--FILE--
+<?php
+
+require_once dirname(__FILE__) . '/cipher_functions.php';
+require_once dirname(__FILE__) . '/../../../lib/Horde/Cipher.php';
+require_once dirname(__FILE__) . '/../../../lib/Horde/Cipher/Blowfish.php';
+
+/* Blowfish */
+// selection of tests from: http://www.counterpane.com/vectors.txt
+echo "Blowfish:\n";
+echo "---------\n\n";
+
+// 64 Bit key text
+echo "64-bit Key\n";
+$key = "\x49\xE9\x5D\x6D\x4C\xA2\x29\xBF";
+$plaintext = "\x02\xFE\x55\x77\x81\x17\xF1\x2A";
+$ciphertext = "\xCF\x9C\x5D\x7A\x49\x86\xAD\xB5";
+testCipher('blowfish', $key, $plaintext, $ciphertext);
+
+$plaintext = "\xFE\xDC\xBA\x98\x76\x54\x32\x10";
+$c[ 1] = "\xF9\xAD\x59\x7C\x49\xDB\x00\x5E"; $k[ 1] = "\xF0";
+$c[ 2] = "\xE9\x1D\x21\xC1\xD9\x61\xA6\xD6"; $k[ 2] = "\xF0\xE1";
+$c[ 3] = "\xE9\xC2\xB7\x0A\x1B\xC6\x5C\xF3"; $k[ 3] = "\xF0\xE1\xD2";
+$c[ 4] = "\xBE\x1E\x63\x94\x08\x64\x0F\x05"; $k[ 4] = "\xF0\xE1\xD2\xC3";
+$c[ 5] = "\xB3\x9E\x44\x48\x1B\xDB\x1E\x6E"; $k[ 5] = "\xF0\xE1\xD2\xC3\xB4";
+$c[ 6] = "\x94\x57\xAA\x83\xB1\x92\x8C\x0D"; $k[ 6] = "\xF0\xE1\xD2\xC3\xB4\xA5";
+$c[ 7] = "\x8B\xB7\x70\x32\xF9\x60\x62\x9D"; $k[ 7] = "\xF0\xE1\xD2\xC3\xB4\xA5\x96";
+$c[ 8] = "\xE8\x7A\x24\x4E\x2C\xC8\x5E\x82"; $k[ 8] = "\xF0\xE1\xD2\xC3\xB4\xA5\x96\x87";
+$c[ 9] = "\x15\x75\x0E\x7A\x4F\x4E\xC5\x77"; $k[ 9] = "\xF0\xE1\xD2\xC3\xB4\xA5\x96\x87\x78";
+$c[10] = "\x12\x2B\xA7\x0B\x3A\xB6\x4A\xE0"; $k[10] = "\xF0\xE1\xD2\xC3\xB4\xA5\x96\x87\x78\x69";
+$c[11] = "\x3A\x83\x3C\x9A\xFF\xC5\x37\xF6"; $k[11] = "\xF0\xE1\xD2\xC3\xB4\xA5\x96\x87\x78\x69\x5A";
+$c[12] = "\x94\x09\xDA\x87\xA9\x0F\x6B\xF2"; $k[12] = "\xF0\xE1\xD2\xC3\xB4\xA5\x96\x87\x78\x69\x5A\x4B";
+$c[13] = "\x88\x4F\x80\x62\x50\x60\xB8\xB4"; $k[13] = "\xF0\xE1\xD2\xC3\xB4\xA5\x96\x87\x78\x69\x5A\x4B\x3C";
+$c[14] = "\x1F\x85\x03\x1C\x19\xE1\x19\x68"; $k[14] = "\xF0\xE1\xD2\xC3\xB4\xA5\x96\x87\x78\x69\x5A\x4B\x3C\x2D";
+$c[15] = "\x79\xD9\x37\x3A\x71\x4C\xA3\x4F"; $k[15] = "\xF0\xE1\xD2\xC3\xB4\xA5\x96\x87\x78\x69\x5A\x4B\x3C\x2D\x1E";
+$c[16] = "\x93\x14\x28\x87\xEE\x3B\xE1\x5C"; $k[16] = "\xF0\xE1\xD2\xC3\xB4\xA5\x96\x87\x78\x69\x5A\x4B\x3C\x2D\x1E\x0F";
+$c[17] = "\x03\x42\x9E\x83\x8C\xE2\xD1\x4B"; $k[17] = "\xF0\xE1\xD2\xC3\xB4\xA5\x96\x87\x78\x69\x5A\x4B\x3C\x2D\x1E\x0F\x00";
+$c[18] = "\xA4\x29\x9E\x27\x46\x9F\xF6\x7B"; $k[18] = "\xF0\xE1\xD2\xC3\xB4\xA5\x96\x87\x78\x69\x5A\x4B\x3C\x2D\x1E\x0F\x00\x11";
+$c[19] = "\xAF\xD5\xAE\xD1\xC1\xBC\x96\xA8"; $k[19] = "\xF0\xE1\xD2\xC3\xB4\xA5\x96\x87\x78\x69\x5A\x4B\x3C\x2D\x1E\x0F\x00\x11\x22";
+$c[20] = "\x10\x85\x1C\x0E\x38\x58\xDA\x9F"; $k[20] = "\xF0\xE1\xD2\xC3\xB4\xA5\x96\x87\x78\x69\x5A\x4B\x3C\x2D\x1E\x0F\x00\x11\x22\x33";
+$c[21] = "\xE6\xF5\x1E\xD7\x9B\x9D\xB2\x1F"; $k[21] = "\xF0\xE1\xD2\xC3\xB4\xA5\x96\x87\x78\x69\x5A\x4B\x3C\x2D\x1E\x0F\x00\x11\x22\x33\x44";
+$c[22] = "\x64\xA6\xE1\x4A\xFD\x36\xB4\x6F"; $k[22] = "\xF0\xE1\xD2\xC3\xB4\xA5\x96\x87\x78\x69\x5A\x4B\x3C\x2D\x1E\x0F\x00\x11\x22\x33\x44\x55";
+$c[23] = "\x80\xC7\xD7\xD4\x5A\x54\x79\xAD"; $k[23] = "\xF0\xE1\xD2\xC3\xB4\xA5\x96\x87\x78\x69\x5A\x4B\x3C\x2D\x1E\x0F\x00\x11\x22\x33\x44\x55\x66";
+$c[24] = "\x05\x04\x4B\x62\xFA\x52\xD0\x80"; $k[24] = "\xF0\xE1\xD2\xC3\xB4\xA5\x96\x87\x78\x69\x5A\x4B\x3C\x2D\x1E\x0F\x00\x11\x22\x33\x44\x55\x66\x77";
+foreach ($k as $id => $key) {
+    echo (strlen($key) * 8) . "-bit Key\n";
+    testCipher('blowfish', $key, $plaintext, $c[$id]);
+}
+
+?>
+--EXPECT--
+Blowfish:
+---------
+
+64-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+8-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+16-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+24-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+32-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+40-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+48-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+56-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+64-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+72-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+80-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+88-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+96-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+104-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+112-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+120-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+128-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+136-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+144-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+152-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+160-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+168-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+176-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+184-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+192-bit Key
+Testing Encryption: Pass
+Testing Decryption: Pass
diff --git a/framework/Cipher/test/Horde/Cipher/Cipher6.phpt b/framework/Cipher/test/Horde/Cipher/Cipher6.phpt
new file mode 100644 (file)
index 0000000..3fbd681
--- /dev/null
@@ -0,0 +1,76 @@
+--TEST--
+Blockmode Horde_Cipher:: Tests
+--FILE--
+<?php
+
+require_once dirname(__FILE__) . '/cipher_functions.php';
+require_once dirname(__FILE__) . '/../../../lib/Horde/Cipher.php';
+require_once dirname(__FILE__) . '/../../../lib/Horde/Cipher/BlockMode.php';
+require_once dirname(__FILE__) . '/../../../lib/Horde/Cipher/Blowfish.php';
+require_once dirname(__FILE__) . '/../../../lib/Horde/Cipher/BlockMode/Cbc.php';
+require_once dirname(__FILE__) . '/../../../lib/Horde/Cipher/BlockMode/Cfb64.php';
+require_once dirname(__FILE__) . '/../../../lib/Horde/Cipher/BlockMode/Ecb.php';
+require_once dirname(__FILE__) . '/../../../lib/Horde/Cipher/BlockMode/Ofb64.php';
+
+/* Block Mode Tests */
+echo "Block Mode Tests:\n";
+echo "-----------------\n";
+echo "(using Blowfish test vectors)\n\n";
+
+$key = "\x01\x23\x45\x67\x89\xAB\xCD\xEF\xF0\xE1\xD2\xC3\xB4\xA5\x96\x87";
+$iv = "\xFE\xDC\xBA\x98\x76\x54\x32\x10";
+$plaintext = "7654321 Now is the time for ";
+
+echo "Cipher Block Chaining (CBC) Test\n";
+$ciphertext = "\x6B\x77\xB4\xD6\x30\x06\xDE\xE6\x05\xB1\x56\xE2\x74\x03\x97\x93\x58\xDE\xB9\xE7\x15\x46\x16\xD9\x59\xF1\x65\x2B\xD5\xFF\x92\xCC";
+$cipher = &Horde_Cipher::factory('blowfish');
+$cipher->setBlockMode("cbc");
+$cipher->setKey($key);
+$cipher->setIV($iv);
+testBlockCipher($cipher, $plaintext, $ciphertext);
+
+echo "Electronic Code Book (ECB) Test\n";
+$ciphertext = "\x2a\xfd\x7d\xaa\x60\x62\x6b\xa3\x86\x16\x46\x8c\xc2\x9c\xf6\xe1\x29\x1e\x81\x7c\xc7\x40\x98\x2d\x6f\x87\xac\x5f\x17\x1a\xab\xea";
+$cipher = &Horde_Cipher::factory('blowfish');
+$cipher->setBlockMode("ecb");
+$cipher->setKey($key);
+$cipher->setIV($iv);
+testBlockCipher($cipher, $plaintext, $ciphertext);
+
+echo "64 Bit Cipher Feedback (CFB64) Test\n";
+$ciphertext = "\xE7\x32\x14\xA2\x82\x21\x39\xCA\xF2\x6E\xCF\x6D\x2E\xB9\xE7\x6E\x3D\xA3\xDE\x04\xD1\x51\x72\x00\x51\x9D\x57\xA6";
+$cipher = &Horde_Cipher::factory('blowfish');
+$cipher->setBlockMode("cfb64");
+$cipher->setKey($key);
+$cipher->setIV($iv);
+testBlockCipher($cipher, $plaintext, $ciphertext);
+
+echo "64 Bit Output Feedback (OFB64) Test\n";
+$ciphertext = "\xE7\x32\x14\xA2\x82\x21\x39\xCA\x62\xB3\x43\xCC\x5B\x65\x58\x73\x10\xDD\x90\x8D\x0C\x24\x1B\x22\x63\xC2\xCF\x80";
+$cipher = &Horde_Cipher::factory('blowfish');
+$cipher->setBlockMode("ofb64");
+$cipher->setKey($key);
+$cipher->setIV($iv);
+testBlockCipher($cipher, $plaintext, $ciphertext);
+
+?>
+--EXPECT--
+Block Mode Tests:
+-----------------
+(using Blowfish test vectors)
+
+Cipher Block Chaining (CBC) Test
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+Electronic Code Book (ECB) Test
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+64 Bit Cipher Feedback (CFB64) Test
+Testing Encryption: Pass
+Testing Decryption: Pass
+
+64 Bit Output Feedback (OFB64) Test
+Testing Encryption: Pass
+Testing Decryption: Pass
diff --git a/framework/Cipher/test/Horde/Cipher/cipher_functions.php b/framework/Cipher/test/Horde/Cipher/cipher_functions.php
new file mode 100644 (file)
index 0000000..1e87e72
--- /dev/null
@@ -0,0 +1,66 @@
+<?php
+/**
+ * This script contains functions used for the cipher tests.
+ *
+ * @package Horde_Cipher
+ */
+
+require_once 'Horde/String.php';
+
+function testBlockCipher(&$cipher, $plaintext, $ciphertext)
+{
+    echo "Testing Encryption: ";
+    if ($cipher->encrypt($plaintext) == $ciphertext) {
+        echo "Pass\n";
+    } else {
+        echo "Fail\n";
+    }
+    echo "Testing Decryption: ";
+    if ($cipher->decrypt($ciphertext) == $plaintext) {
+        echo "Pass\n";
+    } else {
+        echo "Fail\n";
+    }
+    echo "\n";
+    flush();
+}
+
+function testCipher($cipher, $key,  $plaintext, $ciphertext)
+{
+    $cipher = &Horde_Cipher::factory($cipher);
+    $cipher->setKey($key);
+
+    echo "Testing Encryption: ";
+    $res = $cipher->encryptBlock($plaintext);
+    if ($res == $ciphertext) {
+        echo "Pass\n";
+    } else {
+        echo "Fail\n";
+        echo "Returned: ";
+        for ($i = 0; $i < strlen($res); $i++) {
+            echo str_pad(dechex(ord(substr($res, $i, 1))), 2, '0', STR_PAD_LEFT) . " ";
+        } echo "\n";
+        echo "Expected: ";
+        for ($i = 0; $i < strlen($ciphertext); $i++) {
+            echo str_pad(dechex(ord(substr($ciphertext, $i, 1))), 2, '0', STR_PAD_LEFT)  . " ";
+        } echo "\n";
+
+    }
+    echo "Testing Decryption: ";
+    $res = $cipher->decryptBlock($ciphertext);
+    if ($res == $plaintext) {
+        echo "Pass\n";
+    } else {
+        echo "Fail\n";
+        echo "Returned: ";
+        for ($i = 0; $i < strlen($res); $i++) {
+            echo str_pad(dechex(ord(substr($res, $i, 1))), 2, '0', STR_PAD_LEFT) . " ";
+        } echo "\n";
+        echo "Expected: ";
+        for ($i = 0; $i < strlen($plaintext); $i++) {
+            echo str_pad(dechex(ord(substr($plaintext, $i, 1))), 2, '0', STR_PAD_LEFT)  . " ";
+        } echo "\n";
+    }
+    echo "\n";
+    flush();
+}